From e2d81d9a72768e6b020dadc6e66d71b2162391bc Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Wed, 4 Dec 2024 14:42:56 +0100 Subject: [PATCH 001/120] Provider integration database migration (#6) * Add provider integration tables * Rename address book to known destination * Rename transfer relationship for future proofing * Remove default to now on connection's table date time columns due to the integrity hash at the application level. * Set the connection's credential column as nullable to better fit the initiation flow. * Fix typo on known destination relationship name. * Add request JSON in the transfers as a wildcard. --- apps/armory/Makefile | 6 +- apps/policy-engine/Makefile | 2 + .../module/persistence/schema/schema.prisma | 2 +- apps/vault/Makefile | 2 + .../migration.sql | 141 ++++++++++++++++ .../module/persistence/schema/schema.prisma | 153 +++++++++++++++++- 6 files changed, 296 insertions(+), 10 deletions(-) create mode 100644 apps/vault/src/shared/module/persistence/schema/migrations/20241203160823_add_provider_integration_tables/migration.sql diff --git a/apps/armory/Makefile b/apps/armory/Makefile index 697e9cc49..3a00927be 100644 --- a/apps/armory/Makefile +++ b/apps/armory/Makefile @@ -30,13 +30,15 @@ armory/build: # === Code format === armory/format: - npx nx format:write --projects ${ARMORY_PROJECT_NAME} + npx nx format:write --projects ${ARMORY_PROJECT_NAME} + npx prisma format --schema ${ARMORY_DATABASE_SCHEMA} armory/lint: npx nx lint ${ARMORY_PROJECT_NAME} -- --fix armory/format/check: - npx nx format:check --projects ${ARMORY_PROJECT_NAME} + npx nx format:check --projects ${ARMORY_PROJECT_NAME} + npx prisma format --schema ${ARMORY_DATABASE_SCHEMA} armory/lint/check: npx nx lint ${ARMORY_PROJECT_NAME} diff --git a/apps/policy-engine/Makefile b/apps/policy-engine/Makefile index 29ee09bfb..792f83a4a 100644 --- a/apps/policy-engine/Makefile +++ b/apps/policy-engine/Makefile @@ -43,9 +43,11 @@ policy-engine/lint/check: policy-engine/format: npx nx format:write --projects ${POLICY_ENGINE_PROJECT_NAME} + npx prisma format --schema ${POLICY_ENGINE_DATABASE_SCHEMA} policy-engine/format/check: npx nx format:check --projects ${POLICY_ENGINE_PROJECT_NAME} + npx prisma format --schema ${POLICY_ENGINE_DATABASE_SCHEMA} # === Database === diff --git a/apps/policy-engine/src/shared/module/persistence/schema/schema.prisma b/apps/policy-engine/src/shared/module/persistence/schema/schema.prisma index 80ff7df43..3990d8226 100644 --- a/apps/policy-engine/src/shared/module/persistence/schema/schema.prisma +++ b/apps/policy-engine/src/shared/module/persistence/schema/schema.prisma @@ -13,7 +13,7 @@ datasource db { } model Engine { - id String @id + id String @id masterKey String? @map("master_key") adminApiKey String? @map("admin_api_key") diff --git a/apps/vault/Makefile b/apps/vault/Makefile index 7b2c4852e..d6a23932f 100644 --- a/apps/vault/Makefile +++ b/apps/vault/Makefile @@ -30,12 +30,14 @@ vault/build: vault/format: npx nx format:write --projects ${VAULT_PROJECT_NAME} + npx prisma format --schema ${VAULT_DATABASE_SCHEMA} vault/lint: npx nx lint ${VAULT_PROJECT_NAME} -- --fix vault/format/check: npx nx format:check --projects ${VAULT_PROJECT_NAME} + npx prisma format --schema ${VAULT_DATABASE_SCHEMA} vault/lint/check: npx nx lint ${VAULT_PROJECT_NAME} diff --git a/apps/vault/src/shared/module/persistence/schema/migrations/20241203160823_add_provider_integration_tables/migration.sql b/apps/vault/src/shared/module/persistence/schema/migrations/20241203160823_add_provider_integration_tables/migration.sql new file mode 100644 index 000000000..a98962f75 --- /dev/null +++ b/apps/vault/src/shared/module/persistence/schema/migrations/20241203160823_add_provider_integration_tables/migration.sql @@ -0,0 +1,141 @@ +-- CreateTable +CREATE TABLE "provider_wallet" ( + "id" TEXT NOT NULL, + "label" TEXT, + "client_id" TEXT NOT NULL, + "provider" TEXT NOT NULL, + "external_id" TEXT NOT NULL, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "provider_wallet_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "provider_account" ( + "id" TEXT NOT NULL, + "label" TEXT, + "client_id" TEXT NOT NULL, + "provider" TEXT NOT NULL, + "external_id" TEXT NOT NULL, + "wallet_id" TEXT NOT NULL, + "network_id" TEXT NOT NULL, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "provider_account_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "provider_address" ( + "id" TEXT NOT NULL, + "client_id" TEXT NOT NULL, + "provider" TEXT NOT NULL, + "external_id" TEXT NOT NULL, + "account_id" TEXT NOT NULL, + "address" TEXT NOT NULL, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "provider_address_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "provider_known_destination" ( + "id" TEXT NOT NULL, + "client_id" TEXT NOT NULL, + "connection_id" TEXT NOT NULL, + "provider" TEXT NOT NULL, + "external_id" TEXT NOT NULL, + "external_classification" TEXT, + "address" TEXT NOT NULL, + "asset_id" TEXT, + "network_id" TEXT NOT NULL, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "provider_known_destination_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "provider_connection" ( + "id" TEXT NOT NULL, + "client_id" TEXT NOT NULL, + "provider" TEXT NOT NULL, + "url" TEXT NOT NULL, + "label" TEXT, + "credentials" JSONB NOT NULL, + "status" TEXT NOT NULL, + "_integrity" TEXT NOT NULL, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) NOT NULL, + "revoked_at" TIMESTAMP(3), + + CONSTRAINT "provider_connection_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "provider_wallet_connection" ( + "client_id" TEXT NOT NULL, + "connection_id" TEXT NOT NULL, + "wallet_id" TEXT NOT NULL, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "provider_wallet_connection_pkey" PRIMARY KEY ("client_id","connection_id","wallet_id") +); + +-- CreateTable +CREATE TABLE "provider_sync" ( + "id" TEXT NOT NULL, + "client_id" TEXT NOT NULL, + "connection_id" TEXT NOT NULL, + "status" TEXT NOT NULL, + "error_name" TEXT, + "error_message" TEXT, + "error_trace_id" TEXT, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "completed_at" TIMESTAMP(3), + + CONSTRAINT "provider_sync_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "provider_transfer" ( + "id" TEXT NOT NULL, + "client_id" TEXT NOT NULL, + "source_wallet_id" TEXT, + "source_account_id" TEXT, + "source_address_id" TEXT, + "provider" TEXT NOT NULL, + "external_id" TEXT NOT NULL, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "provider_transfer_pkey" PRIMARY KEY ("id") +); + +-- AddForeignKey +ALTER TABLE "provider_account" ADD CONSTRAINT "provider_account_wallet_id_fkey" FOREIGN KEY ("wallet_id") REFERENCES "provider_wallet"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "provider_address" ADD CONSTRAINT "provider_address_account_id_fkey" FOREIGN KEY ("account_id") REFERENCES "provider_account"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "provider_known_destination" ADD CONSTRAINT "provider_known_destination_connection_id_fkey" FOREIGN KEY ("connection_id") REFERENCES "provider_connection"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "provider_wallet_connection" ADD CONSTRAINT "provider_wallet_connection_connection_id_fkey" FOREIGN KEY ("connection_id") REFERENCES "provider_connection"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "provider_wallet_connection" ADD CONSTRAINT "provider_wallet_connection_wallet_id_fkey" FOREIGN KEY ("wallet_id") REFERENCES "provider_wallet"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "provider_sync" ADD CONSTRAINT "provider_sync_connection_id_fkey" FOREIGN KEY ("connection_id") REFERENCES "provider_connection"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "provider_transfer" ADD CONSTRAINT "provider_transfer_source_wallet_id_fkey" FOREIGN KEY ("source_wallet_id") REFERENCES "provider_wallet"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "provider_transfer" ADD CONSTRAINT "provider_transfer_source_account_id_fkey" FOREIGN KEY ("source_account_id") REFERENCES "provider_account"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "provider_transfer" ADD CONSTRAINT "provider_transfer_source_address_id_fkey" FOREIGN KEY ("source_address_id") REFERENCES "provider_address"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/apps/vault/src/shared/module/persistence/schema/schema.prisma b/apps/vault/src/shared/module/persistence/schema/schema.prisma index d9602a4b7..424120c9b 100644 --- a/apps/vault/src/shared/module/persistence/schema/schema.prisma +++ b/apps/vault/src/shared/module/persistence/schema/schema.prisma @@ -1,11 +1,11 @@ generator client { - provider = "prisma-client-js" + provider = "prisma-client-js" binaryTargets = ["native", "debian-openssl-1.1.x", "debian-openssl-3.0.x"] // Output into a separate subdirectory so multiple schemas can be used in a // monorepo. // // Reference: https://github.com/nrwl/nx-recipes/tree/main/nestjs-prisma - output = "../../../../../../../node_modules/@prisma/client/vault" + output = "../../../../../../../node_modules/@prisma/client/vault" } datasource db { @@ -14,7 +14,7 @@ datasource db { } model Vault { - id String @id + id String @id masterKey String? @map("master_key") adminApiKey String? @map("admin_api_key") @@ -24,10 +24,149 @@ model Vault { // TODO: (@wcalderipe, 12/03/23) use hstore extension for better performance. // See https://www.postgresql.org/docs/9.1/hstore.html model KeyValue { - key String @id - clientId String? @map("client_id") - collection String - value String + key String @id + clientId String? @map("client_id") + collection String + value String @@map("key_value") } + +model ProviderWallet { + id String @id + label String? + clientId String @map("client_id") + provider String + externalId String @map("external_id") + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") + + accounts ProviderAccount[] + connections ProviderWalletConnection[] + sourceTransfers ProviderTransfer[] @relation("SourceWallet") + + @@map("provider_wallet") +} + +model ProviderAccount { + id String @id + label String? + clientId String @map("client_id") + provider String + externalId String @map("external_id") + walletId String @map("wallet_id") + networkId String @map("network_id") + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") + + wallet ProviderWallet @relation(fields: [walletId], references: [id]) + addresses ProviderAddress[] + + sourceTransfers ProviderTransfer[] @relation("SourceAccount") + + @@map("provider_account") +} + +model ProviderAddress { + id String @id + clientId String @map("client_id") + provider String + externalId String @map("external_id") + accountId String @map("account_id") + address String + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") + + account ProviderAccount @relation(fields: [accountId], references: [id]) + + sourceTransfers ProviderTransfer[] @relation("SourceAddress") + + @@map("provider_address") +} + +model ProviderKnownDestination { + id String @id + clientId String @map("client_id") + connectionId String @map("connection_id") + provider String + externalId String @map("external_id") + externalClassification String? @map("external_classification") + address String + assetId String? @map("asset_id") + networkId String @map("network_id") + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") + + connection ProviderConnection @relation(fields: [connectionId], references: [id]) + + @@map("provider_known_destination") +} + +model ProviderConnection { + id String @id + clientId String @map("client_id") + provider String + url String + label String? + credentials Json? + status String + integrity String @map("_integrity") + // IMPORTANT: Don't default DateTime to `now()` on this table because the + // integrity column needs to hash all data at the application level. + createdAt DateTime @map("created_at") + updatedAt DateTime @map("updated_at") + revokedAt DateTime? @map("revoked_at") + + knownDestinations ProviderKnownDestination[] + connections ProviderWalletConnection[] + syncs ProviderSync[] + + @@map("provider_connection") +} + +model ProviderWalletConnection { + clientId String @map("client_id") + connectionId String @map("connection_id") + walletId String @map("wallet_id") + createdAt DateTime @default(now()) @map("created_at") + + connection ProviderConnection @relation(fields: [connectionId], references: [id]) + wallet ProviderWallet @relation(fields: [walletId], references: [id]) + + @@id([clientId, connectionId, walletId]) + @@map("provider_wallet_connection") +} + +model ProviderSync { + id String @id + clientId String @map("client_id") + connectionId String @map("connection_id") + status String + errorName String? @map("error_name") + errorMessage String? @map("error_message") + errorTraceId String? @map("error_trace_id") + createdAt DateTime @default(now()) @map("created_at") + completedAt DateTime? @map("completed_at") + + connection ProviderConnection @relation(fields: [connectionId], references: [id]) + + @@map("provider_sync") +} + +model ProviderTransfer { + id String @id + clientId String @map("client_id") + sourceWalletId String? @map("source_wallet_id") + sourceAccountId String? @map("source_account_id") + sourceAddressId String? @map("source_address_id") + provider String + externalId String @map("external_id") + request Json + createdAt DateTime @default(now()) @map("created_at") + + sourceWallet ProviderWallet? @relation("SourceWallet", fields: [sourceWalletId], references: [id]) + sourceAccount ProviderAccount? @relation("SourceAccount", fields: [sourceAccountId], references: [id]) + sourceAddress ProviderAddress? @relation("SourceAddress", fields: [sourceAddressId], references: [id]) + + @@map("provider_transfer") +} From 2dcc4db4651e825e97f1b18b4530376b367dc9b6 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Wed, 4 Dec 2024 14:43:11 +0100 Subject: [PATCH 002/120] Move Vault constants to shared (#7) * Move Vault constant to shared * Rename constant file --- .../src/client/__test__/e2e/client.spec.ts | 2 +- apps/vault/src/main.constant.ts | 12 ----- apps/vault/src/main.ts | 2 +- apps/vault/src/shared/constant.ts | 53 +++++++++++++++++++ .../shared/decorator/admin-guard.decorator.ts | 2 +- .../encryption-module-option.factory.ts | 2 +- .../__test__/unit/admin-api-key.guard.spec.ts | 2 +- .../src/shared/guard/admin-api-key.guard.ts | 2 +- 8 files changed, 59 insertions(+), 18 deletions(-) delete mode 100644 apps/vault/src/main.constant.ts create mode 100644 apps/vault/src/shared/constant.ts diff --git a/apps/vault/src/client/__test__/e2e/client.spec.ts b/apps/vault/src/client/__test__/e2e/client.spec.ts index fc9ec29f2..0e1fcd73b 100644 --- a/apps/vault/src/client/__test__/e2e/client.spec.ts +++ b/apps/vault/src/client/__test__/e2e/client.spec.ts @@ -7,7 +7,7 @@ import { Test, TestingModule } from '@nestjs/testing' import request from 'supertest' import { v4 as uuid } from 'uuid' import { Config, load } from '../../../main.config' -import { REQUEST_HEADER_API_KEY } from '../../../main.constant' +import { REQUEST_HEADER_API_KEY } from '../../../shared/constant' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' import { AppService } from '../../../vault/core/service/app.service' diff --git a/apps/vault/src/main.constant.ts b/apps/vault/src/main.constant.ts deleted file mode 100644 index 23749d4bd..000000000 --- a/apps/vault/src/main.constant.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { RawAesWrappingSuiteIdentifier } from '@aws-crypto/client-node' -import { adminApiKeySecurity, gnapSecurity } from '@narval/nestjs-shared' - -export const REQUEST_HEADER_API_KEY = 'x-api-key' -export const REQUEST_HEADER_AUTHORIZATION = 'Authorization' - -export const ENCRYPTION_KEY_NAMESPACE = 'armory.vault' -export const ENCRYPTION_KEY_NAME = 'storage-encryption' -export const ENCRYPTION_WRAPPING_SUITE = RawAesWrappingSuiteIdentifier.AES256_GCM_IV12_TAG16_NO_PADDING - -export const GNAP_SECURITY = gnapSecurity() -export const ADMIN_API_KEY_SECURITY = adminApiKeySecurity(REQUEST_HEADER_API_KEY) diff --git a/apps/vault/src/main.ts b/apps/vault/src/main.ts index 5142d6630..10f947bdb 100644 --- a/apps/vault/src/main.ts +++ b/apps/vault/src/main.ts @@ -12,8 +12,8 @@ import { INestApplication, ValidationPipe } from '@nestjs/common' import { NestFactory } from '@nestjs/core' import { lastValueFrom, map, of, switchMap } from 'rxjs' import { Config } from './main.config' -import { ADMIN_API_KEY_SECURITY, GNAP_SECURITY } from './main.constant' import { MainModule, ProvisionModule } from './main.module' +import { ADMIN_API_KEY_SECURITY, GNAP_SECURITY } from './shared/constant' /** * Adds global pipes to the application. diff --git a/apps/vault/src/shared/constant.ts b/apps/vault/src/shared/constant.ts new file mode 100644 index 000000000..a6855b556 --- /dev/null +++ b/apps/vault/src/shared/constant.ts @@ -0,0 +1,53 @@ +import { RawAesWrappingSuiteIdentifier } from '@aws-crypto/client-node' +import { adminApiKeySecurity, gnapSecurity } from '@narval/nestjs-shared' +import { ClassSerializerInterceptor, ValidationPipe } from '@nestjs/common' +import { APP_FILTER, APP_INTERCEPTOR, APP_PIPE } from '@nestjs/core' +import { ZodValidationPipe } from 'nestjs-zod' +import { ApplicationExceptionFilter } from './filter/application-exception.filter' +import { ZodExceptionFilter } from './filter/zod-exception.filter' + +export const REQUEST_HEADER_API_KEY = 'x-api-key' +export const REQUEST_HEADER_AUTHORIZATION = 'Authorization' + +export const ENCRYPTION_KEY_NAMESPACE = 'armory.vault' +export const ENCRYPTION_KEY_NAME = 'storage-encryption' +export const ENCRYPTION_WRAPPING_SUITE = RawAesWrappingSuiteIdentifier.AES256_GCM_IV12_TAG16_NO_PADDING + +export const GNAP_SECURITY = gnapSecurity() +export const ADMIN_API_KEY_SECURITY = adminApiKeySecurity(REQUEST_HEADER_API_KEY) + +// +// Providers +// + +export const HTTP_VALIDATION_PIPES = [ + { + provide: APP_PIPE, + // Enable transformation after validation for HTTP response serialization. + useFactory: () => new ValidationPipe({ transform: true }) + }, + { + provide: APP_PIPE, + useClass: ZodValidationPipe + } +] + +export const HTTP_EXCEPTION_FILTERS = [ + { + provide: APP_FILTER, + useClass: ApplicationExceptionFilter + }, + { + provide: APP_FILTER, + useClass: ZodExceptionFilter + } +] + +export const DEFAULT_HTTP_MODULE_PROVIDERS = [ + { + provide: APP_INTERCEPTOR, + useClass: ClassSerializerInterceptor + }, + ...HTTP_EXCEPTION_FILTERS, + ...HTTP_VALIDATION_PIPES +] diff --git a/apps/vault/src/shared/decorator/admin-guard.decorator.ts b/apps/vault/src/shared/decorator/admin-guard.decorator.ts index a2217db2d..11671fc17 100644 --- a/apps/vault/src/shared/decorator/admin-guard.decorator.ts +++ b/apps/vault/src/shared/decorator/admin-guard.decorator.ts @@ -1,6 +1,6 @@ import { UseGuards, applyDecorators } from '@nestjs/common' import { ApiHeader, ApiSecurity } from '@nestjs/swagger' -import { ADMIN_API_KEY_SECURITY, REQUEST_HEADER_API_KEY } from '../../main.constant' +import { ADMIN_API_KEY_SECURITY, REQUEST_HEADER_API_KEY } from '../constant' import { AdminApiKeyGuard } from '../guard/admin-api-key.guard' export function AdminGuard() { diff --git a/apps/vault/src/shared/factory/encryption-module-option.factory.ts b/apps/vault/src/shared/factory/encryption-module-option.factory.ts index 76ff73c14..15a0d5eef 100644 --- a/apps/vault/src/shared/factory/encryption-module-option.factory.ts +++ b/apps/vault/src/shared/factory/encryption-module-option.factory.ts @@ -10,8 +10,8 @@ import { LoggerService } from '@narval/nestjs-shared' import { toBytes } from '@narval/policy-engine-shared' import { Injectable } from '@nestjs/common' import { Config } from '../../main.config' -import { ENCRYPTION_KEY_NAME, ENCRYPTION_KEY_NAMESPACE, ENCRYPTION_WRAPPING_SUITE } from '../../main.constant' import { AppService } from '../../vault/core/service/app.service' +import { ENCRYPTION_KEY_NAME, ENCRYPTION_KEY_NAMESPACE, ENCRYPTION_WRAPPING_SUITE } from '../constant' @Injectable() export class EncryptionModuleOptionFactory { diff --git a/apps/vault/src/shared/guard/__test__/unit/admin-api-key.guard.spec.ts b/apps/vault/src/shared/guard/__test__/unit/admin-api-key.guard.spec.ts index 46941811e..630b143f9 100644 --- a/apps/vault/src/shared/guard/__test__/unit/admin-api-key.guard.spec.ts +++ b/apps/vault/src/shared/guard/__test__/unit/admin-api-key.guard.spec.ts @@ -1,8 +1,8 @@ import { secret } from '@narval/nestjs-shared' import { ExecutionContext } from '@nestjs/common' import { mock } from 'jest-mock-extended' -import { REQUEST_HEADER_API_KEY } from '../../../../main.constant' import { AppService } from '../../../../vault/core/service/app.service' +import { REQUEST_HEADER_API_KEY } from '../../../constant' import { ApplicationException } from '../../../exception/application.exception' import { AdminApiKeyGuard } from '../../admin-api-key.guard' diff --git a/apps/vault/src/shared/guard/admin-api-key.guard.ts b/apps/vault/src/shared/guard/admin-api-key.guard.ts index 2c7e9fbd0..41b9855a4 100644 --- a/apps/vault/src/shared/guard/admin-api-key.guard.ts +++ b/apps/vault/src/shared/guard/admin-api-key.guard.ts @@ -1,7 +1,7 @@ import { secret } from '@narval/nestjs-shared' import { CanActivate, ExecutionContext, HttpStatus, Injectable } from '@nestjs/common' -import { REQUEST_HEADER_API_KEY } from '../../main.constant' import { AppService } from '../../vault/core/service/app.service' +import { REQUEST_HEADER_API_KEY } from '../constant' import { ApplicationException } from '../exception/application.exception' @Injectable() From b8adf9bf688407dd56c0ac800f3dc2bc6fd6c3a3 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Wed, 4 Dec 2024 16:26:02 +0100 Subject: [PATCH 003/120] Refactor privateKeyToJwk and getPublicKey to return the right type given the input (#8) * Refactor privateKeyToJwk and getPublicKey to return the right type * Fix broken tests * Rollback the RSA length to 2048 * Add comment about RSA length side effect --- .../integration/data-store.service.spec.ts | 4 +- packages/signature/src/lib/types.ts | 26 ++++++++-- packages/signature/src/lib/utils.ts | 47 +++++++++++++++++-- 3 files changed, 67 insertions(+), 10 deletions(-) diff --git a/apps/policy-engine/src/engine/core/service/__test__/integration/data-store.service.spec.ts b/apps/policy-engine/src/engine/core/service/__test__/integration/data-store.service.spec.ts index bace43dbf..65a2b0da0 100644 --- a/apps/policy-engine/src/engine/core/service/__test__/integration/data-store.service.spec.ts +++ b/apps/policy-engine/src/engine/core/service/__test__/integration/data-store.service.spec.ts @@ -10,7 +10,7 @@ import { PolicyStore, SourceType } from '@narval/policy-engine-shared' -import { Jwk, PublicKey, getPublicKey, privateKeyToJwk } from '@narval/signature' +import { PrivateKey, PublicKey, getPublicKey, privateKeyToJwk } from '@narval/signature' import { HttpStatus } from '@nestjs/common' import { Test } from '@nestjs/testing' @@ -27,7 +27,7 @@ const UNSAFE_PRIVATE_KEY = '0x7cfef3303797cbc7515d9ce22ffe849c701b0f2812f999b084 describe(DataStoreService.name, () => { let service: DataStoreService - let privateKey: Jwk + let privateKey: PrivateKey let publicKey: PublicKey let entityStore: EntityStore let policyStore: PolicyStore diff --git a/packages/signature/src/lib/types.ts b/packages/signature/src/lib/types.ts index 02ab01d34..3cc446eea 100644 --- a/packages/signature/src/lib/types.ts +++ b/packages/signature/src/lib/types.ts @@ -18,9 +18,23 @@ export const Curves = { export type Curves = (typeof Curves)[keyof typeof Curves] export const Alg = { - ES256K: 'ES256K', // secp256k1, an Ethereum EOA - ES256: 'ES256', // secp256r1, ecdsa but not ethereum + /** + * SECP256K1 + * + * Examples: + * - Used by Ethereum + */ + ES256K: 'ES256K', + /** + * SECP256R1, ECDSA but not Ethereum + */ + ES256: 'ES256', RS256: 'RS256', + /** + * Examples: + * - Used by Solan + * - Uses SHA512 and doesn't require a pre-hashed payload + */ EDDSA: 'EDDSA' } as const @@ -28,7 +42,13 @@ export type Alg = (typeof Alg)[keyof typeof Alg] export const SigningAlg = { ES256K: 'ES256K', - EIP191: 'EIP191', // ecdsa on secp256k1 with keccak256 & data prefixed w/ \x19Ethereum Signed Message:\n + len(message) + /** + * ECDSA on SECP256K1 with KECCAK256 and data prefixed + * + * Examples: + * - \x19Ethereum Signed Message:\n + len(message) + */ + EIP191: 'EIP191', ES256: 'ES256', RS256: 'RS256', ED25519: 'EDDSA' diff --git a/packages/signature/src/lib/utils.ts b/packages/signature/src/lib/utils.ts index 744207776..1bec37b16 100644 --- a/packages/signature/src/lib/utils.ts +++ b/packages/signature/src/lib/utils.ts @@ -361,24 +361,43 @@ export const privateKeyToHex = async (jwk: Jwk): Promise => { } } -export const privateKeyToJwk = (key: Hex, alg: Alg = Alg.ES256K, keyId?: string): PrivateKey => { +type AlgToPrivateKeyType = { + [Alg.ES256K]: Secp256k1PrivateKey + [Alg.ES256]: P256PrivateKey + [Alg.EDDSA]: Ed25519PrivateKey + [Alg.RS256]: never +} + +export const privateKeyToJwk = ( + key: Hex, + alg: A = Alg.ES256K as A, + keyId?: string +): AlgToPrivateKeyType[A] => { switch (alg) { case Alg.ES256K: - return secp256k1PrivateKeyToJwk(key, keyId) + return secp256k1PrivateKeyToJwk(key, keyId) as AlgToPrivateKeyType[A] case Alg.ES256: - return p256PrivateKeyToJwk(key, keyId) + return p256PrivateKeyToJwk(key, keyId) as AlgToPrivateKeyType[A] case Alg.EDDSA: - return ed25519PrivateKeyToJwk(key, keyId) + return ed25519PrivateKeyToJwk(key, keyId) as AlgToPrivateKeyType[A] case Alg.RS256: throw new JwtError({ message: 'Conversion from Hex to JWK not supported for RSA keys' }) + default: + throw new JwtError({ + message: `Unsupported algorithm: ${alg}` + }) } } const generateRsaPrivateKey = async ( opts: { keyId?: string + /** + * IMPORTANT: Increasing the length will significantly increase the + * generation time. + */ modulusLength?: number use?: Use } = { @@ -421,7 +440,16 @@ export const generateJwk = async ( alg: Alg, opts?: { keyId?: string + /** + * Increase the length of the RSA key. + * + * IMPORTANT: Increasing the length will significantly increase the + * generation time. + */ modulusLength?: number + /** + * RSA Only. + */ use?: Use } ): Promise => { @@ -449,7 +477,16 @@ export const generateJwk = async ( export const nowSeconds = (): number => Math.floor(Date.now() / 1000) -export const getPublicKey = (key: Jwk): PublicKey => publicKeySchema.parse(key) +type AlgToPublicKeyType = { + ES256K: Secp256k1PublicKey + ES256: P256PublicKey + EDDSA: Ed25519PublicKey + RS256: RsaPublicKey +} + +export const getPublicKey = >(key: Jwk & { alg: A }): AlgToPublicKeyType[A] => { + return publicKeySchema.parse(key) as AlgToPublicKeyType[A] +} export const requestWithoutWildcardFields = ( request: object, From 0432536cf3376248e6ae1c10f057e6df074709da Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Wed, 4 Dec 2024 16:43:52 +0100 Subject: [PATCH 004/120] Create connection draft --- .../broker/__test__/e2e/connection.spec.ts | 79 +++++++++++++++++++ apps/vault/src/broker/broker.module.ts | 13 +++ .../broker/core/service/connection.service.ts | 54 +++++++++++++ .../src/broker/core/type/connection.type.ts | 60 ++++++++++++++ .../src/broker/core/type/provider.type.ts | 7 ++ .../rest/controller/connection.controller.ts | 33 ++++++++ .../rest/dto/request/create-connection.dto.ts | 4 + .../http/rest/dto/response/connection.dto.ts | 9 +++ .../repository/connection.repository.ts | 31 ++++++++ .../src/lib/__test__/unit/util.spec.ts | 3 +- 10 files changed, 292 insertions(+), 1 deletion(-) create mode 100644 apps/vault/src/broker/__test__/e2e/connection.spec.ts create mode 100644 apps/vault/src/broker/broker.module.ts create mode 100644 apps/vault/src/broker/core/service/connection.service.ts create mode 100644 apps/vault/src/broker/core/type/connection.type.ts create mode 100644 apps/vault/src/broker/core/type/provider.type.ts create mode 100644 apps/vault/src/broker/http/rest/controller/connection.controller.ts create mode 100644 apps/vault/src/broker/http/rest/dto/request/create-connection.dto.ts create mode 100644 apps/vault/src/broker/http/rest/dto/response/connection.dto.ts create mode 100644 apps/vault/src/broker/persistence/repository/connection.repository.ts diff --git a/apps/vault/src/broker/__test__/e2e/connection.spec.ts b/apps/vault/src/broker/__test__/e2e/connection.spec.ts new file mode 100644 index 000000000..b2f23475b --- /dev/null +++ b/apps/vault/src/broker/__test__/e2e/connection.spec.ts @@ -0,0 +1,79 @@ +import { ConfigModule } from '@narval/config-module' +import { EncryptionModuleOptionProvider } from '@narval/encryption-module' +import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' +import { Alg, generateJwk, privateKeyToHex } from '@narval/signature' +import { HttpStatus, INestApplication } from '@nestjs/common' +import { Test, TestingModule } from '@nestjs/testing' +import request from 'supertest' +import { load } from '../../../main.config' +import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' +import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' +import { BrokerModule } from '../../broker.module' +import { Provider } from '../../core/type/connection.type' + +describe('Connection', () => { + let app: INestApplication + let module: TestingModule + let testPrismaService: TestPrismaService + + beforeAll(async () => { + module = await Test.createTestingModule({ + imports: [ + LoggerModule.forTest(), + ConfigModule.forRoot({ + load: [load], + isGlobal: true + }), + BrokerModule + ] + }) + .overrideProvider(EncryptionModuleOptionProvider) + .useValue({ + keyring: getTestRawAesKeyring() + }) + .compile() + + app = module.createNestApplication() + + testPrismaService = module.get(TestPrismaService) + + await testPrismaService.truncateAll() + + await app.init() + }) + + afterAll(async () => { + await testPrismaService.truncateAll() + await module.close() + await app.close() + }) + + describe('POST /connections', () => { + it('creates a new connection to anchorage', async () => { + const privateKey = await generateJwk(Alg.EDDSA) + const privateKeyHex = await privateKeyToHex(privateKey) + const clientId = 'test-client-id' + const connection = { + provider: Provider.ANCHORAGE, + connectionId: 'test-connection-id', + label: 'Test Anchorage Connection', + url: 'http://provider.narval.xyz', + credentials: { + apiKey: 'test-api-key', + privateKey: privateKeyHex + } + } + + const { status, body } = await request(app.getHttpServer()) + .post('/connections') + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .send(connection) + + expect(body).toEqual({ + connectionId: connection.connectionId, + clientId + }) + expect(status).toEqual(HttpStatus.CREATED) + }) + }) +}) diff --git a/apps/vault/src/broker/broker.module.ts b/apps/vault/src/broker/broker.module.ts new file mode 100644 index 000000000..3928d42dc --- /dev/null +++ b/apps/vault/src/broker/broker.module.ts @@ -0,0 +1,13 @@ +import { Module } from '@nestjs/common' +import { DEFAULT_HTTP_MODULE_PROVIDERS } from '../shared/constant' +import { PersistenceModule } from '../shared/module/persistence/persistence.module' +import { ConnectionService } from './core/service/connection.service' +import { ConnectionController } from './http/rest/controller/connection.controller' +import { ConnectionRepository } from './persistence/repository/connection.repository' + +@Module({ + imports: [PersistenceModule], + controllers: [ConnectionController], + providers: [...DEFAULT_HTTP_MODULE_PROVIDERS, ConnectionService, ConnectionRepository] +}) +export class BrokerModule {} diff --git a/apps/vault/src/broker/core/service/connection.service.ts b/apps/vault/src/broker/core/service/connection.service.ts new file mode 100644 index 000000000..82ea9210c --- /dev/null +++ b/apps/vault/src/broker/core/service/connection.service.ts @@ -0,0 +1,54 @@ +import { Alg, Ed25519PrivateKey, generateJwk, getPublicKey, hash, privateKeyToJwk } from '@narval/signature' +import { HttpStatus, Injectable } from '@nestjs/common' +import { v4 as uuid } from 'uuid' +import { ApplicationException } from '../../../shared/exception/application.exception' +import { ConnectionRepository } from '../../persistence/repository/connection.repository' +import { Connection, ConnectionStatus, CreateConnection } from '../type/connection.type' + +@Injectable() +export class ConnectionService { + constructor(private readonly connectionRepository: ConnectionRepository) {} + + async create(clientId: string, input: CreateConnection): Promise { + const now = new Date() + const privateKey = await this.getPrivateKey(input) + + if (privateKey.kty) { + const connection = { + clientId, + id: input.connectionId || uuid(), + provider: input.provider, + status: ConnectionStatus.ACTIVE, + url: input.url, + credentials: { + apiKey: input.credentials.apiKey, + privateKey, + publicKey: getPublicKey(privateKey) + }, + createdAt: now, + updatedAt: now, + revokedAt: undefined + } + + return this.connectionRepository.save({ + ...connection, + // TODO: Sign the hash. + integrity: hash(connection) + }) + } + + throw new ApplicationException({ + message: 'Invalid private key type', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY + }) + } + + // TODO: This is Anchorage specific. + private async getPrivateKey({ credentials: credential }: CreateConnection): Promise { + if (credential.privateKey) { + return privateKeyToJwk(credential.privateKey, Alg.EDDSA) + } + + return await generateJwk(Alg.EDDSA) + } +} diff --git a/apps/vault/src/broker/core/type/connection.type.ts b/apps/vault/src/broker/core/type/connection.type.ts new file mode 100644 index 000000000..89bf8744a --- /dev/null +++ b/apps/vault/src/broker/core/type/connection.type.ts @@ -0,0 +1,60 @@ +import { hexSchema } from '@narval/policy-engine-shared' +import { ed25519PrivateKeySchema, ed25519PublicKeySchema } from '@narval/signature' +import { z } from 'zod' + +export const Provider = { + ANCHORAGE: 'anchorage' +} as const +export type Provider = keyof typeof Provider + +export const ConnectionStatus = { + PENDING: 'pending', + ACTIVE: 'active', + REVOKED: 'revoked' +} as const + +const SharedConnection = z.object({ + id: z.string(), + clientId: z.string(), + provider: z.nativeEnum(Provider), + url: z.string().url(), + status: z.nativeEnum(ConnectionStatus).default(ConnectionStatus.ACTIVE), + integrity: z.string(), + label: z.string().optional(), + createdAt: z.date(), + updatedAt: z.date().optional(), + revokedAt: z.date().optional() +}) + +export const AnchorageCredentials = z.object({ + // NOTE: The API key is optional in the initiation flow. + apiKey: z.string().optional(), + publicKey: ed25519PublicKeySchema, + privateKey: ed25519PrivateKeySchema +}) + +const AnchorageConnection = SharedConnection.extend({ + provider: z.literal(Provider.ANCHORAGE), + credentials: AnchorageCredentials +}) + +export const Connection = AnchorageConnection +export type Connection = z.infer + +const SharedCreateConnection = z.object({ + connectionId: z.string().optional(), + provider: z.nativeEnum(Provider), + url: z.string().url(), + label: z.string().optional(), + createdAt: z.date().optional() +}) + +export const CreateConnection = SharedCreateConnection.extend({ + provider: z.literal(Provider.ANCHORAGE), + credentials: z.object({ + apiKey: z.string(), + // Ed25519, hex format + privateKey: hexSchema.optional() + }) +}) +export type CreateConnection = z.infer diff --git a/apps/vault/src/broker/core/type/provider.type.ts b/apps/vault/src/broker/core/type/provider.type.ts new file mode 100644 index 000000000..a3e5afba0 --- /dev/null +++ b/apps/vault/src/broker/core/type/provider.type.ts @@ -0,0 +1,7 @@ +// How to build a credential with the right private key Alg? +// +// Pass the input type that's part of the CreateConnection +// Get a provider specific credential +export interface CredentialBuilder { + build(input: Input): Promise +} diff --git a/apps/vault/src/broker/http/rest/controller/connection.controller.ts b/apps/vault/src/broker/http/rest/controller/connection.controller.ts new file mode 100644 index 000000000..e1aa45bd4 --- /dev/null +++ b/apps/vault/src/broker/http/rest/controller/connection.controller.ts @@ -0,0 +1,33 @@ +import { Body, Controller, HttpStatus, Post } from '@nestjs/common' +import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' +import { ClientId } from '../../../../shared/decorator/client-id.decorator' +import { ConnectionService } from '../../../core/service/connection.service' +import { CreateConnectionDto } from '../dto/request/create-connection.dto' +import { ConnectionDto } from '../dto/response/connection.dto' + +@Controller({ + path: 'connections', + version: '1' +}) +@ApiTags('Connection') +export class ConnectionController { + constructor(private readonly connectionService: ConnectionService) {} + + @Post() + @ApiOperation({ + summary: 'Securely stores a provider connection' + }) + @ApiResponse({ + description: 'The stored provider connection reference', + status: HttpStatus.CREATED, + type: ConnectionDto + }) + async create(@ClientId() clientId: string, @Body() body: CreateConnectionDto): Promise { + const connection = await this.connectionService.create(clientId, body) + + return { + connectionId: connection.id, + clientId: connection.clientId + } + } +} diff --git a/apps/vault/src/broker/http/rest/dto/request/create-connection.dto.ts b/apps/vault/src/broker/http/rest/dto/request/create-connection.dto.ts new file mode 100644 index 000000000..84517ed1e --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/request/create-connection.dto.ts @@ -0,0 +1,4 @@ +import { createZodDto } from 'nestjs-zod' +import { CreateConnection } from '../../../../core/type/connection.type' + +export class CreateConnectionDto extends createZodDto(CreateConnection) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/connection.dto.ts b/apps/vault/src/broker/http/rest/dto/response/connection.dto.ts new file mode 100644 index 000000000..1c7ed54c1 --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/response/connection.dto.ts @@ -0,0 +1,9 @@ +import { createZodDto } from 'nestjs-zod' +import { z } from 'zod' + +export class ConnectionDto extends createZodDto( + z.object({ + connectionId: z.string(), + clientId: z.string() + }) +) {} diff --git a/apps/vault/src/broker/persistence/repository/connection.repository.ts b/apps/vault/src/broker/persistence/repository/connection.repository.ts new file mode 100644 index 000000000..1f743051c --- /dev/null +++ b/apps/vault/src/broker/persistence/repository/connection.repository.ts @@ -0,0 +1,31 @@ +import { Injectable } from '@nestjs/common' +import { Prisma } from '@prisma/client/vault' +import { SetRequired } from 'type-fest' +import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' +import { Connection } from '../../core/type/connection.type' + +@Injectable() +export class ConnectionRepository { + constructor(private prismaService: PrismaService) {} + + async save(connection: SetRequired): Promise { + await this.prismaService.providerConnection.create({ + data: { + id: connection.id, + clientId: connection.clientId, + provider: connection.provider, + url: connection.url, + label: connection.label, + status: connection.status, + // TODO + credentials: Prisma.JsonNull, + integrity: connection.integrity, + createdAt: connection.createdAt, + updatedAt: connection.updatedAt, + revokedAt: connection.revokedAt + } + }) + + return connection + } +} diff --git a/packages/signature/src/lib/__test__/unit/util.spec.ts b/packages/signature/src/lib/__test__/unit/util.spec.ts index a9c58c0e7..bb0d8d856 100644 --- a/packages/signature/src/lib/__test__/unit/util.spec.ts +++ b/packages/signature/src/lib/__test__/unit/util.spec.ts @@ -120,7 +120,8 @@ describe('isHeader', () => { describe('generateKeys', () => { it('generate a valid RSA key pair and return it as a JWK', async () => { - const key = await generateJwk(Alg.RS256) + // IMPORTANT: Uses a small length to increase the generation speed on tests. + const key = await generateJwk(Alg.RS256, { modulusLength: 1024 }) expect(rsaPrivateKeySchema.safeParse(key).success).toBe(true) }) From 65e887ec26e6099b29ea6176f3482b5337e89cb8 Mon Sep 17 00:00:00 2001 From: Pierre Troger Date: Wed, 4 Dec 2024 17:04:46 +0100 Subject: [PATCH 005/120] basic seed --- .../src/shared/module/persistence/seed.ts | 205 +++++++++++++++++- package.json | 2 +- 2 files changed, 203 insertions(+), 4 deletions(-) diff --git a/apps/vault/src/shared/module/persistence/seed.ts b/apps/vault/src/shared/module/persistence/seed.ts index ae8615705..f3bbb7ad3 100644 --- a/apps/vault/src/shared/module/persistence/seed.ts +++ b/apps/vault/src/shared/module/persistence/seed.ts @@ -1,6 +1,7 @@ /* eslint-disable */ import { LoggerService } from '@narval/nestjs-shared' import { PrismaClient, Vault } from '@prisma/client/vault' +import { v4 } from 'uuid' const prisma = new PrismaClient() @@ -10,15 +11,213 @@ const vault: Vault = { masterKey: 'master-key-xxx' } +const ANCHORAGE_SEED_DATA = { + // Basic client setup + client: { + id: v4(), + provider: 'anchorage' as const + }, + + // Connection details + connection: { + id: v4(), + url: 'https://api.anchorage-staging.com/v2', + label: 'Anchorage Staging', + credentials: { + apiKey: 'sample-api-key', + secretKey: 'sample-secret-key' + } + }, + + // Workspaces represent different organizations. + workspaces: [ + { + wallet: { + id: 'wallet-1', + externalId: 'vault_1', + label: 'Wallet for org1' + }, + accounts: [ + { + // BTC Account + account: { + id: 'account-1', + externalId: 'wallet_1', + label: 'Bitcoin Mainnet', + networkId: '1' + }, + // Multiple addresses for BTC (UTXO) + addresses: [ + { + id: 'address-1', + externalId: 'btc_address_1', + address: 'b1742d35Cc6634C0532925a3b844Bc454e4438f44e' + }, + { + id: 'address-2', + externalId: 'btc_address_2', + address: 'b1123d35Cc6634C0532925a3b844Bc454e4438f789' + } + ] + }, + { + // ETH Account + account: { + id: 'account-2', + externalId: 'wallet_2', + label: 'Ethereum Mainnet', + networkId: '60' + }, + // Single address for ETH (account-based) + addresses: [ + { + id: 'address-3', + externalId: 'eth_addr', + address: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e' + } + ] + } + ] + }, + { + wallet: { + id: 'wallet-2', + externalId: 'vault_2', + label: 'walletForOrg2' + }, + accounts: [ + { + account: { + id: 'account-vault2-1', + externalId: 'wallet_3', + label: 'Trading BTC', + networkId: 'BTC' + }, + addresses: [ + { + id: 'address-vault2-1', + externalId: 'btc_trading_addr_1', + address: 'bt12NGZrVvZG92qGYqzTLjCAewvPZ7JE8S8VxE' + } + ] + } + ] + } + ], + + // Address book entries + knownDestinations: [ + { + id: v4(), + externalId: 'dest1', + address: 'bt12NGZrVvZG92qGYqzTLjCAewvPZ7JE8S8VxE', + networkId: 'BTC', + externalClassification: 'trusted' + } + ] +} + async function main() { const logger = new LoggerService() + logger.log('Seeding Vault database with Anchorage provider data') - logger.log('Seeding Vault database') await prisma.$transaction(async (txn) => { - // await txn.vault.create({ data: vault }) + // 1. Create the connection + + const connection = await txn.providerConnection.create({ + data: { + id: ANCHORAGE_SEED_DATA.connection.id, + clientId: ANCHORAGE_SEED_DATA.client.id, + provider: ANCHORAGE_SEED_DATA.client.provider, + url: ANCHORAGE_SEED_DATA.connection.url, + label: ANCHORAGE_SEED_DATA.connection.label, + credentials: ANCHORAGE_SEED_DATA.connection.credentials, + status: 'active', + integrity: 'sample-integrity-hash', + createdAt: new Date(), + updatedAt: new Date() + } + }) + + // 2. Create each vault (provider wallet) and its contents + for (const workspace of ANCHORAGE_SEED_DATA.workspaces) { + // Create the provider wallet record + const providerWallet = await txn.providerWallet.create({ + data: { + id: workspace.wallet.id, + clientId: ANCHORAGE_SEED_DATA.client.id, + provider: ANCHORAGE_SEED_DATA.client.provider, + label: workspace.wallet.label, + externalId: workspace.wallet.externalId + } + }) + + // Link wallet to connection + await txn.providerWalletConnection.create({ + data: { + clientId: ANCHORAGE_SEED_DATA.client.id, + connectionId: connection.id, + walletId: providerWallet.id + } + }) + + // Create accounts and addresses + for (const accountData of workspace.accounts) { + const account = await txn.providerAccount.create({ + data: { + id: accountData.account.id, + clientId: ANCHORAGE_SEED_DATA.client.id, + provider: ANCHORAGE_SEED_DATA.client.provider, + label: accountData.account.label, + externalId: accountData.account.externalId, + walletId: providerWallet.id, + networkId: accountData.account.networkId + } + }) + + // Create addresses for this account + for (const addrData of accountData.addresses) { + await txn.providerAddress.create({ + data: { + id: addrData.id, + clientId: ANCHORAGE_SEED_DATA.client.id, + provider: ANCHORAGE_SEED_DATA.client.provider, + externalId: addrData.externalId, + accountId: account.id, + address: addrData.address + } + }) + } + } + } + + for (const destData of ANCHORAGE_SEED_DATA.knownDestinations) { + await txn.providerKnownDestination.create({ + data: { + id: destData.id, + clientId: ANCHORAGE_SEED_DATA.client.id, + connectionId: connection.id, + provider: ANCHORAGE_SEED_DATA.client.provider, + externalId: destData.externalId, + externalClassification: destData.externalClassification, + address: destData.address, + networkId: destData.networkId + } + }) + } + + // 4. Create initial sync record + await txn.providerSync.create({ + data: { + id: v4(), + clientId: ANCHORAGE_SEED_DATA.client.id, + connectionId: connection.id, + status: 'success' + } + }) }) - logger.log('Vault database germinated 🌱') + logger.log('Vault database germinated with Anchorage provider data 🌱') } main() diff --git a/package.json b/package.json index 4d411845a..a184328c8 100644 --- a/package.json +++ b/package.json @@ -152,4 +152,4 @@ "nx": { "includedScripts": [] } -} \ No newline at end of file +} From 3f0b159fb6035ed351fef55ffaf8e3370a2b5cfa Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Wed, 4 Dec 2024 17:19:18 +0100 Subject: [PATCH 006/120] Encode and decode Anchorage credentials --- .../broker/__test__/e2e/connection.spec.ts | 31 ++++++++++++++-- .../exception/connection-parse.exception.ts | 3 ++ .../broker/core/service/connection.service.ts | 13 +++---- .../src/broker/core/type/connection.type.ts | 2 +- .../repository/connection.repository.ts | 35 ++++++++++++++++--- 5 files changed, 70 insertions(+), 14 deletions(-) create mode 100644 apps/vault/src/broker/core/exception/connection-parse.exception.ts diff --git a/apps/vault/src/broker/__test__/e2e/connection.spec.ts b/apps/vault/src/broker/__test__/e2e/connection.spec.ts index b2f23475b..76fc6ae3d 100644 --- a/apps/vault/src/broker/__test__/e2e/connection.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/connection.spec.ts @@ -1,7 +1,7 @@ import { ConfigModule } from '@narval/config-module' import { EncryptionModuleOptionProvider } from '@narval/encryption-module' import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' -import { Alg, generateJwk, privateKeyToHex } from '@narval/signature' +import { Alg, Ed25519PrivateKey, generateJwk, getPublicKey, privateKeyToHex } from '@narval/signature' import { HttpStatus, INestApplication } from '@nestjs/common' import { Test, TestingModule } from '@nestjs/testing' import request from 'supertest' @@ -9,11 +9,13 @@ import { load } from '../../../main.config' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' import { BrokerModule } from '../../broker.module' -import { Provider } from '../../core/type/connection.type' +import { ConnectionStatus, Provider } from '../../core/type/connection.type' +import { ConnectionRepository } from '../../persistence/repository/connection.repository' describe('Connection', () => { let app: INestApplication let module: TestingModule + let connectionRepository: ConnectionRepository let testPrismaService: TestPrismaService beforeAll(async () => { @@ -35,7 +37,8 @@ describe('Connection', () => { app = module.createNestApplication() - testPrismaService = module.get(TestPrismaService) + testPrismaService = module.get(TestPrismaService) + connectionRepository = module.get(ConnectionRepository) await testPrismaService.truncateAll() @@ -69,11 +72,33 @@ describe('Connection', () => { .set(REQUEST_HEADER_CLIENT_ID, clientId) .send(connection) + const createdConnection = await connectionRepository.findById(clientId, connection.connectionId) + expect(body).toEqual({ connectionId: connection.connectionId, clientId }) + expect(body.credentials).toEqual(undefined) + expect(status).toEqual(HttpStatus.CREATED) + + expect(createdConnection).toMatchObject({ + clientId, + credentials: { + apiKey: connection.credentials.apiKey, + privateKey, + publicKey: getPublicKey(privateKey as Ed25519PrivateKey) + }, + createdAt: expect.any(Date), + id: connection.connectionId, + integrity: expect.any(String), + label: connection.label, + provider: connection.provider, + revokedAt: undefined, + status: ConnectionStatus.ACTIVE, + updatedAt: expect.any(Date), + url: connection.url + }) }) }) }) diff --git a/apps/vault/src/broker/core/exception/connection-parse.exception.ts b/apps/vault/src/broker/core/exception/connection-parse.exception.ts new file mode 100644 index 000000000..77eaf8f14 --- /dev/null +++ b/apps/vault/src/broker/core/exception/connection-parse.exception.ts @@ -0,0 +1,3 @@ +import { ApplicationException } from '../../../shared/exception/application.exception' + +export class ConnectionParseException extends ApplicationException {} diff --git a/apps/vault/src/broker/core/service/connection.service.ts b/apps/vault/src/broker/core/service/connection.service.ts index 82ea9210c..bf13051fc 100644 --- a/apps/vault/src/broker/core/service/connection.service.ts +++ b/apps/vault/src/broker/core/service/connection.service.ts @@ -16,18 +16,19 @@ export class ConnectionService { if (privateKey.kty) { const connection = { clientId, - id: input.connectionId || uuid(), - provider: input.provider, - status: ConnectionStatus.ACTIVE, - url: input.url, + createdAt: now, credentials: { apiKey: input.credentials.apiKey, privateKey, publicKey: getPublicKey(privateKey) }, - createdAt: now, + id: input.connectionId || uuid(), + label: input.label, + provider: input.provider, + revokedAt: undefined, + status: ConnectionStatus.ACTIVE, updatedAt: now, - revokedAt: undefined + url: input.url } return this.connectionRepository.save({ diff --git a/apps/vault/src/broker/core/type/connection.type.ts b/apps/vault/src/broker/core/type/connection.type.ts index 89bf8744a..07af671f2 100644 --- a/apps/vault/src/broker/core/type/connection.type.ts +++ b/apps/vault/src/broker/core/type/connection.type.ts @@ -22,7 +22,7 @@ const SharedConnection = z.object({ integrity: z.string(), label: z.string().optional(), createdAt: z.date(), - updatedAt: z.date().optional(), + updatedAt: z.date(), revokedAt: z.date().optional() }) diff --git a/apps/vault/src/broker/persistence/repository/connection.repository.ts b/apps/vault/src/broker/persistence/repository/connection.repository.ts index 1f743051c..179bd37ba 100644 --- a/apps/vault/src/broker/persistence/repository/connection.repository.ts +++ b/apps/vault/src/broker/persistence/repository/connection.repository.ts @@ -1,7 +1,7 @@ -import { Injectable } from '@nestjs/common' -import { Prisma } from '@prisma/client/vault' +import { HttpStatus, Injectable } from '@nestjs/common' import { SetRequired } from 'type-fest' import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' +import { ConnectionParseException } from '../../core/exception/connection-parse.exception' import { Connection } from '../../core/type/connection.type' @Injectable() @@ -17,8 +17,8 @@ export class ConnectionRepository { url: connection.url, label: connection.label, status: connection.status, - // TODO - credentials: Prisma.JsonNull, + // TODO: ENCRYPTION + credentials: connection.credentials, integrity: connection.integrity, createdAt: connection.createdAt, updatedAt: connection.updatedAt, @@ -28,4 +28,31 @@ export class ConnectionRepository { return connection } + + async findById(clientId: string, id: string): Promise { + const result = await this.prismaService.providerConnection.findUnique({ + where: { clientId, id } + }) + + const parse = Connection.safeParse({ + ...result, + // Prisma always returns null for optional fields that don't have a + // value, rather than undefined. This is actually by design and aligns + // with how NULL values work in databases. + label: result?.label || undefined, + revokedAt: result?.revokedAt || undefined + }) + + if (parse.success) { + return parse.data + } + + throw new ConnectionParseException({ + message: 'Fail to parse connection after read', + suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, + context: { + errors: parse.error.errors + } + }) + } } From db902a2656afa1e70718baa8e82cd73f2fe89d65 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Wed, 4 Dec 2024 17:20:31 +0100 Subject: [PATCH 007/120] Remove provider type draft --- apps/vault/src/broker/core/type/provider.type.ts | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 apps/vault/src/broker/core/type/provider.type.ts diff --git a/apps/vault/src/broker/core/type/provider.type.ts b/apps/vault/src/broker/core/type/provider.type.ts deleted file mode 100644 index a3e5afba0..000000000 --- a/apps/vault/src/broker/core/type/provider.type.ts +++ /dev/null @@ -1,7 +0,0 @@ -// How to build a credential with the right private key Alg? -// -// Pass the input type that's part of the CreateConnection -// Get a provider specific credential -export interface CredentialBuilder { - build(input: Input): Promise -} From ae1f0a90a2148f2060474976354d4d20bee465a6 Mon Sep 17 00:00:00 2001 From: Pierre Troger Date: Wed, 4 Dec 2024 18:02:57 +0100 Subject: [PATCH 008/120] clarified seed object --- .../src/shared/module/persistence/seed.ts | 394 ++++++++++-------- 1 file changed, 216 insertions(+), 178 deletions(-) diff --git a/apps/vault/src/shared/module/persistence/seed.ts b/apps/vault/src/shared/module/persistence/seed.ts index f3bbb7ad3..a8bdaa438 100644 --- a/apps/vault/src/shared/module/persistence/seed.ts +++ b/apps/vault/src/shared/module/persistence/seed.ts @@ -1,223 +1,261 @@ /* eslint-disable */ import { LoggerService } from '@narval/nestjs-shared' -import { PrismaClient, Vault } from '@prisma/client/vault' +import { PrismaClient } from '@prisma/client/vault' import { v4 } from 'uuid' const prisma = new PrismaClient() -const vault: Vault = { - id: '7d704a62-d15e-4382-a826-1eb41563043b', - adminApiKey: 'admin-api-key-xxx', - masterKey: 'master-key-xxx' -} - -const ANCHORAGE_SEED_DATA = { - // Basic client setup - client: { - id: v4(), - provider: 'anchorage' as const - }, - - // Connection details - connection: { - id: v4(), - url: 'https://api.anchorage-staging.com/v2', - label: 'Anchorage Staging', - credentials: { - apiKey: 'sample-api-key', - secretKey: 'sample-secret-key' - } - }, +const clientId = 'client-1' - // Workspaces represent different organizations. - workspaces: [ - { - wallet: { +// Organize all data by connection +const ANCHORAGE_CONNECTIONS = [ + { + connection: { + id: 'connection-1', + clientId, + provider: 'anchorage', + integrity: 'sample-integrity-hash', + url: 'https://api.anchorage-staging.com/v2', + label: 'Anchorage Staging - SubCustomer 1', + credentials: { + apiKey: 'sample-api-key', + secretKey: 'sample-secret-key' + }, + createdAt: new Date(), + updatedAt: new Date(), + revokedAt: null, + status: 'active' + }, + wallets: [ + { id: 'wallet-1', + clientId, + provider: 'anchorage', + label: 'Wallet for SubCustomer 1', externalId: 'vault_1', - label: 'Wallet for org1' - }, - accounts: [ - { - // BTC Account - account: { - id: 'account-1', - externalId: 'wallet_1', + createdAt: new Date(), + updatedAt: new Date(), + accounts: [ + { + id: 'accountWallet1Btc', + clientId, + provider: 'anchorage', label: 'Bitcoin Mainnet', - networkId: '1' - }, - // Multiple addresses for BTC (UTXO) - addresses: [ - { - id: 'address-1', - externalId: 'btc_address_1', - address: 'b1742d35Cc6634C0532925a3b844Bc454e4438f44e' - }, - { - id: 'address-2', - externalId: 'btc_address_2', - address: 'b1123d35Cc6634C0532925a3b844Bc454e4438f789' - } - ] - }, - { - // ETH Account - account: { - id: 'account-2', - externalId: 'wallet_2', - label: 'Ethereum Mainnet', - networkId: '60' + externalId: 'wallet_1', + networkId: '1', + createdAt: new Date(), + updatedAt: new Date(), + addresses: [ + { + id: 'address-acc-wallet-1-btc-1', + clientId, + provider: 'anchorage', + externalId: 'btc_address_1', + address: 'b1742d35Cc6634C0532925a3b844Bc454e4438f44e', + createdAt: new Date(), + updatedAt: new Date() + }, + { + id: 'address-acc-wallet-1-btc-2', + clientId, + provider: 'anchorage', + externalId: 'btc_address_2', + address: 'b1123d35Cc6634C0532925a3b844Bc454e4438f789', + createdAt: new Date(), + updatedAt: new Date() + } + ] }, - // Single address for ETH (account-based) - addresses: [ - { - id: 'address-3', - externalId: 'eth_addr', - address: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e' - } - ] - } - ] + { + id: 'accountWallet1Eth', + clientId, + provider: 'anchorage', + label: 'Trading BTC', + externalId: 'wallet_3', + networkId: '60', + createdAt: new Date(), + updatedAt: new Date(), + addresses: [ + { + id: 'address-account-wallet-1-eth', + clientId, + provider: 'anchorage', + externalId: 'eth_addr', + address: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e', + createdAt: new Date(), + updatedAt: new Date() + } + ] + } + ] + } + ], + knownDestinations: [ + { + id: 'dest1', + clientId, + provider: 'anchorage', + assetId: 'BTC', + externalId: 'dest1', + address: 'bt12NGZrVvZG92qGYqzTLjCAewvPZ7JE8S8VxE', + networkId: 'BTC', + externalClassification: 'trusted', + createdAt: new Date(), + updatedAt: new Date() + } + ] + }, + { + connection: { + id: 'connection-2', + clientId, + provider: 'anchorage', + integrity: 'sample-integrity-hash-2', + url: 'https://api.anchorage-staging.com/v2', + label: 'Anchorage Staging - SubCustomer 2', + credentials: { + apiKey: 'sample-api-key-2', + secretKey: 'sample-secret-key-2' + }, + createdAt: new Date(), + updatedAt: new Date(), + revokedAt: null, + status: 'active' }, - { - wallet: { + wallets: [ + { id: 'wallet-2', + clientId, + provider: 'anchorage', + label: 'Wallet for SubCustomer 2', externalId: 'vault_2', - label: 'walletForOrg2' - }, - accounts: [ - { - account: { - id: 'account-vault2-1', - externalId: 'wallet_3', - label: 'Trading BTC', - networkId: 'BTC' - }, - addresses: [ - { - id: 'address-vault2-1', - externalId: 'btc_trading_addr_1', - address: 'bt12NGZrVvZG92qGYqzTLjCAewvPZ7JE8S8VxE' - } - ] - } - ] - } - ], - - // Address book entries - knownDestinations: [ - { - id: v4(), - externalId: 'dest1', - address: 'bt12NGZrVvZG92qGYqzTLjCAewvPZ7JE8S8VxE', - networkId: 'BTC', - externalClassification: 'trusted' - } - ] -} + createdAt: new Date(), + updatedAt: new Date(), + accounts: [ + { + id: 'accountWallet2Eth', + clientId, + provider: 'anchorage', + label: 'Ethereum Mainnet', + externalId: 'wallet_2', + networkId: '60', + createdAt: new Date(), + updatedAt: new Date(), + addresses: [ + { + id: 'address-account-wallet-2-eth', + clientId, + provider: 'anchorage', + externalId: 'btc_trading_addr_1', + address: 'bt12NGZrVvZG92qGYqzTLjCAewvPZ7JE8S8VxE', + createdAt: new Date(), + updatedAt: new Date() + } + ] + } + ] + } + ], + knownDestinations: [] + } +] async function main() { const logger = new LoggerService() logger.log('Seeding Vault database with Anchorage provider data') await prisma.$transaction(async (txn) => { - // 1. Create the connection - - const connection = await txn.providerConnection.create({ - data: { - id: ANCHORAGE_SEED_DATA.connection.id, - clientId: ANCHORAGE_SEED_DATA.client.id, - provider: ANCHORAGE_SEED_DATA.client.provider, - url: ANCHORAGE_SEED_DATA.connection.url, - label: ANCHORAGE_SEED_DATA.connection.label, - credentials: ANCHORAGE_SEED_DATA.connection.credentials, - status: 'active', - integrity: 'sample-integrity-hash', - createdAt: new Date(), - updatedAt: new Date() - } - }) - - // 2. Create each vault (provider wallet) and its contents - for (const workspace of ANCHORAGE_SEED_DATA.workspaces) { - // Create the provider wallet record - const providerWallet = await txn.providerWallet.create({ + // Process each connection group + for (const group of ANCHORAGE_CONNECTIONS) { + // Create connection + const connection = await txn.providerConnection.create({ data: { - id: workspace.wallet.id, - clientId: ANCHORAGE_SEED_DATA.client.id, - provider: ANCHORAGE_SEED_DATA.client.provider, - label: workspace.wallet.label, - externalId: workspace.wallet.externalId + ...group.connection, + credentials: group.connection.credentials as any } }) - // Link wallet to connection - await txn.providerWalletConnection.create({ - data: { - clientId: ANCHORAGE_SEED_DATA.client.id, - connectionId: connection.id, - walletId: providerWallet.id - } - }) + // Process wallets and their hierarchies + for (const wallet of group.wallets) { + // Create wallet + const createdWallet = await txn.providerWallet.create({ + data: { + id: wallet.id, + clientId: wallet.clientId, + provider: wallet.provider, + label: wallet.label, + externalId: wallet.externalId, + createdAt: wallet.createdAt, + updatedAt: wallet.updatedAt + } + }) - // Create accounts and addresses - for (const accountData of workspace.accounts) { - const account = await txn.providerAccount.create({ + // Link wallet to connection + await txn.providerWalletConnection.create({ data: { - id: accountData.account.id, - clientId: ANCHORAGE_SEED_DATA.client.id, - provider: ANCHORAGE_SEED_DATA.client.provider, - label: accountData.account.label, - externalId: accountData.account.externalId, - walletId: providerWallet.id, - networkId: accountData.account.networkId + clientId: wallet.clientId, + connectionId: connection.id, + walletId: createdWallet.id } }) - // Create addresses for this account - for (const addrData of accountData.addresses) { - await txn.providerAddress.create({ + // Create accounts and addresses + for (const account of wallet.accounts) { + const createdAccount = await txn.providerAccount.create({ data: { - id: addrData.id, - clientId: ANCHORAGE_SEED_DATA.client.id, - provider: ANCHORAGE_SEED_DATA.client.provider, - externalId: addrData.externalId, - accountId: account.id, - address: addrData.address + id: account.id, + clientId: account.clientId, + provider: account.provider, + label: account.label, + externalId: account.externalId, + walletId: createdWallet.id, + networkId: account.networkId, + createdAt: account.createdAt, + updatedAt: account.updatedAt } }) + + // Create addresses for this account + for (const address of account.addresses) { + await txn.providerAddress.create({ + data: { + id: address.id, + clientId: address.clientId, + provider: address.provider, + externalId: address.externalId, + accountId: createdAccount.id, + address: address.address, + createdAt: address.createdAt, + updatedAt: address.updatedAt + } + }) + } } } - } - for (const destData of ANCHORAGE_SEED_DATA.knownDestinations) { - await txn.providerKnownDestination.create({ + // Create known destinations + for (const dest of group.knownDestinations) { + await txn.providerKnownDestination.create({ + data: { + ...dest, + connectionId: connection.id + } + }) + } + + // Create sync record for this connection + await txn.providerSync.create({ data: { - id: destData.id, - clientId: ANCHORAGE_SEED_DATA.client.id, + id: v4(), + clientId, connectionId: connection.id, - provider: ANCHORAGE_SEED_DATA.client.provider, - externalId: destData.externalId, - externalClassification: destData.externalClassification, - address: destData.address, - networkId: destData.networkId + status: 'success' } }) } - - // 4. Create initial sync record - await txn.providerSync.create({ - data: { - id: v4(), - clientId: ANCHORAGE_SEED_DATA.client.id, - connectionId: connection.id, - status: 'success' - } - }) }) - logger.log('Vault database germinated with Anchorage provider data 🌱') + logger.log('Vault database germinated 🌱') } main() From 6e576588c028c5648fdebf1bdc3d0a0031c56170 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Thu, 5 Dec 2024 17:45:50 +0100 Subject: [PATCH 009/120] Initiate, activate and create flow with encryption --- .../broker/__test__/e2e/connection.spec.ts | 188 +++++++++++++++++- apps/vault/src/broker/broker.module.ts | 3 +- .../broker/core/exception/broker.exception.ts | 3 + .../exception/connection-parse.exception.ts | 14 +- ...nvalid-connection-private-key.exception.ts | 13 ++ ...issing-connection-credentials.exception.ts | 13 ++ .../broker/core/service/connection.service.ts | 181 +++++++++++++++-- .../src/broker/core/type/connection.type.ts | 50 ++++- .../rest/controller/connection.controller.ts | 23 ++- .../dto/request/initiate-connection.dto.ts | 4 + .../http/rest/dto/response/connection.dto.ts | 4 +- .../dto/response/pending-connection.dto.ts | 4 + .../repository/connection.repository.ts | 54 ++++- .../encryption/core/encryption-key.service.ts | 18 ++ .../core/service/encryption-key.service.ts | 57 ++++++ .../core/type/encryption-key.type.ts | 10 + .../src/encryption/encryption-key.module.ts | 11 + .../controller/encryption-key.controller.ts | 0 .../persistence/encryption-key.repository.ts | 35 ++++ .../migration.sql | 13 ++ .../migration.sql | 10 + .../module/persistence/schema/schema.prisma | 13 +- 22 files changed, 666 insertions(+), 55 deletions(-) create mode 100644 apps/vault/src/broker/core/exception/broker.exception.ts create mode 100644 apps/vault/src/broker/core/exception/invalid-connection-private-key.exception.ts create mode 100644 apps/vault/src/broker/core/exception/missing-connection-credentials.exception.ts create mode 100644 apps/vault/src/broker/http/rest/dto/request/initiate-connection.dto.ts create mode 100644 apps/vault/src/broker/http/rest/dto/response/pending-connection.dto.ts create mode 100644 apps/vault/src/encryption/core/encryption-key.service.ts create mode 100644 apps/vault/src/encryption/core/service/encryption-key.service.ts create mode 100644 apps/vault/src/encryption/core/type/encryption-key.type.ts create mode 100644 apps/vault/src/encryption/encryption-key.module.ts create mode 100644 apps/vault/src/encryption/http/rest/controller/encryption-key.controller.ts create mode 100644 apps/vault/src/encryption/persistence/encryption-key.repository.ts create mode 100644 apps/vault/src/shared/module/persistence/schema/migrations/20241205125125_set_provider_connection_url_to_nullable/migration.sql create mode 100644 apps/vault/src/shared/module/persistence/schema/migrations/20241205133709_add_encryption_key_table/migration.sql diff --git a/apps/vault/src/broker/__test__/e2e/connection.spec.ts b/apps/vault/src/broker/__test__/e2e/connection.spec.ts index 76fc6ae3d..17b5c7a1b 100644 --- a/apps/vault/src/broker/__test__/e2e/connection.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/connection.spec.ts @@ -1,10 +1,21 @@ import { ConfigModule } from '@narval/config-module' import { EncryptionModuleOptionProvider } from '@narval/encryption-module' import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' -import { Alg, Ed25519PrivateKey, generateJwk, getPublicKey, privateKeyToHex } from '@narval/signature' +import { + Alg, + Ed25519PrivateKey, + ed25519PublicKeySchema, + generateJwk, + getPublicKey, + privateKeyToHex, + rsaEncrypt, + rsaPublicKeySchema +} from '@narval/signature' import { HttpStatus, INestApplication } from '@nestjs/common' import { Test, TestingModule } from '@nestjs/testing' import request from 'supertest' +import { v4 as uuid } from 'uuid' +import { ZodSchema } from 'zod' import { load } from '../../../main.config' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' @@ -12,12 +23,34 @@ import { BrokerModule } from '../../broker.module' import { ConnectionStatus, Provider } from '../../core/type/connection.type' import { ConnectionRepository } from '../../persistence/repository/connection.repository' +const toMatchZodSchema = (received: unknown, schema: ZodSchema): void => { + const parse = schema.safeParse(received) + + if (parse.success) { + return + } + + const message = [ + 'Expected value to match schema:', + 'Received:', + `${JSON.stringify(received, null, 2)}`, + 'Validation errors:', + parse.error.errors.map((err) => `- ${err.message}`).join('\n') + ].join('\n') + + throw new Error(message) +} + describe('Connection', () => { let app: INestApplication let module: TestingModule let connectionRepository: ConnectionRepository let testPrismaService: TestPrismaService + const url = 'http://provider.narval.xyz' + + const clientId = uuid() + beforeAll(async () => { module = await Test.createTestingModule({ imports: [ @@ -51,16 +84,47 @@ describe('Connection', () => { await app.close() }) + beforeEach(async () => { + await testPrismaService.truncateAll() + }) + + describe('POST /connections/initiate', () => { + it('initiates a new connection to anchorage', async () => { + const connection = { + provider: Provider.ANCHORAGE, + url, + connectionId: uuid() + } + + const { status, body } = await request(app.getHttpServer()) + .post('/connections/initiate') + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .send(connection) + + expect(body).toMatchObject({ + clientId, + connectionId: connection.connectionId, + provider: connection.provider, + status: ConnectionStatus.PENDING + }) + + toMatchZodSchema(body.publicKey, ed25519PublicKeySchema) + toMatchZodSchema(body.encryptionPublicKey, rsaPublicKeySchema) + + expect(status).toEqual(HttpStatus.CREATED) + }) + }) + describe('POST /connections', () => { - it('creates a new connection to anchorage', async () => { + it('creates a new connection to anchorage with plain credentials', async () => { const privateKey = await generateJwk(Alg.EDDSA) const privateKeyHex = await privateKeyToHex(privateKey) - const clientId = 'test-client-id' + const connectionId = uuid() const connection = { provider: Provider.ANCHORAGE, - connectionId: 'test-connection-id', + connectionId, label: 'Test Anchorage Connection', - url: 'http://provider.narval.xyz', + url, credentials: { apiKey: 'test-api-key', privateKey: privateKeyHex @@ -75,10 +139,10 @@ describe('Connection', () => { const createdConnection = await connectionRepository.findById(clientId, connection.connectionId) expect(body).toEqual({ - connectionId: connection.connectionId, - clientId + connectionId, + clientId, + status: ConnectionStatus.ACTIVE }) - expect(body.credentials).toEqual(undefined) expect(status).toEqual(HttpStatus.CREATED) @@ -90,7 +154,7 @@ describe('Connection', () => { publicKey: getPublicKey(privateKey as Ed25519PrivateKey) }, createdAt: expect.any(Date), - id: connection.connectionId, + id: connectionId, integrity: expect.any(String), label: connection.label, provider: connection.provider, @@ -100,5 +164,111 @@ describe('Connection', () => { url: connection.url }) }) + + it('activates a pending connection to anchorage with plain credentials', async () => { + const connectionId = uuid() + const provider = Provider.ANCHORAGE + const label = 'Test Anchorage Connection' + const credentials = { + apiKey: 'test-api-key' + } + + const { body: pendingConnection } = await request(app.getHttpServer()) + .post('/connections/initiate') + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .send({ connectionId, provider }) + + const { status, body } = await request(app.getHttpServer()) + .post('/connections') + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .send({ + provider, + connectionId, + label, + url, + credentials + }) + + expect(body).toEqual({ + clientId, + connectionId, + status: ConnectionStatus.ACTIVE + }) + expect(status).toEqual(HttpStatus.CREATED) + + const createdConnection = await connectionRepository.findById(clientId, connectionId) + + expect(createdConnection).toMatchObject({ + clientId, + createdAt: expect.any(Date), + id: connectionId, + integrity: expect.any(String), + label, + provider, + revokedAt: undefined, + status: ConnectionStatus.ACTIVE, + updatedAt: expect.any(Date), + url + }) + + expect(createdConnection.credentials).toMatchObject({ + apiKey: credentials.apiKey, + publicKey: pendingConnection.publicKey + }) + }) + + it('activates a pending connection to anchorage with encrypted credentials', async () => { + const connectionId = uuid() + const provider = Provider.ANCHORAGE + const label = 'Test Anchorage Connection' + const credentials = { + apiKey: 'test-api-key' + } + + const { body: pendingConnection } = await request(app.getHttpServer()) + .post('/connections/initiate') + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .send({ connectionId, provider }) + + const encryptedCredentials = await rsaEncrypt(JSON.stringify(credentials), pendingConnection.encryptionPublicKey) + + const { status, body } = await request(app.getHttpServer()) + .post('/connections') + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .send({ + provider, + connectionId, + label, + url, + encryptedCredentials + }) + + expect(body).toEqual({ + clientId, + connectionId, + status: ConnectionStatus.ACTIVE + }) + expect(status).toEqual(HttpStatus.CREATED) + + const createdConnection = await connectionRepository.findById(clientId, connectionId) + + expect(createdConnection).toMatchObject({ + clientId, + createdAt: expect.any(Date), + id: connectionId, + integrity: expect.any(String), + label, + provider, + revokedAt: undefined, + status: ConnectionStatus.ACTIVE, + updatedAt: expect.any(Date), + url + }) + + expect(createdConnection.credentials).toMatchObject({ + apiKey: credentials.apiKey, + publicKey: pendingConnection.publicKey + }) + }) }) }) diff --git a/apps/vault/src/broker/broker.module.ts b/apps/vault/src/broker/broker.module.ts index 3928d42dc..a4df3dbb2 100644 --- a/apps/vault/src/broker/broker.module.ts +++ b/apps/vault/src/broker/broker.module.ts @@ -1,4 +1,5 @@ import { Module } from '@nestjs/common' +import { EncryptionKeyModule } from '../encryption/encryption-key.module' import { DEFAULT_HTTP_MODULE_PROVIDERS } from '../shared/constant' import { PersistenceModule } from '../shared/module/persistence/persistence.module' import { ConnectionService } from './core/service/connection.service' @@ -6,7 +7,7 @@ import { ConnectionController } from './http/rest/controller/connection.controll import { ConnectionRepository } from './persistence/repository/connection.repository' @Module({ - imports: [PersistenceModule], + imports: [PersistenceModule, EncryptionKeyModule], controllers: [ConnectionController], providers: [...DEFAULT_HTTP_MODULE_PROVIDERS, ConnectionService, ConnectionRepository] }) diff --git a/apps/vault/src/broker/core/exception/broker.exception.ts b/apps/vault/src/broker/core/exception/broker.exception.ts new file mode 100644 index 000000000..a598da3d2 --- /dev/null +++ b/apps/vault/src/broker/core/exception/broker.exception.ts @@ -0,0 +1,3 @@ +import { ApplicationException } from '../../../shared/exception/application.exception' + +export class BrokerException extends ApplicationException {} diff --git a/apps/vault/src/broker/core/exception/connection-parse.exception.ts b/apps/vault/src/broker/core/exception/connection-parse.exception.ts index 77eaf8f14..0d7efee51 100644 --- a/apps/vault/src/broker/core/exception/connection-parse.exception.ts +++ b/apps/vault/src/broker/core/exception/connection-parse.exception.ts @@ -1,3 +1,13 @@ -import { ApplicationException } from '../../../shared/exception/application.exception' +import { HttpStatus } from '@nestjs/common' +import { ApplicationExceptionParams } from '../../../shared/exception/application.exception' +import { BrokerException } from './broker.exception' -export class ConnectionParseException extends ApplicationException {} +export class ConnectionParseException extends BrokerException { + constructor(params?: Partial) { + super({ + message: params?.message || 'Fail to parse connection after read', + suggestedHttpStatusCode: params?.suggestedHttpStatusCode || HttpStatus.INTERNAL_SERVER_ERROR, + ...params + }) + } +} diff --git a/apps/vault/src/broker/core/exception/invalid-connection-private-key.exception.ts b/apps/vault/src/broker/core/exception/invalid-connection-private-key.exception.ts new file mode 100644 index 000000000..c5984d291 --- /dev/null +++ b/apps/vault/src/broker/core/exception/invalid-connection-private-key.exception.ts @@ -0,0 +1,13 @@ +import { HttpStatus } from '@nestjs/common' +import { ApplicationExceptionParams } from '../../../shared/exception/application.exception' +import { BrokerException } from './broker.exception' + +export class InvalidConnectionPrivateKeyException extends BrokerException { + constructor(params?: Partial) { + super({ + message: params?.message || 'Invalid connection credential private key type', + suggestedHttpStatusCode: params?.suggestedHttpStatusCode || HttpStatus.UNPROCESSABLE_ENTITY, + ...params + }) + } +} diff --git a/apps/vault/src/broker/core/exception/missing-connection-credentials.exception.ts b/apps/vault/src/broker/core/exception/missing-connection-credentials.exception.ts new file mode 100644 index 000000000..169d96426 --- /dev/null +++ b/apps/vault/src/broker/core/exception/missing-connection-credentials.exception.ts @@ -0,0 +1,13 @@ +import { HttpStatus } from '@nestjs/common' +import { ApplicationExceptionParams } from '../../../shared/exception/application.exception' +import { BrokerException } from './broker.exception' + +export class MissingConnectionCredentialsException extends BrokerException { + constructor(params?: Partial) { + super({ + message: params?.message || 'Missing connection credentials', + suggestedHttpStatusCode: params?.suggestedHttpStatusCode || HttpStatus.UNPROCESSABLE_ENTITY, + ...params + }) + } +} diff --git a/apps/vault/src/broker/core/service/connection.service.ts b/apps/vault/src/broker/core/service/connection.service.ts index bf13051fc..dbc538dd5 100644 --- a/apps/vault/src/broker/core/service/connection.service.ts +++ b/apps/vault/src/broker/core/service/connection.service.ts @@ -1,15 +1,114 @@ -import { Alg, Ed25519PrivateKey, generateJwk, getPublicKey, hash, privateKeyToJwk } from '@narval/signature' -import { HttpStatus, Injectable } from '@nestjs/common' +import { Alg, Ed25519PrivateKey, generateJwk, getPublicKey, privateKeyToJwk } from '@narval/signature' +import { Injectable, NotImplementedException } from '@nestjs/common' +import { SetRequired } from 'type-fest' import { v4 as uuid } from 'uuid' -import { ApplicationException } from '../../../shared/exception/application.exception' +import { EncryptionKeyService } from '../../../encryption/core/service/encryption-key.service' import { ConnectionRepository } from '../../persistence/repository/connection.repository' -import { Connection, ConnectionStatus, CreateConnection } from '../type/connection.type' +import { InvalidConnectionPrivateKeyException } from '../exception/invalid-connection-private-key.exception' +import { MissingConnectionCredentialsException } from '../exception/missing-connection-credentials.exception' +import { + Connection, + ConnectionStatus, + CreateConnection, + CreateCredentials, + InitiateConnection, + PendingConnection, + Provider +} from '../type/connection.type' @Injectable() export class ConnectionService { - constructor(private readonly connectionRepository: ConnectionRepository) {} + constructor( + private readonly connectionRepository: ConnectionRepository, + private readonly encryptionKeyService: EncryptionKeyService + ) {} + + async initiate(clientId: string, input: InitiateConnection): Promise { + const now = new Date() + const privateKey = await this.generatePrivateKey() + const encryptionKey = await this.encryptionKeyService.generate(clientId) + const connection = { + clientId, + createdAt: now, + credentials: { + privateKey, + publicKey: getPublicKey(privateKey) + }, + id: input.connectionId || uuid(), + provider: input.provider, + status: ConnectionStatus.PENDING, + revokedAt: undefined, + updatedAt: now, + // TODO: (@wcalderipe, 05/12/24): HMAC hash and signature. + integrity: 'TODO INITIATE CONNECTION' + } + + await this.connectionRepository.create(connection) + + return { + clientId: connection.clientId, + connectionId: connection.id, + encryptionPublicKey: encryptionKey.publicKey, + provider: connection.provider, + publicKey: connection.credentials.publicKey, + status: connection.status + } + } + + // TODO: (@wcalderipe, 05/12/24): The return type is Anchorage specific. + private async getPrivateKey({ provider, credentials }: CreateConnection): Promise { + if (!credentials) { + throw new MissingConnectionCredentialsException() + } + + if (provider === Provider.ANCHORAGE) { + if (credentials.privateKey) { + return privateKeyToJwk(credentials.privateKey, Alg.EDDSA) + } + + return await generateJwk(Alg.EDDSA) + } + + throw new NotImplementedException(`Unsupported provider private key getter: ${provider}`) + } + + // TODO: (@wcalderipe, 05/12/24): The return type is Anchorage specific. + private async generatePrivateKey(): Promise { + return await generateJwk(Alg.EDDSA) + } async create(clientId: string, input: CreateConnection): Promise { + // If a connection ID is provided, check if the connection already + // exists. If it does, activate the connection. + if (input.connectionId) { + if (await this.connectionRepository.exists(clientId, input.connectionId)) { + return this.activate(clientId, { + ...input, + connectionId: input.connectionId + }) + } + } + + if (input.credentials) { + return this.createActiveConnection(clientId, input) + } + + if (input.encryptedCredentials) { + const credentials = await this.buildCreateCredentials(clientId, input) + + return this.createActiveConnection(clientId, { ...input, credentials }) + } + + throw new MissingConnectionCredentialsException() + } + + private async createActiveConnection(clientId: string, input: CreateConnection): Promise { + // By this point, the credentials should have already been decrypted + // and decoded. + if (!input.credentials) { + throw new MissingConnectionCredentialsException() + } + const now = new Date() const privateKey = await this.getPrivateKey(input) @@ -25,31 +124,73 @@ export class ConnectionService { id: input.connectionId || uuid(), label: input.label, provider: input.provider, + url: input.url, revokedAt: undefined, status: ConnectionStatus.ACTIVE, updatedAt: now, - url: input.url + // TODO: (@wcalderipe, 05/12/24): HMAC hash and signature. + integrity: 'TODO CREATE CONNECTION' } - return this.connectionRepository.save({ - ...connection, - // TODO: Sign the hash. - integrity: hash(connection) - }) + return this.connectionRepository.create(connection) } - throw new ApplicationException({ - message: 'Invalid private key type', - suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY - }) + throw new InvalidConnectionPrivateKeyException() } - // TODO: This is Anchorage specific. - private async getPrivateKey({ credentials: credential }: CreateConnection): Promise { - if (credential.privateKey) { - return privateKeyToJwk(credential.privateKey, Alg.EDDSA) + async activate(clientId: string, input: SetRequired): Promise { + const pendingConnection = await this.connectionRepository.findById(clientId, input.connectionId) + + // TODO: Ensure the connection status is pending. + const now = new Date() + + const credentials = await this.buildCreateCredentials(clientId, input) + + const connection = { + id: input.connectionId, + status: ConnectionStatus.ACTIVE, + label: input.label, + url: input.url, + updatedAt: now, + credentials: { + ...pendingConnection.credentials, + apiKey: credentials.apiKey + }, + // TODO: (@wcalderipe, 05/12/24): HMAC hash and signature. + integrity: 'TODO ACTIVATE CONNECTION' } - return await generateJwk(Alg.EDDSA) + await this.connectionRepository.update(connection) + + return { ...pendingConnection, ...connection } + } + + async exists(clientId: string, connectionId?: string): Promise { + if (connectionId) { + return this.connectionRepository.exists(clientId, connectionId) + } + + return false + } + + private async buildCreateCredentials(clientId: string, input: CreateConnection): Promise { + if (input.encryptedCredentials) { + const raw = await this.encryptionKeyService.decrypt(clientId, input.encryptedCredentials) + const parse = CreateCredentials.safeParse(JSON.parse(raw)) + + if (parse.success) { + return parse.data + } + + throw new InvalidConnectionPrivateKeyException({ + context: { errors: parse.error.errors } + }) + } + + if (input.credentials) { + return input.credentials + } + + throw new MissingConnectionCredentialsException() } } diff --git a/apps/vault/src/broker/core/type/connection.type.ts b/apps/vault/src/broker/core/type/connection.type.ts index 07af671f2..270227ed8 100644 --- a/apps/vault/src/broker/core/type/connection.type.ts +++ b/apps/vault/src/broker/core/type/connection.type.ts @@ -1,5 +1,5 @@ import { hexSchema } from '@narval/policy-engine-shared' -import { ed25519PrivateKeySchema, ed25519PublicKeySchema } from '@narval/signature' +import { ed25519PrivateKeySchema, ed25519PublicKeySchema, rsaPublicKeySchema } from '@narval/signature' import { z } from 'zod' export const Provider = { @@ -17,7 +17,7 @@ const SharedConnection = z.object({ id: z.string(), clientId: z.string(), provider: z.nativeEnum(Provider), - url: z.string().url(), + url: z.string().url().optional(), status: z.nativeEnum(ConnectionStatus).default(ConnectionStatus.ACTIVE), integrity: z.string(), label: z.string().optional(), @@ -41,20 +41,50 @@ const AnchorageConnection = SharedConnection.extend({ export const Connection = AnchorageConnection export type Connection = z.infer +export const Credentials = AnchorageCredentials +export type Credentials = z.infer + +const SharedPendingConnection = z.object({ + clientId: z.string(), + connectionId: z.string(), + provider: z.nativeEnum(Provider), + status: z.literal(ConnectionStatus.PENDING), + encryptionPublicKey: rsaPublicKeySchema +}) + +// TODO: (@wcalderipe, 05/12/24): Extend to other providers. +export const PendingConnection = SharedPendingConnection.extend({ + provider: z.literal(Provider.ANCHORAGE), + publicKey: ed25519PublicKeySchema +}) +export type PendingConnection = z.infer + +export const InitiateConnection = z.object({ + connectionId: z.string().optional(), + provider: z.nativeEnum(Provider) +}) +export type InitiateConnection = z.infer + const SharedCreateConnection = z.object({ connectionId: z.string().optional(), - provider: z.nativeEnum(Provider), - url: z.string().url(), + createdAt: z.date().optional(), + encryptedCredentials: z.string().optional().describe('RSA encrypted JSON string of the credentials'), label: z.string().optional(), - createdAt: z.date().optional() + provider: z.nativeEnum(Provider), + url: z.string().url() +}) + +const AnchorageCreateCredentials = z.object({ + apiKey: z.string(), + privateKey: hexSchema.optional().describe('Ed25519 private key in hex format') }) +export const CreateCredentials = AnchorageCreateCredentials +export type CreateCredentials = z.infer + +// TODO: (@wcalderipe, 05/12/24): Extend to other providers. export const CreateConnection = SharedCreateConnection.extend({ provider: z.literal(Provider.ANCHORAGE), - credentials: z.object({ - apiKey: z.string(), - // Ed25519, hex format - privateKey: hexSchema.optional() - }) + credentials: CreateCredentials.optional() }) export type CreateConnection = z.infer diff --git a/apps/vault/src/broker/http/rest/controller/connection.controller.ts b/apps/vault/src/broker/http/rest/controller/connection.controller.ts index e1aa45bd4..33b2b637a 100644 --- a/apps/vault/src/broker/http/rest/controller/connection.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/connection.controller.ts @@ -2,8 +2,11 @@ import { Body, Controller, HttpStatus, Post } from '@nestjs/common' import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../shared/decorator/client-id.decorator' import { ConnectionService } from '../../../core/service/connection.service' +import { Connection } from '../../../core/type/connection.type' import { CreateConnectionDto } from '../dto/request/create-connection.dto' +import { InitiateConnectionDto } from '../dto/request/initiate-connection.dto' import { ConnectionDto } from '../dto/response/connection.dto' +import { PendingConnectionDto } from '../dto/response/pending-connection.dto' @Controller({ path: 'connections', @@ -13,6 +16,19 @@ import { ConnectionDto } from '../dto/response/connection.dto' export class ConnectionController { constructor(private readonly connectionService: ConnectionService) {} + @Post('/initiate') + @ApiOperation({ + summary: 'Initiate a connection' + }) + @ApiResponse({ + description: 'Connection public key and encryption key', + status: HttpStatus.CREATED, + type: PendingConnectionDto + }) + async initiate(@ClientId() clientId: string, @Body() body: InitiateConnectionDto): Promise { + return this.connectionService.initiate(clientId, body) + } + @Post() @ApiOperation({ summary: 'Securely stores a provider connection' @@ -25,9 +41,14 @@ export class ConnectionController { async create(@ClientId() clientId: string, @Body() body: CreateConnectionDto): Promise { const connection = await this.connectionService.create(clientId, body) + return this.toResponse(connection) + } + + private toResponse(connection: Connection) { return { connectionId: connection.id, - clientId: connection.clientId + clientId: connection.clientId, + status: connection.status } } } diff --git a/apps/vault/src/broker/http/rest/dto/request/initiate-connection.dto.ts b/apps/vault/src/broker/http/rest/dto/request/initiate-connection.dto.ts new file mode 100644 index 000000000..a09ca5d7c --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/request/initiate-connection.dto.ts @@ -0,0 +1,4 @@ +import { createZodDto } from 'nestjs-zod' +import { InitiateConnection } from '../../../../core/type/connection.type' + +export class InitiateConnectionDto extends createZodDto(InitiateConnection) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/connection.dto.ts b/apps/vault/src/broker/http/rest/dto/response/connection.dto.ts index 1c7ed54c1..dca6e53c1 100644 --- a/apps/vault/src/broker/http/rest/dto/response/connection.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/connection.dto.ts @@ -1,9 +1,11 @@ import { createZodDto } from 'nestjs-zod' import { z } from 'zod' +import { ConnectionStatus } from '../../../../core/type/connection.type' export class ConnectionDto extends createZodDto( z.object({ connectionId: z.string(), - clientId: z.string() + clientId: z.string(), + status: z.nativeEnum(ConnectionStatus) }) ) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/pending-connection.dto.ts b/apps/vault/src/broker/http/rest/dto/response/pending-connection.dto.ts new file mode 100644 index 000000000..02443c4de --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/response/pending-connection.dto.ts @@ -0,0 +1,4 @@ +import { createZodDto } from 'nestjs-zod' +import { PendingConnection } from '../../../../core/type/connection.type' + +export class PendingConnectionDto extends createZodDto(PendingConnection) {} diff --git a/apps/vault/src/broker/persistence/repository/connection.repository.ts b/apps/vault/src/broker/persistence/repository/connection.repository.ts index 179bd37ba..06a4b3a95 100644 --- a/apps/vault/src/broker/persistence/repository/connection.repository.ts +++ b/apps/vault/src/broker/persistence/repository/connection.repository.ts @@ -1,4 +1,4 @@ -import { HttpStatus, Injectable } from '@nestjs/common' +import { Injectable } from '@nestjs/common' import { SetRequired } from 'type-fest' import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' import { ConnectionParseException } from '../../core/exception/connection-parse.exception' @@ -8,8 +8,38 @@ import { Connection } from '../../core/type/connection.type' export class ConnectionRepository { constructor(private prismaService: PrismaService) {} - async save(connection: SetRequired): Promise { - await this.prismaService.providerConnection.create({ + async create(connection: SetRequired): Promise { + await this.prismaService.providerConnection.upsert({ + where: { id: connection.id }, + update: { + url: connection.url, + label: connection.label, + status: connection.status, + credentials: connection.credentials, + integrity: connection.integrity, + updatedAt: connection.updatedAt + }, + create: { + id: connection.id, + clientId: connection.clientId, + provider: connection.provider, + url: connection.url, + label: connection.label, + status: connection.status, + credentials: connection.credentials, + integrity: connection.integrity, + createdAt: connection.createdAt, + updatedAt: connection.updatedAt, + revokedAt: connection.revokedAt + } + }) + + return connection + } + + async update(connection: SetRequired, 'id'>): Promise, 'id'>> { + await this.prismaService.providerConnection.update({ + where: { id: connection.id }, data: { id: connection.id, clientId: connection.clientId, @@ -17,7 +47,6 @@ export class ConnectionRepository { url: connection.url, label: connection.label, status: connection.status, - // TODO: ENCRYPTION credentials: connection.credentials, integrity: connection.integrity, createdAt: connection.createdAt, @@ -40,7 +69,8 @@ export class ConnectionRepository { // value, rather than undefined. This is actually by design and aligns // with how NULL values work in databases. label: result?.label || undefined, - revokedAt: result?.revokedAt || undefined + revokedAt: result?.revokedAt || undefined, + url: result?.url || undefined }) if (parse.success) { @@ -48,11 +78,15 @@ export class ConnectionRepository { } throw new ConnectionParseException({ - message: 'Fail to parse connection after read', - suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, - context: { - errors: parse.error.errors - } + context: { errors: parse.error.errors } + }) + } + + async exists(clientId: string, id: string): Promise { + const count = await this.prismaService.providerConnection.count({ + where: { id, clientId } }) + + return count > 0 } } diff --git a/apps/vault/src/encryption/core/encryption-key.service.ts b/apps/vault/src/encryption/core/encryption-key.service.ts new file mode 100644 index 000000000..8f7dfa7da --- /dev/null +++ b/apps/vault/src/encryption/core/encryption-key.service.ts @@ -0,0 +1,18 @@ +import { Alg, RsaPrivateKey, RsaPublicKey, generateJwk, rsaPrivateKeyToPublicKey } from '@narval/signature' +import { Injectable } from '@nestjs/common' + +const DEFAULT_RSA_MODULUS_LENGTH = 4096 + +@Injectable() +export class EncryptionKeyService { + async generate(clientId: string, opts?: { modulusLenght?: number }): Promise { + const modulusLength = opts?.modulusLenght || DEFAULT_RSA_MODULUS_LENGTH + + const privateKey = await generateJwk(Alg.RS256, { use: 'enc', modulusLength }) + const publicKey = rsaPrivateKeyToPublicKey(privateKey) + + return publicKey + } + + decrypt(clientId: string, data: string): Promise {} +} diff --git a/apps/vault/src/encryption/core/service/encryption-key.service.ts b/apps/vault/src/encryption/core/service/encryption-key.service.ts new file mode 100644 index 000000000..b03fc1b81 --- /dev/null +++ b/apps/vault/src/encryption/core/service/encryption-key.service.ts @@ -0,0 +1,57 @@ +import { Alg, RsaPrivateKey, generateJwk, rsaDecrypt, rsaPrivateKeyToPublicKey } from '@narval/signature' +import { HttpStatus, Injectable } from '@nestjs/common' +import { decodeProtectedHeader } from 'jose' +import { ApplicationException } from '../../../shared/exception/application.exception' +import { EncryptionKeyRepository } from '../../persistence/encryption-key.repository' +import { EncryptionKey } from '../type/encryption-key.type' + +const DEFAULT_RSA_MODULUS_LENGTH = 4096 + +@Injectable() +export class EncryptionKeyService { + constructor(private readonly encryptionKeyRepository: EncryptionKeyRepository) {} + + async generate(clientId: string, opts?: { modulusLenght?: number }): Promise { + const modulusLength = opts?.modulusLenght || DEFAULT_RSA_MODULUS_LENGTH + const privateKey = await generateJwk(Alg.RS256, { use: 'enc', modulusLength }) + const publicKey = rsaPrivateKeyToPublicKey(privateKey) + const encryptionKey = { + clientId, + privateKey, + publicKey, + createdAt: new Date() + } + + return this.encryptionKeyRepository.create(encryptionKey) + } + + async decrypt(clientId: string, data: string): Promise { + const header = decodeProtectedHeader(data) + const kid = header.kid + + if (!kid) { + throw new ApplicationException({ + message: 'Missing kid in JWE header', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY + }) + } + + const encryptionKey = await this.encryptionKeyRepository.findByKid(kid) + + if (encryptionKey) { + if (encryptionKey.clientId !== clientId) { + throw new ApplicationException({ + message: "Encryption key doesn't belong to client", + suggestedHttpStatusCode: HttpStatus.UNAUTHORIZED + }) + } + + return rsaDecrypt(data, encryptionKey.privateKey) + } + + throw new ApplicationException({ + message: 'Encryption key not found', + suggestedHttpStatusCode: HttpStatus.NOT_FOUND + }) + } +} diff --git a/apps/vault/src/encryption/core/type/encryption-key.type.ts b/apps/vault/src/encryption/core/type/encryption-key.type.ts new file mode 100644 index 000000000..010c87d8a --- /dev/null +++ b/apps/vault/src/encryption/core/type/encryption-key.type.ts @@ -0,0 +1,10 @@ +import { rsaPrivateKeySchema, rsaPublicKeySchema } from '@narval/signature' +import { z } from 'zod' + +export const EncryptionKey = z.object({ + clientId: z.string(), + publicKey: rsaPublicKeySchema, + privateKey: rsaPrivateKeySchema, + createdAt: z.date() +}) +export type EncryptionKey = z.infer diff --git a/apps/vault/src/encryption/encryption-key.module.ts b/apps/vault/src/encryption/encryption-key.module.ts new file mode 100644 index 000000000..25e01e799 --- /dev/null +++ b/apps/vault/src/encryption/encryption-key.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common' +import { PersistenceModule } from '../shared/module/persistence/persistence.module' +import { EncryptionKeyService } from './core/service/encryption-key.service' +import { EncryptionKeyRepository } from './persistence/encryption-key.repository' + +@Module({ + imports: [PersistenceModule], + providers: [EncryptionKeyRepository, EncryptionKeyService], + exports: [EncryptionKeyService] +}) +export class EncryptionKeyModule {} diff --git a/apps/vault/src/encryption/http/rest/controller/encryption-key.controller.ts b/apps/vault/src/encryption/http/rest/controller/encryption-key.controller.ts new file mode 100644 index 000000000..e69de29bb diff --git a/apps/vault/src/encryption/persistence/encryption-key.repository.ts b/apps/vault/src/encryption/persistence/encryption-key.repository.ts new file mode 100644 index 000000000..7e32ea215 --- /dev/null +++ b/apps/vault/src/encryption/persistence/encryption-key.repository.ts @@ -0,0 +1,35 @@ +import { rsaPrivateKeySchema, rsaPublicKeySchema } from '@narval/signature' +import { Injectable } from '@nestjs/common' +import { PrismaService } from '../../shared/module/persistence/service/prisma.service' +import { EncryptionKey } from '../core/type/encryption-key.type' + +@Injectable() +export class EncryptionKeyRepository { + constructor(private readonly prismaService: PrismaService) {} + + async create(encryptionKey: EncryptionKey): Promise { + await this.prismaService.encryptionKey.create({ + data: { + id: encryptionKey.privateKey.kid, + clientId: encryptionKey.clientId, + privateKey: rsaPrivateKeySchema.parse(encryptionKey.privateKey), + publicKey: rsaPublicKeySchema.parse(encryptionKey.publicKey), + createdAt: encryptionKey.createdAt + } + }) + + return encryptionKey + } + + async findByKid(kid: string): Promise { + const encryptionKey = await this.prismaService.encryptionKey.findUnique({ + where: { id: kid } + }) + + if (encryptionKey) { + return EncryptionKey.parse(encryptionKey) + } + + return null + } +} diff --git a/apps/vault/src/shared/module/persistence/schema/migrations/20241205125125_set_provider_connection_url_to_nullable/migration.sql b/apps/vault/src/shared/module/persistence/schema/migrations/20241205125125_set_provider_connection_url_to_nullable/migration.sql new file mode 100644 index 000000000..f4e93112a --- /dev/null +++ b/apps/vault/src/shared/module/persistence/schema/migrations/20241205125125_set_provider_connection_url_to_nullable/migration.sql @@ -0,0 +1,13 @@ +/* + Warnings: + + - Added the required column `request` to the `provider_transfer` table without a default value. This is not possible if the table is not empty. + +*/ +-- AlterTable +ALTER TABLE "provider_connection" ALTER COLUMN "url" DROP NOT NULL, +ALTER COLUMN "credentials" DROP NOT NULL, +ALTER COLUMN "created_at" DROP DEFAULT; + +-- AlterTable +ALTER TABLE "provider_transfer" ADD COLUMN "request" JSONB NOT NULL; diff --git a/apps/vault/src/shared/module/persistence/schema/migrations/20241205133709_add_encryption_key_table/migration.sql b/apps/vault/src/shared/module/persistence/schema/migrations/20241205133709_add_encryption_key_table/migration.sql new file mode 100644 index 000000000..f431d39c4 --- /dev/null +++ b/apps/vault/src/shared/module/persistence/schema/migrations/20241205133709_add_encryption_key_table/migration.sql @@ -0,0 +1,10 @@ +-- CreateTable +CREATE TABLE "encryption_key" ( + "id" TEXT NOT NULL, + "client_id" TEXT NOT NULL, + "private_key" JSONB NOT NULL, + "public_key" JSONB NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "encryption_key_pkey" PRIMARY KEY ("id") +); diff --git a/apps/vault/src/shared/module/persistence/schema/schema.prisma b/apps/vault/src/shared/module/persistence/schema/schema.prisma index 424120c9b..6d4a0a681 100644 --- a/apps/vault/src/shared/module/persistence/schema/schema.prisma +++ b/apps/vault/src/shared/module/persistence/schema/schema.prisma @@ -32,6 +32,17 @@ model KeyValue { @@map("key_value") } +model EncryptionKey { + id String @id @default(cuid()) + clientId String @map("client_id") + privateKey Json @map("private_key") + publicKey Json @map("public_key") + + createdAt DateTime @default(now()) + + @@map("encryption_key") +} + model ProviderWallet { id String @id label String? @@ -106,7 +117,7 @@ model ProviderConnection { id String @id clientId String @map("client_id") provider String - url String + url String? label String? credentials Json? status String From 034fbd82a621f1986d33914497ae54b0d0101934 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Thu, 5 Dec 2024 18:26:53 +0100 Subject: [PATCH 010/120] Add tests for the encryption key --- apps/vault/jest.config.ts | 3 +- .../broker/__test__/e2e/connection.spec.ts | 13 +--- .../encryption/core/encryption-key.service.ts | 18 ------ .../exception/encryption-key.exception.ts | 3 + .../exception/invalid-jwe-header.exception.ts | 13 ++++ .../core/exception/not-found.exception.ts | 13 ++++ .../core/exception/unauthorized.exception.ts | 13 ++++ .../encryption-key.service.spec.ts | 61 +++++++++++++++++++ .../core/service/encryption-key.service.ts | 21 +++---- 9 files changed, 114 insertions(+), 44 deletions(-) delete mode 100644 apps/vault/src/encryption/core/encryption-key.service.ts create mode 100644 apps/vault/src/encryption/core/exception/encryption-key.exception.ts create mode 100644 apps/vault/src/encryption/core/exception/invalid-jwe-header.exception.ts create mode 100644 apps/vault/src/encryption/core/exception/not-found.exception.ts create mode 100644 apps/vault/src/encryption/core/exception/unauthorized.exception.ts create mode 100644 apps/vault/src/encryption/core/service/__test__/integration/encryption-key.service.spec.ts diff --git a/apps/vault/jest.config.ts b/apps/vault/jest.config.ts index d19762a82..b3d7101ff 100644 --- a/apps/vault/jest.config.ts +++ b/apps/vault/jest.config.ts @@ -13,8 +13,7 @@ const config: Config = { tsconfig: '/tsconfig.spec.json' } ] - }, - workerThreads: true // EXPERIMENTAL; lets BigInt serialization work + } } export default config diff --git a/apps/vault/src/broker/__test__/e2e/connection.spec.ts b/apps/vault/src/broker/__test__/e2e/connection.spec.ts index 17b5c7a1b..39ae203e4 100644 --- a/apps/vault/src/broker/__test__/e2e/connection.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/connection.spec.ts @@ -1,5 +1,4 @@ import { ConfigModule } from '@narval/config-module' -import { EncryptionModuleOptionProvider } from '@narval/encryption-module' import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' import { Alg, @@ -18,7 +17,6 @@ import { v4 as uuid } from 'uuid' import { ZodSchema } from 'zod' import { load } from '../../../main.config' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' -import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' import { BrokerModule } from '../../broker.module' import { ConnectionStatus, Provider } from '../../core/type/connection.type' import { ConnectionRepository } from '../../persistence/repository/connection.repository' @@ -61,12 +59,7 @@ describe('Connection', () => { }), BrokerModule ] - }) - .overrideProvider(EncryptionModuleOptionProvider) - .useValue({ - keyring: getTestRawAesKeyring() - }) - .compile() + }).compile() app = module.createNestApplication() @@ -165,7 +158,7 @@ describe('Connection', () => { }) }) - it('activates a pending connection to anchorage with plain credentials', async () => { + it('activates an anchorage pending connection with plain credentials', async () => { const connectionId = uuid() const provider = Provider.ANCHORAGE const label = 'Test Anchorage Connection' @@ -217,7 +210,7 @@ describe('Connection', () => { }) }) - it('activates a pending connection to anchorage with encrypted credentials', async () => { + it('activates an anchorage pending connection with encrypted credentials', async () => { const connectionId = uuid() const provider = Provider.ANCHORAGE const label = 'Test Anchorage Connection' diff --git a/apps/vault/src/encryption/core/encryption-key.service.ts b/apps/vault/src/encryption/core/encryption-key.service.ts deleted file mode 100644 index 8f7dfa7da..000000000 --- a/apps/vault/src/encryption/core/encryption-key.service.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Alg, RsaPrivateKey, RsaPublicKey, generateJwk, rsaPrivateKeyToPublicKey } from '@narval/signature' -import { Injectable } from '@nestjs/common' - -const DEFAULT_RSA_MODULUS_LENGTH = 4096 - -@Injectable() -export class EncryptionKeyService { - async generate(clientId: string, opts?: { modulusLenght?: number }): Promise { - const modulusLength = opts?.modulusLenght || DEFAULT_RSA_MODULUS_LENGTH - - const privateKey = await generateJwk(Alg.RS256, { use: 'enc', modulusLength }) - const publicKey = rsaPrivateKeyToPublicKey(privateKey) - - return publicKey - } - - decrypt(clientId: string, data: string): Promise {} -} diff --git a/apps/vault/src/encryption/core/exception/encryption-key.exception.ts b/apps/vault/src/encryption/core/exception/encryption-key.exception.ts new file mode 100644 index 000000000..bb7bbb896 --- /dev/null +++ b/apps/vault/src/encryption/core/exception/encryption-key.exception.ts @@ -0,0 +1,3 @@ +import { ApplicationException } from '../../../shared/exception/application.exception' + +export class EncryptionKeyException extends ApplicationException {} diff --git a/apps/vault/src/encryption/core/exception/invalid-jwe-header.exception.ts b/apps/vault/src/encryption/core/exception/invalid-jwe-header.exception.ts new file mode 100644 index 000000000..773746edd --- /dev/null +++ b/apps/vault/src/encryption/core/exception/invalid-jwe-header.exception.ts @@ -0,0 +1,13 @@ +import { HttpStatus } from '@nestjs/common' +import { ApplicationExceptionParams } from '../../../shared/exception/application.exception' +import { EncryptionKeyException } from './encryption-key.exception' + +export class InvalidJweHeaderException extends EncryptionKeyException { + constructor(params?: Partial) { + super({ + message: params?.message || 'Invalid JWE header', + suggestedHttpStatusCode: params?.suggestedHttpStatusCode || HttpStatus.UNPROCESSABLE_ENTITY, + ...params + }) + } +} diff --git a/apps/vault/src/encryption/core/exception/not-found.exception.ts b/apps/vault/src/encryption/core/exception/not-found.exception.ts new file mode 100644 index 000000000..db56a9aec --- /dev/null +++ b/apps/vault/src/encryption/core/exception/not-found.exception.ts @@ -0,0 +1,13 @@ +import { HttpStatus } from '@nestjs/common' +import { ApplicationExceptionParams } from '../../../shared/exception/application.exception' +import { EncryptionKeyException } from './encryption-key.exception' + +export class NotFoundException extends EncryptionKeyException { + constructor(params?: Partial) { + super({ + message: params?.message || 'Encryption key not found', + suggestedHttpStatusCode: params?.suggestedHttpStatusCode || HttpStatus.NOT_FOUND, + ...params + }) + } +} diff --git a/apps/vault/src/encryption/core/exception/unauthorized.exception.ts b/apps/vault/src/encryption/core/exception/unauthorized.exception.ts new file mode 100644 index 000000000..507cd6a92 --- /dev/null +++ b/apps/vault/src/encryption/core/exception/unauthorized.exception.ts @@ -0,0 +1,13 @@ +import { HttpStatus } from '@nestjs/common' +import { ApplicationExceptionParams } from '../../../shared/exception/application.exception' +import { EncryptionKeyException } from './encryption-key.exception' + +export class UnauthorizedException extends EncryptionKeyException { + constructor(params?: Partial) { + super({ + message: params?.message || "Encryption key doesn't belong to client", + suggestedHttpStatusCode: params?.suggestedHttpStatusCode || HttpStatus.UNAUTHORIZED, + ...params + }) + } +} diff --git a/apps/vault/src/encryption/core/service/__test__/integration/encryption-key.service.spec.ts b/apps/vault/src/encryption/core/service/__test__/integration/encryption-key.service.spec.ts new file mode 100644 index 000000000..633a9571f --- /dev/null +++ b/apps/vault/src/encryption/core/service/__test__/integration/encryption-key.service.spec.ts @@ -0,0 +1,61 @@ +import { ConfigModule } from '@narval/config-module' +import { LoggerModule } from '@narval/nestjs-shared' +import { getPublicKey, rsaPrivateKeySchema, rsaPublicKeySchema } from '@narval/signature' +import { Test } from '@nestjs/testing' +import { v4 as uuid } from 'uuid' +import { load } from '../../../../../main.config' +import { PersistenceModule } from '../../../../../shared/module/persistence/persistence.module' +import { EncryptionKeyRepository } from '../../../../persistence/encryption-key.repository' +import { EncryptionKeyService } from '../../encryption-key.service' + +describe(EncryptionKeyService.name, () => { + let encryptionKeyService: EncryptionKeyService + let encryptionKeyRepository: EncryptionKeyRepository + + const clientId = uuid() + + beforeEach(async () => { + const module = await Test.createTestingModule({ + imports: [ + PersistenceModule, + LoggerModule.forTest(), + ConfigModule.forRoot({ + load: [load], + isGlobal: true + }) + ], + providers: [EncryptionKeyService, EncryptionKeyRepository] + }).compile() + + encryptionKeyService = module.get(EncryptionKeyService) + encryptionKeyRepository = module.get(EncryptionKeyRepository) + }) + + describe('generate', () => { + it('returns rsa private and public keys', async () => { + const encryptionKey = await encryptionKeyService.generate(clientId) + + expect(rsaPrivateKeySchema.safeParse(encryptionKey.privateKey).success).toEqual(true) + expect(rsaPublicKeySchema.safeParse(encryptionKey.publicKey).success).toEqual(true) + }) + + it('uses private kid as id', async () => { + const { privateKey } = await encryptionKeyService.generate(clientId) + + const encryptionKey = await encryptionKeyRepository.findByKid(privateKey.kid) + + expect(encryptionKey).toMatchObject({ + clientId, + privateKey, + publicKey: getPublicKey(privateKey) + }) + }) + }) + + describe('decrypt', () => { + it.todo('throws InvalidJweHeaderException when kid is missing') + it.todo('throws NotFoundException when encryption key is not found') + it.todo('throws UnauthorizedException when encryption key clientId is different than the given clientId') + it.todo('decrypts data using rsa private key') + }) +}) diff --git a/apps/vault/src/encryption/core/service/encryption-key.service.ts b/apps/vault/src/encryption/core/service/encryption-key.service.ts index b03fc1b81..e34196ff4 100644 --- a/apps/vault/src/encryption/core/service/encryption-key.service.ts +++ b/apps/vault/src/encryption/core/service/encryption-key.service.ts @@ -1,8 +1,10 @@ import { Alg, RsaPrivateKey, generateJwk, rsaDecrypt, rsaPrivateKeyToPublicKey } from '@narval/signature' -import { HttpStatus, Injectable } from '@nestjs/common' +import { Injectable } from '@nestjs/common' import { decodeProtectedHeader } from 'jose' -import { ApplicationException } from '../../../shared/exception/application.exception' import { EncryptionKeyRepository } from '../../persistence/encryption-key.repository' +import { InvalidJweHeaderException } from '../exception/invalid-jwe-header.exception' +import { NotFoundException } from '../exception/not-found.exception' +import { UnauthorizedException } from '../exception/unauthorized.exception' import { EncryptionKey } from '../type/encryption-key.type' const DEFAULT_RSA_MODULUS_LENGTH = 4096 @@ -30,28 +32,19 @@ export class EncryptionKeyService { const kid = header.kid if (!kid) { - throw new ApplicationException({ - message: 'Missing kid in JWE header', - suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY - }) + throw new InvalidJweHeaderException() } const encryptionKey = await this.encryptionKeyRepository.findByKid(kid) if (encryptionKey) { if (encryptionKey.clientId !== clientId) { - throw new ApplicationException({ - message: "Encryption key doesn't belong to client", - suggestedHttpStatusCode: HttpStatus.UNAUTHORIZED - }) + throw new UnauthorizedException({ context: { kid, clientId } }) } return rsaDecrypt(data, encryptionKey.privateKey) } - throw new ApplicationException({ - message: 'Encryption key not found', - suggestedHttpStatusCode: HttpStatus.NOT_FOUND - }) + throw new NotFoundException({ context: { kid } }) } } From cfb6ad0ed53569d4f87fa21d412d2153a80e8d3a Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Fri, 6 Dec 2024 09:56:10 +0100 Subject: [PATCH 011/120] Rename encryption module to transit encryption --- apps/vault/src/broker/broker.module.ts | 4 ++-- apps/vault/src/broker/core/service/connection.service.ts | 2 +- .../core/exception/encryption-key.exception.ts | 0 .../core/exception/invalid-jwe-header.exception.ts | 0 .../core/exception/not-found.exception.ts | 0 .../core/exception/unauthorized.exception.ts | 0 .../__test__/integration/encryption-key.service.spec.ts | 0 .../core/service/encryption-key.service.ts | 0 .../core/type/encryption-key.type.ts | 0 .../http/rest/controller/encryption-key.controller.ts | 0 .../persistence/encryption-key.repository.ts | 0 .../transit-encryption.module.ts} | 2 +- 12 files changed, 4 insertions(+), 4 deletions(-) rename apps/vault/src/{encryption => transit-encryption}/core/exception/encryption-key.exception.ts (100%) rename apps/vault/src/{encryption => transit-encryption}/core/exception/invalid-jwe-header.exception.ts (100%) rename apps/vault/src/{encryption => transit-encryption}/core/exception/not-found.exception.ts (100%) rename apps/vault/src/{encryption => transit-encryption}/core/exception/unauthorized.exception.ts (100%) rename apps/vault/src/{encryption => transit-encryption}/core/service/__test__/integration/encryption-key.service.spec.ts (100%) rename apps/vault/src/{encryption => transit-encryption}/core/service/encryption-key.service.ts (100%) rename apps/vault/src/{encryption => transit-encryption}/core/type/encryption-key.type.ts (100%) rename apps/vault/src/{encryption => transit-encryption}/http/rest/controller/encryption-key.controller.ts (100%) rename apps/vault/src/{encryption => transit-encryption}/persistence/encryption-key.repository.ts (100%) rename apps/vault/src/{encryption/encryption-key.module.ts => transit-encryption/transit-encryption.module.ts} (91%) diff --git a/apps/vault/src/broker/broker.module.ts b/apps/vault/src/broker/broker.module.ts index a4df3dbb2..0ce70bb80 100644 --- a/apps/vault/src/broker/broker.module.ts +++ b/apps/vault/src/broker/broker.module.ts @@ -1,13 +1,13 @@ import { Module } from '@nestjs/common' -import { EncryptionKeyModule } from '../encryption/encryption-key.module' import { DEFAULT_HTTP_MODULE_PROVIDERS } from '../shared/constant' import { PersistenceModule } from '../shared/module/persistence/persistence.module' +import { TransitEncryptionModule } from '../transit-encryption/transit-encryption.module' import { ConnectionService } from './core/service/connection.service' import { ConnectionController } from './http/rest/controller/connection.controller' import { ConnectionRepository } from './persistence/repository/connection.repository' @Module({ - imports: [PersistenceModule, EncryptionKeyModule], + imports: [PersistenceModule, TransitEncryptionModule], controllers: [ConnectionController], providers: [...DEFAULT_HTTP_MODULE_PROVIDERS, ConnectionService, ConnectionRepository] }) diff --git a/apps/vault/src/broker/core/service/connection.service.ts b/apps/vault/src/broker/core/service/connection.service.ts index dbc538dd5..14b00a8f4 100644 --- a/apps/vault/src/broker/core/service/connection.service.ts +++ b/apps/vault/src/broker/core/service/connection.service.ts @@ -2,7 +2,7 @@ import { Alg, Ed25519PrivateKey, generateJwk, getPublicKey, privateKeyToJwk } fr import { Injectable, NotImplementedException } from '@nestjs/common' import { SetRequired } from 'type-fest' import { v4 as uuid } from 'uuid' -import { EncryptionKeyService } from '../../../encryption/core/service/encryption-key.service' +import { EncryptionKeyService } from '../../../transit-encryption/core/service/encryption-key.service' import { ConnectionRepository } from '../../persistence/repository/connection.repository' import { InvalidConnectionPrivateKeyException } from '../exception/invalid-connection-private-key.exception' import { MissingConnectionCredentialsException } from '../exception/missing-connection-credentials.exception' diff --git a/apps/vault/src/encryption/core/exception/encryption-key.exception.ts b/apps/vault/src/transit-encryption/core/exception/encryption-key.exception.ts similarity index 100% rename from apps/vault/src/encryption/core/exception/encryption-key.exception.ts rename to apps/vault/src/transit-encryption/core/exception/encryption-key.exception.ts diff --git a/apps/vault/src/encryption/core/exception/invalid-jwe-header.exception.ts b/apps/vault/src/transit-encryption/core/exception/invalid-jwe-header.exception.ts similarity index 100% rename from apps/vault/src/encryption/core/exception/invalid-jwe-header.exception.ts rename to apps/vault/src/transit-encryption/core/exception/invalid-jwe-header.exception.ts diff --git a/apps/vault/src/encryption/core/exception/not-found.exception.ts b/apps/vault/src/transit-encryption/core/exception/not-found.exception.ts similarity index 100% rename from apps/vault/src/encryption/core/exception/not-found.exception.ts rename to apps/vault/src/transit-encryption/core/exception/not-found.exception.ts diff --git a/apps/vault/src/encryption/core/exception/unauthorized.exception.ts b/apps/vault/src/transit-encryption/core/exception/unauthorized.exception.ts similarity index 100% rename from apps/vault/src/encryption/core/exception/unauthorized.exception.ts rename to apps/vault/src/transit-encryption/core/exception/unauthorized.exception.ts diff --git a/apps/vault/src/encryption/core/service/__test__/integration/encryption-key.service.spec.ts b/apps/vault/src/transit-encryption/core/service/__test__/integration/encryption-key.service.spec.ts similarity index 100% rename from apps/vault/src/encryption/core/service/__test__/integration/encryption-key.service.spec.ts rename to apps/vault/src/transit-encryption/core/service/__test__/integration/encryption-key.service.spec.ts diff --git a/apps/vault/src/encryption/core/service/encryption-key.service.ts b/apps/vault/src/transit-encryption/core/service/encryption-key.service.ts similarity index 100% rename from apps/vault/src/encryption/core/service/encryption-key.service.ts rename to apps/vault/src/transit-encryption/core/service/encryption-key.service.ts diff --git a/apps/vault/src/encryption/core/type/encryption-key.type.ts b/apps/vault/src/transit-encryption/core/type/encryption-key.type.ts similarity index 100% rename from apps/vault/src/encryption/core/type/encryption-key.type.ts rename to apps/vault/src/transit-encryption/core/type/encryption-key.type.ts diff --git a/apps/vault/src/encryption/http/rest/controller/encryption-key.controller.ts b/apps/vault/src/transit-encryption/http/rest/controller/encryption-key.controller.ts similarity index 100% rename from apps/vault/src/encryption/http/rest/controller/encryption-key.controller.ts rename to apps/vault/src/transit-encryption/http/rest/controller/encryption-key.controller.ts diff --git a/apps/vault/src/encryption/persistence/encryption-key.repository.ts b/apps/vault/src/transit-encryption/persistence/encryption-key.repository.ts similarity index 100% rename from apps/vault/src/encryption/persistence/encryption-key.repository.ts rename to apps/vault/src/transit-encryption/persistence/encryption-key.repository.ts diff --git a/apps/vault/src/encryption/encryption-key.module.ts b/apps/vault/src/transit-encryption/transit-encryption.module.ts similarity index 91% rename from apps/vault/src/encryption/encryption-key.module.ts rename to apps/vault/src/transit-encryption/transit-encryption.module.ts index 25e01e799..838560ca8 100644 --- a/apps/vault/src/encryption/encryption-key.module.ts +++ b/apps/vault/src/transit-encryption/transit-encryption.module.ts @@ -8,4 +8,4 @@ import { EncryptionKeyRepository } from './persistence/encryption-key.repository providers: [EncryptionKeyRepository, EncryptionKeyService], exports: [EncryptionKeyService] }) -export class EncryptionKeyModule {} +export class TransitEncryptionModule {} From 56e5e730a1e40d9a488585d2731d8a521ffae4e6 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Fri, 6 Dec 2024 10:29:18 +0100 Subject: [PATCH 012/120] Add tests to the decrypt --- .../encryption-key.service.spec.ts | 117 +++++++++++++++++- .../core/service/encryption-key.service.ts | 6 +- 2 files changed, 115 insertions(+), 8 deletions(-) diff --git a/apps/vault/src/transit-encryption/core/service/__test__/integration/encryption-key.service.spec.ts b/apps/vault/src/transit-encryption/core/service/__test__/integration/encryption-key.service.spec.ts index 633a9571f..d8e256c63 100644 --- a/apps/vault/src/transit-encryption/core/service/__test__/integration/encryption-key.service.spec.ts +++ b/apps/vault/src/transit-encryption/core/service/__test__/integration/encryption-key.service.spec.ts @@ -1,13 +1,38 @@ import { ConfigModule } from '@narval/config-module' import { LoggerModule } from '@narval/nestjs-shared' -import { getPublicKey, rsaPrivateKeySchema, rsaPublicKeySchema } from '@narval/signature' +import { + Alg, + RsaPrivateKey, + RsaPublicKey, + Use, + generateJwk, + getPublicKey, + rsaEncrypt, + rsaPrivateKeySchema, + rsaPrivateKeyToPublicKey, + rsaPublicKeySchema +} from '@narval/signature' import { Test } from '@nestjs/testing' +import { omit } from 'lodash' import { v4 as uuid } from 'uuid' import { load } from '../../../../../main.config' import { PersistenceModule } from '../../../../../shared/module/persistence/persistence.module' import { EncryptionKeyRepository } from '../../../../persistence/encryption-key.repository' +import { InvalidJweHeaderException } from '../../../exception/invalid-jwe-header.exception' +import { NotFoundException } from '../../../exception/not-found.exception' +import { UnauthorizedException } from '../../../exception/unauthorized.exception' +import { EncryptionKey } from '../../../type/encryption-key.type' import { EncryptionKeyService } from '../../encryption-key.service' +// NOTE: Uses the smallest modulus lenght required by jose package for +// test performance reasons. +const SMALLEST_RSA_MODULUS_LENGTH = 2048 + +const GENERATE_RSA_KEY_OPTIONS: { use: Use; modulusLength: number } = { + use: 'enc', + modulusLength: SMALLEST_RSA_MODULUS_LENGTH +} + describe(EncryptionKeyService.name, () => { let encryptionKeyService: EncryptionKeyService let encryptionKeyRepository: EncryptionKeyRepository @@ -53,9 +78,91 @@ describe(EncryptionKeyService.name, () => { }) describe('decrypt', () => { - it.todo('throws InvalidJweHeaderException when kid is missing') - it.todo('throws NotFoundException when encryption key is not found') - it.todo('throws UnauthorizedException when encryption key clientId is different than the given clientId') - it.todo('decrypts data using rsa private key') + it('decrypts data using rsa private key', async () => { + const privateKey = await generateJwk(Alg.RS256, { use: 'enc', modulusLength: 2048 }) + const publicKey = rsaPrivateKeyToPublicKey(privateKey) + const encryptionKey = { + clientId, + privateKey, + publicKey, + createdAt: new Date() + } + await encryptionKeyRepository.create(encryptionKey) + + const secret = 'secret message' + const encryptedData = await rsaEncrypt(secret, publicKey) + + const decryptedData = await encryptionKeyService.decrypt(clientId, encryptedData) + expect(decryptedData).toBe(secret) + }) + + it('throws InvalidJweHeaderException when public key kid is missing', async () => { + const privateKey = await generateJwk(Alg.RS256, GENERATE_RSA_KEY_OPTIONS) + const publicKey = omit(rsaPrivateKeyToPublicKey(privateKey), 'kid') + + // Mock the repository to bypass schema validation + jest.spyOn(encryptionKeyRepository, 'create').mockImplementationOnce((encryptionKey) => { + return Promise.resolve({ + ...encryptionKey, + publicKey: omit(publicKey, 'kid') + } as EncryptionKey) + }) + + const encryptionKey = { + clientId, + privateKey, + publicKey, + createdAt: new Date() + } + + await encryptionKeyRepository.create(encryptionKey as EncryptionKey) + const encryptedData = await rsaEncrypt('secret', publicKey as RsaPublicKey) + + try { + await encryptionKeyService.decrypt(clientId, encryptedData) + fail('expected to have thrown InvalidJweHeaderException') + } catch (error) { + expect(error).toBeInstanceOf(InvalidJweHeaderException) + } + }) + + it('throws NotFoundException when encryption key is not found', async () => { + const privateKey = await generateJwk(Alg.RS256, GENERATE_RSA_KEY_OPTIONS) + const publicKey = rsaPrivateKeyToPublicKey(privateKey) + const encryptedData = await rsaEncrypt('secret', publicKey) + + try { + await encryptionKeyService.decrypt(clientId, encryptedData) + fail('expected to have thrown NotFoundException') + } catch (error) { + expect(error).toBeInstanceOf(NotFoundException) + expect(error.context).toEqual({ kid: publicKey.kid }) + } + }) + + it('throws UnauthorizedException when encryption key clientId is different than the given clientId', async () => { + const differentClientId = uuid() + const privateKey = await generateJwk(Alg.RS256, GENERATE_RSA_KEY_OPTIONS) + const publicKey = rsaPrivateKeyToPublicKey(privateKey) + const encryptionKey = { + clientId: differentClientId, + privateKey, + publicKey, + createdAt: new Date() + } + await encryptionKeyRepository.create(encryptionKey) + const encryptedData = await rsaEncrypt('secret', publicKey) + + try { + await encryptionKeyService.decrypt(clientId, encryptedData) + fail('expected to have thrown UnauthorizedException') + } catch (error) { + expect(error).toBeInstanceOf(UnauthorizedException) + expect(error.context).toEqual({ + kid: publicKey.kid, + clientId + }) + } + }) }) }) diff --git a/apps/vault/src/transit-encryption/core/service/encryption-key.service.ts b/apps/vault/src/transit-encryption/core/service/encryption-key.service.ts index e34196ff4..d95910817 100644 --- a/apps/vault/src/transit-encryption/core/service/encryption-key.service.ts +++ b/apps/vault/src/transit-encryption/core/service/encryption-key.service.ts @@ -27,8 +27,8 @@ export class EncryptionKeyService { return this.encryptionKeyRepository.create(encryptionKey) } - async decrypt(clientId: string, data: string): Promise { - const header = decodeProtectedHeader(data) + async decrypt(clientId: string, encryptedData: string): Promise { + const header = decodeProtectedHeader(encryptedData) const kid = header.kid if (!kid) { @@ -42,7 +42,7 @@ export class EncryptionKeyService { throw new UnauthorizedException({ context: { kid, clientId } }) } - return rsaDecrypt(data, encryptionKey.privateKey) + return rsaDecrypt(encryptedData, encryptionKey.privateKey) } throw new NotFoundException({ context: { kid } }) From ef0eae5df0a4ca188db2b82ffff09e151ac2b4f4 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Fri, 6 Dec 2024 10:31:51 +0100 Subject: [PATCH 013/120] Rename table to transit_encryption_key --- .../migration.sql | 4 ++-- apps/vault/src/shared/module/persistence/schema/schema.prisma | 4 ++-- .../persistence/encryption-key.repository.ts | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) rename apps/vault/src/shared/module/persistence/schema/migrations/{20241205133709_add_encryption_key_table => 20241206093046_add_transit_encryption_key_table}/migration.sql (66%) diff --git a/apps/vault/src/shared/module/persistence/schema/migrations/20241205133709_add_encryption_key_table/migration.sql b/apps/vault/src/shared/module/persistence/schema/migrations/20241206093046_add_transit_encryption_key_table/migration.sql similarity index 66% rename from apps/vault/src/shared/module/persistence/schema/migrations/20241205133709_add_encryption_key_table/migration.sql rename to apps/vault/src/shared/module/persistence/schema/migrations/20241206093046_add_transit_encryption_key_table/migration.sql index f431d39c4..1f75f1545 100644 --- a/apps/vault/src/shared/module/persistence/schema/migrations/20241205133709_add_encryption_key_table/migration.sql +++ b/apps/vault/src/shared/module/persistence/schema/migrations/20241206093046_add_transit_encryption_key_table/migration.sql @@ -1,10 +1,10 @@ -- CreateTable -CREATE TABLE "encryption_key" ( +CREATE TABLE "transit_encryption_key" ( "id" TEXT NOT NULL, "client_id" TEXT NOT NULL, "private_key" JSONB NOT NULL, "public_key" JSONB NOT NULL, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - CONSTRAINT "encryption_key_pkey" PRIMARY KEY ("id") + CONSTRAINT "transit_encryption_key_pkey" PRIMARY KEY ("id") ); diff --git a/apps/vault/src/shared/module/persistence/schema/schema.prisma b/apps/vault/src/shared/module/persistence/schema/schema.prisma index 6d4a0a681..46160f5f8 100644 --- a/apps/vault/src/shared/module/persistence/schema/schema.prisma +++ b/apps/vault/src/shared/module/persistence/schema/schema.prisma @@ -32,7 +32,7 @@ model KeyValue { @@map("key_value") } -model EncryptionKey { +model TransitEncryptionKey { id String @id @default(cuid()) clientId String @map("client_id") privateKey Json @map("private_key") @@ -40,7 +40,7 @@ model EncryptionKey { createdAt DateTime @default(now()) - @@map("encryption_key") + @@map("transit_encryption_key") } model ProviderWallet { diff --git a/apps/vault/src/transit-encryption/persistence/encryption-key.repository.ts b/apps/vault/src/transit-encryption/persistence/encryption-key.repository.ts index 7e32ea215..89194f768 100644 --- a/apps/vault/src/transit-encryption/persistence/encryption-key.repository.ts +++ b/apps/vault/src/transit-encryption/persistence/encryption-key.repository.ts @@ -8,7 +8,7 @@ export class EncryptionKeyRepository { constructor(private readonly prismaService: PrismaService) {} async create(encryptionKey: EncryptionKey): Promise { - await this.prismaService.encryptionKey.create({ + await this.prismaService.transitEncryptionKey.create({ data: { id: encryptionKey.privateKey.kid, clientId: encryptionKey.clientId, @@ -22,7 +22,7 @@ export class EncryptionKeyRepository { } async findByKid(kid: string): Promise { - const encryptionKey = await this.prismaService.encryptionKey.findUnique({ + const encryptionKey = await this.prismaService.transitEncryptionKey.findUnique({ where: { id: kid } }) From c4e309a43c8db8e1ada0ee0cc8aacb163649bcc1 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Fri, 6 Dec 2024 14:38:04 +0100 Subject: [PATCH 014/120] Work in progress with repository static map method --- .../broker/__test__/e2e/connection.spec.ts | 30 ++++++++++++++++ .../core/exception/not-found.exception.ts | 13 +++++++ .../broker/core/service/connection.service.ts | 22 ++++++++++++ .../src/broker/core/type/connection.type.ts | 16 +++++---- .../rest/controller/connection.controller.ts | 16 ++++++++- .../repository/connection.repository.ts | 36 +++++++++++++++++-- 6 files changed, 123 insertions(+), 10 deletions(-) create mode 100644 apps/vault/src/broker/core/exception/not-found.exception.ts diff --git a/apps/vault/src/broker/__test__/e2e/connection.spec.ts b/apps/vault/src/broker/__test__/e2e/connection.spec.ts index 39ae203e4..1d56dcfd4 100644 --- a/apps/vault/src/broker/__test__/e2e/connection.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/connection.spec.ts @@ -18,6 +18,7 @@ import { ZodSchema } from 'zod' import { load } from '../../../main.config' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { BrokerModule } from '../../broker.module' +import { ConnectionService } from '../../core/service/connection.service' import { ConnectionStatus, Provider } from '../../core/type/connection.type' import { ConnectionRepository } from '../../persistence/repository/connection.repository' @@ -43,6 +44,7 @@ describe('Connection', () => { let app: INestApplication let module: TestingModule let connectionRepository: ConnectionRepository + let connectionService: ConnectionService let testPrismaService: TestPrismaService const url = 'http://provider.narval.xyz' @@ -65,6 +67,7 @@ describe('Connection', () => { testPrismaService = module.get(TestPrismaService) connectionRepository = module.get(ConnectionRepository) + connectionService = module.get(ConnectionService) await testPrismaService.truncateAll() @@ -264,4 +267,31 @@ describe('Connection', () => { }) }) }) + + describe('DELETE /connections/:id', () => { + it.only('revokes an existing connection', async () => { + const connection = await connectionService.create(clientId, { + connectionId: uuid(), + label: 'test revoke connection', + provider: Provider.ANCHORAGE, + url, + credentials: { + apiKey: 'test-api-key', + privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) + } + }) + + const { status } = await request(app.getHttpServer()) + .delete(`/connections/${connection.id}`) + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .send() + + expect(status).toEqual(HttpStatus.NO_CONTENT) + + const revokedConnection = await connectionService.findById(clientId, connection.id) + + expect(revokedConnection?.credentials).toEqual(undefined) + expect(revokedConnection?.revokedAt).toEqual(expect.any(Date)) + }) + }) }) diff --git a/apps/vault/src/broker/core/exception/not-found.exception.ts b/apps/vault/src/broker/core/exception/not-found.exception.ts new file mode 100644 index 000000000..292c9e2a5 --- /dev/null +++ b/apps/vault/src/broker/core/exception/not-found.exception.ts @@ -0,0 +1,13 @@ +import { HttpStatus } from '@nestjs/common' +import { ApplicationExceptionParams } from '../../../shared/exception/application.exception' +import { BrokerException } from './broker.exception' + +export class NotFoundException extends BrokerException { + constructor(params?: Partial) { + super({ + message: params?.message || 'Not found', + suggestedHttpStatusCode: params?.suggestedHttpStatusCode || HttpStatus.NOT_FOUND, + ...params + }) + } +} diff --git a/apps/vault/src/broker/core/service/connection.service.ts b/apps/vault/src/broker/core/service/connection.service.ts index 14b00a8f4..75678e7ae 100644 --- a/apps/vault/src/broker/core/service/connection.service.ts +++ b/apps/vault/src/broker/core/service/connection.service.ts @@ -6,6 +6,7 @@ import { EncryptionKeyService } from '../../../transit-encryption/core/service/e import { ConnectionRepository } from '../../persistence/repository/connection.repository' import { InvalidConnectionPrivateKeyException } from '../exception/invalid-connection-private-key.exception' import { MissingConnectionCredentialsException } from '../exception/missing-connection-credentials.exception' +import { NotFoundException } from '../exception/not-found.exception' import { Connection, ConnectionStatus, @@ -193,4 +194,25 @@ export class ConnectionService { throw new MissingConnectionCredentialsException() } + + async findById(clientId: string, connectionId: string): Promise { + return this.connectionRepository.findById(clientId, connectionId) + } + + async revoke(clientId: string, connectionId: string): Promise { + const connection = await this.connectionRepository.findById(clientId, connectionId) + + if (connection) { + await this.connectionRepository.update({ + id: connectionId, + credentials: null, + status: ConnectionStatus.REVOKED, + revokedAt: new Date() + }) + + return true + } + + throw new NotFoundException({ context: { clientId, connectionId } }) + } } diff --git a/apps/vault/src/broker/core/type/connection.type.ts b/apps/vault/src/broker/core/type/connection.type.ts index 270227ed8..e9bac171e 100644 --- a/apps/vault/src/broker/core/type/connection.type.ts +++ b/apps/vault/src/broker/core/type/connection.type.ts @@ -13,7 +13,7 @@ export const ConnectionStatus = { REVOKED: 'revoked' } as const -const SharedConnection = z.object({ +const BaseConnection = z.object({ id: z.string(), clientId: z.string(), provider: z.nativeEnum(Provider), @@ -33,7 +33,7 @@ export const AnchorageCredentials = z.object({ privateKey: ed25519PrivateKeySchema }) -const AnchorageConnection = SharedConnection.extend({ +const AnchorageConnection = BaseConnection.extend({ provider: z.literal(Provider.ANCHORAGE), credentials: AnchorageCredentials }) @@ -41,10 +41,14 @@ const AnchorageConnection = SharedConnection.extend({ export const Connection = AnchorageConnection export type Connection = z.infer +const RevokedConnection = Connection.omit({ + credentials: true +}) + export const Credentials = AnchorageCredentials export type Credentials = z.infer -const SharedPendingConnection = z.object({ +const BasePendingConnection = z.object({ clientId: z.string(), connectionId: z.string(), provider: z.nativeEnum(Provider), @@ -53,7 +57,7 @@ const SharedPendingConnection = z.object({ }) // TODO: (@wcalderipe, 05/12/24): Extend to other providers. -export const PendingConnection = SharedPendingConnection.extend({ +export const PendingConnection = BasePendingConnection.extend({ provider: z.literal(Provider.ANCHORAGE), publicKey: ed25519PublicKeySchema }) @@ -65,7 +69,7 @@ export const InitiateConnection = z.object({ }) export type InitiateConnection = z.infer -const SharedCreateConnection = z.object({ +const BaseCreateConnection = z.object({ connectionId: z.string().optional(), createdAt: z.date().optional(), encryptedCredentials: z.string().optional().describe('RSA encrypted JSON string of the credentials'), @@ -83,7 +87,7 @@ export const CreateCredentials = AnchorageCreateCredentials export type CreateCredentials = z.infer // TODO: (@wcalderipe, 05/12/24): Extend to other providers. -export const CreateConnection = SharedCreateConnection.extend({ +export const CreateConnection = BaseCreateConnection.extend({ provider: z.literal(Provider.ANCHORAGE), credentials: CreateCredentials.optional() }) diff --git a/apps/vault/src/broker/http/rest/controller/connection.controller.ts b/apps/vault/src/broker/http/rest/controller/connection.controller.ts index 33b2b637a..87135e00a 100644 --- a/apps/vault/src/broker/http/rest/controller/connection.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/connection.controller.ts @@ -1,4 +1,4 @@ -import { Body, Controller, HttpStatus, Post } from '@nestjs/common' +import { Body, Controller, Delete, HttpCode, HttpStatus, Param, Post } from '@nestjs/common' import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../shared/decorator/client-id.decorator' import { ConnectionService } from '../../../core/service/connection.service' @@ -51,4 +51,18 @@ export class ConnectionController { status: connection.status } } + + @Delete(':connectionId') + @ApiOperation({ + summary: 'Securely stores a provider connection' + }) + @ApiResponse({ + description: 'The stored provider connection reference', + status: HttpStatus.CREATED, + type: ConnectionDto + }) + @HttpCode(HttpStatus.NO_CONTENT) + async revoke(@ClientId() clientId: string, @Param('connectionId') connectionId: string): Promise { + await this.connectionService.revoke(clientId, connectionId) + } } diff --git a/apps/vault/src/broker/persistence/repository/connection.repository.ts b/apps/vault/src/broker/persistence/repository/connection.repository.ts index 06a4b3a95..0218dd515 100644 --- a/apps/vault/src/broker/persistence/repository/connection.repository.ts +++ b/apps/vault/src/broker/persistence/repository/connection.repository.ts @@ -1,13 +1,43 @@ import { Injectable } from '@nestjs/common' +import { Prisma, ProviderConnection } from '@prisma/client/vault' import { SetRequired } from 'type-fest' import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' import { ConnectionParseException } from '../../core/exception/connection-parse.exception' -import { Connection } from '../../core/type/connection.type' +import { Connection, Credentials } from '../../core/type/connection.type' + +type Update = SetRequired< + Partial< + Omit & { + credentials: Credentials | null + } + >, + 'id' +> @Injectable() export class ConnectionRepository { constructor(private prismaService: PrismaService) {} + static map(result: ProviderConnection): Connection { + const parse = Connection.safeParse({ + ...result, + // Prisma always returns null for optional fields that don't have a + // value, rather than undefined. This is actually by design and aligns + // with how NULL values work in databases. + label: result?.label || undefined, + revokedAt: result?.revokedAt || undefined, + url: result?.url || undefined + }) + + if (parse.success) { + return parse.data + } + + throw new ConnectionParseException({ + context: { errors: parse.error.errors } + }) + } + async create(connection: SetRequired): Promise { await this.prismaService.providerConnection.upsert({ where: { id: connection.id }, @@ -37,7 +67,7 @@ export class ConnectionRepository { return connection } - async update(connection: SetRequired, 'id'>): Promise, 'id'>> { + async update(connection: Update): Promise { await this.prismaService.providerConnection.update({ where: { id: connection.id }, data: { @@ -47,7 +77,7 @@ export class ConnectionRepository { url: connection.url, label: connection.label, status: connection.status, - credentials: connection.credentials, + credentials: connection.credentials === null ? Prisma.JsonNull : connection.credentials, integrity: connection.integrity, createdAt: connection.createdAt, updatedAt: connection.updatedAt, From fd491322d64807e5e88f79ed9103e7c7b92d13ca Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Fri, 6 Dec 2024 14:42:45 +0100 Subject: [PATCH 015/120] Add connection findAll --- .../repository/connection.repository.ts | 34 +++++++------------ 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/apps/vault/src/broker/persistence/repository/connection.repository.ts b/apps/vault/src/broker/persistence/repository/connection.repository.ts index 0218dd515..177c51193 100644 --- a/apps/vault/src/broker/persistence/repository/connection.repository.ts +++ b/apps/vault/src/broker/persistence/repository/connection.repository.ts @@ -18,15 +18,15 @@ type Update = SetRequired< export class ConnectionRepository { constructor(private prismaService: PrismaService) {} - static map(result: ProviderConnection): Connection { + static map(model?: ProviderConnection | null): Connection { const parse = Connection.safeParse({ - ...result, + ...model, // Prisma always returns null for optional fields that don't have a // value, rather than undefined. This is actually by design and aligns // with how NULL values work in databases. - label: result?.label || undefined, - revokedAt: result?.revokedAt || undefined, - url: result?.url || undefined + label: model?.label || undefined, + revokedAt: model?.revokedAt || undefined, + url: model?.url || undefined }) if (parse.success) { @@ -89,27 +89,19 @@ export class ConnectionRepository { } async findById(clientId: string, id: string): Promise { - const result = await this.prismaService.providerConnection.findUnique({ + const model = await this.prismaService.providerConnection.findUnique({ where: { clientId, id } }) - const parse = Connection.safeParse({ - ...result, - // Prisma always returns null for optional fields that don't have a - // value, rather than undefined. This is actually by design and aligns - // with how NULL values work in databases. - label: result?.label || undefined, - revokedAt: result?.revokedAt || undefined, - url: result?.url || undefined - }) - - if (parse.success) { - return parse.data - } + return ConnectionRepository.map(model) + } - throw new ConnectionParseException({ - context: { errors: parse.error.errors } + async findAll(clientId: string): Promise { + const models = await this.prismaService.providerConnection.findMany({ + where: { clientId } }) + + return models.map(ConnectionRepository.map) } async exists(clientId: string, id: string): Promise { From 6fb1cc9cbd6f43ea35a586be9ef677722fbadae9 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Fri, 6 Dec 2024 17:56:30 +0100 Subject: [PATCH 016/120] Refactor connection to have a clear boundary on statuses --- .../broker/__test__/e2e/connection.spec.ts | 88 ++++++++------- .../broker/core/service/connection.service.ts | 92 ++++++++++------ .../src/broker/core/type/connection.type.ts | 76 ++++++------- .../rest/controller/connection.controller.ts | 29 +++-- .../dto/response/pending-connection.dto.ts | 17 ++- .../repository/connection.repository.ts | 102 +++++++++--------- 6 files changed, 232 insertions(+), 172 deletions(-) diff --git a/apps/vault/src/broker/__test__/e2e/connection.spec.ts b/apps/vault/src/broker/__test__/e2e/connection.spec.ts index 1d56dcfd4..8774796b9 100644 --- a/apps/vault/src/broker/__test__/e2e/connection.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/connection.spec.ts @@ -19,8 +19,7 @@ import { load } from '../../../main.config' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { BrokerModule } from '../../broker.module' import { ConnectionService } from '../../core/service/connection.service' -import { ConnectionStatus, Provider } from '../../core/type/connection.type' -import { ConnectionRepository } from '../../persistence/repository/connection.repository' +import { ConnectionStatus, Provider, isActiveConnection, isRevokedConnection } from '../../core/type/connection.type' const toMatchZodSchema = (received: unknown, schema: ZodSchema): void => { const parse = schema.safeParse(received) @@ -43,7 +42,6 @@ const toMatchZodSchema = (received: unknown, schema: ZodSchema): void => { describe('Connection', () => { let app: INestApplication let module: TestingModule - let connectionRepository: ConnectionRepository let connectionService: ConnectionService let testPrismaService: TestPrismaService @@ -66,7 +64,6 @@ describe('Connection', () => { app = module.createNestApplication() testPrismaService = module.get(TestPrismaService) - connectionRepository = module.get(ConnectionRepository) connectionService = module.get(ConnectionService) await testPrismaService.truncateAll() @@ -104,7 +101,9 @@ describe('Connection', () => { status: ConnectionStatus.PENDING }) - toMatchZodSchema(body.publicKey, ed25519PublicKeySchema) + expect(body.credentials.privateKey).toEqual(undefined) + + toMatchZodSchema(body.credentials.publicKey, ed25519PublicKeySchema) toMatchZodSchema(body.encryptionPublicKey, rsaPublicKeySchema) expect(status).toEqual(HttpStatus.CREATED) @@ -132,7 +131,7 @@ describe('Connection', () => { .set(REQUEST_HEADER_CLIENT_ID, clientId) .send(connection) - const createdConnection = await connectionRepository.findById(clientId, connection.connectionId) + const createdConnection = await connectionService.findById(clientId, connection.connectionId) expect(body).toEqual({ connectionId, @@ -150,11 +149,10 @@ describe('Connection', () => { publicKey: getPublicKey(privateKey as Ed25519PrivateKey) }, createdAt: expect.any(Date), - id: connectionId, + connectionId, integrity: expect.any(String), label: connection.label, provider: connection.provider, - revokedAt: undefined, status: ConnectionStatus.ACTIVE, updatedAt: expect.any(Date), url: connection.url @@ -165,9 +163,7 @@ describe('Connection', () => { const connectionId = uuid() const provider = Provider.ANCHORAGE const label = 'Test Anchorage Connection' - const credentials = { - apiKey: 'test-api-key' - } + const credentials = { apiKey: 'test-api-key' } const { body: pendingConnection } = await request(app.getHttpServer()) .post('/connections/initiate') @@ -178,11 +174,11 @@ describe('Connection', () => { .post('/connections') .set(REQUEST_HEADER_CLIENT_ID, clientId) .send({ - provider, connectionId, + credentials, label, - url, - credentials + provider, + url }) expect(body).toEqual({ @@ -192,25 +188,28 @@ describe('Connection', () => { }) expect(status).toEqual(HttpStatus.CREATED) - const createdConnection = await connectionRepository.findById(clientId, connectionId) + const createdConnection = await connectionService.findById(clientId, connectionId) expect(createdConnection).toMatchObject({ clientId, - createdAt: expect.any(Date), - id: connectionId, - integrity: expect.any(String), + connectionId, label, provider, - revokedAt: undefined, + url, + createdAt: expect.any(Date), + integrity: expect.any(String), status: ConnectionStatus.ACTIVE, - updatedAt: expect.any(Date), - url + updatedAt: expect.any(Date) }) - expect(createdConnection.credentials).toMatchObject({ - apiKey: credentials.apiKey, - publicKey: pendingConnection.publicKey - }) + if (isActiveConnection(createdConnection)) { + expect(createdConnection.credentials).toMatchObject({ + apiKey: credentials.apiKey, + publicKey: pendingConnection.credentials.publicKey + }) + } else { + fail('expected an active connection') + } }) it('activates an anchorage pending connection with encrypted credentials', async () => { @@ -246,30 +245,33 @@ describe('Connection', () => { }) expect(status).toEqual(HttpStatus.CREATED) - const createdConnection = await connectionRepository.findById(clientId, connectionId) + const createdConnection = await connectionService.findById(clientId, connectionId) expect(createdConnection).toMatchObject({ clientId, - createdAt: expect.any(Date), - id: connectionId, - integrity: expect.any(String), + connectionId, label, provider, - revokedAt: undefined, + url, + createdAt: expect.any(Date), + integrity: expect.any(String), status: ConnectionStatus.ACTIVE, - updatedAt: expect.any(Date), - url + updatedAt: expect.any(Date) }) - expect(createdConnection.credentials).toMatchObject({ - apiKey: credentials.apiKey, - publicKey: pendingConnection.publicKey - }) + if (isActiveConnection(createdConnection)) { + expect(createdConnection.credentials).toMatchObject({ + apiKey: credentials.apiKey, + publicKey: pendingConnection.credentials.publicKey + }) + } else { + fail('expected an active connection') + } }) }) describe('DELETE /connections/:id', () => { - it.only('revokes an existing connection', async () => { + it('revokes an existing connection', async () => { const connection = await connectionService.create(clientId, { connectionId: uuid(), label: 'test revoke connection', @@ -282,16 +284,20 @@ describe('Connection', () => { }) const { status } = await request(app.getHttpServer()) - .delete(`/connections/${connection.id}`) + .delete(`/connections/${connection.connectionId}`) .set(REQUEST_HEADER_CLIENT_ID, clientId) .send() expect(status).toEqual(HttpStatus.NO_CONTENT) - const revokedConnection = await connectionService.findById(clientId, connection.id) + const updatedConnection = await connectionService.findById(clientId, connection.connectionId) - expect(revokedConnection?.credentials).toEqual(undefined) - expect(revokedConnection?.revokedAt).toEqual(expect.any(Date)) + if (isRevokedConnection(updatedConnection)) { + expect(updatedConnection.credentials).toEqual(null) + expect(updatedConnection.revokedAt).toEqual(expect.any(Date)) + } else { + fail('expected a revoked connection') + } }) }) }) diff --git a/apps/vault/src/broker/core/service/connection.service.ts b/apps/vault/src/broker/core/service/connection.service.ts index 75678e7ae..c9053f8d7 100644 --- a/apps/vault/src/broker/core/service/connection.service.ts +++ b/apps/vault/src/broker/core/service/connection.service.ts @@ -1,20 +1,25 @@ import { Alg, Ed25519PrivateKey, generateJwk, getPublicKey, privateKeyToJwk } from '@narval/signature' -import { Injectable, NotImplementedException } from '@nestjs/common' +import { HttpStatus, Injectable, NotImplementedException } from '@nestjs/common' import { SetRequired } from 'type-fest' import { v4 as uuid } from 'uuid' import { EncryptionKeyService } from '../../../transit-encryption/core/service/encryption-key.service' import { ConnectionRepository } from '../../persistence/repository/connection.repository' +import { BrokerException } from '../exception/broker.exception' import { InvalidConnectionPrivateKeyException } from '../exception/invalid-connection-private-key.exception' import { MissingConnectionCredentialsException } from '../exception/missing-connection-credentials.exception' import { NotFoundException } from '../exception/not-found.exception' import { + ActiveConnection, Connection, ConnectionStatus, CreateConnection, CreateCredentials, InitiateConnection, PendingConnection, - Provider + Provider, + isActiveConnection, + isPendingConnection, + isRevokedConnection } from '../type/connection.type' @Injectable() @@ -29,14 +34,15 @@ export class ConnectionService { const privateKey = await this.generatePrivateKey() const encryptionKey = await this.encryptionKeyService.generate(clientId) const connection = { + connectionId: input.connectionId || uuid(), clientId, createdAt: now, + provider: input.provider, credentials: { privateKey, publicKey: getPublicKey(privateKey) }, - id: input.connectionId || uuid(), - provider: input.provider, + encryptionPublicKey: encryptionKey.publicKey, status: ConnectionStatus.PENDING, revokedAt: undefined, updatedAt: now, @@ -48,10 +54,16 @@ export class ConnectionService { return { clientId: connection.clientId, - connectionId: connection.id, + connectionId: connection.connectionId, + integrity: connection.integrity, + createdAt: connection.createdAt, + updatedAt: connection.updatedAt, + credentials: { + privateKey, + publicKey: connection.credentials.publicKey + }, encryptionPublicKey: encryptionKey.publicKey, provider: connection.provider, - publicKey: connection.credentials.publicKey, status: connection.status } } @@ -78,7 +90,7 @@ export class ConnectionService { return await generateJwk(Alg.EDDSA) } - async create(clientId: string, input: CreateConnection): Promise { + async create(clientId: string, input: CreateConnection): Promise { // If a connection ID is provided, check if the connection already // exists. If it does, activate the connection. if (input.connectionId) { @@ -103,7 +115,7 @@ export class ConnectionService { throw new MissingConnectionCredentialsException() } - private async createActiveConnection(clientId: string, input: CreateConnection): Promise { + private async createActiveConnection(clientId: string, input: CreateConnection): Promise { // By this point, the credentials should have already been decrypted // and decoded. if (!input.credentials) { @@ -122,7 +134,7 @@ export class ConnectionService { privateKey, publicKey: getPublicKey(privateKey) }, - id: input.connectionId || uuid(), + connectionId: input.connectionId || uuid(), label: input.label, provider: input.provider, url: input.url, @@ -133,37 +145,46 @@ export class ConnectionService { integrity: 'TODO CREATE CONNECTION' } - return this.connectionRepository.create(connection) + await this.connectionRepository.create(connection) + + return connection } throw new InvalidConnectionPrivateKeyException() } - async activate(clientId: string, input: SetRequired): Promise { + async activate(clientId: string, input: SetRequired): Promise { const pendingConnection = await this.connectionRepository.findById(clientId, input.connectionId) - // TODO: Ensure the connection status is pending. - const now = new Date() + if (isPendingConnection(pendingConnection)) { + // TODO: Ensure the connection status is pending. + const now = new Date() - const credentials = await this.buildCreateCredentials(clientId, input) + const credentials = await this.buildCreateCredentials(clientId, input) - const connection = { - id: input.connectionId, - status: ConnectionStatus.ACTIVE, - label: input.label, - url: input.url, - updatedAt: now, - credentials: { - ...pendingConnection.credentials, - apiKey: credentials.apiKey - }, - // TODO: (@wcalderipe, 05/12/24): HMAC hash and signature. - integrity: 'TODO ACTIVATE CONNECTION' - } + const connection = { + connectionId: input.connectionId, + status: ConnectionStatus.ACTIVE, + label: input.label, + url: input.url, + updatedAt: now, + credentials: { + ...pendingConnection.credentials, + apiKey: credentials.apiKey + }, + // TODO: (@wcalderipe, 05/12/24): HMAC hash and signature. + integrity: 'TODO ACTIVATE CONNECTION' + } - await this.connectionRepository.update(connection) + await this.connectionRepository.update(connection) + + return { ...pendingConnection, ...connection } + } - return { ...pendingConnection, ...connection } + throw new BrokerException({ + message: "Cannot activate connection because it's not pending", + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY + }) } async exists(clientId: string, connectionId?: string): Promise { @@ -195,16 +216,23 @@ export class ConnectionService { throw new MissingConnectionCredentialsException() } - async findById(clientId: string, connectionId: string): Promise { + async findById(clientId: string, connectionId: string): Promise { return this.connectionRepository.findById(clientId, connectionId) } async revoke(clientId: string, connectionId: string): Promise { const connection = await this.connectionRepository.findById(clientId, connectionId) - if (connection) { + if (isRevokedConnection(connection)) { + throw new BrokerException({ + message: 'Connection already revoked', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY + }) + } + + if (isActiveConnection(connection) || isPendingConnection(connection)) { await this.connectionRepository.update({ - id: connectionId, + connectionId: connectionId, credentials: null, status: ConnectionStatus.REVOKED, revokedAt: new Date() diff --git a/apps/vault/src/broker/core/type/connection.type.ts b/apps/vault/src/broker/core/type/connection.type.ts index e9bac171e..455f1a865 100644 --- a/apps/vault/src/broker/core/type/connection.type.ts +++ b/apps/vault/src/broker/core/type/connection.type.ts @@ -12,83 +12,83 @@ export const ConnectionStatus = { ACTIVE: 'active', REVOKED: 'revoked' } as const +export type ConnectionStatus = (typeof ConnectionStatus)[keyof typeof ConnectionStatus] const BaseConnection = z.object({ - id: z.string(), + connectionId: z.string(), clientId: z.string(), provider: z.nativeEnum(Provider), url: z.string().url().optional(), - status: z.nativeEnum(ConnectionStatus).default(ConnectionStatus.ACTIVE), integrity: z.string(), label: z.string().optional(), + credentials: z.unknown().nullish(), createdAt: z.date(), - updatedAt: z.date(), - revokedAt: z.date().optional() + updatedAt: z.date() }) export const AnchorageCredentials = z.object({ - // NOTE: The API key is optional in the initiation flow. apiKey: z.string().optional(), publicKey: ed25519PublicKeySchema, privateKey: ed25519PrivateKeySchema }) +export type AnchorageCredentials = z.infer -const AnchorageConnection = BaseConnection.extend({ +const ActiveConnection = BaseConnection.extend({ + status: z.literal(ConnectionStatus.ACTIVE), provider: z.literal(Provider.ANCHORAGE), credentials: AnchorageCredentials }) +export type ActiveConnection = z.infer -export const Connection = AnchorageConnection -export type Connection = z.infer - -const RevokedConnection = Connection.omit({ - credentials: true +const RevokedConnection = BaseConnection.extend({ + status: z.literal(ConnectionStatus.REVOKED), + provider: z.literal(Provider.ANCHORAGE), + revokedAt: z.date() }) +export type RevokedConnection = z.infer -export const Credentials = AnchorageCredentials -export type Credentials = z.infer - -const BasePendingConnection = z.object({ - clientId: z.string(), - connectionId: z.string(), - provider: z.nativeEnum(Provider), +export const PendingConnection = BaseConnection.extend({ status: z.literal(ConnectionStatus.PENDING), - encryptionPublicKey: rsaPublicKeySchema -}) - -// TODO: (@wcalderipe, 05/12/24): Extend to other providers. -export const PendingConnection = BasePendingConnection.extend({ provider: z.literal(Provider.ANCHORAGE), - publicKey: ed25519PublicKeySchema + credentials: AnchorageCredentials, + encryptionPublicKey: rsaPublicKeySchema.optional() }) export type PendingConnection = z.infer +export const Connection = z.discriminatedUnion('status', [ActiveConnection, RevokedConnection, PendingConnection]) +export type Connection = z.infer + export const InitiateConnection = z.object({ connectionId: z.string().optional(), provider: z.nativeEnum(Provider) }) export type InitiateConnection = z.infer -const BaseCreateConnection = z.object({ - connectionId: z.string().optional(), - createdAt: z.date().optional(), - encryptedCredentials: z.string().optional().describe('RSA encrypted JSON string of the credentials'), - label: z.string().optional(), - provider: z.nativeEnum(Provider), - url: z.string().url() -}) - -const AnchorageCreateCredentials = z.object({ +export const CreateCredentials = z.object({ apiKey: z.string(), privateKey: hexSchema.optional().describe('Ed25519 private key in hex format') }) - -export const CreateCredentials = AnchorageCreateCredentials export type CreateCredentials = z.infer -// TODO: (@wcalderipe, 05/12/24): Extend to other providers. -export const CreateConnection = BaseCreateConnection.extend({ +export const CreateConnection = z.object({ + connectionId: z.string().optional(), + createdAt: z.date().optional(), + encryptedCredentials: z.string().optional().describe('RSA encrypted JSON string of the credentials'), + label: z.string().optional(), provider: z.literal(Provider.ANCHORAGE), + url: z.string().url(), credentials: CreateCredentials.optional() }) export type CreateConnection = z.infer + +export const isPendingConnection = (connection: Connection): connection is PendingConnection => { + return connection.status === ConnectionStatus.PENDING +} + +export const isActiveConnection = (connection: Connection): connection is ActiveConnection => { + return connection.status === ConnectionStatus.ACTIVE +} + +export const isRevokedConnection = (connection: Connection): connection is RevokedConnection => { + return connection.status === ConnectionStatus.REVOKED +} diff --git a/apps/vault/src/broker/http/rest/controller/connection.controller.ts b/apps/vault/src/broker/http/rest/controller/connection.controller.ts index 87135e00a..7aad775be 100644 --- a/apps/vault/src/broker/http/rest/controller/connection.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/connection.controller.ts @@ -18,35 +18,41 @@ export class ConnectionController { @Post('/initiate') @ApiOperation({ - summary: 'Initiate a connection' + summary: 'Initiate a new connection', + description: + 'This endpoint initiates a new connection by generating a public key and an encryption key for secure communication.' }) @ApiResponse({ - description: 'Connection public key and encryption key', + description: 'Returns the public key and encryption key for the initiated connection.', status: HttpStatus.CREATED, type: PendingConnectionDto }) async initiate(@ClientId() clientId: string, @Body() body: InitiateConnectionDto): Promise { - return this.connectionService.initiate(clientId, body) + const pendingConnection = await this.connectionService.initiate(clientId, body) + + return PendingConnectionDto.create(pendingConnection) } @Post() @ApiOperation({ - summary: 'Securely stores a provider connection' + summary: 'Store a provider connection securely', + description: + 'This endpoint securely stores the details of a provider connection, ensuring that all sensitive information is encrypted.' }) @ApiResponse({ - description: 'The stored provider connection reference', + description: 'Returns a reference to the stored provider connection.', status: HttpStatus.CREATED, type: ConnectionDto }) async create(@ClientId() clientId: string, @Body() body: CreateConnectionDto): Promise { const connection = await this.connectionService.create(clientId, body) - return this.toResponse(connection) + return ConnectionDto.create(this.toResponse(connection)) } private toResponse(connection: Connection) { return { - connectionId: connection.id, + connectionId: connection.connectionId, clientId: connection.clientId, status: connection.status } @@ -54,12 +60,13 @@ export class ConnectionController { @Delete(':connectionId') @ApiOperation({ - summary: 'Securely stores a provider connection' + summary: 'Revoke an existing connection', + description: + 'This endpoint revokes an existing connection, effectively terminating any ongoing communication and invalidating the connection credentials.' }) @ApiResponse({ - description: 'The stored provider connection reference', - status: HttpStatus.CREATED, - type: ConnectionDto + description: 'Indicates that the connection has been successfully revoked. No content is returned in the response.', + status: HttpStatus.NO_CONTENT }) @HttpCode(HttpStatus.NO_CONTENT) async revoke(@ClientId() clientId: string, @Param('connectionId') connectionId: string): Promise { diff --git a/apps/vault/src/broker/http/rest/dto/response/pending-connection.dto.ts b/apps/vault/src/broker/http/rest/dto/response/pending-connection.dto.ts index 02443c4de..fd151ce01 100644 --- a/apps/vault/src/broker/http/rest/dto/response/pending-connection.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/pending-connection.dto.ts @@ -1,4 +1,19 @@ +import { publicKeySchema } from '@narval/signature' import { createZodDto } from 'nestjs-zod' +import { z } from 'zod' import { PendingConnection } from '../../../../core/type/connection.type' -export class PendingConnectionDto extends createZodDto(PendingConnection) {} +export class PendingConnectionDto extends createZodDto( + PendingConnection.pick({ + clientId: true, + connectionId: true, + provider: true, + status: true, + encryptionPublicKey: true, + createdAt: true + }).extend({ + credentials: z.object({ + publicKey: publicKeySchema.optional() + }) + }) +) {} diff --git a/apps/vault/src/broker/persistence/repository/connection.repository.ts b/apps/vault/src/broker/persistence/repository/connection.repository.ts index 177c51193..6ca6afc65 100644 --- a/apps/vault/src/broker/persistence/repository/connection.repository.ts +++ b/apps/vault/src/broker/persistence/repository/connection.repository.ts @@ -1,18 +1,11 @@ -import { Injectable } from '@nestjs/common' +import { HttpStatus, Injectable } from '@nestjs/common' import { Prisma, ProviderConnection } from '@prisma/client/vault' -import { SetRequired } from 'type-fest' +import { omit } from 'lodash' import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' +import { BrokerException } from '../../core/exception/broker.exception' import { ConnectionParseException } from '../../core/exception/connection-parse.exception' -import { Connection, Credentials } from '../../core/type/connection.type' - -type Update = SetRequired< - Partial< - Omit & { - credentials: Credentials | null - } - >, - 'id' -> +import { NotFoundException } from '../../core/exception/not-found.exception' +import { Connection, ConnectionStatus } from '../../core/type/connection.type' @Injectable() export class ConnectionRepository { @@ -21,6 +14,7 @@ export class ConnectionRepository { static map(model?: ProviderConnection | null): Connection { const parse = Connection.safeParse({ ...model, + connectionId: model?.id, // Prisma always returns null for optional fields that don't have a // value, rather than undefined. This is actually by design and aligns // with how NULL values work in databases. @@ -38,62 +32,72 @@ export class ConnectionRepository { }) } - async create(connection: SetRequired): Promise { + async create(connection: Connection): Promise { + const data = { + clientId: connection.clientId, + createdAt: connection.createdAt, + credentials: connection.credentials !== null ? connection.credentials : Prisma.JsonNull, + id: connection.connectionId, + integrity: connection.integrity, + label: connection.label, + provider: connection.provider, + status: connection.status, + updatedAt: connection.updatedAt, + url: connection.url + } + await this.prismaService.providerConnection.upsert({ - where: { id: connection.id }, - update: { - url: connection.url, - label: connection.label, - status: connection.status, - credentials: connection.credentials, - integrity: connection.integrity, - updatedAt: connection.updatedAt - }, - create: { - id: connection.id, - clientId: connection.clientId, - provider: connection.provider, - url: connection.url, - label: connection.label, - status: connection.status, - credentials: connection.credentials, - integrity: connection.integrity, - createdAt: connection.createdAt, - updatedAt: connection.updatedAt, - revokedAt: connection.revokedAt - } + where: { id: connection.connectionId }, + create: data, + update: omit(data, 'id') }) return connection } - async update(connection: Update): Promise { + async update(connection: { + connectionId: string + credentials?: unknown | null + integrity?: string + label?: string + revokedAt?: Date + status?: ConnectionStatus + updatedAt?: Date + url?: string + }): Promise { + if (!connection.connectionId) { + throw new BrokerException({ + message: 'Missing connectionId', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY + }) + } + await this.prismaService.providerConnection.update({ - where: { id: connection.id }, + where: { id: connection.connectionId }, data: { - id: connection.id, - clientId: connection.clientId, - provider: connection.provider, - url: connection.url, + credentials: connection.credentials !== null ? connection.credentials : Prisma.JsonNull, + integrity: connection.integrity, label: connection.label, + revokedAt: connection.revokedAt, status: connection.status, - credentials: connection.credentials === null ? Prisma.JsonNull : connection.credentials, - integrity: connection.integrity, - createdAt: connection.createdAt, updatedAt: connection.updatedAt, - revokedAt: connection.revokedAt + url: connection.url } }) - return connection + return true } - async findById(clientId: string, id: string): Promise { + async findById(clientId: string, connectionId: string): Promise { const model = await this.prismaService.providerConnection.findUnique({ - where: { clientId, id } + where: { clientId, id: connectionId } }) - return ConnectionRepository.map(model) + if (model) { + return ConnectionRepository.map(model) + } + + throw new NotFoundException({ context: { clientId, connectionId } }) } async findAll(clientId: string): Promise { From d3fce5c7b667be0ca17343d3a42f830d39b469da Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Mon, 9 Dec 2024 16:12:18 +0100 Subject: [PATCH 017/120] List connections endpoint --- .../broker/__test__/e2e/connection.spec.ts | 41 +++++++++++++++++++ .../broker/core/service/connection.service.ts | 4 ++ .../src/broker/core/type/connection.type.ts | 2 +- .../rest/controller/connection.controller.ts | 19 ++++++++- .../rest/dto/response/connection-list.dto.ts | 7 ++++ 5 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 apps/vault/src/broker/http/rest/dto/response/connection-list.dto.ts diff --git a/apps/vault/src/broker/__test__/e2e/connection.spec.ts b/apps/vault/src/broker/__test__/e2e/connection.spec.ts index 8774796b9..a439f7733 100644 --- a/apps/vault/src/broker/__test__/e2e/connection.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/connection.spec.ts @@ -12,6 +12,7 @@ import { } from '@narval/signature' import { HttpStatus, INestApplication } from '@nestjs/common' import { Test, TestingModule } from '@nestjs/testing' +import { times } from 'lodash' import request from 'supertest' import { v4 as uuid } from 'uuid' import { ZodSchema } from 'zod' @@ -300,4 +301,44 @@ describe('Connection', () => { } }) }) + + describe('GET /connections', () => { + it('responds with connections from the given client', async () => { + await Promise.all( + times(3, async () => + connectionService.create(clientId, { + connectionId: uuid(), + label: 'test revoke connection', + provider: Provider.ANCHORAGE, + url, + credentials: { + apiKey: 'test-api-key', + privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) + } + }) + ) + ) + + const { status, body } = await request(app.getHttpServer()) + .get('/connections') + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .send() + + expect(body.connections.length).toEqual(3) + + expect(body.connections[0]).toMatchObject({ + connectionId: expect.any(String), + integrity: expect.any(String), + clientId, + createdAt: expect.any(String), + updatedAt: expect.any(String), + label: 'test revoke connection', + provider: Provider.ANCHORAGE, + url + }) + expect(body.connections[0]).not.toHaveProperty('credentials') + + expect(status).toEqual(HttpStatus.OK) + }) + }) }) diff --git a/apps/vault/src/broker/core/service/connection.service.ts b/apps/vault/src/broker/core/service/connection.service.ts index c9053f8d7..f74721ff1 100644 --- a/apps/vault/src/broker/core/service/connection.service.ts +++ b/apps/vault/src/broker/core/service/connection.service.ts @@ -220,6 +220,10 @@ export class ConnectionService { return this.connectionRepository.findById(clientId, connectionId) } + async findAll(clientId: string): Promise { + return this.connectionRepository.findAll(clientId) + } + async revoke(clientId: string, connectionId: string): Promise { const connection = await this.connectionRepository.findById(clientId, connectionId) diff --git a/apps/vault/src/broker/core/type/connection.type.ts b/apps/vault/src/broker/core/type/connection.type.ts index 455f1a865..dc5c4ce0e 100644 --- a/apps/vault/src/broker/core/type/connection.type.ts +++ b/apps/vault/src/broker/core/type/connection.type.ts @@ -14,7 +14,7 @@ export const ConnectionStatus = { } as const export type ConnectionStatus = (typeof ConnectionStatus)[keyof typeof ConnectionStatus] -const BaseConnection = z.object({ +export const BaseConnection = z.object({ connectionId: z.string(), clientId: z.string(), provider: z.nativeEnum(Provider), diff --git a/apps/vault/src/broker/http/rest/controller/connection.controller.ts b/apps/vault/src/broker/http/rest/controller/connection.controller.ts index 7aad775be..086176c26 100644 --- a/apps/vault/src/broker/http/rest/controller/connection.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/connection.controller.ts @@ -1,10 +1,11 @@ -import { Body, Controller, Delete, HttpCode, HttpStatus, Param, Post } from '@nestjs/common' +import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post } from '@nestjs/common' import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../shared/decorator/client-id.decorator' import { ConnectionService } from '../../../core/service/connection.service' import { Connection } from '../../../core/type/connection.type' import { CreateConnectionDto } from '../dto/request/create-connection.dto' import { InitiateConnectionDto } from '../dto/request/initiate-connection.dto' +import { ConnectionListDto } from '../dto/response/connection-list.dto' import { ConnectionDto } from '../dto/response/connection.dto' import { PendingConnectionDto } from '../dto/response/pending-connection.dto' @@ -72,4 +73,20 @@ export class ConnectionController { async revoke(@ClientId() clientId: string, @Param('connectionId') connectionId: string): Promise { await this.connectionService.revoke(clientId, connectionId) } + + @Get() + @ApiOperation({ + summary: 'List all connections', + description: 'This endpoint retrieves a list of all connections associated with the client.' + }) + @ApiResponse({ + description: 'Returns a list of connections associated with the client.', + type: ConnectionListDto, + status: HttpStatus.OK + }) + async list(@ClientId() clientId: string): Promise { + const connections = await this.connectionService.findAll(clientId) + + return ConnectionListDto.create({ connections }) + } } diff --git a/apps/vault/src/broker/http/rest/dto/response/connection-list.dto.ts b/apps/vault/src/broker/http/rest/dto/response/connection-list.dto.ts new file mode 100644 index 000000000..ec52976a5 --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/response/connection-list.dto.ts @@ -0,0 +1,7 @@ +import { createZodDto } from 'nestjs-zod' +import { z } from 'zod' +import { BaseConnection } from '../../../../core/type/connection.type' + +export class ConnectionListDto extends createZodDto( + z.object({ connections: z.array(BaseConnection.omit({ credentials: true })) }) +) {} From a63764ba188703d4ca12054c3a4bed01d277990a Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Mon, 9 Dec 2024 16:34:19 +0100 Subject: [PATCH 018/120] Add endpoint to get connection by ID --- .../broker/__test__/e2e/connection.spec.ts | 60 +++++++++++++++++-- .../src/broker/core/type/connection.type.ts | 13 ++-- .../rest/controller/connection.controller.ts | 28 +++++---- .../http/rest/dto/response/connection.dto.ts | 11 +--- 4 files changed, 83 insertions(+), 29 deletions(-) diff --git a/apps/vault/src/broker/__test__/e2e/connection.spec.ts b/apps/vault/src/broker/__test__/e2e/connection.spec.ts index a439f7733..1c17adc96 100644 --- a/apps/vault/src/broker/__test__/e2e/connection.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/connection.spec.ts @@ -135,9 +135,15 @@ describe('Connection', () => { const createdConnection = await connectionService.findById(clientId, connection.connectionId) expect(body).toEqual({ - connectionId, clientId, - status: ConnectionStatus.ACTIVE + connectionId, + url, + createdAt: expect.any(String), + integrity: expect.any(String), + label: connection.label, + provider: connection.provider, + status: ConnectionStatus.ACTIVE, + updatedAt: expect.any(String) }) expect(status).toEqual(HttpStatus.CREATED) @@ -185,7 +191,13 @@ describe('Connection', () => { expect(body).toEqual({ clientId, connectionId, - status: ConnectionStatus.ACTIVE + label, + provider, + url, + createdAt: expect.any(String), + integrity: 'TODO ACTIVATE CONNECTION', + status: ConnectionStatus.ACTIVE, + updatedAt: expect.any(String) }) expect(status).toEqual(HttpStatus.CREATED) @@ -242,7 +254,13 @@ describe('Connection', () => { expect(body).toEqual({ clientId, connectionId, - status: ConnectionStatus.ACTIVE + label, + provider, + url, + createdAt: expect.any(String), + integrity: 'TODO ACTIVATE CONNECTION', + status: ConnectionStatus.ACTIVE, + updatedAt: expect.any(String) }) expect(status).toEqual(HttpStatus.CREATED) @@ -341,4 +359,38 @@ describe('Connection', () => { expect(status).toEqual(HttpStatus.OK) }) }) + + describe('GET /connections/:connectionId', () => { + it('responds with the specific connection', async () => { + const connection = await connectionService.create(clientId, { + connectionId: uuid(), + label: 'test revoke connection', + provider: Provider.ANCHORAGE, + url, + credentials: { + apiKey: 'test-api-key', + privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) + } + }) + + const { status, body } = await request(app.getHttpServer()) + .get(`/connections/${connection.connectionId}`) + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .send() + + expect(body).toMatchObject({ + connectionId: expect.any(String), + integrity: expect.any(String), + clientId, + createdAt: expect.any(String), + updatedAt: expect.any(String), + label: 'test revoke connection', + provider: Provider.ANCHORAGE, + url + }) + expect(body).not.toHaveProperty('credentials') + + expect(status).toEqual(HttpStatus.OK) + }) + }) }) diff --git a/apps/vault/src/broker/core/type/connection.type.ts b/apps/vault/src/broker/core/type/connection.type.ts index dc5c4ce0e..49b6376ed 100644 --- a/apps/vault/src/broker/core/type/connection.type.ts +++ b/apps/vault/src/broker/core/type/connection.type.ts @@ -15,15 +15,16 @@ export const ConnectionStatus = { export type ConnectionStatus = (typeof ConnectionStatus)[keyof typeof ConnectionStatus] export const BaseConnection = z.object({ - connectionId: z.string(), clientId: z.string(), - provider: z.nativeEnum(Provider), - url: z.string().url().optional(), + connectionId: z.string(), + createdAt: z.date(), + credentials: z.unknown().nullish(), integrity: z.string(), label: z.string().optional(), - credentials: z.unknown().nullish(), - createdAt: z.date(), - updatedAt: z.date() + provider: z.nativeEnum(Provider), + status: z.nativeEnum(ConnectionStatus).default(ConnectionStatus.ACTIVE), + updatedAt: z.date(), + url: z.string().url().optional() }) export const AnchorageCredentials = z.object({ diff --git a/apps/vault/src/broker/http/rest/controller/connection.controller.ts b/apps/vault/src/broker/http/rest/controller/connection.controller.ts index 086176c26..1c8be0541 100644 --- a/apps/vault/src/broker/http/rest/controller/connection.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/connection.controller.ts @@ -2,7 +2,6 @@ import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post } from import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../shared/decorator/client-id.decorator' import { ConnectionService } from '../../../core/service/connection.service' -import { Connection } from '../../../core/type/connection.type' import { CreateConnectionDto } from '../dto/request/create-connection.dto' import { InitiateConnectionDto } from '../dto/request/initiate-connection.dto' import { ConnectionListDto } from '../dto/response/connection-list.dto' @@ -48,15 +47,7 @@ export class ConnectionController { async create(@ClientId() clientId: string, @Body() body: CreateConnectionDto): Promise { const connection = await this.connectionService.create(clientId, body) - return ConnectionDto.create(this.toResponse(connection)) - } - - private toResponse(connection: Connection) { - return { - connectionId: connection.connectionId, - clientId: connection.clientId, - status: connection.status - } + return ConnectionDto.create(connection) } @Delete(':connectionId') @@ -89,4 +80,21 @@ export class ConnectionController { return ConnectionListDto.create({ connections }) } + + @Get(':connectionId') + @ApiOperation({ + summary: 'Retrieve a specific connection by ID', + description: + 'This endpoint retrieves the details of a specific connection associated with the client, identified by the ID.' + }) + @ApiResponse({ + description: 'Returns the details of the specified connection.', + type: ConnectionDto, + status: HttpStatus.OK + }) + async getById(@ClientId() clientId: string, @Param('connectionId') connectionId: string): Promise { + const connection = await this.connectionService.findById(clientId, connectionId) + + return ConnectionDto.create(connection) + } } diff --git a/apps/vault/src/broker/http/rest/dto/response/connection.dto.ts b/apps/vault/src/broker/http/rest/dto/response/connection.dto.ts index dca6e53c1..4f6b7f0ec 100644 --- a/apps/vault/src/broker/http/rest/dto/response/connection.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/connection.dto.ts @@ -1,11 +1,4 @@ import { createZodDto } from 'nestjs-zod' -import { z } from 'zod' -import { ConnectionStatus } from '../../../../core/type/connection.type' +import { BaseConnection } from '../../../../core/type/connection.type' -export class ConnectionDto extends createZodDto( - z.object({ - connectionId: z.string(), - clientId: z.string(), - status: z.nativeEnum(ConnectionStatus) - }) -) {} +export class ConnectionDto extends createZodDto(BaseConnection.omit({ credentials: true })) {} From cf6ba8fd2c47167756133d018771b2b428eba39b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 16:59:07 +0000 Subject: [PATCH 019/120] Bump @nestjs/platform-express from 10.3.9 to 10.4.15 Bumps [@nestjs/platform-express](https://github.com/nestjs/nest/tree/HEAD/packages/platform-express) from 10.3.9 to 10.4.15. - [Release notes](https://github.com/nestjs/nest/releases) - [Commits](https://github.com/nestjs/nest/commits/v10.4.15/packages/platform-express) --- updated-dependencies: - dependency-name: "@nestjs/platform-express" dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 213 +++++++++++++++++++++++++++++++++++++++++++--- package.json | 2 +- 2 files changed, 203 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index 39d7f87ab..1c0c647cc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,7 @@ "@nestjs/common": "10.3.10", "@nestjs/config": "3.1.1", "@nestjs/core": "10.4.7", - "@nestjs/platform-express": "10.3.9", + "@nestjs/platform-express": "10.4.15", "@nestjs/swagger": "7.4.0", "@noble/curves": "1.6.0", "@noble/ed25519": "1.7.1", @@ -6836,15 +6836,15 @@ } }, "node_modules/@nestjs/platform-express": { - "version": "10.3.9", - "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.3.9.tgz", - "integrity": "sha512-si/UzobP6YUtYtCT1cSyQYHHzU3yseqYT6l7OHSMVvfG1+TqxaAqI6nmrix02LO+l1YntHRXEs3p+v9a7EfrSQ==", + "version": "10.4.15", + "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.4.15.tgz", + "integrity": "sha512-63ZZPkXHjoDyO7ahGOVcybZCRa7/Scp6mObQKjcX/fTEq1YJeU75ELvMsuQgc8U2opMGOBD7GVuc4DV0oeDHoA==", "dependencies": { - "body-parser": "1.20.2", + "body-parser": "1.20.3", "cors": "2.8.5", - "express": "4.19.2", + "express": "4.21.2", "multer": "1.4.4-lts.1", - "tslib": "2.6.2" + "tslib": "2.8.1" }, "funding": { "type": "opencollective", @@ -6855,10 +6855,201 @@ "@nestjs/core": "^10.0.0" } }, + "node_modules/@nestjs/platform-express/node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/@nestjs/platform-express/node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@nestjs/platform-express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/@nestjs/platform-express/node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/@nestjs/platform-express/node_modules/express": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.12", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@nestjs/platform-express/node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/@nestjs/platform-express/node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@nestjs/platform-express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/@nestjs/platform-express/node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" + }, + "node_modules/@nestjs/platform-express/node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/@nestjs/platform-express/node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/@nestjs/platform-express/node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/@nestjs/platform-express/node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/@nestjs/platform-express/node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/@nestjs/platform-express/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "node_modules/@nestjs/schematics": { "version": "9.2.0", @@ -45267,7 +45458,7 @@ }, "packages/armory-sdk": { "name": "@narval-xyz/armory-sdk", - "version": "0.9.1", + "version": "0.10.0", "license": "MPL-2.0", "dependencies": { "@noble/curves": "1.6.0", diff --git a/package.json b/package.json index 4d411845a..e5c984790 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "@nestjs/common": "10.3.10", "@nestjs/config": "3.1.1", "@nestjs/core": "10.4.7", - "@nestjs/platform-express": "10.3.9", + "@nestjs/platform-express": "10.4.15", "@nestjs/swagger": "7.4.0", "@noble/curves": "1.6.0", "@noble/ed25519": "1.7.1", From 350eedbca81febb69234dfeca9e4015b2c4fb632 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 16:59:38 +0000 Subject: [PATCH 020/120] Bump axios-retry from 4.4.2 to 4.5.0 Bumps [axios-retry](https://github.com/softonic/axios-retry) from 4.4.2 to 4.5.0. - [Changelog](https://github.com/softonic/axios-retry/blob/master/CHANGELOG.md) - [Commits](https://github.com/softonic/axios-retry/compare/v4.4.2...v4.5.0) --- updated-dependencies: - dependency-name: axios-retry dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 10 +++++----- package.json | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 39d7f87ab..10066f40d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54,7 +54,7 @@ "@scure/bip39": "1.3.0", "@tanstack/react-query": "5.51.11", "axios": "1.7.7", - "axios-retry": "4.4.2", + "axios-retry": "4.5.0", "bull": "4.16.4", "class-transformer": "0.5.1", "class-validator": "0.14.1", @@ -21587,9 +21587,9 @@ } }, "node_modules/axios-retry": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-4.4.2.tgz", - "integrity": "sha512-2fjo9uDNBQjX8+GMEGOFG5TrLMZ3QijjeRYcgBI2MhrsabnvcIAfLxxIhG7+CCD68vPEQY3IM2llV70ZsrqPvA==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-4.5.0.tgz", + "integrity": "sha512-aR99oXhpEDGo0UuAlYcn2iGRds30k366Zfa05XWScR9QaQD4JYiP3/1Qt1u7YlefUOK+cn0CcwoL1oefavQUlQ==", "dependencies": { "is-retry-allowed": "^2.2.0" }, @@ -45267,7 +45267,7 @@ }, "packages/armory-sdk": { "name": "@narval-xyz/armory-sdk", - "version": "0.9.1", + "version": "0.10.0", "license": "MPL-2.0", "dependencies": { "@noble/curves": "1.6.0", diff --git a/package.json b/package.json index 4d411845a..217c7bc86 100644 --- a/package.json +++ b/package.json @@ -113,7 +113,7 @@ "@scure/bip39": "1.3.0", "@tanstack/react-query": "5.51.11", "axios": "1.7.7", - "axios-retry": "4.4.2", + "axios-retry": "4.5.0", "bull": "4.16.4", "class-transformer": "0.5.1", "class-validator": "0.14.1", From 94842fe9979c9c825d9213d0b96b2e5f1819d99b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 17:00:01 +0000 Subject: [PATCH 021/120] Bump @openapitools/openapi-generator-cli from 2.13.4 to 2.15.3 Bumps [@openapitools/openapi-generator-cli](https://github.com/OpenAPITools/openapi-generator-cli) from 2.13.4 to 2.15.3. - [Release notes](https://github.com/OpenAPITools/openapi-generator-cli/releases) - [Changelog](https://github.com/OpenAPITools/openapi-generator-cli/blob/master/.releaserc) - [Commits](https://github.com/OpenAPITools/openapi-generator-cli/compare/v2.13.4...v2.15.3) --- updated-dependencies: - dependency-name: "@openapitools/openapi-generator-cli" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 367 ++++++++++++++++++++++++++++++++++++++++------ package.json | 2 +- 2 files changed, 321 insertions(+), 48 deletions(-) diff --git a/package-lock.json b/package-lock.json index 39d7f87ab..af74d3c62 100644 --- a/package-lock.json +++ b/package-lock.json @@ -104,7 +104,7 @@ "@nx/node": "19.2.0", "@nx/webpack": "19.6.3", "@nx/workspace": "19.7.3", - "@openapitools/openapi-generator-cli": "2.13.4", + "@openapitools/openapi-generator-cli": "2.15.3", "@swc-node/register": "1.10.9", "@swc/core": "1.7.26", "@swc/helpers": "0.5.11", @@ -12012,50 +12012,61 @@ } }, "node_modules/@openapitools/openapi-generator-cli": { - "version": "2.13.4", - "resolved": "https://registry.npmjs.org/@openapitools/openapi-generator-cli/-/openapi-generator-cli-2.13.4.tgz", - "integrity": "sha512-4JKyrk55ohQK2FcuZbPdNvxdyXD14jjOIvE8hYjJ+E1cHbRbfXQXbYnjTODFE52Gx8eAxz8C9icuhDYDLn7nww==", + "version": "2.15.3", + "resolved": "https://registry.npmjs.org/@openapitools/openapi-generator-cli/-/openapi-generator-cli-2.15.3.tgz", + "integrity": "sha512-2UBnsDlMt36thhdXxisbA1qReVtbCaw+NCvXoslRXlaJBL4qkAmZUhNeDLNu3LCbwA2PASMWhJSqeLwgwMCitw==", "dev": true, "hasInstallScript": true, "dependencies": { - "@nestjs/axios": "3.0.2", - "@nestjs/common": "10.3.0", - "@nestjs/core": "10.3.0", + "@nestjs/axios": "3.1.1", + "@nestjs/common": "10.4.6", + "@nestjs/core": "10.4.6", "@nuxtjs/opencollective": "0.3.2", - "axios": "1.6.8", + "axios": "1.7.7", "chalk": "4.1.2", "commander": "8.3.0", "compare-versions": "4.1.4", "concurrently": "6.5.1", "console.table": "0.10.0", "fs-extra": "10.1.0", - "glob": "7.2.3", - "https-proxy-agent": "7.0.4", + "glob": "9.3.5", "inquirer": "8.2.6", "lodash": "4.17.21", + "proxy-agent": "6.4.0", "reflect-metadata": "0.1.13", "rxjs": "7.8.1", - "tslib": "2.6.2" + "tslib": "2.8.1" }, "bin": { "openapi-generator-cli": "main.js" }, "engines": { - "node": ">=10.0.0" + "node": ">=16" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/openapi_generator" } }, + "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/axios": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-3.1.1.tgz", + "integrity": "sha512-ySoxrzqX80P1q6LKLKGcgyBd2utg4gbC+4FsJNpXYvILorMlxss/ECNogD9EXLCE4JS5exVFD5ez0nK5hXcNTQ==", + "dev": true, + "peerDependencies": { + "@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0", + "axios": "^1.3.1", + "rxjs": "^6.0.0 || ^7.0.0" + } + }, "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/common": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.3.0.tgz", - "integrity": "sha512-DGv34UHsZBxCM3H5QGE2XE/+oLJzz5+714JQjBhjD9VccFlQs3LRxo/epso4l7nJIiNlZkPyIUC8WzfU/5RTsQ==", + "version": "10.4.6", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.4.6.tgz", + "integrity": "sha512-KkezkZvU9poWaNq4L+lNvx+386hpOxPJkfXBBeSMrcqBOx8kVr36TGN2uYkF4Ta4zNu1KbCjmZbc0rhHSg296g==", "dev": true, "dependencies": { "iterare": "1.2.1", - "tslib": "2.6.2", + "tslib": "2.7.0", "uid": "2.0.2" }, "funding": { @@ -12065,7 +12076,7 @@ "peerDependencies": { "class-transformer": "*", "class-validator": "*", - "reflect-metadata": "^0.1.12", + "reflect-metadata": "^0.1.12 || ^0.2.0", "rxjs": "^7.1.0" }, "peerDependenciesMeta": { @@ -12077,18 +12088,24 @@ } } }, + "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/common/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + }, "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/core": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.3.0.tgz", - "integrity": "sha512-N06P5ncknW/Pm8bj964WvLIZn2gNhHliCBoAO1LeBvNImYkecqKcrmLbY49Fa1rmMfEM3MuBHeDys3edeuYAOA==", + "version": "10.4.6", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.4.6.tgz", + "integrity": "sha512-zXVPxCNRfO6gAy0yvEDjUxE/8gfZICJFpsl2lZAUH31bPb6m+tXuhUq2mVCTEltyMYQ+DYtRe+fEYM2v152N1g==", "dev": true, "hasInstallScript": true, "dependencies": { "@nuxtjs/opencollective": "0.3.2", "fast-safe-stringify": "2.1.1", "iterare": "1.2.1", - "path-to-regexp": "3.2.0", - "tslib": "2.6.2", + "path-to-regexp": "3.3.0", + "tslib": "2.7.0", "uid": "2.0.2" }, "funding": { @@ -12100,7 +12117,7 @@ "@nestjs/microservices": "^10.0.0", "@nestjs/platform-express": "^10.0.0", "@nestjs/websockets": "^10.0.0", - "reflect-metadata": "^0.1.12", + "reflect-metadata": "^0.1.12 || ^0.2.0", "rxjs": "^7.1.0" }, "peerDependenciesMeta": { @@ -12115,16 +12132,11 @@ } } }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/axios": { - "version": "1.6.8", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", - "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", - "dev": true, - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } + "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/core/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true }, "node_modules/@openapitools/openapi-generator-cli/node_modules/commander": { "version": "8.3.0", @@ -12149,6 +12161,54 @@ "node": ">=12" } }, + "node_modules/@openapitools/openapi-generator-cli/node_modules/glob": { + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", + "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "minimatch": "^8.0.2", + "minipass": "^4.2.4", + "path-scurry": "^1.6.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@openapitools/openapi-generator-cli/node_modules/minimatch": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", + "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@openapitools/openapi-generator-cli/node_modules/minipass": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", + "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@openapitools/openapi-generator-cli/node_modules/path-to-regexp": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.3.0.tgz", + "integrity": "sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==", + "dev": true + }, "node_modules/@openapitools/openapi-generator-cli/node_modules/reflect-metadata": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", @@ -12156,9 +12216,9 @@ "dev": true }, "node_modules/@openapitools/openapi-generator-cli/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true }, "node_modules/@opentelemetry/api": { @@ -19114,6 +19174,12 @@ "node": ">= 10" } }, + "node_modules/@tootallnate/quickjs-emscripten": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", + "dev": true + }, "node_modules/@trysound/sax": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", @@ -20974,12 +21040,9 @@ } }, "node_modules/agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dependencies": { - "debug": "^4.3.4" - }, + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", "engines": { "node": ">= 14" } @@ -21895,6 +21958,15 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, + "node_modules/basic-ftp": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", + "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", @@ -24268,6 +24340,15 @@ "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", "dev": true }, + "node_modules/data-uri-to-buffer": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", + "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", + "dev": true, + "engines": { + "node": ">= 14" + } + }, "node_modules/data-urls": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", @@ -24586,6 +24667,32 @@ "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==" }, + "node_modules/degenerator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", + "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", + "dev": true, + "dependencies": { + "ast-types": "^0.13.4", + "escodegen": "^2.1.0", + "esprima": "^4.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/degenerator/node_modules/ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "dev": true, + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/del": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", @@ -27810,6 +27917,20 @@ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, + "node_modules/get-uri": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.4.tgz", + "integrity": "sha512-E1b1lFFLvLgak2whF2xDBcOy6NLVGZBqqjJjsIhvopKfWWEi64pLVTWWehV8KlLerZkfNTA95sTe2OdJKm1OzQ==", + "dev": true, + "dependencies": { + "basic-ftp": "^5.0.2", + "data-uri-to-buffer": "^6.0.2", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/github-slugger": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.5.0.tgz", @@ -28940,11 +29061,11 @@ } }, "node_modules/https-proxy-agent": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", - "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "dependencies": { - "agent-base": "^7.0.2", + "agent-base": "^7.1.2", "debug": "4" }, "engines": { @@ -29359,6 +29480,19 @@ "url": "https://opencollective.com/ioredis" } }, + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "dev": true, + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -31314,6 +31448,12 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "dev": true + }, "node_modules/jsc-android": { "version": "250231.0.0", "resolved": "https://registry.npmjs.org/jsc-android/-/jsc-android-250231.0.0.tgz", @@ -35971,6 +36111,15 @@ } } }, + "node_modules/netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/next": { "version": "14.2.4", "resolved": "https://registry.npmjs.org/next/-/next-14.2.4.tgz", @@ -36938,6 +37087,51 @@ "node": ">=6" } }, + "node_modules/pac-proxy-agent": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.1.0.tgz", + "integrity": "sha512-Z5FnLVVZSnX7WjBg0mhDtydeRZ1xMcATZThjySQUHqr+0ksP8kqaw23fNKkaaN/Z8gwLUs/W7xdl0I75eP2Xyw==", + "dev": true, + "dependencies": { + "@tootallnate/quickjs-emscripten": "^0.23.0", + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "get-uri": "^6.0.1", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.6", + "pac-resolver": "^7.0.1", + "socks-proxy-agent": "^8.0.5" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-proxy-agent/node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-resolver": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", + "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", + "dev": true, + "dependencies": { + "degenerator": "^5.0.0", + "netmask": "^2.0.2" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/package-json": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/package-json/-/package-json-8.1.1.tgz", @@ -38512,6 +38706,47 @@ "node": ">= 0.10" } }, + "node_modules/proxy-agent": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz", + "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==", + "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.1", + "https-proxy-agent": "^7.0.3", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.0.1", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/proxy-compare": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-2.5.1.tgz", @@ -41157,6 +41392,16 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, "node_modules/snake-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", @@ -41210,6 +41455,34 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/socks": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "dev": true, + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", + "dev": true, + "dependencies": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "socks": "^2.8.3" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/sonic-boom": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-2.8.0.tgz", @@ -45267,7 +45540,7 @@ }, "packages/armory-sdk": { "name": "@narval-xyz/armory-sdk", - "version": "0.9.1", + "version": "0.10.0", "license": "MPL-2.0", "dependencies": { "@noble/curves": "1.6.0", diff --git a/package.json b/package.json index 4d411845a..4727e17c2 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "@nx/node": "19.2.0", "@nx/webpack": "19.6.3", "@nx/workspace": "19.7.3", - "@openapitools/openapi-generator-cli": "2.13.4", + "@openapitools/openapi-generator-cli": "2.15.3", "@swc-node/register": "1.10.9", "@swc/core": "1.7.26", "@swc/helpers": "0.5.11", From 33416895f02d8aeba5feef4379bba6fdf0ea353b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 17:00:20 +0000 Subject: [PATCH 022/120] Bump dotenv from 16.4.5 to 16.4.7 Bumps [dotenv](https://github.com/motdotla/dotenv) from 16.4.5 to 16.4.7. - [Changelog](https://github.com/motdotla/dotenv/blob/master/CHANGELOG.md) - [Commits](https://github.com/motdotla/dotenv/compare/v16.4.5...v16.4.7) --- updated-dependencies: - dependency-name: dotenv dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package-lock.json | 10 +++++----- package.json | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 39d7f87ab..8565fb564 100644 --- a/package-lock.json +++ b/package-lock.json @@ -123,7 +123,7 @@ "@typescript-eslint/parser": "7.9.0", "autoprefixer": "10.4.20", "babel-jest": "29.7.0", - "dotenv": "16.4.5", + "dotenv": "16.4.7", "dotenv-cli": "7.3.0", "eslint": "8.57.0", "eslint-config-next": "14.2.6", @@ -24944,9 +24944,9 @@ } }, "node_modules/dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", "dev": true, "engines": { "node": ">=12" @@ -45267,7 +45267,7 @@ }, "packages/armory-sdk": { "name": "@narval-xyz/armory-sdk", - "version": "0.9.1", + "version": "0.10.0", "license": "MPL-2.0", "dependencies": { "@noble/curves": "1.6.0", diff --git a/package.json b/package.json index 4d411845a..84047d7ba 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "@typescript-eslint/parser": "7.9.0", "autoprefixer": "10.4.20", "babel-jest": "29.7.0", - "dotenv": "16.4.5", + "dotenv": "16.4.7", "dotenv-cli": "7.3.0", "eslint": "8.57.0", "eslint-config-next": "14.2.6", From 280054b8b86af7a0b89f5648b80e9f84baa134c0 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Tue, 10 Dec 2024 10:29:28 +0100 Subject: [PATCH 023/120] Add update connection endpoint --- .../broker/__test__/e2e/connection.spec.ts | 73 ++++++- .../connection-already-revoked.exception.ts | 12 ++ ...nnection-invalid-credentials.exception.ts} | 4 +- ...nnection-invalid-private-key.exception.ts} | 2 +- .../broker/core/exception/update.exception.ts | 13 ++ .../broker/core/service/connection.service.ts | 184 ++++++++++++++---- .../src/broker/core/type/connection.type.ts | 15 +- .../rest/controller/connection.controller.ts | 25 ++- .../rest/dto/request/update-connection.dto.ts | 10 + .../repository/connection.repository.ts | 44 +++-- apps/vault/src/main.module.ts | 4 +- 11 files changed, 308 insertions(+), 78 deletions(-) create mode 100644 apps/vault/src/broker/core/exception/connection-already-revoked.exception.ts rename apps/vault/src/broker/core/exception/{missing-connection-credentials.exception.ts => connection-invalid-credentials.exception.ts} (76%) rename apps/vault/src/broker/core/exception/{invalid-connection-private-key.exception.ts => connection-invalid-private-key.exception.ts} (88%) create mode 100644 apps/vault/src/broker/core/exception/update.exception.ts create mode 100644 apps/vault/src/broker/http/rest/dto/request/update-connection.dto.ts diff --git a/apps/vault/src/broker/__test__/e2e/connection.spec.ts b/apps/vault/src/broker/__test__/e2e/connection.spec.ts index 1c17adc96..29e714427 100644 --- a/apps/vault/src/broker/__test__/e2e/connection.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/connection.spec.ts @@ -18,9 +18,16 @@ import { v4 as uuid } from 'uuid' import { ZodSchema } from 'zod' import { load } from '../../../main.config' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' +import { EncryptionKeyService } from '../../../transit-encryption/core/service/encryption-key.service' import { BrokerModule } from '../../broker.module' import { ConnectionService } from '../../core/service/connection.service' -import { ConnectionStatus, Provider, isActiveConnection, isRevokedConnection } from '../../core/type/connection.type' +import { + ActiveConnection, + ConnectionStatus, + Provider, + isActiveConnection, + isRevokedConnection +} from '../../core/type/connection.type' const toMatchZodSchema = (received: unknown, schema: ZodSchema): void => { const parse = schema.safeParse(received) @@ -44,6 +51,7 @@ describe('Connection', () => { let app: INestApplication let module: TestingModule let connectionService: ConnectionService + let encryptionKeyService: EncryptionKeyService let testPrismaService: TestPrismaService const url = 'http://provider.narval.xyz' @@ -66,6 +74,7 @@ describe('Connection', () => { testPrismaService = module.get(TestPrismaService) connectionService = module.get(ConnectionService) + encryptionKeyService = module.get(EncryptionKeyService) await testPrismaService.truncateAll() @@ -293,7 +302,7 @@ describe('Connection', () => { it('revokes an existing connection', async () => { const connection = await connectionService.create(clientId, { connectionId: uuid(), - label: 'test revoke connection', + label: 'test connection', provider: Provider.ANCHORAGE, url, credentials: { @@ -326,7 +335,7 @@ describe('Connection', () => { times(3, async () => connectionService.create(clientId, { connectionId: uuid(), - label: 'test revoke connection', + label: 'test connection', provider: Provider.ANCHORAGE, url, credentials: { @@ -345,14 +354,14 @@ describe('Connection', () => { expect(body.connections.length).toEqual(3) expect(body.connections[0]).toMatchObject({ - connectionId: expect.any(String), - integrity: expect.any(String), clientId, + url, + connectionId: expect.any(String), createdAt: expect.any(String), - updatedAt: expect.any(String), - label: 'test revoke connection', + integrity: expect.any(String), + label: expect.any(String), provider: Provider.ANCHORAGE, - url + updatedAt: expect.any(String) }) expect(body.connections[0]).not.toHaveProperty('credentials') @@ -364,7 +373,7 @@ describe('Connection', () => { it('responds with the specific connection', async () => { const connection = await connectionService.create(clientId, { connectionId: uuid(), - label: 'test revoke connection', + label: 'test connection', provider: Provider.ANCHORAGE, url, credentials: { @@ -384,7 +393,7 @@ describe('Connection', () => { clientId, createdAt: expect.any(String), updatedAt: expect.any(String), - label: 'test revoke connection', + label: 'test connection', provider: Provider.ANCHORAGE, url }) @@ -393,4 +402,48 @@ describe('Connection', () => { expect(status).toEqual(HttpStatus.OK) }) }) + + describe('PATCH /connections/:connectionId', () => { + it('updates the given connection', async () => { + const connection = await connectionService.create(clientId, { + connectionId: uuid(), + label: 'test connection', + provider: Provider.ANCHORAGE, + url, + credentials: { + apiKey: 'test-api-key', + privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) + } + }) + const newPrivateKey = await generateJwk(Alg.EDDSA) + const newCredentials = { + apiKey: 'new-api-key', + privateKey: await privateKeyToHex(newPrivateKey) + } + const encryptionKey = await encryptionKeyService.generate(clientId, { modulusLenght: 2048 }) + const encryptedCredentials = await rsaEncrypt(JSON.stringify(newCredentials), encryptionKey.publicKey) + + const { status, body } = await request(app.getHttpServer()) + .patch(`/connections/${connection.connectionId}`) + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .send({ + label: 'new label', + encryptedCredentials + }) + + expect(body).toMatchObject({ label: 'new label' }) + expect(body).not.toHaveProperty('credentials') + + expect(status).toEqual(HttpStatus.OK) + + const updatedConnection = (await connectionService.findById( + clientId, + connection.connectionId + )) as ActiveConnection + + expect(updatedConnection.credentials.apiKey).toEqual(newCredentials.apiKey) + expect(updatedConnection.credentials.privateKey).toEqual(newPrivateKey) + expect(updatedConnection.credentials.publicKey).toEqual(getPublicKey(newPrivateKey as Ed25519PrivateKey)) + }) + }) }) diff --git a/apps/vault/src/broker/core/exception/connection-already-revoked.exception.ts b/apps/vault/src/broker/core/exception/connection-already-revoked.exception.ts new file mode 100644 index 000000000..fe82ec7d0 --- /dev/null +++ b/apps/vault/src/broker/core/exception/connection-already-revoked.exception.ts @@ -0,0 +1,12 @@ +import { HttpStatus } from '@nestjs/common' +import { BrokerException } from './broker.exception' + +export class ConnectionAlreadyRevokedException extends BrokerException { + constructor(context: { clientId: string; connectionId: string }) { + super({ + message: 'Connection already revoked', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, + context + }) + } +} diff --git a/apps/vault/src/broker/core/exception/missing-connection-credentials.exception.ts b/apps/vault/src/broker/core/exception/connection-invalid-credentials.exception.ts similarity index 76% rename from apps/vault/src/broker/core/exception/missing-connection-credentials.exception.ts rename to apps/vault/src/broker/core/exception/connection-invalid-credentials.exception.ts index 169d96426..c62754fb2 100644 --- a/apps/vault/src/broker/core/exception/missing-connection-credentials.exception.ts +++ b/apps/vault/src/broker/core/exception/connection-invalid-credentials.exception.ts @@ -2,10 +2,10 @@ import { HttpStatus } from '@nestjs/common' import { ApplicationExceptionParams } from '../../../shared/exception/application.exception' import { BrokerException } from './broker.exception' -export class MissingConnectionCredentialsException extends BrokerException { +export class ConnectionInvalidCredentialsException extends BrokerException { constructor(params?: Partial) { super({ - message: params?.message || 'Missing connection credentials', + message: params?.message || 'Invalid connection credentials', suggestedHttpStatusCode: params?.suggestedHttpStatusCode || HttpStatus.UNPROCESSABLE_ENTITY, ...params }) diff --git a/apps/vault/src/broker/core/exception/invalid-connection-private-key.exception.ts b/apps/vault/src/broker/core/exception/connection-invalid-private-key.exception.ts similarity index 88% rename from apps/vault/src/broker/core/exception/invalid-connection-private-key.exception.ts rename to apps/vault/src/broker/core/exception/connection-invalid-private-key.exception.ts index c5984d291..03ab5b711 100644 --- a/apps/vault/src/broker/core/exception/invalid-connection-private-key.exception.ts +++ b/apps/vault/src/broker/core/exception/connection-invalid-private-key.exception.ts @@ -2,7 +2,7 @@ import { HttpStatus } from '@nestjs/common' import { ApplicationExceptionParams } from '../../../shared/exception/application.exception' import { BrokerException } from './broker.exception' -export class InvalidConnectionPrivateKeyException extends BrokerException { +export class ConnectionInvalidPrivateKeyException extends BrokerException { constructor(params?: Partial) { super({ message: params?.message || 'Invalid connection credential private key type', diff --git a/apps/vault/src/broker/core/exception/update.exception.ts b/apps/vault/src/broker/core/exception/update.exception.ts new file mode 100644 index 000000000..c58474722 --- /dev/null +++ b/apps/vault/src/broker/core/exception/update.exception.ts @@ -0,0 +1,13 @@ +import { HttpStatus } from '@nestjs/common' +import { ApplicationExceptionParams } from '../../../shared/exception/application.exception' +import { BrokerException } from './broker.exception' + +export class UpdateException extends BrokerException { + constructor(params?: Partial) { + super({ + message: params?.message || 'Failed to update model', + suggestedHttpStatusCode: params?.suggestedHttpStatusCode || HttpStatus.INTERNAL_SERVER_ERROR, + ...params + }) + } +} diff --git a/apps/vault/src/broker/core/service/connection.service.ts b/apps/vault/src/broker/core/service/connection.service.ts index f74721ff1..2b53c11b9 100644 --- a/apps/vault/src/broker/core/service/connection.service.ts +++ b/apps/vault/src/broker/core/service/connection.service.ts @@ -1,15 +1,26 @@ -import { Alg, Ed25519PrivateKey, generateJwk, getPublicKey, privateKeyToJwk } from '@narval/signature' +import { + Alg, + Ed25519PrivateKey, + Ed25519PublicKey, + Hex, + generateJwk, + getPublicKey, + privateKeyToJwk +} from '@narval/signature' import { HttpStatus, Injectable, NotImplementedException } from '@nestjs/common' import { SetRequired } from 'type-fest' import { v4 as uuid } from 'uuid' import { EncryptionKeyService } from '../../../transit-encryption/core/service/encryption-key.service' import { ConnectionRepository } from '../../persistence/repository/connection.repository' import { BrokerException } from '../exception/broker.exception' -import { InvalidConnectionPrivateKeyException } from '../exception/invalid-connection-private-key.exception' -import { MissingConnectionCredentialsException } from '../exception/missing-connection-credentials.exception' +import { ConnectionAlreadyRevokedException } from '../exception/connection-already-revoked.exception' +import { ConnectionInvalidCredentialsException } from '../exception/connection-invalid-credentials.exception' +import { ConnectionInvalidPrivateKeyException } from '../exception/connection-invalid-private-key.exception' import { NotFoundException } from '../exception/not-found.exception' +import { UpdateException } from '../exception/update.exception' import { ActiveConnection, + AnchorageCredentials, Connection, ConnectionStatus, CreateConnection, @@ -17,6 +28,7 @@ import { InitiateConnection, PendingConnection, Provider, + UpdateConnection, isActiveConnection, isPendingConnection, isRevokedConnection @@ -68,31 +80,14 @@ export class ConnectionService { } } - // TODO: (@wcalderipe, 05/12/24): The return type is Anchorage specific. - private async getPrivateKey({ provider, credentials }: CreateConnection): Promise { - if (!credentials) { - throw new MissingConnectionCredentialsException() - } - - if (provider === Provider.ANCHORAGE) { - if (credentials.privateKey) { - return privateKeyToJwk(credentials.privateKey, Alg.EDDSA) - } - - return await generateJwk(Alg.EDDSA) - } - - throw new NotImplementedException(`Unsupported provider private key getter: ${provider}`) - } - // TODO: (@wcalderipe, 05/12/24): The return type is Anchorage specific. private async generatePrivateKey(): Promise { return await generateJwk(Alg.EDDSA) } async create(clientId: string, input: CreateConnection): Promise { - // If a connection ID is provided, check if the connection already - // exists. If it does, activate the connection. + // If a connection ID is provided, check if the connection already exists. + // If it does, activate the connection. if (input.connectionId) { if (await this.connectionRepository.exists(clientId, input.connectionId)) { return this.activate(clientId, { @@ -107,23 +102,23 @@ export class ConnectionService { } if (input.encryptedCredentials) { - const credentials = await this.buildCreateCredentials(clientId, input) + const credentials = await this.getInputCredentials(clientId, input) return this.createActiveConnection(clientId, { ...input, credentials }) } - throw new MissingConnectionCredentialsException() + throw new ConnectionInvalidCredentialsException() } private async createActiveConnection(clientId: string, input: CreateConnection): Promise { - // By this point, the credentials should have already been decrypted - // and decoded. + // By this point, the credentials should have already been decrypted and + // decoded. if (!input.credentials) { - throw new MissingConnectionCredentialsException() + throw new ConnectionInvalidCredentialsException() } const now = new Date() - const privateKey = await this.getPrivateKey(input) + const { privateKey, publicKey } = await this.parseInputCredentials(clientId, input.provider, input) if (privateKey.kty) { const connection = { @@ -132,7 +127,7 @@ export class ConnectionService { credentials: { apiKey: input.credentials.apiKey, privateKey, - publicKey: getPublicKey(privateKey) + publicKey }, connectionId: input.connectionId || uuid(), label: input.label, @@ -150,7 +145,7 @@ export class ConnectionService { return connection } - throw new InvalidConnectionPrivateKeyException() + throw new ConnectionInvalidPrivateKeyException() } async activate(clientId: string, input: SetRequired): Promise { @@ -160,9 +155,10 @@ export class ConnectionService { // TODO: Ensure the connection status is pending. const now = new Date() - const credentials = await this.buildCreateCredentials(clientId, input) + const credentials = await this.getInputCredentials(clientId, input) const connection = { + clientId, connectionId: input.connectionId, status: ConnectionStatus.ACTIVE, label: input.label, @@ -187,15 +183,113 @@ export class ConnectionService { }) } - async exists(clientId: string, connectionId?: string): Promise { - if (connectionId) { - return this.connectionRepository.exists(clientId, connectionId) + // TODO: (@wcalderipe, 05/12/24): The return type is Anchorage specific. + private async parseInputCredentials( + clientId: string, + provider: Provider, + input: CreateConnection | UpdateConnection + ): Promise { + // During the creation process, the input credentials can be one of the + // following: + // - A plain credential object containing an API key and a private key in + // hex format. + // - Encrypted credentials, which are an RSA-encrypted JSON representation + // of the plain credentials. + // + // Steps to handle the credentials: + // - Extract the credentials from the input data. + // - Ensure that either `credentials` or `encryptedCredentials` is + // provided. + // - If the credentials are encrypted, decrypt and parse the JSON. + // - Validate the credentials against the expected schema. + + if (provider === Provider.ANCHORAGE) { + if (input.encryptedCredentials) { + const raw = await this.encryptionKeyService.decrypt(clientId, input.encryptedCredentials) + + const parse = CreateCredentials.safeParse(JSON.parse(raw)) + + if (parse.success) { + const { privateKey, publicKey } = this.privateKeyHexToKeyPair(Alg.EDDSA, parse.data.privateKey) + + return { + apiKey: parse.data.apiKey, + privateKey: privateKey as Ed25519PrivateKey, + publicKey: publicKey as Ed25519PublicKey + } + } + + throw new ConnectionInvalidPrivateKeyException({ + message: 'Invalid input private key schema', + context: { errors: parse.error.errors } + }) + } + + if (input.credentials) { + const { privateKey, publicKey } = this.privateKeyHexToKeyPair(Alg.EDDSA, input.credentials.privateKey) + + return { + apiKey: input.credentials.apiKey, + privateKey: privateKey as Ed25519PrivateKey, + publicKey: publicKey as Ed25519PublicKey + } + } + + throw new ConnectionInvalidCredentialsException({ + message: 'Missing input credentials or encryptedCredentials' + }) } - return false + throw new NotImplementedException(`Unsupported provider private key getter: ${provider}`) + } + + private privateKeyHexToKeyPair(alg: Alg, privateKeyHex?: Hex) { + if (privateKeyHex) { + const privateKey = privateKeyToJwk(privateKeyHex, alg) + + return { + privateKey: privateKey, + publicKey: getPublicKey(privateKey) + } + } + + throw new ConnectionInvalidPrivateKeyException({ + message: 'Invalid private key hex' + }) } - private async buildCreateCredentials(clientId: string, input: CreateConnection): Promise { + async update(input: UpdateConnection): Promise { + const connection = await this.connectionRepository.findById(input.clientId, input.connectionId) + const hasCredentials = input.credentials || input.encryptedCredentials + const update = { + ...input, + ...(hasCredentials + ? { credentials: await this.parseInputCredentials(input.clientId, connection.provider, input) } + : {}) + } + + const isUpdated = await this.connectionRepository.update(update) + + if (isUpdated) { + return Connection.parse({ + ...connection, + ...update + }) + } + + throw new UpdateException({ + context: { + model: 'Connection', + connectionId: input.connectionId, + clientId: input.clientId + } + }) + } + + private async getInputCredentials( + clientId: string, + input: CreateConnection | UpdateConnection + ): Promise { if (input.encryptedCredentials) { const raw = await this.encryptionKeyService.decrypt(clientId, input.encryptedCredentials) const parse = CreateCredentials.safeParse(JSON.parse(raw)) @@ -204,7 +298,7 @@ export class ConnectionService { return parse.data } - throw new InvalidConnectionPrivateKeyException({ + throw new ConnectionInvalidPrivateKeyException({ context: { errors: parse.error.errors } }) } @@ -213,7 +307,15 @@ export class ConnectionService { return input.credentials } - throw new MissingConnectionCredentialsException() + throw new ConnectionInvalidCredentialsException() + } + + async exists(clientId: string, connectionId?: string): Promise { + if (connectionId) { + return this.connectionRepository.exists(clientId, connectionId) + } + + return false } async findById(clientId: string, connectionId: string): Promise { @@ -228,14 +330,12 @@ export class ConnectionService { const connection = await this.connectionRepository.findById(clientId, connectionId) if (isRevokedConnection(connection)) { - throw new BrokerException({ - message: 'Connection already revoked', - suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY - }) + throw new ConnectionAlreadyRevokedException({ clientId, connectionId }) } if (isActiveConnection(connection) || isPendingConnection(connection)) { await this.connectionRepository.update({ + clientId, connectionId: connectionId, credentials: null, status: ConnectionStatus.REVOKED, diff --git a/apps/vault/src/broker/core/type/connection.type.ts b/apps/vault/src/broker/core/type/connection.type.ts index 49b6376ed..d9ce54f59 100644 --- a/apps/vault/src/broker/core/type/connection.type.ts +++ b/apps/vault/src/broker/core/type/connection.type.ts @@ -5,7 +5,7 @@ import { z } from 'zod' export const Provider = { ANCHORAGE: 'anchorage' } as const -export type Provider = keyof typeof Provider +export type Provider = (typeof Provider)[keyof typeof Provider] export const ConnectionStatus = { PENDING: 'pending', @@ -82,6 +82,19 @@ export const CreateConnection = z.object({ }) export type CreateConnection = z.infer +export const UpdateConnection = z.object({ + clientId: z.string(), + connectionId: z.string(), + credentials: CreateCredentials.nullish(), + encryptedCredentials: z.string().optional().describe('RSA encrypted JSON string of the credentials'), + integrity: z.string().optional(), + label: z.string().optional(), + status: z.nativeEnum(ConnectionStatus).optional(), + updatedAt: z.date().optional(), + url: z.string().url().optional() +}) +export type UpdateConnection = z.infer + export const isPendingConnection = (connection: Connection): connection is PendingConnection => { return connection.status === ConnectionStatus.PENDING } diff --git a/apps/vault/src/broker/http/rest/controller/connection.controller.ts b/apps/vault/src/broker/http/rest/controller/connection.controller.ts index 1c8be0541..83e646c8f 100644 --- a/apps/vault/src/broker/http/rest/controller/connection.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/connection.controller.ts @@ -1,9 +1,10 @@ -import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post } from '@nestjs/common' +import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Patch, Post } from '@nestjs/common' import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../shared/decorator/client-id.decorator' import { ConnectionService } from '../../../core/service/connection.service' import { CreateConnectionDto } from '../dto/request/create-connection.dto' import { InitiateConnectionDto } from '../dto/request/initiate-connection.dto' +import { UpdateConnectionDto } from '../dto/request/update-connection.dto' import { ConnectionListDto } from '../dto/response/connection-list.dto' import { ConnectionDto } from '../dto/response/connection.dto' import { PendingConnectionDto } from '../dto/response/pending-connection.dto' @@ -18,7 +19,7 @@ export class ConnectionController { @Post('/initiate') @ApiOperation({ - summary: 'Initiate a new connection', + summary: 'Initiate a new provider connection', description: 'This endpoint initiates a new connection by generating a public key and an encryption key for secure communication.' }) @@ -97,4 +98,24 @@ export class ConnectionController { return ConnectionDto.create(connection) } + + @Patch(':connectionId') + @ApiResponse({ + description: 'Returns a reference to the updated provider connection.', + status: HttpStatus.OK, + type: ConnectionDto + }) + async update( + @ClientId() clientId: string, + @Param('connectionId') connectionId: string, + @Body() body: UpdateConnectionDto + ): Promise { + const connection = await this.connectionService.update({ + ...body, + clientId, + connectionId + }) + + return ConnectionDto.create(connection) + } } diff --git a/apps/vault/src/broker/http/rest/dto/request/update-connection.dto.ts b/apps/vault/src/broker/http/rest/dto/request/update-connection.dto.ts new file mode 100644 index 000000000..c37ea52ff --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/request/update-connection.dto.ts @@ -0,0 +1,10 @@ +import { createZodDto } from 'nestjs-zod' +import { CreateConnection } from '../../../../core/type/connection.type' + +export class UpdateConnectionDto extends createZodDto( + CreateConnection.pick({ + label: true, + encryptedCredentials: true, + credentials: true + }) +) {} diff --git a/apps/vault/src/broker/persistence/repository/connection.repository.ts b/apps/vault/src/broker/persistence/repository/connection.repository.ts index 6ca6afc65..f25fd47dd 100644 --- a/apps/vault/src/broker/persistence/repository/connection.repository.ts +++ b/apps/vault/src/broker/persistence/repository/connection.repository.ts @@ -7,6 +7,18 @@ import { ConnectionParseException } from '../../core/exception/connection-parse. import { NotFoundException } from '../../core/exception/not-found.exception' import { Connection, ConnectionStatus } from '../../core/type/connection.type' +type UpdateConnection = { + clientId: string + connectionId: string + credentials?: unknown | null + integrity?: string + label?: string + revokedAt?: Date + status?: ConnectionStatus + updatedAt?: Date + url?: string +} + @Injectable() export class ConnectionRepository { constructor(private prismaService: PrismaService) {} @@ -55,17 +67,8 @@ export class ConnectionRepository { return connection } - async update(connection: { - connectionId: string - credentials?: unknown | null - integrity?: string - label?: string - revokedAt?: Date - status?: ConnectionStatus - updatedAt?: Date - url?: string - }): Promise { - if (!connection.connectionId) { + async update(updateConnection: UpdateConnection): Promise { + if (!updateConnection.connectionId) { throw new BrokerException({ message: 'Missing connectionId', suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY @@ -73,15 +76,18 @@ export class ConnectionRepository { } await this.prismaService.providerConnection.update({ - where: { id: connection.connectionId }, + where: { + id: updateConnection.connectionId, + clientId: updateConnection.clientId + }, data: { - credentials: connection.credentials !== null ? connection.credentials : Prisma.JsonNull, - integrity: connection.integrity, - label: connection.label, - revokedAt: connection.revokedAt, - status: connection.status, - updatedAt: connection.updatedAt, - url: connection.url + credentials: updateConnection.credentials !== null ? updateConnection.credentials : Prisma.JsonNull, + integrity: updateConnection.integrity, + label: updateConnection.label, + revokedAt: updateConnection.revokedAt, + status: updateConnection.status, + updatedAt: updateConnection.updatedAt, + url: updateConnection.url } }) diff --git a/apps/vault/src/main.module.ts b/apps/vault/src/main.module.ts index 4ef645e83..ed87f9ca5 100644 --- a/apps/vault/src/main.module.ts +++ b/apps/vault/src/main.module.ts @@ -4,6 +4,7 @@ import { HttpLoggerMiddleware, LoggerModule, OpenTelemetryModule } from '@narval import { MiddlewareConsumer, Module, NestModule, OnModuleInit, ValidationPipe, forwardRef } from '@nestjs/common' import { APP_PIPE } from '@nestjs/core' import { ZodValidationPipe } from 'nestjs-zod' +import { BrokerModule } from './broker/broker.module' import { ClientModule } from './client/client.module' import { load } from './main.config' import { EncryptionModuleOptionFactory } from './shared/factory/encryption-module-option.factory' @@ -31,7 +32,8 @@ const INFRASTRUCTURE_MODULES = [ // Domain VaultModule, - ClientModule + ClientModule, + BrokerModule ], providers: [ { From ada1061861b787a7282ba84ba27f1eec01be8f79 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Tue, 10 Dec 2024 10:39:15 +0100 Subject: [PATCH 024/120] Improve invalid connection status error handling --- .../connection-already-revoked.exception.ts | 12 ----------- .../connection-invalid-status.exception.ts | 13 ++++++++++++ .../broker/core/service/connection.service.ts | 20 ++++++++++++------- 3 files changed, 26 insertions(+), 19 deletions(-) delete mode 100644 apps/vault/src/broker/core/exception/connection-already-revoked.exception.ts create mode 100644 apps/vault/src/broker/core/exception/connection-invalid-status.exception.ts diff --git a/apps/vault/src/broker/core/exception/connection-already-revoked.exception.ts b/apps/vault/src/broker/core/exception/connection-already-revoked.exception.ts deleted file mode 100644 index fe82ec7d0..000000000 --- a/apps/vault/src/broker/core/exception/connection-already-revoked.exception.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { HttpStatus } from '@nestjs/common' -import { BrokerException } from './broker.exception' - -export class ConnectionAlreadyRevokedException extends BrokerException { - constructor(context: { clientId: string; connectionId: string }) { - super({ - message: 'Connection already revoked', - suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, - context - }) - } -} diff --git a/apps/vault/src/broker/core/exception/connection-invalid-status.exception.ts b/apps/vault/src/broker/core/exception/connection-invalid-status.exception.ts new file mode 100644 index 000000000..4caa1b669 --- /dev/null +++ b/apps/vault/src/broker/core/exception/connection-invalid-status.exception.ts @@ -0,0 +1,13 @@ +import { HttpStatus } from '@nestjs/common' +import { ConnectionStatus } from '../type/connection.type' +import { BrokerException } from './broker.exception' + +export class ConnectionInvalidStatusException extends BrokerException { + constructor(context: { from: ConnectionStatus; to: ConnectionStatus; clientId: string; connectionId: string }) { + super({ + message: `Cannot change connection status from ${context.from} to ${context.to}`, + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, + context + }) + } +} diff --git a/apps/vault/src/broker/core/service/connection.service.ts b/apps/vault/src/broker/core/service/connection.service.ts index 2b53c11b9..9881fb428 100644 --- a/apps/vault/src/broker/core/service/connection.service.ts +++ b/apps/vault/src/broker/core/service/connection.service.ts @@ -7,15 +7,14 @@ import { getPublicKey, privateKeyToJwk } from '@narval/signature' -import { HttpStatus, Injectable, NotImplementedException } from '@nestjs/common' +import { Injectable, NotImplementedException } from '@nestjs/common' import { SetRequired } from 'type-fest' import { v4 as uuid } from 'uuid' import { EncryptionKeyService } from '../../../transit-encryption/core/service/encryption-key.service' import { ConnectionRepository } from '../../persistence/repository/connection.repository' -import { BrokerException } from '../exception/broker.exception' -import { ConnectionAlreadyRevokedException } from '../exception/connection-already-revoked.exception' import { ConnectionInvalidCredentialsException } from '../exception/connection-invalid-credentials.exception' import { ConnectionInvalidPrivateKeyException } from '../exception/connection-invalid-private-key.exception' +import { ConnectionInvalidStatusException } from '../exception/connection-invalid-status.exception' import { NotFoundException } from '../exception/not-found.exception' import { UpdateException } from '../exception/update.exception' import { @@ -177,9 +176,11 @@ export class ConnectionService { return { ...pendingConnection, ...connection } } - throw new BrokerException({ - message: "Cannot activate connection because it's not pending", - suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY + throw new ConnectionInvalidStatusException({ + from: pendingConnection.status, + to: ConnectionStatus.ACTIVE, + clientId, + connectionId: input.connectionId }) } @@ -330,7 +331,12 @@ export class ConnectionService { const connection = await this.connectionRepository.findById(clientId, connectionId) if (isRevokedConnection(connection)) { - throw new ConnectionAlreadyRevokedException({ clientId, connectionId }) + throw new ConnectionInvalidStatusException({ + from: connection.status, + to: ConnectionStatus.REVOKED, + clientId, + connectionId + }) } if (isActiveConnection(connection) || isPendingConnection(connection)) { From 678fc211cf633928a37e811d927fa58194c7ebe2 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Tue, 10 Dec 2024 10:49:31 +0100 Subject: [PATCH 025/120] Bump RSA key length from 2048 to 4096 --- .../vault/src/client/__test__/e2e/client.spec.ts | 16 ++++++++++++++-- .../integration/encryption-key.service.spec.ts | 5 +---- .../core/service/encryption-key.service.ts | 11 ++++++++--- apps/vault/src/vault/__test__/e2e/wallet.spec.ts | 6 +++++- packages/signature/src/lib/utils.ts | 12 +++++++++++- 5 files changed, 39 insertions(+), 11 deletions(-) diff --git a/apps/vault/src/client/__test__/e2e/client.spec.ts b/apps/vault/src/client/__test__/e2e/client.spec.ts index 0e1fcd73b..9650f5bf9 100644 --- a/apps/vault/src/client/__test__/e2e/client.spec.ts +++ b/apps/vault/src/client/__test__/e2e/client.spec.ts @@ -1,7 +1,14 @@ import { ConfigModule, ConfigService } from '@narval/config-module' import { EncryptionModuleOptionProvider } from '@narval/encryption-module' import { LoggerModule, secret } from '@narval/nestjs-shared' -import { Alg, PrivateKey, generateJwk, rsaPublicKeySchema, secp256k1PublicKeySchema } from '@narval/signature' +import { + Alg, + PrivateKey, + SMALLEST_RSA_MODULUS_LENGTH, + generateJwk, + rsaPublicKeySchema, + secp256k1PublicKeySchema +} from '@narval/signature' import { HttpStatus, INestApplication } from '@nestjs/common' import { Test, TestingModule } from '@nestjs/testing' import request from 'supertest' @@ -147,7 +154,12 @@ describe('Client', () => { }) it('creates a new client with RSA backup public key', async () => { - const rsaBackupKey = rsaPublicKeySchema.parse(await generateJwk(Alg.RS256, { keyId: 'rsaBackupKeyId' })) + const rsaBackupKey = rsaPublicKeySchema.parse( + await generateJwk(Alg.RS256, { + modulusLength: SMALLEST_RSA_MODULUS_LENGTH, + keyId: 'rsaBackupKeyId' + }) + ) const validClientPayload: CreateClientDto = { ...payload, diff --git a/apps/vault/src/transit-encryption/core/service/__test__/integration/encryption-key.service.spec.ts b/apps/vault/src/transit-encryption/core/service/__test__/integration/encryption-key.service.spec.ts index d8e256c63..36a0c232a 100644 --- a/apps/vault/src/transit-encryption/core/service/__test__/integration/encryption-key.service.spec.ts +++ b/apps/vault/src/transit-encryption/core/service/__test__/integration/encryption-key.service.spec.ts @@ -4,6 +4,7 @@ import { Alg, RsaPrivateKey, RsaPublicKey, + SMALLEST_RSA_MODULUS_LENGTH, Use, generateJwk, getPublicKey, @@ -24,10 +25,6 @@ import { UnauthorizedException } from '../../../exception/unauthorized.exception import { EncryptionKey } from '../../../type/encryption-key.type' import { EncryptionKeyService } from '../../encryption-key.service' -// NOTE: Uses the smallest modulus lenght required by jose package for -// test performance reasons. -const SMALLEST_RSA_MODULUS_LENGTH = 2048 - const GENERATE_RSA_KEY_OPTIONS: { use: Use; modulusLength: number } = { use: 'enc', modulusLength: SMALLEST_RSA_MODULUS_LENGTH diff --git a/apps/vault/src/transit-encryption/core/service/encryption-key.service.ts b/apps/vault/src/transit-encryption/core/service/encryption-key.service.ts index d95910817..b68055b16 100644 --- a/apps/vault/src/transit-encryption/core/service/encryption-key.service.ts +++ b/apps/vault/src/transit-encryption/core/service/encryption-key.service.ts @@ -1,4 +1,11 @@ -import { Alg, RsaPrivateKey, generateJwk, rsaDecrypt, rsaPrivateKeyToPublicKey } from '@narval/signature' +import { + Alg, + DEFAULT_RSA_MODULUS_LENGTH, + RsaPrivateKey, + generateJwk, + rsaDecrypt, + rsaPrivateKeyToPublicKey +} from '@narval/signature' import { Injectable } from '@nestjs/common' import { decodeProtectedHeader } from 'jose' import { EncryptionKeyRepository } from '../../persistence/encryption-key.repository' @@ -7,8 +14,6 @@ import { NotFoundException } from '../exception/not-found.exception' import { UnauthorizedException } from '../exception/unauthorized.exception' import { EncryptionKey } from '../type/encryption-key.type' -const DEFAULT_RSA_MODULUS_LENGTH = 4096 - @Injectable() export class EncryptionKeyService { constructor(private readonly encryptionKeyRepository: EncryptionKeyRepository) {} diff --git a/apps/vault/src/vault/__test__/e2e/wallet.spec.ts b/apps/vault/src/vault/__test__/e2e/wallet.spec.ts index 63b461cfe..dfb10d4bc 100644 --- a/apps/vault/src/vault/__test__/e2e/wallet.spec.ts +++ b/apps/vault/src/vault/__test__/e2e/wallet.spec.ts @@ -8,6 +8,7 @@ import { Payload, RsaPrivateKey, RsaPublicKey, + SMALLEST_RSA_MODULUS_LENGTH, SigningAlg, buildSignerEip191, generateJwk, @@ -203,7 +204,10 @@ describe('Generate', () => { it('saves a backup when client got a backupKey', async () => { const accessToken = await getAccessToken([Permission.WALLET_CREATE]) const keyId = 'backupKeyId' - const backupKey = await generateJwk(Alg.RS256, { keyId }) + const backupKey = await generateJwk(Alg.RS256, { + keyId, + modulusLength: SMALLEST_RSA_MODULUS_LENGTH + }) const clientWithBackupKey: Client = { ...client, diff --git a/packages/signature/src/lib/utils.ts b/packages/signature/src/lib/utils.ts index 1bec37b16..8284e3cc3 100644 --- a/packages/signature/src/lib/utils.ts +++ b/packages/signature/src/lib/utils.ts @@ -391,6 +391,16 @@ export const privateKeyToJwk = ( } } +export const DEFAULT_RSA_MODULUS_LENGTH = 4096 + +/** + * The smallest modulus lenght required by jose package. Useful to speed + * up tests. + * + * IMPORTANT: DO NOT use it in production. + */ +export const SMALLEST_RSA_MODULUS_LENGTH = 2048 + const generateRsaPrivateKey = async ( opts: { keyId?: string @@ -401,7 +411,7 @@ const generateRsaPrivateKey = async ( modulusLength?: number use?: Use } = { - modulusLength: 2048 + modulusLength: DEFAULT_RSA_MODULUS_LENGTH } ): Promise => { const { privateKey } = await generateKeyPair(Alg.RS256, { From e8b9a295d795fa2465d5a6e48b76bec5f0663cca Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Tue, 10 Dec 2024 10:53:51 +0100 Subject: [PATCH 026/120] Update patch endpoint docs --- .../broker/http/rest/controller/connection.controller.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/vault/src/broker/http/rest/controller/connection.controller.ts b/apps/vault/src/broker/http/rest/controller/connection.controller.ts index 83e646c8f..d07638a97 100644 --- a/apps/vault/src/broker/http/rest/controller/connection.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/connection.controller.ts @@ -100,8 +100,13 @@ export class ConnectionController { } @Patch(':connectionId') + @ApiOperation({ + summary: 'Update a specific connection by ID', + description: + 'This endpoint updates the details of a specific connection associated with the client, identified by the connection ID.' + }) @ApiResponse({ - description: 'Returns a reference to the updated provider connection.', + description: 'Returns the updated details of the provider connection.', status: HttpStatus.OK, type: ConnectionDto }) From b2b30be233ef9115dc242794313e1f488339a017 Mon Sep 17 00:00:00 2001 From: Pierre Troger Date: Tue, 10 Dec 2024 17:42:26 +0100 Subject: [PATCH 027/120] cleanup seed --- .../src/shared/module/persistence/seed.ts | 141 +++++++++--------- 1 file changed, 72 insertions(+), 69 deletions(-) diff --git a/apps/vault/src/shared/module/persistence/seed.ts b/apps/vault/src/shared/module/persistence/seed.ts index a8bdaa438..c8279e957 100644 --- a/apps/vault/src/shared/module/persistence/seed.ts +++ b/apps/vault/src/shared/module/persistence/seed.ts @@ -175,82 +175,85 @@ async function main() { } }) - // Process wallets and their hierarchies - for (const wallet of group.wallets) { - // Create wallet - const createdWallet = await txn.providerWallet.create({ - data: { - id: wallet.id, - clientId: wallet.clientId, - provider: wallet.provider, - label: wallet.label, - externalId: wallet.externalId, - createdAt: wallet.createdAt, - updatedAt: wallet.updatedAt - } - }) + const wallets = group.wallets.map((wallet) => ({ + id: wallet.id, + clientId: wallet.clientId, + provider: wallet.provider, + label: wallet.label, + externalId: wallet.externalId, + createdAt: wallet.createdAt, + updatedAt: wallet.updatedAt + })) - // Link wallet to connection - await txn.providerWalletConnection.create({ - data: { - clientId: wallet.clientId, - connectionId: connection.id, - walletId: createdWallet.id - } - }) + const providerWalletConnection = wallets.map((wallet) => ({ + clientId: wallet.clientId, + connectionId: connection.id, + walletId: wallet.id + })) - // Create accounts and addresses - for (const account of wallet.accounts) { - const createdAccount = await txn.providerAccount.create({ - data: { - id: account.id, - clientId: account.clientId, - provider: account.provider, - label: account.label, - externalId: account.externalId, - walletId: createdWallet.id, - networkId: account.networkId, - createdAt: account.createdAt, - updatedAt: account.updatedAt - } - }) + const accounts = group.wallets.flatMap((wallet) => + wallet.accounts.map((account) => ({ + id: account.id, + clientId: account.clientId, + provider: account.provider, + label: account.label, + externalId: account.externalId, + walletId: wallet.id, + networkId: account.networkId, + createdAt: account.createdAt, + updatedAt: account.updatedAt + })) + ) - // Create addresses for this account - for (const address of account.addresses) { - await txn.providerAddress.create({ - data: { - id: address.id, - clientId: address.clientId, - provider: address.provider, - externalId: address.externalId, - accountId: createdAccount.id, - address: address.address, - createdAt: address.createdAt, - updatedAt: address.updatedAt - } - }) - } - } - } + const addresses = group.wallets.flatMap((wallet) => + wallet.accounts.flatMap((acc) => + acc.addresses.map((address) => ({ + id: address.id, + clientId: address.clientId, + provider: address.provider, + externalId: address.externalId, + accountId: acc.id, + address: address.address, + createdAt: address.createdAt, + updatedAt: address.updatedAt + })) + ) + ) - // Create known destinations - for (const dest of group.knownDestinations) { - await txn.providerKnownDestination.create({ - data: { - ...dest, - connectionId: connection.id - } - }) + const knownDestinations = group.knownDestinations.map((dest) => ({ + ...dest, + connectionId: group.connection.id + })) + + const sync = { + id: v4(), + clientId, + connectionId: group.connection.id, + status: 'success' } - // Create sync record for this connection + await txn.providerWallet.createMany({ + data: wallets + }) + + await txn.providerWalletConnection.createMany({ + data: providerWalletConnection + }) + + await txn.providerAccount.createMany({ + data: accounts + }) + + await txn.providerAddress.createMany({ + data: addresses + }) + + await txn.providerKnownDestination.createMany({ + data: knownDestinations + }) + await txn.providerSync.create({ - data: { - id: v4(), - clientId, - connectionId: connection.id, - status: 'success' - } + data: sync }) } }) From f72fcec010e74db85549eb24c66c73dc1c2f04b6 Mon Sep 17 00:00:00 2001 From: Ptroger <44851272+Ptroger@users.noreply.github.com> Date: Wed, 11 Dec 2024 14:45:04 +0100 Subject: [PATCH 028/120] Feature/nar 1987 get wallets accounts addresses (#11) * structure for vault-custodian * rebased of broker branch, deleted skeleton * basis * wallet get endpoint * wallets by client and wallets by id * accounts by wallet * return all relationships, use Connection repository static map * withPagination * pagination in nestjs-shared and tested both in wallets and package * account getters * address getters * added connections endpoints * removed custom encoding, removed skip/take parameters * removed duplicated test utils * split mocks and utils for tests * validFields renamed to cursorOrderColumns and mandatory * Update apps/vault/src/broker/core/type/indexed-resources.type.ts Co-authored-by: William Calderipe * added findAll request for wallet and accounts * parsing provider --------- Co-authored-by: William Calderipe --- .../src/broker/__test__/e2e/account.spec.ts | 180 ++++++++++++++++ .../src/broker/__test__/e2e/address.spec.ts | 141 +++++++++++++ .../broker/__test__/e2e/connection.spec.ts | 105 +++++++++- .../src/broker/__test__/e2e/wallet.spec.ts | 198 ++++++++++++++++++ .../__test__/util/map-db-to-returned.ts | 64 ++++++ .../src/broker/__test__/util/mock-data.ts | 143 +++++++++++++ apps/vault/src/broker/broker.module.ts | 30 ++- .../broker/core/service/account.service.ts | 25 +++ .../broker/core/service/address.service.ts | 17 ++ .../broker/core/service/connection.service.ts | 36 +++- .../src/broker/core/service/wallet.service.ts | 29 +++ .../src/broker/core/type/connection.type.ts | 2 + .../core/type/indexed-resources.type.ts | 47 +++++ .../rest/controller/account.controller.ts | 87 ++++++++ .../rest/controller/address.controller.ts | 57 +++++ .../rest/controller/connection.controller.ts | 41 ++++ .../http/rest/controller/wallet.controller.ts | 86 ++++++++ .../http/rest/dto/response/account.dto.ts | 9 + .../http/rest/dto/response/accounts.dto.ts | 8 + .../http/rest/dto/response/address.dto.ts | 9 + .../http/rest/dto/response/addresses.dto.ts | 8 + .../http/rest/dto/response/wallet.dto.ts | 9 + .../http/rest/dto/response/wallets.dto.ts | 9 + .../repository/account.repository.ts | 124 +++++++++++ .../repository/address.repository.ts | 54 +++++ .../repository/connection.repository.ts | 10 +- .../repository/wallet.repository.ts | 171 +++++++++++++++ .../service/test-prisma.service.ts | 30 +++ .../src/lib/__test__/unit/pagination.spec.ts | 109 ++++++++++ .../nestjs-shared/src/lib/decorator/index.ts | 2 + .../decorator/pagination-param.decorator.ts | 7 + .../src/lib/decorator/pagination.decorator.ts | 60 ++++++ packages/nestjs-shared/src/lib/dto/index.ts | 1 + .../src/lib/dto/paginated.dto.ts | 19 ++ packages/nestjs-shared/src/lib/type/index.ts | 1 + .../src/lib/type/pagination.type.ts | 49 +++++ packages/nestjs-shared/src/lib/util/index.ts | 1 + .../src/lib/util/pagination.util.ts | 71 +++++++ 38 files changed, 2040 insertions(+), 9 deletions(-) create mode 100644 apps/vault/src/broker/__test__/e2e/account.spec.ts create mode 100644 apps/vault/src/broker/__test__/e2e/address.spec.ts create mode 100644 apps/vault/src/broker/__test__/e2e/wallet.spec.ts create mode 100644 apps/vault/src/broker/__test__/util/map-db-to-returned.ts create mode 100644 apps/vault/src/broker/__test__/util/mock-data.ts create mode 100644 apps/vault/src/broker/core/service/account.service.ts create mode 100644 apps/vault/src/broker/core/service/address.service.ts create mode 100644 apps/vault/src/broker/core/service/wallet.service.ts create mode 100644 apps/vault/src/broker/core/type/indexed-resources.type.ts create mode 100644 apps/vault/src/broker/http/rest/controller/account.controller.ts create mode 100644 apps/vault/src/broker/http/rest/controller/address.controller.ts create mode 100644 apps/vault/src/broker/http/rest/controller/wallet.controller.ts create mode 100644 apps/vault/src/broker/http/rest/dto/response/account.dto.ts create mode 100644 apps/vault/src/broker/http/rest/dto/response/accounts.dto.ts create mode 100644 apps/vault/src/broker/http/rest/dto/response/address.dto.ts create mode 100644 apps/vault/src/broker/http/rest/dto/response/addresses.dto.ts create mode 100644 apps/vault/src/broker/http/rest/dto/response/wallet.dto.ts create mode 100644 apps/vault/src/broker/http/rest/dto/response/wallets.dto.ts create mode 100644 apps/vault/src/broker/persistence/repository/account.repository.ts create mode 100644 apps/vault/src/broker/persistence/repository/address.repository.ts create mode 100644 apps/vault/src/broker/persistence/repository/wallet.repository.ts create mode 100644 packages/nestjs-shared/src/lib/__test__/unit/pagination.spec.ts create mode 100644 packages/nestjs-shared/src/lib/decorator/pagination-param.decorator.ts create mode 100644 packages/nestjs-shared/src/lib/decorator/pagination.decorator.ts create mode 100644 packages/nestjs-shared/src/lib/dto/paginated.dto.ts create mode 100644 packages/nestjs-shared/src/lib/type/pagination.type.ts create mode 100644 packages/nestjs-shared/src/lib/util/pagination.util.ts diff --git a/apps/vault/src/broker/__test__/e2e/account.spec.ts b/apps/vault/src/broker/__test__/e2e/account.spec.ts new file mode 100644 index 000000000..bd4e37c0b --- /dev/null +++ b/apps/vault/src/broker/__test__/e2e/account.spec.ts @@ -0,0 +1,180 @@ +import { ConfigModule } from '@narval/config-module' +import { EncryptionModuleOptionProvider } from '@narval/encryption-module' +import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' +import { HttpStatus, INestApplication } from '@nestjs/common' +import { Test, TestingModule } from '@nestjs/testing' +import request from 'supertest' +import { load } from '../../../main.config' +import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' +import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' +import { BrokerModule } from '../../broker.module' +import { getExpectedAccount, getExpectedAddress } from '../util/map-db-to-returned' +import { TEST_ACCOUNTS, TEST_ADDRESSES, TEST_CLIENT_ID } from '../util/mock-data' + +describe('Account', () => { + let app: INestApplication + let module: TestingModule + let testPrismaService: TestPrismaService + + beforeAll(async () => { + module = await Test.createTestingModule({ + imports: [ + LoggerModule.forTest(), + ConfigModule.forRoot({ + load: [load], + isGlobal: true + }), + BrokerModule + ] + }) + .overrideProvider(EncryptionModuleOptionProvider) + .useValue({ + keyring: getTestRawAesKeyring() + }) + .compile() + + app = module.createNestApplication() + testPrismaService = module.get(TestPrismaService) + + await app.init() + }) + + beforeEach(async () => { + await testPrismaService.truncateAll() + await testPrismaService.seedBrokerTestData() + }) + + afterAll(async () => { + await testPrismaService.truncateAll() + await module.close() + await app.close() + }) + + describe('GET /accounts', () => { + it('returns the list of accounts with addresses for the client', async () => { + const response = await request(app.getHttpServer()).get('/accounts').set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + expect(response.status).toEqual(HttpStatus.OK) + + expect(response.body).toEqual({ + accounts: TEST_ACCOUNTS.map(getExpectedAccount), + page: {} + }) + }) + + it('returns empty list for unknown client', async () => { + const response = await request(app.getHttpServer()) + .get('/accounts') + .set(REQUEST_HEADER_CLIENT_ID, 'unknown-client') + expect(response.status).toEqual(HttpStatus.OK) + + expect(response.body).toEqual({ accounts: [], page: {} }) + }) + }) + + describe('GET /accounts with pagination', () => { + it('returns limited number of accounts when limit parameter is provided', async () => { + const limit = 1 + const response = await request(app.getHttpServer()) + .get(`/accounts?limit=${limit}`) + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + expect(response.status).toEqual(HttpStatus.OK) + + expect(response.body.accounts).toHaveLength(limit) + expect(response.body.page).toHaveProperty('next') + }) + + it('returns next page of results using cursor', async () => { + // First request + const firstResponse = await request(app.getHttpServer()) + .get('/accounts?limit=1') + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + expect(firstResponse.status).toEqual(HttpStatus.OK) + + const cursor = firstResponse.body.page?.next + expect(cursor).toBeDefined() + + // Second request using the cursor + const secondResponse = await request(app.getHttpServer()) + .get(`/accounts?cursor=${cursor}&limit=1`) + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + expect(secondResponse.status).toEqual(HttpStatus.OK) + + expect(secondResponse.body.accounts).toHaveLength(1) + expect(secondResponse.body.accounts[0].accountId).not.toBe(firstResponse.body.accounts[0].accountId) + }) + + it('handles descending orderBy createdAt parameter correctly', async () => { + const response = await request(app.getHttpServer()) + .get(`/accounts?orderBy=createdAt&desc=true`) + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + expect(response.status).toEqual(HttpStatus.OK) + + const returnedAccounts = response.body.accounts + expect(returnedAccounts).toHaveLength(TEST_ACCOUNTS.length) + expect(new Date(returnedAccounts[0].createdAt).getTime()).toBeGreaterThanOrEqual( + new Date(returnedAccounts[1].createdAt).getTime() + ) + }) + }) + + describe('GET /accounts/:accountId', () => { + it('returns the account details with addresses', async () => { + const account = TEST_ACCOUNTS[0] + const response = await request(app.getHttpServer()) + .get(`/accounts/${account.id}`) + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + expect(response.status).toEqual(HttpStatus.OK) + expect(response.body).toEqual({ + account: getExpectedAccount(account) + }) + }) + + it('returns 404 with proper error message for non-existent account', async () => { + const response = await request(app.getHttpServer()) + .get(`/accounts/non-existent`) + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + expect(response.status).toEqual(HttpStatus.NOT_FOUND) + }) + + it('returns 404 when accessing account from unknown client', async () => { + const response = await request(app.getHttpServer()) + .get(`/accounts/${TEST_ACCOUNTS[0].id}`) + .set(REQUEST_HEADER_CLIENT_ID, 'unknown-client') + expect(response.status).toEqual(HttpStatus.NOT_FOUND) + }) + }) + + describe('GET /accounts/:accountId/addresses', () => { + it('returns the list of addresses for the account', async () => { + const account = TEST_ACCOUNTS[0] + const addresses = TEST_ADDRESSES.filter((addr) => addr.accountId === account.id) + + const response = await request(app.getHttpServer()) + .get(`/accounts/${account.id}/addresses`) + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + expect(response.status).toEqual(HttpStatus.OK) + + expect(response.body).toEqual({ + addresses: addresses.map(getExpectedAddress), + page: {} + }) + }) + + it('returns empty addresses array for account with no addresses', async () => { + // Create a new account without addresses + const accountWithoutAddresses = { + ...TEST_ACCOUNTS[0], + id: 'account-without-addresses' + } + await testPrismaService.getClient().providerAccount.create({ + data: accountWithoutAddresses + }) + + const response = await request(app.getHttpServer()) + .get(`/accounts/${accountWithoutAddresses.id}/addresses`) + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + expect(response.status).toEqual(HttpStatus.OK) + expect(response.body).toEqual({ addresses: [], page: {} }) + }) + }) +}) diff --git a/apps/vault/src/broker/__test__/e2e/address.spec.ts b/apps/vault/src/broker/__test__/e2e/address.spec.ts new file mode 100644 index 000000000..9212dace6 --- /dev/null +++ b/apps/vault/src/broker/__test__/e2e/address.spec.ts @@ -0,0 +1,141 @@ +import { ConfigModule } from '@narval/config-module' +import { EncryptionModuleOptionProvider } from '@narval/encryption-module' +import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' +import { HttpStatus, INestApplication } from '@nestjs/common' +import { Test, TestingModule } from '@nestjs/testing' +import request from 'supertest' +import { load } from '../../../main.config' +import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' +import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' +import { BrokerModule } from '../../broker.module' +import { getExpectedAddress } from '../util/map-db-to-returned' +import { TEST_ADDRESSES, TEST_CLIENT_ID } from '../util/mock-data' + +describe('Address', () => { + let app: INestApplication + let module: TestingModule + let testPrismaService: TestPrismaService + + beforeAll(async () => { + module = await Test.createTestingModule({ + imports: [ + LoggerModule.forTest(), + ConfigModule.forRoot({ + load: [load], + isGlobal: true + }), + BrokerModule + ] + }) + .overrideProvider(EncryptionModuleOptionProvider) + .useValue({ + keyring: getTestRawAesKeyring() + }) + .compile() + + app = module.createNestApplication() + testPrismaService = module.get(TestPrismaService) + + await app.init() + }) + + beforeEach(async () => { + await testPrismaService.truncateAll() + await testPrismaService.seedBrokerTestData() + }) + + afterAll(async () => { + await testPrismaService.truncateAll() + await module.close() + await app.close() + }) + + describe('GET /addresses', () => { + it('returns the list of addresses for the client', async () => { + const response = await request(app.getHttpServer()) + .get(`/addresses`) + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + expect(response.status).toEqual(HttpStatus.OK) + + expect(response.body).toEqual({ + addresses: TEST_ADDRESSES.map(getExpectedAddress), + page: {} + }) + }) + }) + + describe('GET /addresses with pagination', () => { + it('returns limited number of addresses when limit parameter is provided', async () => { + const limit = 1 + const response = await request(app.getHttpServer()) + .get(`/addresses?limit=${limit}`) + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + + expect(response.body.addresses).toHaveLength(limit) + expect(response.body.page).toHaveProperty('next') + }) + + it('returns next page of results using cursor', async () => { + // First request + const firstResponse = await request(app.getHttpServer()) + .get('/addresses?limit=1') + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .expect(HttpStatus.OK) + + const cursor = firstResponse.body.page?.next + expect(cursor).toBeDefined() + + // Second request using the cursor + const secondResponse = await request(app.getHttpServer()) + .get(`/addresses?cursor=${cursor}&limit=1`) + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .expect(HttpStatus.OK) + + expect(secondResponse.body.addresses).toHaveLength(1) + expect(secondResponse.body.addresses[0].addressId).not.toBe(firstResponse.body.addresses[0].addressId) + }) + + it('handles descending orderBy createdAt parameter correctly', async () => { + const response = await request(app.getHttpServer()) + .get('/addresses?orderBy=createdAt&desc=true') + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .expect(HttpStatus.OK) + + const returnedAddresses = response.body.addresses + expect(returnedAddresses).toHaveLength(TEST_ADDRESSES.length) + expect(new Date(returnedAddresses[0].createdAt).getTime()).toBeGreaterThanOrEqual( + new Date(returnedAddresses[1].createdAt).getTime() + ) + }) + }) + + describe('GET /addresses/:addressId', () => { + it('returns the address details', async () => { + const address = TEST_ADDRESSES[0] + const response = await request(app.getHttpServer()) + .get(`/addresses/${address.id}`) + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + + expect(response.body).toEqual({ + address: getExpectedAddress(address) + }) + expect(response.status).toBe(HttpStatus.OK) + }) + + it('returns 404 with proper error message for non-existent address', async () => { + const response = await request(app.getHttpServer()) + .get('/addresses/non-existent') + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + + expect(response.status).toBe(HttpStatus.NOT_FOUND) + }) + + it('returns 404 when accessing address from different client', async () => { + const response = await request(app.getHttpServer()) + .get(`/addresses/${TEST_ADDRESSES[0].id}`) + .set(REQUEST_HEADER_CLIENT_ID, 'different-client') + + expect(response.status).toBe(HttpStatus.NOT_FOUND) + }) + }) +}) diff --git a/apps/vault/src/broker/__test__/e2e/connection.spec.ts b/apps/vault/src/broker/__test__/e2e/connection.spec.ts index 29e714427..8405084ec 100644 --- a/apps/vault/src/broker/__test__/e2e/connection.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/connection.spec.ts @@ -28,6 +28,14 @@ import { isActiveConnection, isRevokedConnection } from '../../core/type/connection.type' +import { getExpectedAccount, getExpectedWallet } from '../util/map-db-to-returned' +import { + TEST_ACCOUNTS, + TEST_CLIENT_ID, + TEST_CONNECTIONS, + TEST_WALLETS, + TEST_WALLET_CONNECTIONS +} from '../util/mock-data' const toMatchZodSchema = (received: unknown, schema: ZodSchema): void => { const parse = schema.safeParse(received) @@ -56,7 +64,7 @@ describe('Connection', () => { const url = 'http://provider.narval.xyz' - const clientId = uuid() + const clientId = TEST_CLIENT_ID beforeAll(async () => { module = await Test.createTestingModule({ @@ -446,4 +454,99 @@ describe('Connection', () => { expect(updatedConnection.credentials.publicKey).toEqual(getPublicKey(newPrivateKey as Ed25519PrivateKey)) }) }) + + describe('GET /connections/:connectionId/wallets', () => { + it('responds with wallets for the specific connection', async () => { + await testPrismaService.seedBrokerTestData() + + const { status, body } = await request(app.getHttpServer()) + .get(`/connections/${TEST_CONNECTIONS[0].id}/wallets`) + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .send() + + expect(status).toEqual(HttpStatus.OK) + expect(body).toMatchObject({ + wallets: [getExpectedWallet(TEST_WALLETS[0])], + page: {} + }) + }) + + it('returns empty array when connection has no wallets', async () => { + await testPrismaService.seedBrokerTestData() + + const connection = await connectionService.create(clientId, { + connectionId: uuid(), + label: 'test connection', + provider: Provider.ANCHORAGE, + url, + credentials: { + apiKey: 'test-api-key', + privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) + } + }) + + const { status, body } = await request(app.getHttpServer()) + .get(`/connections/${connection.connectionId}/wallets`) + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .send() + + expect(status).toEqual(HttpStatus.OK) + expect(body).toMatchObject({ + wallets: [], + page: {} + }) + }) + }) + + describe('GET /connections/:connectionId/accounts', () => { + it('responds with accounts for the specific connection', async () => { + await testPrismaService.seedBrokerTestData() + + // Assume connection[0] has some wallets which in turn have accounts. + const connectionId = TEST_CONNECTIONS[0].id + const walletsForConnection = TEST_WALLET_CONNECTIONS.filter((wc) => wc.connectionId === connectionId).map( + (wc) => wc.walletId + ) + + const accountsForConnection = TEST_ACCOUNTS.filter((account) => walletsForConnection.includes(account.walletId)) + + const { status, body } = await request(app.getHttpServer()) + .get(`/connections/${connectionId}/accounts`) + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .send() + + expect(status).toEqual(HttpStatus.OK) + expect(body).toMatchObject({ + accounts: accountsForConnection.map(getExpectedAccount), + page: {} + }) + }) + + it('returns empty array when connection has no accounts', async () => { + await testPrismaService.seedBrokerTestData() + + // Create a new connection that doesn't have any associated wallets or accounts + const connection = await connectionService.create(clientId, { + connectionId: uuid(), + label: 'test connection', + provider: Provider.ANCHORAGE, + url, + credentials: { + apiKey: 'test-api-key', + privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) + } + }) + + const { status, body } = await request(app.getHttpServer()) + .get(`/connections/${connection.connectionId}/accounts`) + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .send() + + expect(status).toEqual(HttpStatus.OK) + expect(body).toMatchObject({ + accounts: [], + page: {} + }) + }) + }) }) diff --git a/apps/vault/src/broker/__test__/e2e/wallet.spec.ts b/apps/vault/src/broker/__test__/e2e/wallet.spec.ts new file mode 100644 index 000000000..538cf09b3 --- /dev/null +++ b/apps/vault/src/broker/__test__/e2e/wallet.spec.ts @@ -0,0 +1,198 @@ +import { ConfigModule } from '@narval/config-module' +import { EncryptionModuleOptionProvider } from '@narval/encryption-module' +import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' +import { HttpStatus, INestApplication } from '@nestjs/common' +import { Test, TestingModule } from '@nestjs/testing' +import request from 'supertest' +import { load } from '../../../main.config' +import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' +import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' +import { BrokerModule } from '../../broker.module' +import { getExpectedAccount, getExpectedWallet } from '../util/map-db-to-returned' +import { TEST_ACCOUNTS, TEST_CLIENT_ID, TEST_WALLETS } from '../util/mock-data' + +describe('Wallet', () => { + let app: INestApplication + let module: TestingModule + let testPrismaService: TestPrismaService + + beforeAll(async () => { + module = await Test.createTestingModule({ + imports: [ + LoggerModule.forTest(), + ConfigModule.forRoot({ + load: [load], + isGlobal: true + }), + BrokerModule + ] + }) + .overrideProvider(EncryptionModuleOptionProvider) + .useValue({ + keyring: getTestRawAesKeyring() + }) + .compile() + + app = module.createNestApplication() + testPrismaService = module.get(TestPrismaService) + + await app.init() + }) + + beforeEach(async () => { + await testPrismaService.truncateAll() + await testPrismaService.seedBrokerTestData() + }) + + afterAll(async () => { + await testPrismaService.truncateAll() + await module.close() + await app.close() + }) + + describe('GET /wallets', () => { + it('returns the list of wallets with accounts for the client', async () => { + const res = await request(app.getHttpServer()).get('/wallets').set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + + expect(res.status).toBe(HttpStatus.OK) + expect(res.body).toEqual({ + wallets: TEST_WALLETS.map(getExpectedWallet), + page: {} + }) + }) + + it("doesn't return private connection information", async () => { + const res = await request(app.getHttpServer()).get('/wallets').set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + + expect(res.status).toBe(HttpStatus.OK) + + for (const wallet of res.body.wallets) { + for (const connection of wallet.connections) { + expect(connection).not.toHaveProperty('credentials') + expect(connection).not.toHaveProperty('revokedAt') + } + } + }) + + it('returns empty list for unknown client', async () => { + const res = await request(app.getHttpServer()).get('/wallets').set(REQUEST_HEADER_CLIENT_ID, 'unknown-client') + + expect(res.body).toEqual({ wallets: [], page: {} }) + expect(res.status).toBe(HttpStatus.OK) + }) + }) + + describe('GET /wallets with pagination', () => { + it('returns limited number of wallets when limit parameter is provided', async () => { + // We have 2 wallets in TEST_WALLETS + const limit = 1 + const res = await request(app.getHttpServer()) + .get('/wallets?limit=1') + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + + expect(res.body.wallets).toHaveLength(limit) + expect(res.body.page).toHaveProperty('next') + expect(res.status).toBe(HttpStatus.OK) + }) + + it('returns next page of results using cursor', async () => { + const firstResponse = await request(app.getHttpServer()) + .get(`/wallets?limit=1`) + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + expect(firstResponse.status).toBe(HttpStatus.OK) + + const cursor = firstResponse.body.page?.next + expect(cursor).toBeDefined() + + const secondResponse = await request(app.getHttpServer()) + .get(`/wallets?cursor=${cursor}`) + + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + expect(secondResponse.status).toBe(HttpStatus.OK) + + expect(secondResponse.body.wallets).toHaveLength(1) + // The second wallet should not be the same as the first + expect(secondResponse.body.wallets[0].walletId).not.toBe(firstResponse.body.wallets[0].walletId) + }) + it('handles descending orderBy createdAt parameter correctly', async () => { + const res = await request(app.getHttpServer()) + .get('/wallets?orderBy=createdAt&desc=true') + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + + // Check descending order by createdAt + const returnedWallets = res.body.wallets + expect(returnedWallets).toHaveLength(TEST_WALLETS.length) + expect(res.status).toBe(HttpStatus.OK) + + // When ordering by DESC, first item should have GREATER timestamp than second + expect(new Date(returnedWallets[0].createdAt).getTime()).toBeGreaterThan( + new Date(returnedWallets[1].createdAt).getTime() + ) + }) + + it('throws invalidField orderBy is not a valid field', async () => { + const res = await request(app.getHttpServer()) + .get('/wallets?orderBy=invalid-field') + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + + expect(res.status).toBe(HttpStatus.UNPROCESSABLE_ENTITY) + }) + }) + + describe('GET /wallets/:walletId', () => { + it('returns the wallet details with accounts and addresses', async () => { + const wallet = TEST_WALLETS[0] + const res = await request(app.getHttpServer()) + .get(`/wallets/${wallet.id}`) + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + + expect(res.status).toBe(HttpStatus.OK) + + expect(res.body).toEqual({ + wallet: getExpectedWallet(wallet) + }) + }) + + it('returns 404 with proper error message for non-existent wallet', async () => { + const res = await request(app.getHttpServer()) + .get(`/wallets/non-existent`) + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + + expect(res.status).toBe(HttpStatus.NOT_FOUND) + }) + + it('returns 404 when accessing wallet from wrong client', async () => { + const wallet = TEST_WALLETS[0] + const res = await request(app.getHttpServer()) + .get(`/wallets/${wallet.id}`) + .set(REQUEST_HEADER_CLIENT_ID, 'wrong-client') + + expect(res.status).toBe(HttpStatus.NOT_FOUND) + }) + }) + + describe('GET /wallets/:walletId/accounts', () => { + it('returns the list of accounts for the wallet', async () => { + const wallet = TEST_WALLETS[0] + const accounts = TEST_ACCOUNTS.filter((acc) => acc.walletId === wallet.id) + const res = await request(app.getHttpServer()) + .get(`/wallets/${wallet.id}/accounts`) + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + + expect(res.status).toBe(HttpStatus.OK) + expect(res.body).toEqual({ + accounts: accounts.map(getExpectedAccount), + page: {} + }) + }) + + it('returns empty accounts array for wallet with no accounts', async () => { + const res = await request(app.getHttpServer()) + .get(`/wallets/${TEST_WALLETS[1].id}/accounts`) + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + + expect(res.status).toBe(HttpStatus.OK) + expect(res.body).toEqual({ accounts: [], page: {} }) + }) + }) +}) diff --git a/apps/vault/src/broker/__test__/util/map-db-to-returned.ts b/apps/vault/src/broker/__test__/util/map-db-to-returned.ts new file mode 100644 index 000000000..1ad916425 --- /dev/null +++ b/apps/vault/src/broker/__test__/util/map-db-to-returned.ts @@ -0,0 +1,64 @@ +import { ProviderAccount, ProviderAddress, ProviderConnection, ProviderWallet } from '@prisma/client/vault' +import { PublicConnection } from '../../core/type/connection.type' +import { TEST_ACCOUNTS, TEST_ADDRESSES, TEST_CONNECTIONS, TEST_WALLET_CONNECTIONS } from './mock-data' + +// Helper function to get expected connection format for API response +export const getExpectedConnection = (connection: ProviderConnection): PublicConnection => { + const { + credentials, + revokedAt, + clientId, + createdAt, + updatedAt, + url, + integrity, + id, + ...connectionWithoutPrivateData + } = connection + return PublicConnection.parse({ + ...connectionWithoutPrivateData, + connectionId: connection.id + }) +} + +// Helper function to get expected address format +export const getExpectedAddress = (address: ProviderAddress) => { + const { id, ...addressWithoutId } = address + return { + ...addressWithoutId, + addressId: address.id, + createdAt: new Date(address.createdAt).toISOString(), + updatedAt: new Date(address.updatedAt).toISOString() + } +} + +// Helper function to get expected account format with addresses +export const getExpectedAccount = (account: ProviderAccount) => { + const addresses = TEST_ADDRESSES.filter((addr) => addr.accountId === account.id) + const { id, walletId, ...accountWithoutId } = account + return { + ...accountWithoutId, + walletId, + accountId: account.id, + addresses: addresses.map(getExpectedAddress), + createdAt: new Date(account.createdAt).toISOString(), + updatedAt: new Date(account.updatedAt).toISOString() + } +} + +// Helper function to get expected wallet format with accounts and connections +export const getExpectedWallet = (wallet: ProviderWallet) => { + const accounts = TEST_ACCOUNTS.filter((acc) => acc.walletId === wallet.id) + const walletConnections = TEST_WALLET_CONNECTIONS.filter((conn) => conn.walletId === wallet.id) + const connections = TEST_CONNECTIONS.filter((conn) => walletConnections.some((wc) => wc.connectionId === conn.id)) + const { id, ...walletWithoutId } = wallet + + return { + ...walletWithoutId, + walletId: wallet.id, + accounts: accounts.map(getExpectedAccount), + connections: connections.map(getExpectedConnection), + createdAt: new Date(wallet.createdAt).toISOString(), + updatedAt: new Date(wallet.updatedAt).toISOString() + } +} diff --git a/apps/vault/src/broker/__test__/util/mock-data.ts b/apps/vault/src/broker/__test__/util/mock-data.ts new file mode 100644 index 000000000..114e88ce3 --- /dev/null +++ b/apps/vault/src/broker/__test__/util/mock-data.ts @@ -0,0 +1,143 @@ +const privateKey = { + kty: 'OKP', + crv: 'Ed25519', + alg: 'EDDSA', + kid: '0xaf8dcff8da6aae18c2170f59a0734c8c5c19ca726a1b75993857bd836db00a5f', + x: 'HrmLI5NH3cYp4-HluFGBOcYvARGti_oz0aZMXMzy8m4', + d: 'nq2eDJPp9NAqCdTT_dNerIJFJxegTKmFgDAsFkhbJIA' +} + +const { d: _d, ...publicKey } = privateKey + +export const TEST_CLIENT_ID = 'test-client-id' + +export const TEST_CONNECTIONS = [ + { + id: 'connection-1', + clientId: TEST_CLIENT_ID, + provider: 'anchorage', + url: 'https://api.anchorage.com', + label: 'Test Connection 1', + credentials: { + apiKey: 'test-api-key-1', + privateKey, + publicKey + }, + status: 'active', + integrity: 'test-integrity-1', + createdAt: new Date(), + updatedAt: new Date(), + revokedAt: null + }, + { + id: 'connection-2', + clientId: TEST_CLIENT_ID, + provider: 'anchorage', + url: 'https://api.anchorage.com', + label: 'Test Connection 2', + credentials: { + apiKey: 'test-api-key-1', + privateKey, + publicKey + }, + status: 'active', + integrity: 'test-integrity-2', + createdAt: new Date(), + updatedAt: new Date(), + revokedAt: null + } +] + +export const TEST_WALLET_CONNECTIONS = [ + { + clientId: TEST_CLIENT_ID, + connectionId: 'connection-1', + walletId: 'wallet-1', + createdAt: new Date() + }, + { + clientId: TEST_CLIENT_ID, + connectionId: 'connection-2', + walletId: 'wallet-2', + createdAt: new Date() + } +] + +export const TEST_WALLETS = [ + { + id: 'wallet-1', + clientId: TEST_CLIENT_ID, + provider: 'anchorage', + label: 'Test Wallet 1', + externalId: 'ext-wallet-1', + createdAt: new Date('2024-01-01T00:00:00.000Z'), + updatedAt: new Date('2024-01-01T00:00:00.000Z') + }, + { + id: 'wallet-2', + clientId: TEST_CLIENT_ID, + provider: 'anchorage', + label: 'Test Wallet 2', + externalId: 'ext-wallet-2', + createdAt: new Date('2024-01-01T00:00:01.000Z'), // One second later + updatedAt: new Date('2024-01-01T00:00:01.000Z') + } +] + +export const TEST_ACCOUNTS = [ + { + id: 'account-1', + clientId: TEST_CLIENT_ID, + provider: 'anchorage', + label: 'Test Account 1', + externalId: 'ext-account-1', + walletId: 'wallet-1', // Linking to wallet-1 + networkId: '1', + createdAt: new Date(), + updatedAt: new Date() + }, + { + id: 'account-2', + clientId: TEST_CLIENT_ID, + provider: 'anchorage', + label: 'Test Account 2', + externalId: 'ext-account-2', + walletId: 'wallet-1', // Linking to wallet-1 + networkId: '60', + createdAt: new Date(), + updatedAt: new Date() + } +] + +export const TEST_ADDRESSES = [ + { + id: 'address-1', + clientId: TEST_CLIENT_ID, + provider: 'anchorage', + externalId: 'ext-address-1', + accountId: 'account-1', // Linking to account-1 + address: '0x1234567890123456789012345678901234567890', // Example ETH address + createdAt: new Date(), + updatedAt: new Date() + }, + { + id: 'address-2', + clientId: TEST_CLIENT_ID, + provider: 'anchorage', + externalId: 'ext-address-2', + accountId: 'account-1', // Another address for account-1 + address: '0x0987654321098765432109876543210987654321', // Example ETH address + createdAt: new Date(), + updatedAt: new Date() + }, + { + id: 'address-3', + clientId: TEST_CLIENT_ID, + provider: 'anchorage', + externalId: 'ext-address-3', + accountId: 'account-2', // Linking to account-2 + address: 'bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh', // Example BTC address + createdAt: new Date(), + updatedAt: new Date() + } +] diff --git a/apps/vault/src/broker/broker.module.ts b/apps/vault/src/broker/broker.module.ts index 0ce70bb80..8a0108a2e 100644 --- a/apps/vault/src/broker/broker.module.ts +++ b/apps/vault/src/broker/broker.module.ts @@ -1,14 +1,36 @@ import { Module } from '@nestjs/common' import { DEFAULT_HTTP_MODULE_PROVIDERS } from '../shared/constant' import { PersistenceModule } from '../shared/module/persistence/persistence.module' -import { TransitEncryptionModule } from '../transit-encryption/transit-encryption.module' +import { EncryptionKeyService } from '../transit-encryption/core/service/encryption-key.service' +import { EncryptionKeyRepository } from '../transit-encryption/persistence/encryption-key.repository' +import { AccountService } from './core/service/account.service' +import { AddressService } from './core/service/address.service' import { ConnectionService } from './core/service/connection.service' +import { WalletService } from './core/service/wallet.service' +import { AccountController } from './http/rest/controller/account.controller' +import { AddressController } from './http/rest/controller/address.controller' import { ConnectionController } from './http/rest/controller/connection.controller' +import { WalletController } from './http/rest/controller/wallet.controller' +import { AccountRepository } from './persistence/repository/account.repository' +import { AddressRepository } from './persistence/repository/address.repository' import { ConnectionRepository } from './persistence/repository/connection.repository' +import { WalletRepository } from './persistence/repository/wallet.repository' @Module({ - imports: [PersistenceModule, TransitEncryptionModule], - controllers: [ConnectionController], - providers: [...DEFAULT_HTTP_MODULE_PROVIDERS, ConnectionService, ConnectionRepository] + imports: [PersistenceModule], + controllers: [ConnectionController, WalletController, AccountController, AddressController], + providers: [ + ...DEFAULT_HTTP_MODULE_PROVIDERS, + ConnectionService, + EncryptionKeyService, + EncryptionKeyRepository, + ConnectionRepository, + WalletService, + WalletRepository, + AccountService, + AccountRepository, + AddressService, + AddressRepository + ] }) export class BrokerModule {} diff --git a/apps/vault/src/broker/core/service/account.service.ts b/apps/vault/src/broker/core/service/account.service.ts new file mode 100644 index 000000000..3eaf0a6dd --- /dev/null +++ b/apps/vault/src/broker/core/service/account.service.ts @@ -0,0 +1,25 @@ +import { PaginatedResult, PaginationOptions } from '@narval/nestjs-shared' +import { Injectable } from '@nestjs/common' +import { AccountRepository } from '../../persistence/repository/account.repository' +import { Account, Address } from '../type/indexed-resources.type' + +@Injectable() +export class AccountService { + constructor(private readonly AccountRepository: AccountRepository) {} + + async getAccounts(clientId: string, options: PaginationOptions): Promise> { + return this.AccountRepository.findByClientId(clientId, options) + } + + async getAccount(clientId: string, AccountId: string): Promise { + return this.AccountRepository.findById(clientId, AccountId) + } + + async getAccountAddresses( + clientId: string, + AccountId: string, + options: PaginationOptions + ): Promise> { + return this.AccountRepository.findAddressesByAccountId(clientId, AccountId, options) + } +} diff --git a/apps/vault/src/broker/core/service/address.service.ts b/apps/vault/src/broker/core/service/address.service.ts new file mode 100644 index 000000000..8ca8bd98e --- /dev/null +++ b/apps/vault/src/broker/core/service/address.service.ts @@ -0,0 +1,17 @@ +import { PaginatedResult, PaginationOptions } from '@narval/nestjs-shared' +import { Injectable } from '@nestjs/common' +import { AddressRepository } from '../../persistence/repository/address.repository' +import { Address } from '../type/indexed-resources.type' + +@Injectable() +export class AddressService { + constructor(private readonly AddressRepository: AddressRepository) {} + + async getAddresses(clientId: string, options: PaginationOptions): Promise> { + return this.AddressRepository.findByClientId(clientId, options) + } + + async getAddress(clientId: string, AddressId: string): Promise
{ + return this.AddressRepository.findById(clientId, AddressId) + } +} diff --git a/apps/vault/src/broker/core/service/connection.service.ts b/apps/vault/src/broker/core/service/connection.service.ts index 9881fb428..2328ba32f 100644 --- a/apps/vault/src/broker/core/service/connection.service.ts +++ b/apps/vault/src/broker/core/service/connection.service.ts @@ -1,3 +1,4 @@ +import { PaginatedResult, PaginationOptions } from '@narval/nestjs-shared' import { Alg, Ed25519PrivateKey, @@ -11,7 +12,9 @@ import { Injectable, NotImplementedException } from '@nestjs/common' import { SetRequired } from 'type-fest' import { v4 as uuid } from 'uuid' import { EncryptionKeyService } from '../../../transit-encryption/core/service/encryption-key.service' +import { AccountRepository } from '../../persistence/repository/account.repository' import { ConnectionRepository } from '../../persistence/repository/connection.repository' +import { WalletRepository } from '../../persistence/repository/wallet.repository' import { ConnectionInvalidCredentialsException } from '../exception/connection-invalid-credentials.exception' import { ConnectionInvalidPrivateKeyException } from '../exception/connection-invalid-private-key.exception' import { ConnectionInvalidStatusException } from '../exception/connection-invalid-status.exception' @@ -32,12 +35,15 @@ import { isPendingConnection, isRevokedConnection } from '../type/connection.type' +import { Wallet } from '../type/indexed-resources.type' @Injectable() export class ConnectionService { constructor( private readonly connectionRepository: ConnectionRepository, - private readonly encryptionKeyService: EncryptionKeyService + private readonly encryptionKeyService: EncryptionKeyService, + private readonly walletRepository: WalletRepository, + private readonly accountRepository: AccountRepository ) {} async initiate(clientId: string, input: InitiateConnection): Promise { @@ -353,4 +359,32 @@ export class ConnectionService { throw new NotFoundException({ context: { clientId, connectionId } }) } + + async findWallets( + clientId: string, + connectionId: string, + options: PaginationOptions + ): Promise> { + return this.walletRepository.findAll( + clientId, + { + connectionId + }, + options + ) + } + + async findAccounts( + clientId: string, + connectionId: string, + options: PaginationOptions + ): Promise> { + return this.accountRepository.findAll( + clientId, + { + connectionId + }, + options + ) + } } diff --git a/apps/vault/src/broker/core/service/wallet.service.ts b/apps/vault/src/broker/core/service/wallet.service.ts new file mode 100644 index 000000000..66cebca3e --- /dev/null +++ b/apps/vault/src/broker/core/service/wallet.service.ts @@ -0,0 +1,29 @@ +import { PaginatedResult, PaginationOptions } from '@narval/nestjs-shared' +import { Injectable } from '@nestjs/common' +import { AccountRepository } from '../../persistence/repository/account.repository' +import { WalletRepository } from '../../persistence/repository/wallet.repository' +import { Account, Wallet } from '../type/indexed-resources.type' + +@Injectable() +export class WalletService { + constructor( + private readonly walletRepository: WalletRepository, + private readonly accountRepository: AccountRepository + ) {} + + async getWallets(clientId: string, options: PaginationOptions): Promise> { + return this.walletRepository.findByClientId(clientId, options) + } + + async getWallet(clientId: string, walletId: string): Promise { + return this.walletRepository.findById(clientId, walletId) + } + + async getWalletAccounts( + clientId: string, + walletId: string, + options: PaginationOptions + ): Promise> { + return this.accountRepository.findAll(clientId, { walletId }, options) + } +} diff --git a/apps/vault/src/broker/core/type/connection.type.ts b/apps/vault/src/broker/core/type/connection.type.ts index d9ce54f59..2d1250c02 100644 --- a/apps/vault/src/broker/core/type/connection.type.ts +++ b/apps/vault/src/broker/core/type/connection.type.ts @@ -106,3 +106,5 @@ export const isActiveConnection = (connection: Connection): connection is Active export const isRevokedConnection = (connection: Connection): connection is RevokedConnection => { return connection.status === ConnectionStatus.REVOKED } +export const PublicConnection = BaseConnection.pick({ connectionId: true, status: true, label: true, provider: true }) +export type PublicConnection = z.infer diff --git a/apps/vault/src/broker/core/type/indexed-resources.type.ts b/apps/vault/src/broker/core/type/indexed-resources.type.ts new file mode 100644 index 000000000..a714b6a14 --- /dev/null +++ b/apps/vault/src/broker/core/type/indexed-resources.type.ts @@ -0,0 +1,47 @@ +import { z } from 'zod' +import { BaseConnection, Provider, PublicConnection } from './connection.type' + +// Base schemas without relationships +export const Address = z.object({ + addressId: z.string(), + clientId: z.string(), + provider: z.nativeEnum(Provider), + externalId: z.string(), + accountId: z.string(), + address: z.string(), + createdAt: z.date(), + updatedAt: z.date() +}) +export type Address = z.infer + +export const Account = z.object({ + accountId: z.string(), + label: z.string().nullable().optional(), + addresses: z.array(Address).optional(), + clientId: z.string(), + provider: z.string(), + externalId: z.string(), + walletId: z.string(), + networkId: z.string(), + createdAt: z.date(), + updatedAt: z.date() +}) +export type Account = z.infer + +export const Wallet = z.object({ + walletId: z.string(), + accounts: z.array(Account).optional(), + connections: z.array(BaseConnection).optional(), + label: z.string().nullable().optional(), + clientId: z.string(), + provider: z.string(), + externalId: z.string(), + createdAt: z.date(), + updatedAt: z.date() +}) +export type Wallet = z.infer + +export const PublicWallet = Wallet.extend({ + connections: z.array(PublicConnection) +}) +export type PublicWallet = z.infer diff --git a/apps/vault/src/broker/http/rest/controller/account.controller.ts b/apps/vault/src/broker/http/rest/controller/account.controller.ts new file mode 100644 index 000000000..fe1a9caba --- /dev/null +++ b/apps/vault/src/broker/http/rest/controller/account.controller.ts @@ -0,0 +1,87 @@ +import { Paginated, PaginationOptions, PaginationParam } from '@narval/nestjs-shared' +import { Controller, Get, HttpStatus, Param } from '@nestjs/common' +import { ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger' + +import { ClientId } from '../../../../shared/decorator/client-id.decorator' +import { AccountService } from '../../../core/service/account.service' +import { AccountDto } from '../dto/response/account.dto' +import { PaginatedAccountsDto } from '../dto/response/accounts.dto' +import { PaginatedAddressesDto } from '../dto/response/addresses.dto' + +@Controller({ + path: 'accounts', + version: '1' +}) +@ApiTags('Account') +export class AccountController { + constructor(private readonly accountService: AccountService) {} + + @Get() + @ApiOperation({ + summary: 'List the client accounts' + }) + @Paginated({ + type: PaginatedAccountsDto, + description: 'Returns a paginated list of accounts for the client' + }) + async listByClientId( + @ClientId() clientId: string, + @PaginationParam() options: PaginationOptions + ): Promise { + const { data, page } = await this.accountService.getAccounts(clientId, options) + const ret = PaginatedAccountsDto.create({ + accounts: data, + page + }) + return ret + } + + @Get(':accountId') + @ApiOperation({ + summary: 'Get a specific account by ID' + }) + @ApiParam({ + name: 'accountId', + description: 'The ID of the account to retrieve' + }) + @ApiResponse({ + status: HttpStatus.OK, + type: AccountDto + }) + @ApiResponse({ + status: HttpStatus.NOT_FOUND, + description: 'Account not found' + }) + async getAccountById(@ClientId() clientId: string, @Param('accountId') accountId: string): Promise { + const account = await this.accountService.getAccount(clientId, accountId) + return AccountDto.create({ account }) + } + + @Get(':accountId/addresses') + @ApiOperation({ + summary: 'List addresses for a specific account' + }) + @ApiParam({ + name: 'accountId', + description: 'The ID of the account to retrieve addresses for' + }) + @Paginated({ + type: PaginatedAddressesDto, + description: 'Returns a paginated list of addresses for the client' + }) + @ApiResponse({ + status: HttpStatus.NOT_FOUND, + description: 'Account not found' + }) + async getAccountAddresses( + @ClientId() clientId: string, + @Param('accountId') accountId: string, + @PaginationParam() options: PaginationOptions + ): Promise { + const { data, page } = await this.accountService.getAccountAddresses(clientId, accountId, options) + return PaginatedAddressesDto.create({ + addresses: data, + page + }) + } +} diff --git a/apps/vault/src/broker/http/rest/controller/address.controller.ts b/apps/vault/src/broker/http/rest/controller/address.controller.ts new file mode 100644 index 000000000..87f127f98 --- /dev/null +++ b/apps/vault/src/broker/http/rest/controller/address.controller.ts @@ -0,0 +1,57 @@ +import { Paginated, PaginationOptions, PaginationParam } from '@narval/nestjs-shared' +import { Controller, Get, HttpStatus, Param } from '@nestjs/common' +import { ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger' +import { ClientId } from '../../../../shared/decorator/client-id.decorator' +import { AddressService } from '../../../core/service/address.service' +import { AddressDto } from '../dto/response/address.dto' +import { PaginatedAddressesDto } from '../dto/response/addresses.dto' + +@Controller({ + path: 'addresses', + version: '1' +}) +@ApiTags('Address') +export class AddressController { + constructor(private readonly addressService: AddressService) {} + + @Get() + @ApiOperation({ + summary: 'List the client addresss' + }) + @Paginated({ + type: PaginatedAddressesDto, + description: 'Returns a paginated list of addresss for the client' + }) + async listByClientId( + @ClientId() clientId: string, + @PaginationParam() options: PaginationOptions + ): Promise { + const { data, page } = await this.addressService.getAddresses(clientId, options) + const ret = PaginatedAddressesDto.create({ + addresses: data, + page + }) + return ret + } + + @Get(':addressId') + @ApiOperation({ + summary: 'Get a specific address by ID' + }) + @ApiParam({ + name: 'addressId', + description: 'The ID of the address to retrieve' + }) + @ApiResponse({ + status: HttpStatus.OK, + type: PaginatedAddressesDto + }) + @ApiResponse({ + status: HttpStatus.NOT_FOUND, + description: 'Address not found' + }) + async getAddressById(@ClientId() clientId: string, @Param('addressId') addressId: string): Promise { + const address = await this.addressService.getAddress(clientId, addressId) + return AddressDto.create({ address }) + } +} diff --git a/apps/vault/src/broker/http/rest/controller/connection.controller.ts b/apps/vault/src/broker/http/rest/controller/connection.controller.ts index d07638a97..0fa034fd0 100644 --- a/apps/vault/src/broker/http/rest/controller/connection.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/connection.controller.ts @@ -1,3 +1,4 @@ +import { Paginated, PaginationOptions, PaginationParam } from '@narval/nestjs-shared' import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Patch, Post } from '@nestjs/common' import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../shared/decorator/client-id.decorator' @@ -5,9 +6,11 @@ import { ConnectionService } from '../../../core/service/connection.service' import { CreateConnectionDto } from '../dto/request/create-connection.dto' import { InitiateConnectionDto } from '../dto/request/initiate-connection.dto' import { UpdateConnectionDto } from '../dto/request/update-connection.dto' +import { PaginatedAccountsDto } from '../dto/response/accounts.dto' import { ConnectionListDto } from '../dto/response/connection-list.dto' import { ConnectionDto } from '../dto/response/connection.dto' import { PendingConnectionDto } from '../dto/response/pending-connection.dto' +import { PaginatedWalletsDto } from '../dto/response/wallets.dto' @Controller({ path: 'connections', @@ -123,4 +126,42 @@ export class ConnectionController { return ConnectionDto.create(connection) } + + @Get(':connectionId/wallets') + @ApiOperation({ + summary: 'List wallets for a specific connection', + description: 'This endpoint retrieves a list of wallets associated with a specific connection.' + }) + @Paginated({ + type: PaginatedWalletsDto, + description: 'Returns a paginated list of wallets associated with the connection' + }) + async getWallets( + @ClientId() clientId: string, + @Param('connectionId') connectionId: string, + @PaginationParam() options: PaginationOptions + ): Promise { + const { data, page } = await this.connectionService.findWallets(clientId, connectionId, options) + + return PaginatedWalletsDto.create({ wallets: data, page }) + } + + @Get(':connectionId/accounts') + @ApiOperation({ + summary: 'List accounts for a specific connection', + description: 'This endpoint retrieves a list of accounts associated with a specific connection.' + }) + @Paginated({ + type: PaginatedWalletsDto, + description: 'Returns a paginated list of accounts associated with the connection' + }) + async getAccounts( + @ClientId() clientId: string, + @Param('connectionId') connectionId: string, + @PaginationParam() options: PaginationOptions + ): Promise { + const { data, page } = await this.connectionService.findAccounts(clientId, connectionId, options) + + return PaginatedAccountsDto.create({ accounts: data, page }) + } } diff --git a/apps/vault/src/broker/http/rest/controller/wallet.controller.ts b/apps/vault/src/broker/http/rest/controller/wallet.controller.ts new file mode 100644 index 000000000..5b4d4661f --- /dev/null +++ b/apps/vault/src/broker/http/rest/controller/wallet.controller.ts @@ -0,0 +1,86 @@ +import { Paginated, PaginationOptions, PaginationParam } from '@narval/nestjs-shared' +import { Controller, Get, HttpStatus, Param } from '@nestjs/common' +import { ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger' + +import { ClientId } from '../../../../shared/decorator/client-id.decorator' +import { WalletService } from '../../../core/service/wallet.service' +import { PaginatedAccountsDto } from '../dto/response/accounts.dto' +import { WalletDto } from '../dto/response/wallet.dto' +import { PaginatedWalletsDto } from '../dto/response/wallets.dto' +@Controller({ + path: 'wallets', + version: '1' +}) +@ApiTags('Wallet') +export class WalletController { + constructor(private readonly walletService: WalletService) {} + + @Get() + @ApiOperation({ + summary: 'List the client wallets' + }) + @Paginated({ + type: PaginatedWalletsDto, + description: 'Returns a paginated list of wallets for the client' + }) + async listByClientId( + @ClientId() clientId: string, + @PaginationParam() options: PaginationOptions + ): Promise { + const { data, page } = await this.walletService.getWallets(clientId, options) + const ret = PaginatedWalletsDto.create({ + wallets: data, + page + }) + return ret + } + + @Get(':walletId') + @ApiOperation({ + summary: 'Get a specific wallet by ID' + }) + @ApiParam({ + name: 'walletId', + description: 'The ID of the wallet to retrieve' + }) + @ApiResponse({ + status: HttpStatus.OK, + type: WalletDto + }) + @ApiResponse({ + status: HttpStatus.NOT_FOUND, + description: 'Wallet not found' + }) + async getWalletById(@ClientId() clientId: string, @Param('walletId') walletId: string): Promise { + const wallet = await this.walletService.getWallet(clientId, walletId) + return WalletDto.create({ wallet }) + } + + @Get(':walletId/accounts') + @ApiOperation({ + summary: 'List accounts for a specific wallet' + }) + @ApiParam({ + name: 'walletId', + description: 'The ID of the wallet to retrieve accounts for' + }) + @Paginated({ + type: PaginatedWalletsDto, + description: 'Returns a paginated list of wallets for the client' + }) + @ApiResponse({ + status: HttpStatus.NOT_FOUND, + description: 'Wallet not found' + }) + async getWalletAccounts( + @ClientId() clientId: string, + @Param('walletId') walletId: string, + @PaginationParam() options: PaginationOptions + ): Promise { + const { data, page } = await this.walletService.getWalletAccounts(clientId, walletId, options) + return PaginatedAccountsDto.create({ + accounts: data, + page + }) + } +} diff --git a/apps/vault/src/broker/http/rest/dto/response/account.dto.ts b/apps/vault/src/broker/http/rest/dto/response/account.dto.ts new file mode 100644 index 000000000..a759a00fc --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/response/account.dto.ts @@ -0,0 +1,9 @@ +import { createZodDto } from 'nestjs-zod' +import { z } from 'zod' +import { Account } from '../../../../core/type/indexed-resources.type' + +export class AccountDto extends createZodDto( + z.object({ + account: Account + }) +) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/accounts.dto.ts b/apps/vault/src/broker/http/rest/dto/response/accounts.dto.ts new file mode 100644 index 000000000..9feef934c --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/response/accounts.dto.ts @@ -0,0 +1,8 @@ +import { createPaginatedDto } from '@narval/nestjs-shared' +import { z } from 'zod' +import { Account } from '../../../../core/type/indexed-resources.type' +export class PaginatedAccountsDto extends createPaginatedDto( + z.object({ + accounts: z.array(Account) + }) +) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/address.dto.ts b/apps/vault/src/broker/http/rest/dto/response/address.dto.ts new file mode 100644 index 000000000..570eab03b --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/response/address.dto.ts @@ -0,0 +1,9 @@ +import { createZodDto } from 'nestjs-zod' +import { z } from 'zod' +import { Address } from '../../../../core/type/indexed-resources.type' + +export class AddressDto extends createZodDto( + z.object({ + address: Address + }) +) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/addresses.dto.ts b/apps/vault/src/broker/http/rest/dto/response/addresses.dto.ts new file mode 100644 index 000000000..c646541e6 --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/response/addresses.dto.ts @@ -0,0 +1,8 @@ +import { createPaginatedDto } from '@narval/nestjs-shared' +import { z } from 'zod' +import { Address } from '../../../../core/type/indexed-resources.type' +export class PaginatedAddressesDto extends createPaginatedDto( + z.object({ + addresses: z.array(Address) + }) +) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/wallet.dto.ts b/apps/vault/src/broker/http/rest/dto/response/wallet.dto.ts new file mode 100644 index 000000000..4b165458f --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/response/wallet.dto.ts @@ -0,0 +1,9 @@ +import { createZodDto } from 'nestjs-zod' +import { z } from 'zod' +import { PublicWallet } from '../../../../core/type/indexed-resources.type' + +export class WalletDto extends createZodDto( + z.object({ + wallet: PublicWallet + }) +) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/wallets.dto.ts b/apps/vault/src/broker/http/rest/dto/response/wallets.dto.ts new file mode 100644 index 000000000..bf74179ae --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/response/wallets.dto.ts @@ -0,0 +1,9 @@ +import { createPaginatedDto } from '@narval/nestjs-shared' +import { z } from 'zod' +import { PublicWallet } from '../../../../core/type/indexed-resources.type' + +export class PaginatedWalletsDto extends createPaginatedDto( + z.object({ + wallets: z.array(PublicWallet) + }) +) {} diff --git a/apps/vault/src/broker/persistence/repository/account.repository.ts b/apps/vault/src/broker/persistence/repository/account.repository.ts new file mode 100644 index 000000000..9f48ae4a4 --- /dev/null +++ b/apps/vault/src/broker/persistence/repository/account.repository.ts @@ -0,0 +1,124 @@ +import { PaginatedResult, PaginationOptions, getPaginatedResult, getPaginationQuery } from '@narval/nestjs-shared' +import { Injectable } from '@nestjs/common' +import { ProviderAccount, ProviderAddress } from '@prisma/client/vault' +import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' +import { NotFoundException } from '../../core/exception/not-found.exception' +import { Account, Address } from '../../core/type/indexed-resources.type' +import { AddressRepository } from './address.repository' + +type ProviderAccountAndRelations = ProviderAccount & { + addresses: ProviderAddress[] +} + +type AccountFilters = { + connectionId?: string + walletId?: string +} +@Injectable() +export class AccountRepository { + constructor(private prismaService: PrismaService) {} + + static getCursorOrderColumns(): Array { + return ['createdAt'] + } + + static parseModel(account: ProviderAccountAndRelations): Account { + return { + ...account, + accountId: account.id, + addresses: account.addresses.map(AddressRepository.map) + } + } + + async findByClientId(clientId: string, options?: PaginationOptions): Promise> { + const pagination = getPaginationQuery({ options, cursorOrderColumns: AccountRepository.getCursorOrderColumns() }) + + const result = await this.prismaService.providerAccount.findMany({ + where: { clientId }, + include: { + addresses: true + }, + ...pagination + }) + const { data, page } = getPaginatedResult({ items: result, options: pagination }) + return { + data: data.map(AccountRepository.parseModel), + page + } + } + + async findById(clientId: string, accountId: string): Promise { + const account = await this.prismaService.providerAccount.findUnique({ + where: { clientId, id: accountId }, + include: { + addresses: true + } + }) + if (!account) { + throw new NotFoundException({ + message: 'Account not found', + context: { accountId } + }) + } + + return AccountRepository.parseModel(account) + } + + async findAddressesByAccountId( + clientId: string, + accountId: string, + options: PaginationOptions + ): Promise> { + const pagination = getPaginationQuery({ options, cursorOrderColumns: AccountRepository.getCursorOrderColumns() }) + + const account = await this.prismaService.providerAccount.findUnique({ + where: { clientId, id: accountId }, + include: { + addresses: true, + ...pagination + } + }) + if (!account) { + throw new NotFoundException({ + message: 'Account not found', + context: { accountId } + }) + } + const { data, page } = getPaginatedResult({ items: account.addresses, options: pagination }) + return { + data: data.map(AddressRepository.map), + page + } + } + + async findAll( + clientId: string, + filters?: AccountFilters, + options?: PaginationOptions + ): Promise> { + const pagination = getPaginationQuery({ options, cursorOrderColumns: AccountRepository.getCursorOrderColumns() }) + const result = await this.prismaService.providerAccount.findMany({ + where: { + clientId, + walletId: filters?.walletId, + wallet: { + connections: { + some: { + connectionId: filters?.connectionId + } + } + } + }, + include: { + addresses: true + }, + ...pagination + }) + const { data, page } = getPaginatedResult({ items: result, options: pagination }) + + return { + data: data.map(AccountRepository.parseModel), + page + } + } +} diff --git a/apps/vault/src/broker/persistence/repository/address.repository.ts b/apps/vault/src/broker/persistence/repository/address.repository.ts new file mode 100644 index 000000000..434a37940 --- /dev/null +++ b/apps/vault/src/broker/persistence/repository/address.repository.ts @@ -0,0 +1,54 @@ +import { PaginatedResult, PaginationOptions, getPaginatedResult, getPaginationQuery } from '@narval/nestjs-shared' +import { Injectable } from '@nestjs/common' +import { ProviderAddress } from '@prisma/client/vault' +import { z } from 'zod' +import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' +import { NotFoundException } from '../../core/exception/not-found.exception' +import { Provider } from '../../core/type/connection.type' +import { Address } from '../../core/type/indexed-resources.type' + +@Injectable() +export class AddressRepository { + constructor(private prismaService: PrismaService) {} + + static getCursorOrderColumns(): Array { + return ['createdAt'] + } + + static map(address: ProviderAddress): Address { + return { + ...address, + provider: z.nativeEnum(Provider).parse(address.provider), + addressId: address.id + } + } + + async findByClientId(clientId: string, options?: PaginationOptions): Promise> { + const pagination = getPaginationQuery({ options, cursorOrderColumns: AddressRepository.getCursorOrderColumns() }) + + const result = await this.prismaService.providerAddress.findMany({ + where: { clientId }, + ...pagination + }) + + const { data, page } = getPaginatedResult({ items: result, options: pagination }) + return { + data: data.map(AddressRepository.map), + page + } + } + + async findById(clientId: string, addressId: string): Promise
{ + const address = await this.prismaService.providerAddress.findUnique({ + where: { clientId, id: addressId } + }) + if (!address) { + throw new NotFoundException({ + message: 'Address not found', + context: { addressId } + }) + } + + return AddressRepository.map(address) + } +} diff --git a/apps/vault/src/broker/persistence/repository/connection.repository.ts b/apps/vault/src/broker/persistence/repository/connection.repository.ts index f25fd47dd..f7ae192f8 100644 --- a/apps/vault/src/broker/persistence/repository/connection.repository.ts +++ b/apps/vault/src/broker/persistence/repository/connection.repository.ts @@ -23,7 +23,11 @@ type UpdateConnection = { export class ConnectionRepository { constructor(private prismaService: PrismaService) {} - static map(model?: ProviderConnection | null): Connection { + static getCursorOrderColumns(): Array { + return ['createdAt'] + } + + static parseModel(model?: ProviderConnection | null): Connection { const parse = Connection.safeParse({ ...model, connectionId: model?.id, @@ -100,7 +104,7 @@ export class ConnectionRepository { }) if (model) { - return ConnectionRepository.map(model) + return ConnectionRepository.parseModel(model) } throw new NotFoundException({ context: { clientId, connectionId } }) @@ -111,7 +115,7 @@ export class ConnectionRepository { where: { clientId } }) - return models.map(ConnectionRepository.map) + return models.map(ConnectionRepository.parseModel) } async exists(clientId: string, id: string): Promise { diff --git a/apps/vault/src/broker/persistence/repository/wallet.repository.ts b/apps/vault/src/broker/persistence/repository/wallet.repository.ts new file mode 100644 index 000000000..f677df6a8 --- /dev/null +++ b/apps/vault/src/broker/persistence/repository/wallet.repository.ts @@ -0,0 +1,171 @@ +import { PaginatedResult, PaginationOptions, getPaginatedResult, getPaginationQuery } from '@narval/nestjs-shared' +import { Injectable } from '@nestjs/common' +import { ProviderAccount, ProviderAddress, ProviderConnection, ProviderWallet } from '@prisma/client/vault' +import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' +import { NotFoundException } from '../../core/exception/not-found.exception' +import { Account, Wallet } from '../../core/type/indexed-resources.type' +import { AccountRepository } from './account.repository' +import { ConnectionRepository } from './connection.repository' + +type ProviderWalletsAndRelations = ProviderWallet & { + connections: { connection: ProviderConnection }[] + accounts: Array< + ProviderAccount & { + addresses: ProviderAddress[] + } + > +} + +type WalletFilters = { + connectionId: string +} + +@Injectable() +export class WalletRepository { + constructor(private prismaService: PrismaService) {} + + static getCursorOrderColumns(): Array { + return ['createdAt'] + } + + static parseModel(wallet: ProviderWalletsAndRelations): Wallet { + const { connections, accounts, id, ...walletData } = wallet + + const validConnections = connections.map((join) => { + return ConnectionRepository.parseModel(join.connection) + }) + + const mappedAccounts = accounts.map((account) => { + return AccountRepository.parseModel(account) + }) + + return { + ...walletData, + walletId: id, + accounts: mappedAccounts, + connections: validConnections + } + } + + async findByClientId(clientId: string, options?: PaginationOptions): Promise> { + const pagination = getPaginationQuery({ options, cursorOrderColumns: WalletRepository.getCursorOrderColumns() }) + const result = await this.prismaService.providerWallet.findMany({ + where: { clientId }, + include: { + accounts: { + include: { + addresses: true + } + }, + connections: { + include: { + connection: true + } + } + }, + ...pagination + }) + const { data, page } = getPaginatedResult({ items: result, options: pagination }) + + return { + data: data.map(WalletRepository.parseModel), + page + } + } + + async findById(clientId: string, id: string): Promise { + const wallet = await this.prismaService.providerWallet.findUnique({ + where: { clientId, id }, + include: { + accounts: { + include: { + addresses: true + } + }, + connections: { + include: { + connection: true + } + } + } + }) + if (!wallet) { + throw new NotFoundException({ + message: 'Wallet not found', + context: { walletId: id } + }) + } + + return WalletRepository.parseModel(wallet) + } + + async findAll( + clientId: string, + filters: WalletFilters, + options: PaginationOptions + ): Promise> { + const pagination = getPaginationQuery({ options, cursorOrderColumns: WalletRepository.getCursorOrderColumns() }) + const result = await this.prismaService.providerWallet.findMany({ + where: { + clientId, + connections: { + some: { + connectionId: filters.connectionId + } + } + }, + include: { + accounts: { + include: { + addresses: true + } + }, + connections: { + include: { + connection: true + } + } + }, + ...pagination + }) + const { data, page } = getPaginatedResult({ items: result, options: pagination }) + + return { + data: data.map(WalletRepository.parseModel), + page + } + } + + async findAccountsByWalletId( + clientId: string, + walletId: string, + options: PaginationOptions + ): Promise> { + const pagination = getPaginationQuery({ options, cursorOrderColumns: AccountRepository.getCursorOrderColumns() }) + + const wallet = await this.prismaService.providerWallet.findUnique({ + where: { clientId, id: walletId }, + include: { + accounts: { + include: { + addresses: true + }, + ...pagination + }, + connections: true + } + }) + if (!wallet) { + throw new NotFoundException({ + message: 'Wallet not found', + context: { walletId } + }) + } + const { data, page } = getPaginatedResult({ items: wallet.accounts, options: pagination }) + + return { + data: data.map(AccountRepository.parseModel), + page + } + } +} diff --git a/apps/vault/src/shared/module/persistence/service/test-prisma.service.ts b/apps/vault/src/shared/module/persistence/service/test-prisma.service.ts index 0bfa9ad36..0f9b45051 100644 --- a/apps/vault/src/shared/module/persistence/service/test-prisma.service.ts +++ b/apps/vault/src/shared/module/persistence/service/test-prisma.service.ts @@ -1,5 +1,12 @@ import { Injectable } from '@nestjs/common' import { PrismaClient } from '@prisma/client/vault' +import { + TEST_ACCOUNTS, + TEST_ADDRESSES, + TEST_CONNECTIONS, + TEST_WALLET_CONNECTIONS, + TEST_WALLETS +} from '../../../../broker/__test__/util/mock-data' import { PrismaService } from './prisma.service' @Injectable() @@ -29,4 +36,27 @@ export class TestPrismaService { } } } + + async seedBrokerTestData(): Promise { + const client = this.getClient() + await client.providerWallet.createMany({ + data: TEST_WALLETS + }) + + await client.providerConnection.createMany({ + data: TEST_CONNECTIONS + }) + + await client.providerWalletConnection.createMany({ + data: TEST_WALLET_CONNECTIONS + }) + + await client.providerAccount.createMany({ + data: TEST_ACCOUNTS + }) + + await client.providerAddress.createMany({ + data: TEST_ADDRESSES + }) + } } diff --git a/packages/nestjs-shared/src/lib/__test__/unit/pagination.spec.ts b/packages/nestjs-shared/src/lib/__test__/unit/pagination.spec.ts new file mode 100644 index 000000000..6d4422c30 --- /dev/null +++ b/packages/nestjs-shared/src/lib/__test__/unit/pagination.spec.ts @@ -0,0 +1,109 @@ +import { describe, expect, it } from '@jest/globals' +import { PaginationOptions } from '../../type/pagination.type' +import { getPaginatedResult, getPaginationQuery } from '../../util/pagination.util' + +describe('Pagination Utilities', () => { + // Sample data for testing + const testData = [ + { id: '1', createdAt: new Date('2024-01-01'), name: 'Item 1' }, + { id: '2', createdAt: new Date('2024-01-02'), name: 'Item 2' }, + { id: '3', createdAt: new Date('2024-01-03'), name: 'Item 3' }, + { id: '4', createdAt: new Date('2024-01-04'), name: 'Item 4' }, + { id: '5', createdAt: new Date('2024-01-05'), name: 'Item 5' } + ] + + describe('getPaginatedResult', () => { + it('returns correct number of items with take parameter', () => { + const result = getPaginatedResult({ + items: testData.slice(0, 3), + options: getPaginationQuery({ + options: PaginationOptions.parse({ limit: 2 }), + cursorOrderColumns: ['createdAt'] + }) + }) + expect(result.data).toHaveLength(2) + expect(result.data[0]).toEqual(testData[0]) + expect(result.data[1]).toEqual(testData[1]) + expect(result.page?.next).toBeDefined() + }) + + it('returns undefined next cursor on last page', () => { + const result = getPaginatedResult({ + items: testData, + options: getPaginationQuery({ + options: PaginationOptions.parse({ limit: 10 }), + cursorOrderColumns: ['createdAt'] + }) + }) + expect(result.data).toHaveLength(5) + expect(result.page?.next).toBeUndefined() + }) + + it('works with cursor-based pagination', () => { + // First page + const firstPage = getPaginatedResult({ + items: testData.slice(0, 3), + options: getPaginationQuery({ + options: PaginationOptions.parse({ limit: 2 }), + cursorOrderColumns: ['createdAt'] + }) + }) + expect(firstPage.data).toHaveLength(2) + expect(firstPage.page?.next).toBeDefined() + + // Second page using cursor + const secondPage = getPaginatedResult({ + items: testData.slice(2), + options: getPaginationQuery({ + options: PaginationOptions.parse({ limit: 2, cursor: firstPage.page?.next }), + cursorOrderColumns: ['createdAt'] + }) + }) + + expect(secondPage.data).toHaveLength(2) + expect(secondPage.data[0]).toEqual(testData[2]) + }) + }) + + describe('getPaginationQuery', () => { + it('handles empty options', () => { + const query = getPaginationQuery({ cursorOrderColumns: [] }) + expect(query.take).toBeUndefined() + expect(query.skip).toBeUndefined() + expect(query.cursor).toBeUndefined() + }) + + it('defaults lets you orderBy createdAt', () => { + const query = getPaginationQuery({ + options: PaginationOptions.parse({ limit: 10, orderBy: 'createdAt' }), + cursorOrderColumns: ['createdAt'] + }) + expect(query.orderBy).toEqual({ createdAt: 'asc' }) + }) + + it('lets you provide custom orderByFields', () => { + const query = getPaginationQuery({ + options: PaginationOptions.parse({ limit: 10, orderBy: 'name' }), + cursorOrderColumns: ['name'] + }) + expect(query.orderBy).toEqual({ name: 'asc' }) + }) + + it('throws error for invalid orderByFields', () => { + expect(() => + getPaginationQuery({ + options: PaginationOptions.parse({ limit: 10, orderBy: 'name' }), + cursorOrderColumns: ['createdAt'] + }) + ).toThrow() + }) + + it('adds extra record for cursor calculation', () => { + const query = getPaginationQuery({ + options: PaginationOptions.parse({ limit: 10 }), + cursorOrderColumns: ['createdAt'] + }) + expect(query.take).toBe(11) + }) + }) +}) diff --git a/packages/nestjs-shared/src/lib/decorator/index.ts b/packages/nestjs-shared/src/lib/decorator/index.ts index 3896a386b..2b7af26b8 100644 --- a/packages/nestjs-shared/src/lib/decorator/index.ts +++ b/packages/nestjs-shared/src/lib/decorator/index.ts @@ -2,3 +2,5 @@ export * from './api-gnap-security.decorator' export * from './is-hex-string.decorator' export * from './is-not-empty-array-enum.decorator' export * from './is-not-empty-array-string.decorator' +export * from './pagination-param.decorator' +export * from './pagination.decorator' diff --git a/packages/nestjs-shared/src/lib/decorator/pagination-param.decorator.ts b/packages/nestjs-shared/src/lib/decorator/pagination-param.decorator.ts new file mode 100644 index 000000000..9f0623aef --- /dev/null +++ b/packages/nestjs-shared/src/lib/decorator/pagination-param.decorator.ts @@ -0,0 +1,7 @@ +import { createParamDecorator, ExecutionContext } from '@nestjs/common' +import { PaginationOptions } from '../type/pagination.type' + +export const PaginationParam = createParamDecorator((_data: unknown, context: ExecutionContext): PaginationOptions => { + const req = context.switchToHttp().getRequest() + return PaginationOptions.parse(req.query) +}) diff --git a/packages/nestjs-shared/src/lib/decorator/pagination.decorator.ts b/packages/nestjs-shared/src/lib/decorator/pagination.decorator.ts new file mode 100644 index 000000000..97dcef7e2 --- /dev/null +++ b/packages/nestjs-shared/src/lib/decorator/pagination.decorator.ts @@ -0,0 +1,60 @@ +import { applyDecorators, Type } from '@nestjs/common' +import { ApiQuery, ApiResponse, getSchemaPath } from '@nestjs/swagger' + +type PaginatedDecoratorOptions = { + type: Type + summary?: string + description?: string +} + +export function Paginated(options: PaginatedDecoratorOptions) { + return applyDecorators( + ApiQuery({ + name: 'cursor', + required: false, + type: String, + description: 'Cursor for pagination. Use the next cursor from previous response to get next page' + }), + ApiQuery({ + name: 'limit', + required: false, + type: Number, + description: 'Number of records to return per page' + }), + ApiQuery({ + name: 'orderBy', + required: false, + type: String, + description: 'Field to order results by' + }), + ApiQuery({ + name: 'desc', + required: false, + type: String, + description: 'Set to "true" or "1" for descending order' + }), + ApiResponse({ + status: 200, + description: options.description || 'Successfully retrieved paginated list', + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { $ref: getSchemaPath(options.type) } + }, + page: { + type: 'object', + properties: { + next: { + type: 'string', + description: 'Cursor for the next page of results', + nullable: true + } + } + } + } + } + }) + ) +} diff --git a/packages/nestjs-shared/src/lib/dto/index.ts b/packages/nestjs-shared/src/lib/dto/index.ts index 6e69c84b0..0985667a8 100644 --- a/packages/nestjs-shared/src/lib/dto/index.ts +++ b/packages/nestjs-shared/src/lib/dto/index.ts @@ -1,5 +1,6 @@ export * from './base-action-request.dto' export * from './base-action.dto' +export * from './paginated.dto' export * from './sign-message-request-data-dto' export * from './sign-transaction-request-data.dto' export * from './signature.dto' diff --git a/packages/nestjs-shared/src/lib/dto/paginated.dto.ts b/packages/nestjs-shared/src/lib/dto/paginated.dto.ts new file mode 100644 index 000000000..d924c406b --- /dev/null +++ b/packages/nestjs-shared/src/lib/dto/paginated.dto.ts @@ -0,0 +1,19 @@ +import { createZodDto } from 'nestjs-zod' +import { z } from 'zod' +import { Page } from '../type/pagination.type' + +export function createPaginatedDto>(baseSchema: T) { + const paginatedSchema = baseSchema.extend({ + page: Page.optional() + }) + + return class PaginatedDto extends createZodDto(paginatedSchema) { + static create(data: z.infer): PaginatedDto { + // Parse the data through the schema to trigger transformations + const validated = paginatedSchema.parse(data) + // Create instance and assign parsed data + const instance = new this() + return Object.assign(instance, validated) + } + } +} diff --git a/packages/nestjs-shared/src/lib/type/index.ts b/packages/nestjs-shared/src/lib/type/index.ts index b28a74e4b..041e9070b 100644 --- a/packages/nestjs-shared/src/lib/type/index.ts +++ b/packages/nestjs-shared/src/lib/type/index.ts @@ -1 +1,2 @@ export * from './json.type' +export * from './pagination.type' diff --git a/packages/nestjs-shared/src/lib/type/pagination.type.ts b/packages/nestjs-shared/src/lib/type/pagination.type.ts new file mode 100644 index 000000000..54e7db5e7 --- /dev/null +++ b/packages/nestjs-shared/src/lib/type/pagination.type.ts @@ -0,0 +1,49 @@ +import { z } from 'zod' + +export const Page = z + .object({ + next: z.string().optional() + }) + .optional() + +export type Page = z.infer + +export const createPaginatedSchema = (itemSchema: T) => + z.object({ + data: z.array(itemSchema), + page: Page.optional() + }) + +export type PaginatedResult = z.infer>>> + +export const PaginationOptions = z + .object({ + cursor: z.string().optional(), + limit: z.coerce.number().min(1).max(100).default(25).optional(), + orderBy: z.string().optional(), + desc: z + .string() + .optional() + .transform((val) => val === 'true') + // TODO: @ptroger remamed 'desc' into 'sortOrder' that defaults to 'asc' and is optional + }) + .transform((data) => ({ + cursor: data.cursor, + limit: data.limit, + orderBy: data.orderBy + ? { + [data.orderBy]: data.desc ? ('desc' as const) : ('asc' as const) + } + : undefined + })) + +export type PaginationOptions = z.infer + +export type PrismaPagination = { + take?: number + cursor?: { + id: string + } + skip?: number + orderBy?: Record +} diff --git a/packages/nestjs-shared/src/lib/util/index.ts b/packages/nestjs-shared/src/lib/util/index.ts index a2de1c1aa..b43a9b99f 100644 --- a/packages/nestjs-shared/src/lib/util/index.ts +++ b/packages/nestjs-shared/src/lib/util/index.ts @@ -1,6 +1,7 @@ export * as coerce from './coerce.util' export * as secret from './secret.util' +export * from './pagination.util' export * from './with-api-version.util' export * from './with-cors.util' export * from './with-swagger.util' diff --git a/packages/nestjs-shared/src/lib/util/pagination.util.ts b/packages/nestjs-shared/src/lib/util/pagination.util.ts new file mode 100644 index 000000000..22c42b1dc --- /dev/null +++ b/packages/nestjs-shared/src/lib/util/pagination.util.ts @@ -0,0 +1,71 @@ +import { z } from 'zod' +import { PaginatedResult, PaginationOptions, PrismaPagination } from '../type/pagination.type' + +export function getPaginatedResult({ + items, + options +}: { + items: T[] + options?: PrismaPagination +}): PaginatedResult { + if (!items || items.length === 0) { + return { + data: [], + page: { next: undefined } + } + } + + // limit was increased by one to determine if there's more data + // if limit === items.length, then there's at least one more item + // if limit > items.length, then there's no more data + // if limit === 0, pagination is disabled + const hasNextPage = options?.take && options?.take > 1 && items.length === options.take + + // If there's more data, remove the last item from the list (which is the first item of the next page) + const data = hasNextPage ? items.slice(0, items.length - 1) : items + + return { + data, + page: { + // cursor is the id of the last item that is actually returned + // we can safely access the last item because we know for sure there's at least one more item + next: hasNextPage ? items[items.length - 2]?.id : undefined + } + } +} + +export function getPaginationQuery({ + options, + cursorOrderColumns +}: { + options?: PaginationOptions + cursorOrderColumns: string[] +}): PrismaPagination { + // If no valid fields are provided, default to createdAt + // If someone tries createdAt on a model that doesn't have it, we will throw a 500 + + const validOrderBySchema = z.string().refine( + (value) => cursorOrderColumns.includes(value), + (value) => ({ message: `Invalid orderBy field: ${value}. Valid fields are: ${cursorOrderColumns.join(', ')}` }) + ) + + const key = options?.orderBy && Object.keys(options.orderBy)[0] + + if (key) { + validOrderBySchema.parse(key) + } + + return { + // if limit is enabled (meaning pagination), limit is increased by one to determine if there's more data + // if limit == 0, pagination is disabled + take: typeof options?.limit === 'number' && options.limit > 0 ? options.limit + 1 : undefined, + ...(options?.cursor && { + cursor: { + id: options.cursor + }, + // Skip the cursor record if it was provided + skip: options.cursor ? 1 : undefined + }), + orderBy: options?.orderBy + } +} From 44255a066df2b7bfb7adc9994429e03ba44f5f8e Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Fri, 13 Dec 2024 10:32:08 +0100 Subject: [PATCH 029/120] Add sync API (#19) * Add sync API * Fix minor tasks from last PR * Fix wrong param name * Add pagination in the sync API * Fix pagination decorator type * Fix pagination DTO * Add pagination on the connection * Add connection pagination * Fix unit test * Fix wrong zod default usage --- .../src/broker/__test__/e2e/account.spec.ts | 20 +- .../src/broker/__test__/e2e/address.spec.ts | 4 +- .../broker/__test__/e2e/connection.spec.ts | 34 ++- .../src/broker/__test__/e2e/sync.spec.ts | 273 ++++++++++++++++++ .../src/broker/__test__/e2e/wallet.spec.ts | 22 +- apps/vault/src/broker/broker.module.ts | 24 +- .../broker/core/service/address.service.ts | 2 +- .../broker/core/service/connection.service.ts | 14 +- .../src/broker/core/service/sync.service.ts | 78 +++++ apps/vault/src/broker/core/type/sync.type.ts | 34 +++ .../rest/controller/account.controller.ts | 11 +- .../rest/controller/address.controller.ts | 11 +- .../rest/controller/connection.controller.ts | 24 +- .../http/rest/controller/sync.controller.ts | 72 +++++ .../http/rest/controller/wallet.controller.ts | 10 +- .../http/rest/dto/request/start-sync.dto.ts | 4 + .../http/rest/dto/response/accounts.dto.ts | 8 - .../http/rest/dto/response/addresses.dto.ts | 8 - .../dto/response/paginated-accounts.dto.ts | 11 + .../dto/response/paginated-addresses.dto.ts | 11 + .../dto/response/paginated-connections.dto.ts | 11 + .../rest/dto/response/paginated-syncs.dto.ts | 11 + .../dto/response/paginated-wallets.dto.ts | 11 + .../http/rest/dto/response/sync-list.dto.ts | 9 + .../http/rest/dto/response/sync-status.dto.ts | 10 + .../broker/http/rest/dto/response/sync.dto.ts | 4 + .../http/rest/dto/response/wallets.dto.ts | 9 - .../repository/connection.repository.ts | 40 ++- .../persistence/repository/sync.repository.ts | 109 +++++++ apps/vault/src/main.module.ts | 10 +- .../core/service/encryption-key.service.ts | 4 +- .../controller/encryption-key.controller.ts | 0 .../src/lib/__test__/unit/pagination.spec.ts | 4 +- .../src/lib/decorator/pagination.decorator.ts | 26 +- packages/nestjs-shared/src/lib/dto/index.ts | 1 - .../src/lib/dto/paginated.dto.ts | 19 -- .../src/lib/type/pagination.type.ts | 4 +- .../src/lib/util/pagination.util.ts | 4 +- .../src/lib/__test__/unit/util.spec.ts | 3 +- 39 files changed, 836 insertions(+), 128 deletions(-) create mode 100644 apps/vault/src/broker/__test__/e2e/sync.spec.ts create mode 100644 apps/vault/src/broker/core/service/sync.service.ts create mode 100644 apps/vault/src/broker/core/type/sync.type.ts create mode 100644 apps/vault/src/broker/http/rest/controller/sync.controller.ts create mode 100644 apps/vault/src/broker/http/rest/dto/request/start-sync.dto.ts delete mode 100644 apps/vault/src/broker/http/rest/dto/response/accounts.dto.ts delete mode 100644 apps/vault/src/broker/http/rest/dto/response/addresses.dto.ts create mode 100644 apps/vault/src/broker/http/rest/dto/response/paginated-accounts.dto.ts create mode 100644 apps/vault/src/broker/http/rest/dto/response/paginated-addresses.dto.ts create mode 100644 apps/vault/src/broker/http/rest/dto/response/paginated-connections.dto.ts create mode 100644 apps/vault/src/broker/http/rest/dto/response/paginated-syncs.dto.ts create mode 100644 apps/vault/src/broker/http/rest/dto/response/paginated-wallets.dto.ts create mode 100644 apps/vault/src/broker/http/rest/dto/response/sync-list.dto.ts create mode 100644 apps/vault/src/broker/http/rest/dto/response/sync-status.dto.ts create mode 100644 apps/vault/src/broker/http/rest/dto/response/sync.dto.ts delete mode 100644 apps/vault/src/broker/http/rest/dto/response/wallets.dto.ts create mode 100644 apps/vault/src/broker/persistence/repository/sync.repository.ts delete mode 100644 apps/vault/src/transit-encryption/http/rest/controller/encryption-key.controller.ts delete mode 100644 packages/nestjs-shared/src/lib/dto/paginated.dto.ts diff --git a/apps/vault/src/broker/__test__/e2e/account.spec.ts b/apps/vault/src/broker/__test__/e2e/account.spec.ts index bd4e37c0b..720c8065a 100644 --- a/apps/vault/src/broker/__test__/e2e/account.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/account.spec.ts @@ -57,7 +57,9 @@ describe('Account', () => { expect(response.body).toEqual({ accounts: TEST_ACCOUNTS.map(getExpectedAccount), - page: {} + page: { + next: null + } }) }) @@ -67,7 +69,10 @@ describe('Account', () => { .set(REQUEST_HEADER_CLIENT_ID, 'unknown-client') expect(response.status).toEqual(HttpStatus.OK) - expect(response.body).toEqual({ accounts: [], page: {} }) + expect(response.body).toEqual({ + accounts: [], + page: { next: null } + }) }) }) @@ -156,7 +161,9 @@ describe('Account', () => { expect(response.body).toEqual({ addresses: addresses.map(getExpectedAddress), - page: {} + page: { + next: null + } }) }) @@ -174,7 +181,12 @@ describe('Account', () => { .get(`/accounts/${accountWithoutAddresses.id}/addresses`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) expect(response.status).toEqual(HttpStatus.OK) - expect(response.body).toEqual({ addresses: [], page: {} }) + expect(response.body).toEqual({ + addresses: [], + page: { + next: null + } + }) }) }) }) diff --git a/apps/vault/src/broker/__test__/e2e/address.spec.ts b/apps/vault/src/broker/__test__/e2e/address.spec.ts index 9212dace6..d1348bdcf 100644 --- a/apps/vault/src/broker/__test__/e2e/address.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/address.spec.ts @@ -59,7 +59,9 @@ describe('Address', () => { expect(response.body).toEqual({ addresses: TEST_ADDRESSES.map(getExpectedAddress), - page: {} + page: { + next: null + } }) }) }) diff --git a/apps/vault/src/broker/__test__/e2e/connection.spec.ts b/apps/vault/src/broker/__test__/e2e/connection.spec.ts index 8405084ec..fff629072 100644 --- a/apps/vault/src/broker/__test__/e2e/connection.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/connection.spec.ts @@ -338,7 +338,7 @@ describe('Connection', () => { }) describe('GET /connections', () => { - it('responds with connections from the given client', async () => { + beforeEach(async () => { await Promise.all( times(3, async () => connectionService.create(clientId, { @@ -353,7 +353,9 @@ describe('Connection', () => { }) ) ) + }) + it('responds with connections from the given client', async () => { const { status, body } = await request(app.getHttpServer()) .get('/connections') .set(REQUEST_HEADER_CLIENT_ID, clientId) @@ -375,6 +377,34 @@ describe('Connection', () => { expect(status).toEqual(HttpStatus.OK) }) + + it('responds with limited number of syncs when limit is given', async () => { + const { body } = await request(app.getHttpServer()) + .get('/connections') + .query({ limit: 1 }) + .set(REQUEST_HEADER_CLIENT_ID, clientId) + + expect(body.connections.length).toEqual(1) + expect(body.page).toHaveProperty('next') + }) + + it('responds the next page of results when cursos is given', async () => { + const { body: pageOne } = await request(app.getHttpServer()) + .get('/connections') + .query({ limit: 1 }) + .set(REQUEST_HEADER_CLIENT_ID, clientId) + + const { body: pageTwo } = await request(app.getHttpServer()) + .get('/connections') + .query({ + limit: 1, + cursor: pageOne.page.next + }) + .set(REQUEST_HEADER_CLIENT_ID, clientId) + + expect(pageTwo.connections.length).toEqual(1) + expect(pageTwo.page).toHaveProperty('next') + }) }) describe('GET /connections/:connectionId', () => { @@ -428,7 +458,7 @@ describe('Connection', () => { apiKey: 'new-api-key', privateKey: await privateKeyToHex(newPrivateKey) } - const encryptionKey = await encryptionKeyService.generate(clientId, { modulusLenght: 2048 }) + const encryptionKey = await encryptionKeyService.generate(clientId, { modulusLength: 2048 }) const encryptedCredentials = await rsaEncrypt(JSON.stringify(newCredentials), encryptionKey.publicKey) const { status, body } = await request(app.getHttpServer()) diff --git a/apps/vault/src/broker/__test__/e2e/sync.spec.ts b/apps/vault/src/broker/__test__/e2e/sync.spec.ts new file mode 100644 index 000000000..d47832afe --- /dev/null +++ b/apps/vault/src/broker/__test__/e2e/sync.spec.ts @@ -0,0 +1,273 @@ +import { ConfigModule } from '@narval/config-module' +import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' +import { Alg, generateJwk, privateKeyToHex } from '@narval/signature' +import { HttpStatus, INestApplication } from '@nestjs/common' +import { Test, TestingModule } from '@nestjs/testing' +import request from 'supertest' +import { v4 as uuid } from 'uuid' +import { load } from '../../../main.config' +import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' +import { BrokerModule } from '../../broker.module' +import { ConnectionService } from '../../core/service/connection.service' +import { SyncService } from '../../core/service/sync.service' +import { ActiveConnection, PendingConnection, Provider } from '../../core/type/connection.type' + +describe('Sync', () => { + let app: INestApplication + let module: TestingModule + let syncService: SyncService + let connectionService: ConnectionService + let testPrismaService: TestPrismaService + + let activeConnectionOne: ActiveConnection + // eslint-disable-next-line @typescript-eslint/no-unused-vars + let activeConnectionTwo: ActiveConnection + // eslint-disable-next-line @typescript-eslint/no-unused-vars + let pendingConnection: PendingConnection + + const url = 'http://provider.narval.xyz' + + const apiKey = 'test-api-key' + + const clientId = uuid() + + beforeAll(async () => { + module = await Test.createTestingModule({ + imports: [ + LoggerModule.forTest(), + ConfigModule.forRoot({ + load: [load], + isGlobal: true + }), + BrokerModule + ] + }).compile() + + app = module.createNestApplication() + + testPrismaService = module.get(TestPrismaService) + syncService = module.get(SyncService) + connectionService = module.get(ConnectionService) + + await testPrismaService.truncateAll() + + await app.init() + }) + + afterAll(async () => { + await testPrismaService.truncateAll() + await module.close() + await app.close() + }) + + beforeEach(async () => { + await testPrismaService.truncateAll() + + activeConnectionOne = await connectionService.create(clientId, { + connectionId: uuid(), + provider: Provider.ANCHORAGE, + url, + credentials: { + apiKey, + privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) + } + }) + + activeConnectionTwo = await connectionService.create(clientId, { + connectionId: uuid(), + provider: Provider.ANCHORAGE, + url, + credentials: { + apiKey, + privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) + } + }) + + pendingConnection = await connectionService.initiate(clientId, { + connectionId: uuid(), + provider: Provider.ANCHORAGE + }) + }) + + describe('POST /syncs', () => { + it('starts a sync on every active connection', async () => { + const { status, body } = await request(app.getHttpServer()) + .post('/syncs') + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .send() + + const syncs = await syncService.findAllPaginated(clientId) + const [syncOne, syncTwo] = syncs.data + + expect(body).toMatchObject({ + started: true, + syncs: [ + { + clientId: syncOne.clientId, + connectionId: syncOne.connectionId, + createdAt: syncOne.createdAt.toISOString(), + syncId: syncOne.syncId, + status: syncOne.status + }, + { + clientId: syncTwo.clientId, + connectionId: syncTwo.connectionId, + createdAt: syncTwo.createdAt.toISOString(), + syncId: syncTwo.syncId, + status: syncTwo.status + } + ] + }) + + expect(status).toEqual(HttpStatus.CREATED) + + expect(syncs.data.length).toEqual(2) + }) + + it('starts a sync on the given connection', async () => { + const { status, body } = await request(app.getHttpServer()) + .post('/syncs') + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .send({ connectionId: activeConnectionOne.connectionId }) + + const syncs = await syncService.findAllPaginated(clientId) + const [syncOne] = syncs.data + + expect(body).toEqual({ + started: true, + syncs: [ + { + clientId: syncOne.clientId, + connectionId: activeConnectionOne.connectionId, + createdAt: syncOne.createdAt.toISOString(), + syncId: syncOne.syncId, + status: syncOne.status + } + ] + }) + + expect(status).toEqual(HttpStatus.CREATED) + + expect(syncs.data.length).toEqual(1) + }) + }) + + describe('GET /syncs/:syncId', () => { + it('responds with the specific sync', async () => { + const { syncs } = await syncService.start({ + clientId, + connectionId: activeConnectionOne.connectionId + }) + const [sync] = syncs + + const { status, body } = await request(app.getHttpServer()) + .get(`/syncs/${sync.syncId}`) + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .send() + + expect(body).toMatchObject({ + clientId: sync.clientId, + connectionId: sync.connectionId, + createdAt: sync.createdAt.toISOString(), + syncId: sync.syncId, + status: sync.status + }) + + expect(status).toEqual(HttpStatus.OK) + }) + }) + + describe('GET /syncs', () => { + it('responds with a list of syncs', async () => { + const { syncs } = await syncService.start({ clientId }) + const [syncOne, syncTwo] = syncs + + const { status, body } = await request(app.getHttpServer()) + .get('/syncs') + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .send() + + expect(body).toMatchObject({ + syncs: [ + { + clientId: syncOne.clientId, + connectionId: syncOne.connectionId, + createdAt: syncOne.createdAt.toISOString(), + syncId: syncOne.syncId, + status: syncOne.status + }, + { + clientId: syncTwo.clientId, + connectionId: syncTwo.connectionId, + createdAt: syncTwo.createdAt.toISOString(), + syncId: syncTwo.syncId, + status: syncTwo.status + } + ] + }) + + expect(status).toEqual(HttpStatus.OK) + + expect(body.syncs.length).toEqual(2) + }) + + it('responds with the specific sync filter by connection', async () => { + const { syncs } = await syncService.start({ clientId }) + const [sync] = syncs + + const { status, body } = await request(app.getHttpServer()) + .get('/syncs') + .query({ connectionId: sync.connectionId }) + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .send() + + expect(body).toMatchObject({ + syncs: [ + { + clientId: sync.clientId, + connectionId: sync.connectionId, + createdAt: sync.createdAt.toISOString(), + syncId: sync.syncId, + status: sync.status + } + ] + }) + + expect(status).toEqual(HttpStatus.OK) + + expect(body.syncs.length).toEqual(1) + }) + + it('responds with limited number of syncs when limit is given', async () => { + await syncService.start({ clientId }) + + const { body } = await request(app.getHttpServer()) + .get('/syncs') + .query({ limit: 1 }) + .set(REQUEST_HEADER_CLIENT_ID, clientId) + + expect(body.syncs.length).toEqual(1) + expect(body.page).toHaveProperty('next') + }) + + it('responds the next page of results when cursos is given', async () => { + await syncService.start({ clientId }) + + const { body: pageOne } = await request(app.getHttpServer()) + .get('/syncs') + .query({ limit: 1 }) + .set(REQUEST_HEADER_CLIENT_ID, clientId) + + const { body: pageTwo } = await request(app.getHttpServer()) + .get('/syncs') + .query({ + limit: 1, + cursor: pageOne.page.next + }) + .set(REQUEST_HEADER_CLIENT_ID, clientId) + + expect(pageTwo.syncs.length).toEqual(1) + expect(pageTwo.page).toHaveProperty('next') + }) + }) +}) diff --git a/apps/vault/src/broker/__test__/e2e/wallet.spec.ts b/apps/vault/src/broker/__test__/e2e/wallet.spec.ts index 538cf09b3..b827b08d7 100644 --- a/apps/vault/src/broker/__test__/e2e/wallet.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/wallet.spec.ts @@ -57,7 +57,9 @@ describe('Wallet', () => { expect(res.status).toBe(HttpStatus.OK) expect(res.body).toEqual({ wallets: TEST_WALLETS.map(getExpectedWallet), - page: {} + page: { + next: null + } }) }) @@ -77,7 +79,12 @@ describe('Wallet', () => { it('returns empty list for unknown client', async () => { const res = await request(app.getHttpServer()).get('/wallets').set(REQUEST_HEADER_CLIENT_ID, 'unknown-client') - expect(res.body).toEqual({ wallets: [], page: {} }) + expect(res.body).toEqual({ + wallets: [], + page: { + next: null + } + }) expect(res.status).toBe(HttpStatus.OK) }) }) @@ -182,7 +189,9 @@ describe('Wallet', () => { expect(res.status).toBe(HttpStatus.OK) expect(res.body).toEqual({ accounts: accounts.map(getExpectedAccount), - page: {} + page: { + next: null + } }) }) @@ -192,7 +201,12 @@ describe('Wallet', () => { .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) expect(res.status).toBe(HttpStatus.OK) - expect(res.body).toEqual({ accounts: [], page: {} }) + expect(res.body).toEqual({ + accounts: [], + page: { + next: null + } + }) }) }) }) diff --git a/apps/vault/src/broker/broker.module.ts b/apps/vault/src/broker/broker.module.ts index 8a0108a2e..a1a10fa82 100644 --- a/apps/vault/src/broker/broker.module.ts +++ b/apps/vault/src/broker/broker.module.ts @@ -3,34 +3,40 @@ import { DEFAULT_HTTP_MODULE_PROVIDERS } from '../shared/constant' import { PersistenceModule } from '../shared/module/persistence/persistence.module' import { EncryptionKeyService } from '../transit-encryption/core/service/encryption-key.service' import { EncryptionKeyRepository } from '../transit-encryption/persistence/encryption-key.repository' +import { TransitEncryptionModule } from '../transit-encryption/transit-encryption.module' import { AccountService } from './core/service/account.service' import { AddressService } from './core/service/address.service' import { ConnectionService } from './core/service/connection.service' +import { SyncService } from './core/service/sync.service' import { WalletService } from './core/service/wallet.service' import { AccountController } from './http/rest/controller/account.controller' import { AddressController } from './http/rest/controller/address.controller' import { ConnectionController } from './http/rest/controller/connection.controller' +import { SyncController } from './http/rest/controller/sync.controller' import { WalletController } from './http/rest/controller/wallet.controller' import { AccountRepository } from './persistence/repository/account.repository' import { AddressRepository } from './persistence/repository/address.repository' import { ConnectionRepository } from './persistence/repository/connection.repository' +import { SyncRepository } from './persistence/repository/sync.repository' import { WalletRepository } from './persistence/repository/wallet.repository' @Module({ - imports: [PersistenceModule], - controllers: [ConnectionController, WalletController, AccountController, AddressController], + imports: [PersistenceModule, TransitEncryptionModule], + controllers: [ConnectionController, WalletController, AccountController, AddressController, SyncController], providers: [ ...DEFAULT_HTTP_MODULE_PROVIDERS, + AccountRepository, + AccountService, + AddressRepository, + AddressService, + ConnectionRepository, ConnectionService, - EncryptionKeyService, EncryptionKeyRepository, - ConnectionRepository, - WalletService, + EncryptionKeyService, + SyncRepository, + SyncService, WalletRepository, - AccountService, - AccountRepository, - AddressService, - AddressRepository + WalletService ] }) export class BrokerModule {} diff --git a/apps/vault/src/broker/core/service/address.service.ts b/apps/vault/src/broker/core/service/address.service.ts index 8ca8bd98e..c070821d0 100644 --- a/apps/vault/src/broker/core/service/address.service.ts +++ b/apps/vault/src/broker/core/service/address.service.ts @@ -7,7 +7,7 @@ import { Address } from '../type/indexed-resources.type' export class AddressService { constructor(private readonly AddressRepository: AddressRepository) {} - async getAddresses(clientId: string, options: PaginationOptions): Promise> { + async getAddresses(clientId: string, options?: PaginationOptions): Promise> { return this.AddressRepository.findByClientId(clientId, options) } diff --git a/apps/vault/src/broker/core/service/connection.service.ts b/apps/vault/src/broker/core/service/connection.service.ts index 2328ba32f..422d9bb90 100644 --- a/apps/vault/src/broker/core/service/connection.service.ts +++ b/apps/vault/src/broker/core/service/connection.service.ts @@ -13,7 +13,11 @@ import { SetRequired } from 'type-fest' import { v4 as uuid } from 'uuid' import { EncryptionKeyService } from '../../../transit-encryption/core/service/encryption-key.service' import { AccountRepository } from '../../persistence/repository/account.repository' -import { ConnectionRepository } from '../../persistence/repository/connection.repository' +import { + ConnectionRepository, + FilterOptions, + FindAllPaginatedOptions +} from '../../persistence/repository/connection.repository' import { WalletRepository } from '../../persistence/repository/wallet.repository' import { ConnectionInvalidCredentialsException } from '../exception/connection-invalid-credentials.exception' import { ConnectionInvalidPrivateKeyException } from '../exception/connection-invalid-private-key.exception' @@ -329,8 +333,12 @@ export class ConnectionService { return this.connectionRepository.findById(clientId, connectionId) } - async findAll(clientId: string): Promise { - return this.connectionRepository.findAll(clientId) + async findAll(clientId: string, options?: FilterOptions): Promise { + return this.connectionRepository.findAll(clientId, options) + } + + async findAllPaginated(clientId: string, options?: FindAllPaginatedOptions): Promise> { + return this.connectionRepository.findAllPaginated(clientId, options) } async revoke(clientId: string, connectionId: string): Promise { diff --git a/apps/vault/src/broker/core/service/sync.service.ts b/apps/vault/src/broker/core/service/sync.service.ts new file mode 100644 index 000000000..9beea6425 --- /dev/null +++ b/apps/vault/src/broker/core/service/sync.service.ts @@ -0,0 +1,78 @@ +import { PaginatedResult } from '@narval/nestjs-shared' +import { Injectable } from '@nestjs/common/decorators' +import { v4 as uuid } from 'uuid' +import { FindAllPaginatedOptions, SyncRepository } from '../../persistence/repository/sync.repository' +import { ConnectionStatus } from '../type/connection.type' +import { StartSync, Sync, SyncStatus } from '../type/sync.type' +import { ConnectionService } from './connection.service' + +@Injectable() +export class SyncService { + constructor( + private readonly syncRepository: SyncRepository, + private readonly connectionService: ConnectionService + ) {} + + async start(input: StartSync): Promise<{ + started: boolean + syncs: Sync[] + }> { + const now = new Date() + + if (input.connectionId) { + const syncId = uuid() + const sync = await this.syncRepository.create( + this.toProcessingSync({ + ...input, + connectionId: input.connectionId, + createdAt: now, + syncId + }) + ) + + // TODO: (@wcalderipe, 10/12/24): Sync connection + + return { started: true, syncs: [sync] } + } + + const connections = await this.connectionService.findAll(input.clientId, { + filters: { + status: ConnectionStatus.ACTIVE + } + }) + + const syncs = await this.syncRepository.bulkCreate( + connections.map(({ connectionId }) => + this.toProcessingSync({ + ...input, + connectionId, + createdAt: now, + syncId: uuid() + }) + ) + ) + + // TODO: (@wcalderipe, 10/12/24): Sync connections + + return { started: true, syncs } + } + + private toProcessingSync(input: StartSync & { connectionId: string; createdAt?: Date; syncId?: string }): Sync { + return { + ...input, + completedAt: undefined, + connectionId: input.connectionId, + createdAt: input.createdAt || new Date(), + status: SyncStatus.PROCESSING, + syncId: input.syncId || uuid() + } + } + + async findAllPaginated(clientId: string, options?: FindAllPaginatedOptions): Promise> { + return this.syncRepository.findAllPaginated(clientId, options) + } + + async findById(clientId: string, syncId: string): Promise { + return this.syncRepository.findById(clientId, syncId) + } +} diff --git a/apps/vault/src/broker/core/type/sync.type.ts b/apps/vault/src/broker/core/type/sync.type.ts new file mode 100644 index 000000000..0b7f69a04 --- /dev/null +++ b/apps/vault/src/broker/core/type/sync.type.ts @@ -0,0 +1,34 @@ +import { z } from 'zod' + +export const SyncStatus = { + PROCESSING: 'processing', + SUCCESS: 'success', + FAILED: 'failed' +} as const +export type SyncStatus = (typeof SyncStatus)[keyof typeof SyncStatus] + +export const Sync = z.object({ + clientId: z.string(), + completedAt: z.date().optional(), + connectionId: z.string(), + createdAt: z.date(), + error: z + .object({ + name: z.string().optional(), + message: z.string().optional(), + traceId: z.string().optional() + }) + .optional(), + status: z.nativeEnum(SyncStatus).default(SyncStatus.PROCESSING), + syncId: z.string() +}) +export type Sync = z.infer + +export const StartSync = z.object({ + clientId: z.string(), + connectionId: z + .string() + .describe('The connection to sync. If undefined, start the sync on all active connections') + .optional() +}) +export type StartSync = z.infer diff --git a/apps/vault/src/broker/http/rest/controller/account.controller.ts b/apps/vault/src/broker/http/rest/controller/account.controller.ts index fe1a9caba..3b59fa3b2 100644 --- a/apps/vault/src/broker/http/rest/controller/account.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/account.controller.ts @@ -5,14 +5,14 @@ import { ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../shared/decorator/client-id.decorator' import { AccountService } from '../../../core/service/account.service' import { AccountDto } from '../dto/response/account.dto' -import { PaginatedAccountsDto } from '../dto/response/accounts.dto' -import { PaginatedAddressesDto } from '../dto/response/addresses.dto' +import { PaginatedAccountsDto } from '../dto/response/paginated-accounts.dto' +import { PaginatedAddressesDto } from '../dto/response/paginated-addresses.dto' @Controller({ path: 'accounts', version: '1' }) -@ApiTags('Account') +@ApiTags('Provider Account') export class AccountController { constructor(private readonly accountService: AccountService) {} @@ -71,14 +71,15 @@ export class AccountController { }) @ApiResponse({ status: HttpStatus.NOT_FOUND, - description: 'Account not found' + description: 'Address not found' }) async getAccountAddresses( @ClientId() clientId: string, @Param('accountId') accountId: string, @PaginationParam() options: PaginationOptions - ): Promise { + ): Promise { const { data, page } = await this.accountService.getAccountAddresses(clientId, accountId, options) + return PaginatedAddressesDto.create({ addresses: data, page diff --git a/apps/vault/src/broker/http/rest/controller/address.controller.ts b/apps/vault/src/broker/http/rest/controller/address.controller.ts index 87f127f98..b14d70b43 100644 --- a/apps/vault/src/broker/http/rest/controller/address.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/address.controller.ts @@ -4,13 +4,13 @@ import { ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../shared/decorator/client-id.decorator' import { AddressService } from '../../../core/service/address.service' import { AddressDto } from '../dto/response/address.dto' -import { PaginatedAddressesDto } from '../dto/response/addresses.dto' +import { PaginatedAddressesDto } from '../dto/response/paginated-addresses.dto' @Controller({ path: 'addresses', version: '1' }) -@ApiTags('Address') +@ApiTags('Provider Address') export class AddressController { constructor(private readonly addressService: AddressService) {} @@ -22,16 +22,16 @@ export class AddressController { type: PaginatedAddressesDto, description: 'Returns a paginated list of addresss for the client' }) - async listByClientId( + async list( @ClientId() clientId: string, @PaginationParam() options: PaginationOptions ): Promise { const { data, page } = await this.addressService.getAddresses(clientId, options) - const ret = PaginatedAddressesDto.create({ + + return PaginatedAddressesDto.create({ addresses: data, page }) - return ret } @Get(':addressId') @@ -52,6 +52,7 @@ export class AddressController { }) async getAddressById(@ClientId() clientId: string, @Param('addressId') addressId: string): Promise { const address = await this.addressService.getAddress(clientId, addressId) + return AddressDto.create({ address }) } } diff --git a/apps/vault/src/broker/http/rest/controller/connection.controller.ts b/apps/vault/src/broker/http/rest/controller/connection.controller.ts index 0fa034fd0..b36706472 100644 --- a/apps/vault/src/broker/http/rest/controller/connection.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/connection.controller.ts @@ -6,17 +6,18 @@ import { ConnectionService } from '../../../core/service/connection.service' import { CreateConnectionDto } from '../dto/request/create-connection.dto' import { InitiateConnectionDto } from '../dto/request/initiate-connection.dto' import { UpdateConnectionDto } from '../dto/request/update-connection.dto' -import { PaginatedAccountsDto } from '../dto/response/accounts.dto' import { ConnectionListDto } from '../dto/response/connection-list.dto' import { ConnectionDto } from '../dto/response/connection.dto' +import { PaginatedAccountsDto } from '../dto/response/paginated-accounts.dto' +import { PaginatedConnectionsDto } from '../dto/response/paginated-connections.dto' +import { PaginatedWalletsDto } from '../dto/response/paginated-wallets.dto' import { PendingConnectionDto } from '../dto/response/pending-connection.dto' -import { PaginatedWalletsDto } from '../dto/response/wallets.dto' @Controller({ path: 'connections', version: '1' }) -@ApiTags('Connection') +@ApiTags('Provider Connection') export class ConnectionController { constructor(private readonly connectionService: ConnectionService) {} @@ -79,10 +80,17 @@ export class ConnectionController { type: ConnectionListDto, status: HttpStatus.OK }) - async list(@ClientId() clientId: string): Promise { - const connections = await this.connectionService.findAll(clientId) + @Paginated({ + type: PaginatedConnectionsDto, + description: 'Returns a paginated list of wallets associated with the connection' + }) + async list( + @ClientId() clientId: string, + @PaginationParam() options: PaginationOptions + ): Promise { + const { data, page } = await this.connectionService.findAllPaginated(clientId, options) - return ConnectionListDto.create({ connections }) + return PaginatedConnectionsDto.create({ connections: data, page }) } @Get(':connectionId') @@ -152,14 +160,14 @@ export class ConnectionController { description: 'This endpoint retrieves a list of accounts associated with a specific connection.' }) @Paginated({ - type: PaginatedWalletsDto, + type: PaginatedAccountsDto, description: 'Returns a paginated list of accounts associated with the connection' }) async getAccounts( @ClientId() clientId: string, @Param('connectionId') connectionId: string, @PaginationParam() options: PaginationOptions - ): Promise { + ): Promise { const { data, page } = await this.connectionService.findAccounts(clientId, connectionId, options) return PaginatedAccountsDto.create({ accounts: data, page }) diff --git a/apps/vault/src/broker/http/rest/controller/sync.controller.ts b/apps/vault/src/broker/http/rest/controller/sync.controller.ts new file mode 100644 index 000000000..696a5afb4 --- /dev/null +++ b/apps/vault/src/broker/http/rest/controller/sync.controller.ts @@ -0,0 +1,72 @@ +import { Paginated, PaginationOptions, PaginationParam } from '@narval/nestjs-shared' +import { Body, Controller, Get, HttpStatus, Param, Post, Query } from '@nestjs/common' +import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' +import { ClientId } from '../../../../shared/decorator/client-id.decorator' +import { SyncService } from '../../../core/service/sync.service' +import { StartSyncDto } from '../dto/request/start-sync.dto' +import { PaginatedSyncsDto } from '../dto/response/paginated-syncs.dto' +import { SyncStatusDto } from '../dto/response/sync-status.dto' +import { SyncDto } from '../dto/response/sync.dto' + +@Controller({ + path: 'syncs', + version: '1' +}) +@ApiTags('Provider Sync') +export class SyncController { + constructor(private readonly syncService: SyncService) {} + + @Post() + @ApiOperation({ + summary: 'Start a synchronization process', + description: 'This endpoint starts synchronization process for the client.' + }) + @ApiResponse({ + description: 'Returns the status of the synchronization process.', + status: HttpStatus.CREATED, + type: SyncStatusDto + }) + async start(@ClientId() clientId: string, @Body() body: StartSyncDto): Promise { + return SyncStatusDto.create(await this.syncService.start({ clientId, ...body })) + } + + @Get(':syncId') + @ApiOperation({ + summary: 'Retrieve a specific synchronization process by ID', + description: + 'This endpoint retrieves the details of a specific synchronization process associated with the client, identified by the sync ID.' + }) + @ApiResponse({ + description: 'Returns the details of the specified synchronization process.', + status: HttpStatus.OK, + type: SyncDto + }) + async findById(@ClientId() clientId: string, @Param('syncId') syncId: string): Promise { + const sync = await this.syncService.findById(clientId, syncId) + + return SyncDto.create(sync) + } + + @Get() + @ApiOperation({ + summary: 'Retrieve a list of synchronization processes', + description: + 'This endpoint retrieves a list of synchronization processes associated with the client. Optionally, it can filter the processes by a specific connection ID.' + }) + @Paginated({ + type: PaginatedSyncsDto, + description: 'Returns a paginated list of accounts associated with the connection' + }) + async findAll( + @ClientId() clientId: string, + @PaginationParam() options: PaginationOptions, + @Query('connectionId') connectionId?: string + ): Promise { + const { data, page } = await this.syncService.findAllPaginated(clientId, { + ...options, + filters: { connectionId } + }) + + return PaginatedSyncsDto.create({ syncs: data, page: page }) + } +} diff --git a/apps/vault/src/broker/http/rest/controller/wallet.controller.ts b/apps/vault/src/broker/http/rest/controller/wallet.controller.ts index 5b4d4661f..cec3dd9cb 100644 --- a/apps/vault/src/broker/http/rest/controller/wallet.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/wallet.controller.ts @@ -4,14 +4,14 @@ import { ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../shared/decorator/client-id.decorator' import { WalletService } from '../../../core/service/wallet.service' -import { PaginatedAccountsDto } from '../dto/response/accounts.dto' +import { PaginatedAccountsDto } from '../dto/response/paginated-accounts.dto' +import { PaginatedWalletsDto } from '../dto/response/paginated-wallets.dto' import { WalletDto } from '../dto/response/wallet.dto' -import { PaginatedWalletsDto } from '../dto/response/wallets.dto' @Controller({ path: 'wallets', version: '1' }) -@ApiTags('Wallet') +@ApiTags('Provider Wallet') export class WalletController { constructor(private readonly walletService: WalletService) {} @@ -65,8 +65,8 @@ export class WalletController { description: 'The ID of the wallet to retrieve accounts for' }) @Paginated({ - type: PaginatedWalletsDto, - description: 'Returns a paginated list of wallets for the client' + type: PaginatedAccountsDto, + description: 'Returns a paginated list of accounts' }) @ApiResponse({ status: HttpStatus.NOT_FOUND, diff --git a/apps/vault/src/broker/http/rest/dto/request/start-sync.dto.ts b/apps/vault/src/broker/http/rest/dto/request/start-sync.dto.ts new file mode 100644 index 000000000..938084b83 --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/request/start-sync.dto.ts @@ -0,0 +1,4 @@ +import { createZodDto } from 'nestjs-zod' +import { StartSync } from '../../../../core/type/sync.type' + +export class StartSyncDto extends createZodDto(StartSync.omit({ clientId: true })) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/accounts.dto.ts b/apps/vault/src/broker/http/rest/dto/response/accounts.dto.ts deleted file mode 100644 index 9feef934c..000000000 --- a/apps/vault/src/broker/http/rest/dto/response/accounts.dto.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { createPaginatedDto } from '@narval/nestjs-shared' -import { z } from 'zod' -import { Account } from '../../../../core/type/indexed-resources.type' -export class PaginatedAccountsDto extends createPaginatedDto( - z.object({ - accounts: z.array(Account) - }) -) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/addresses.dto.ts b/apps/vault/src/broker/http/rest/dto/response/addresses.dto.ts deleted file mode 100644 index c646541e6..000000000 --- a/apps/vault/src/broker/http/rest/dto/response/addresses.dto.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { createPaginatedDto } from '@narval/nestjs-shared' -import { z } from 'zod' -import { Address } from '../../../../core/type/indexed-resources.type' -export class PaginatedAddressesDto extends createPaginatedDto( - z.object({ - addresses: z.array(Address) - }) -) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/paginated-accounts.dto.ts b/apps/vault/src/broker/http/rest/dto/response/paginated-accounts.dto.ts new file mode 100644 index 000000000..8d122075d --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/response/paginated-accounts.dto.ts @@ -0,0 +1,11 @@ +import { Page } from '@narval/nestjs-shared' +import { createZodDto } from 'nestjs-zod' +import { z } from 'zod' +import { Account } from '../../../../core/type/indexed-resources.type' + +export class PaginatedAccountsDto extends createZodDto( + z.object({ + accounts: z.array(Account), + page: Page + }) +) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/paginated-addresses.dto.ts b/apps/vault/src/broker/http/rest/dto/response/paginated-addresses.dto.ts new file mode 100644 index 000000000..7439a35c0 --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/response/paginated-addresses.dto.ts @@ -0,0 +1,11 @@ +import { Page } from '@narval/nestjs-shared' +import { createZodDto } from 'nestjs-zod' +import { z } from 'zod' +import { Address } from '../../../../core/type/indexed-resources.type' + +export class PaginatedAddressesDto extends createZodDto( + z.object({ + addresses: z.array(Address), + page: Page + }) +) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/paginated-connections.dto.ts b/apps/vault/src/broker/http/rest/dto/response/paginated-connections.dto.ts new file mode 100644 index 000000000..f01f6e24d --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/response/paginated-connections.dto.ts @@ -0,0 +1,11 @@ +import { Page } from '@narval/nestjs-shared' +import { createZodDto } from 'nestjs-zod' +import { z } from 'zod' +import { BaseConnection } from '../../../../core/type/connection.type' + +export class PaginatedConnectionsDto extends createZodDto( + z.object({ + connections: z.array(BaseConnection.omit({ credentials: true })), + page: Page + }) +) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/paginated-syncs.dto.ts b/apps/vault/src/broker/http/rest/dto/response/paginated-syncs.dto.ts new file mode 100644 index 000000000..71b52084f --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/response/paginated-syncs.dto.ts @@ -0,0 +1,11 @@ +import { Page } from '@narval/nestjs-shared' +import { createZodDto } from 'nestjs-zod' +import { z } from 'zod' +import { Sync } from '../../../../core/type/sync.type' + +export class PaginatedSyncsDto extends createZodDto( + z.object({ + page: Page, + syncs: z.array(Sync) + }) +) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/paginated-wallets.dto.ts b/apps/vault/src/broker/http/rest/dto/response/paginated-wallets.dto.ts new file mode 100644 index 000000000..e2b53673d --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/response/paginated-wallets.dto.ts @@ -0,0 +1,11 @@ +import { Page } from '@narval/nestjs-shared' +import { createZodDto } from 'nestjs-zod' +import { z } from 'zod' +import { PublicWallet } from '../../../../core/type/indexed-resources.type' + +export class PaginatedWalletsDto extends createZodDto( + z.object({ + wallets: z.array(PublicWallet), + page: Page + }) +) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/sync-list.dto.ts b/apps/vault/src/broker/http/rest/dto/response/sync-list.dto.ts new file mode 100644 index 000000000..aaf9ef534 --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/response/sync-list.dto.ts @@ -0,0 +1,9 @@ +import { createZodDto } from 'nestjs-zod' +import { z } from 'zod' +import { Sync } from '../../../../core/type/sync.type' + +export class SyncListDto extends createZodDto( + z.object({ + syncs: z.array(Sync) + }) +) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/sync-status.dto.ts b/apps/vault/src/broker/http/rest/dto/response/sync-status.dto.ts new file mode 100644 index 000000000..2560f4489 --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/response/sync-status.dto.ts @@ -0,0 +1,10 @@ +import { createZodDto } from 'nestjs-zod' +import { z } from 'zod' +import { Sync } from '../../../../core/type/sync.type' + +export class SyncStatusDto extends createZodDto( + z.object({ + started: z.boolean(), + syncs: z.array(Sync) + }) +) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/sync.dto.ts b/apps/vault/src/broker/http/rest/dto/response/sync.dto.ts new file mode 100644 index 000000000..a4988ffb5 --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/response/sync.dto.ts @@ -0,0 +1,4 @@ +import { createZodDto } from 'nestjs-zod' +import { Sync } from '../../../../core/type/sync.type' + +export class SyncDto extends createZodDto(Sync) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/wallets.dto.ts b/apps/vault/src/broker/http/rest/dto/response/wallets.dto.ts deleted file mode 100644 index bf74179ae..000000000 --- a/apps/vault/src/broker/http/rest/dto/response/wallets.dto.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { createPaginatedDto } from '@narval/nestjs-shared' -import { z } from 'zod' -import { PublicWallet } from '../../../../core/type/indexed-resources.type' - -export class PaginatedWalletsDto extends createPaginatedDto( - z.object({ - wallets: z.array(PublicWallet) - }) -) {} diff --git a/apps/vault/src/broker/persistence/repository/connection.repository.ts b/apps/vault/src/broker/persistence/repository/connection.repository.ts index f7ae192f8..cec4b4b20 100644 --- a/apps/vault/src/broker/persistence/repository/connection.repository.ts +++ b/apps/vault/src/broker/persistence/repository/connection.repository.ts @@ -1,3 +1,4 @@ +import { PaginatedResult, PaginationOptions, getPaginatedResult, getPaginationQuery } from '@narval/nestjs-shared' import { HttpStatus, Injectable } from '@nestjs/common' import { Prisma, ProviderConnection } from '@prisma/client/vault' import { omit } from 'lodash' @@ -7,7 +8,7 @@ import { ConnectionParseException } from '../../core/exception/connection-parse. import { NotFoundException } from '../../core/exception/not-found.exception' import { Connection, ConnectionStatus } from '../../core/type/connection.type' -type UpdateConnection = { +export type UpdateConnection = { clientId: string connectionId: string credentials?: unknown | null @@ -19,6 +20,14 @@ type UpdateConnection = { url?: string } +export type FilterOptions = { + filters?: { + status?: ConnectionStatus + } +} + +export type FindAllPaginatedOptions = PaginationOptions & FilterOptions + @Injectable() export class ConnectionRepository { constructor(private prismaService: PrismaService) {} @@ -110,14 +119,39 @@ export class ConnectionRepository { throw new NotFoundException({ context: { clientId, connectionId } }) } - async findAll(clientId: string): Promise { + async findAll(clientId: string, options?: FilterOptions): Promise { const models = await this.prismaService.providerConnection.findMany({ - where: { clientId } + where: { + clientId, + status: options?.filters?.status + } }) return models.map(ConnectionRepository.parseModel) } + async findAllPaginated(clientId: string, options?: FindAllPaginatedOptions): Promise> { + const pagination = getPaginationQuery({ + options: PaginationOptions.parse(options), + cursorOrderColumns: ConnectionRepository.getCursorOrderColumns() + }) + + const models = await this.prismaService.providerConnection.findMany({ + where: { + clientId, + status: options?.filters?.status + }, + ...pagination + }) + + const { data, page } = getPaginatedResult({ items: models, options: pagination }) + + return { + data: data.map(ConnectionRepository.parseModel), + page + } + } + async exists(clientId: string, id: string): Promise { const count = await this.prismaService.providerConnection.count({ where: { id, clientId } diff --git a/apps/vault/src/broker/persistence/repository/sync.repository.ts b/apps/vault/src/broker/persistence/repository/sync.repository.ts new file mode 100644 index 000000000..1a1fffa2d --- /dev/null +++ b/apps/vault/src/broker/persistence/repository/sync.repository.ts @@ -0,0 +1,109 @@ +import { PaginatedResult, PaginationOptions, getPaginatedResult, getPaginationQuery } from '@narval/nestjs-shared' +import { Injectable } from '@nestjs/common/decorators' +import { ProviderSync } from '@prisma/client/vault' +import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' +import { NotFoundException } from '../../core/exception/not-found.exception' +import { Sync, SyncStatus } from '../../core/type/sync.type' + +export type FindAllPaginatedOptions = PaginationOptions & { + filters?: { + connectionId?: string + status?: SyncStatus + } +} + +@Injectable() +export class SyncRepository { + constructor(private readonly prismaService: PrismaService) {} + + static parseModel(model?: ProviderSync | null): Sync { + return Sync.parse({ + ...model, + syncId: model?.id, + // Prisma always returns null for optional fields that don't have a + // value, rather than undefined. This is actually by design and aligns + // with how NULL values work in databases. + completedAt: model?.completedAt || undefined, + error: + model?.errorName || model?.errorMessage || model?.errorTraceId + ? { + name: model?.errorName || undefined, + message: model?.errorMessage || undefined, + traceId: model?.errorTraceId || undefined + } + : undefined + }) + } + + static parseEntity(entity: Sync): ProviderSync { + return { + id: entity.syncId, + clientId: entity.clientId, + completedAt: entity.completedAt || null, + connectionId: entity.connectionId, + createdAt: entity.createdAt, + errorName: entity.error?.name || null, + errorMessage: entity.error?.message || null, + errorTraceId: entity.error?.traceId || null, + status: entity.status + } + } + + static getCursorOrderColumns(): Array { + return ['createdAt'] + } + + async create(sync: Sync): Promise { + await this.prismaService.providerSync.create({ + data: SyncRepository.parseEntity(sync) + }) + + return sync + } + + async bulkCreate(syncs: Sync[]): Promise { + await this.prismaService.providerSync.createMany({ + data: syncs.map(SyncRepository.parseEntity) + }) + + return syncs + } + + async findById(clientId: string, syncId: string): Promise { + const model = await this.prismaService.providerSync.findUnique({ + where: { + clientId, + id: syncId + } + }) + + if (model) { + return SyncRepository.parseModel(model) + } + + throw new NotFoundException({ context: { clientId, syncId } }) + } + + async findAllPaginated(clientId: string, options?: FindAllPaginatedOptions): Promise> { + const pagination = getPaginationQuery({ + options, + cursorOrderColumns: SyncRepository.getCursorOrderColumns() + }) + + const models = await this.prismaService.providerSync.findMany({ + where: { + clientId, + status: options?.filters?.status, + connectionId: options?.filters?.connectionId + }, + ...pagination + }) + + const { data, page } = getPaginatedResult({ items: models, options: pagination }) + + return { + data: data.map(SyncRepository.parseModel), + page + } + } +} diff --git a/apps/vault/src/main.module.ts b/apps/vault/src/main.module.ts index ed87f9ca5..2abf98230 100644 --- a/apps/vault/src/main.module.ts +++ b/apps/vault/src/main.module.ts @@ -2,7 +2,7 @@ import { ConfigModule, ConfigService } from '@narval/config-module' import { EncryptionModule } from '@narval/encryption-module' import { HttpLoggerMiddleware, LoggerModule, OpenTelemetryModule } from '@narval/nestjs-shared' import { MiddlewareConsumer, Module, NestModule, OnModuleInit, ValidationPipe, forwardRef } from '@nestjs/common' -import { APP_PIPE } from '@nestjs/core' +import { APP_PIPE, RouterModule } from '@nestjs/core' import { ZodValidationPipe } from 'nestjs-zod' import { BrokerModule } from './broker/broker.module' import { ClientModule } from './client/client.module' @@ -33,7 +33,13 @@ const INFRASTRUCTURE_MODULES = [ // Domain VaultModule, ClientModule, - BrokerModule + BrokerModule, + RouterModule.register([ + { + path: 'provider', + module: BrokerModule + } + ]) ], providers: [ { diff --git a/apps/vault/src/transit-encryption/core/service/encryption-key.service.ts b/apps/vault/src/transit-encryption/core/service/encryption-key.service.ts index b68055b16..a35b4d48d 100644 --- a/apps/vault/src/transit-encryption/core/service/encryption-key.service.ts +++ b/apps/vault/src/transit-encryption/core/service/encryption-key.service.ts @@ -18,8 +18,8 @@ import { EncryptionKey } from '../type/encryption-key.type' export class EncryptionKeyService { constructor(private readonly encryptionKeyRepository: EncryptionKeyRepository) {} - async generate(clientId: string, opts?: { modulusLenght?: number }): Promise { - const modulusLength = opts?.modulusLenght || DEFAULT_RSA_MODULUS_LENGTH + async generate(clientId: string, opts?: { modulusLength?: number }): Promise { + const modulusLength = opts?.modulusLength || DEFAULT_RSA_MODULUS_LENGTH const privateKey = await generateJwk(Alg.RS256, { use: 'enc', modulusLength }) const publicKey = rsaPrivateKeyToPublicKey(privateKey) const encryptionKey = { diff --git a/apps/vault/src/transit-encryption/http/rest/controller/encryption-key.controller.ts b/apps/vault/src/transit-encryption/http/rest/controller/encryption-key.controller.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/nestjs-shared/src/lib/__test__/unit/pagination.spec.ts b/packages/nestjs-shared/src/lib/__test__/unit/pagination.spec.ts index 6d4422c30..b2ad17c51 100644 --- a/packages/nestjs-shared/src/lib/__test__/unit/pagination.spec.ts +++ b/packages/nestjs-shared/src/lib/__test__/unit/pagination.spec.ts @@ -27,7 +27,7 @@ describe('Pagination Utilities', () => { expect(result.page?.next).toBeDefined() }) - it('returns undefined next cursor on last page', () => { + it('returns null next cursor on last page', () => { const result = getPaginatedResult({ items: testData, options: getPaginationQuery({ @@ -36,7 +36,7 @@ describe('Pagination Utilities', () => { }) }) expect(result.data).toHaveLength(5) - expect(result.page?.next).toBeUndefined() + expect(result.page?.next).toEqual(null) }) it('works with cursor-based pagination', () => { diff --git a/packages/nestjs-shared/src/lib/decorator/pagination.decorator.ts b/packages/nestjs-shared/src/lib/decorator/pagination.decorator.ts index 97dcef7e2..c51852327 100644 --- a/packages/nestjs-shared/src/lib/decorator/pagination.decorator.ts +++ b/packages/nestjs-shared/src/lib/decorator/pagination.decorator.ts @@ -1,5 +1,5 @@ -import { applyDecorators, Type } from '@nestjs/common' -import { ApiQuery, ApiResponse, getSchemaPath } from '@nestjs/swagger' +import { applyDecorators, HttpStatus, Type } from '@nestjs/common' +import { ApiQuery, ApiResponse } from '@nestjs/swagger' type PaginatedDecoratorOptions = { type: Type @@ -34,27 +34,9 @@ export function Paginated(options: PaginatedDecoratorOptions) { description: 'Set to "true" or "1" for descending order' }), ApiResponse({ - status: 200, + status: HttpStatus.OK, description: options.description || 'Successfully retrieved paginated list', - schema: { - type: 'object', - properties: { - data: { - type: 'array', - items: { $ref: getSchemaPath(options.type) } - }, - page: { - type: 'object', - properties: { - next: { - type: 'string', - description: 'Cursor for the next page of results', - nullable: true - } - } - } - } - } + type: options.type }) ) } diff --git a/packages/nestjs-shared/src/lib/dto/index.ts b/packages/nestjs-shared/src/lib/dto/index.ts index 0985667a8..6e69c84b0 100644 --- a/packages/nestjs-shared/src/lib/dto/index.ts +++ b/packages/nestjs-shared/src/lib/dto/index.ts @@ -1,6 +1,5 @@ export * from './base-action-request.dto' export * from './base-action.dto' -export * from './paginated.dto' export * from './sign-message-request-data-dto' export * from './sign-transaction-request-data.dto' export * from './signature.dto' diff --git a/packages/nestjs-shared/src/lib/dto/paginated.dto.ts b/packages/nestjs-shared/src/lib/dto/paginated.dto.ts deleted file mode 100644 index d924c406b..000000000 --- a/packages/nestjs-shared/src/lib/dto/paginated.dto.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { createZodDto } from 'nestjs-zod' -import { z } from 'zod' -import { Page } from '../type/pagination.type' - -export function createPaginatedDto>(baseSchema: T) { - const paginatedSchema = baseSchema.extend({ - page: Page.optional() - }) - - return class PaginatedDto extends createZodDto(paginatedSchema) { - static create(data: z.infer): PaginatedDto { - // Parse the data through the schema to trigger transformations - const validated = paginatedSchema.parse(data) - // Create instance and assign parsed data - const instance = new this() - return Object.assign(instance, validated) - } - } -} diff --git a/packages/nestjs-shared/src/lib/type/pagination.type.ts b/packages/nestjs-shared/src/lib/type/pagination.type.ts index 54e7db5e7..2700ef384 100644 --- a/packages/nestjs-shared/src/lib/type/pagination.type.ts +++ b/packages/nestjs-shared/src/lib/type/pagination.type.ts @@ -2,7 +2,7 @@ import { z } from 'zod' export const Page = z .object({ - next: z.string().optional() + next: z.string().nullable() }) .optional() @@ -11,7 +11,7 @@ export type Page = z.infer export const createPaginatedSchema = (itemSchema: T) => z.object({ data: z.array(itemSchema), - page: Page.optional() + page: Page }) export type PaginatedResult = z.infer>>> diff --git a/packages/nestjs-shared/src/lib/util/pagination.util.ts b/packages/nestjs-shared/src/lib/util/pagination.util.ts index 22c42b1dc..36f432a6b 100644 --- a/packages/nestjs-shared/src/lib/util/pagination.util.ts +++ b/packages/nestjs-shared/src/lib/util/pagination.util.ts @@ -11,7 +11,7 @@ export function getPaginatedResult({ if (!items || items.length === 0) { return { data: [], - page: { next: undefined } + page: { next: null } } } @@ -29,7 +29,7 @@ export function getPaginatedResult({ page: { // cursor is the id of the last item that is actually returned // we can safely access the last item because we know for sure there's at least one more item - next: hasNextPage ? items[items.length - 2]?.id : undefined + next: hasNextPage ? items[items.length - 2]?.id : null } } } diff --git a/packages/signature/src/lib/__test__/unit/util.spec.ts b/packages/signature/src/lib/__test__/unit/util.spec.ts index bb0d8d856..fc76cafd6 100644 --- a/packages/signature/src/lib/__test__/unit/util.spec.ts +++ b/packages/signature/src/lib/__test__/unit/util.spec.ts @@ -18,6 +18,7 @@ import { secp256k1PublicKeySchema } from '../../types' import { + SMALLEST_RSA_MODULUS_LENGTH, ed25519polyfilled, ellipticPrivateKeyToHex, generateJwk, @@ -121,7 +122,7 @@ describe('isHeader', () => { describe('generateKeys', () => { it('generate a valid RSA key pair and return it as a JWK', async () => { // IMPORTANT: Uses a small length to increase the generation speed on tests. - const key = await generateJwk(Alg.RS256, { modulusLength: 1024 }) + const key = await generateJwk(Alg.RS256, { modulusLength: SMALLEST_RSA_MODULUS_LENGTH }) expect(rsaPrivateKeySchema.safeParse(key).success).toBe(true) }) From 5eb7138de6f10c7f656659a56655651c0acad4ca Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Mon, 16 Dec 2024 12:44:53 +0100 Subject: [PATCH 030/120] Add Anchorage sync (#20) * Add sync API * Fix minor tasks from last PR * Fix wrong param name * Add pagination in the sync API * Fix pagination decorator type * Fix pagination DTO * Add pagination on the connection * Add connection pagination * Fix unit test * Add Anchorage vaults sync * Add Anchorage accounts sync * Sync wip * authenticating anchorage requests * raw naming changed to proxy, added a service * passthrough requests to anchorage (#22) * passthrough requests to anchorage * removed logs * passin through status code and e2e tests * use seedsvc pattern, fixed controller * removed unnecesseary semi-colon * changed anchorage error, return the same error to the client * Sync accounts and addresses * Delete SLIP 44 util * Ensure sync idempotency * Change HTTP module to not be global * Add sync update and track errors * Fix extra semi col * Disable retry on the engine * Rename HTTP module method to register * Refactor anchorage signed request builder * Temp disable Nock --------- Co-authored-by: Pierre Troger Co-authored-by: Ptroger <44851272+Ptroger@users.noreply.github.com> --- .../integration/data-store.service.spec.ts | 2 +- .../policy-engine/src/engine/engine.module.ts | 2 +- .../http-data-store.repository.spec.ts | 2 +- apps/vault/.env.default | 6 + apps/vault/jest.setup.ts | 29 +- .../src/broker/__test__/e2e/account.spec.ts | 3 +- .../src/broker/__test__/e2e/proxy.spec.ts | 223 ++++++++++ .../src/broker/__test__/e2e/sync.spec.ts | 119 ++--- .../__test__/util/map-db-to-returned.ts | 2 + apps/vault/src/broker/broker.module.ts | 30 +- .../exception/connection-invalid.exception.ts | 13 + .../core/exception/model-invalid.exception.ts | 11 + .../core/exception/proxy-request.exception.ts | 30 ++ .../core/exception/url-parser.exception.ts | 12 + .../unit/anchorage-request-builder.spec.ts | 149 +++++++ .../core/lib/anchorage-request-builder.ts | 80 ++++ .../anchorage-sync.service.spec.ts | 158 +++++++ .../integration/mocks/anchorage/handlers.ts | 18 + .../response/vaults-addresses-ok.json | 14 + .../mocks/anchorage/response/vaults-ok.json | 61 +++ .../mocks/anchorage/response/wallets-ok.json | 363 ++++++++++++++++ .../integration/mocks/anchorage/server.ts | 55 +++ .../broker/core/service/account.service.ts | 26 +- .../broker/core/service/address.service.ts | 16 +- .../core/service/anchorage-sync.service.ts | 274 ++++++++++++ .../broker/core/service/connection.service.ts | 37 +- .../src/broker/core/service/proxy.service.ts | 49 +++ .../src/broker/core/service/sync.service.ts | 71 ++- .../src/broker/core/service/wallet.service.ts | 30 +- .../src/broker/core/type/connection.type.ts | 11 +- .../core/type/indexed-resources.type.ts | 6 +- .../broker/http/client/anchorage.client.ts | 315 ++++++++++++++ .../rest/controller/connection.controller.ts | 19 +- .../http/rest/controller/proxy.controller.ts | 65 +++ .../http/rest/controller/wallet.controller.ts | 14 +- .../src/broker/persistence/connection.seed.ts | 48 +++ .../repository/account.repository.ts | 86 +++- .../repository/address.repository.ts | 58 ++- .../repository/connection.repository.ts | 16 + .../persistence/repository/sync.repository.ts | 75 +++- .../repository/wallet.repository.ts | 136 +++++- .../decorator/connection-id.decorator.ts | 12 + .../migration.sql | 20 + .../module/persistence/schema/schema.prisma | 8 + .../src/shared/module/persistence/seed.ts | 74 +++- .../persistence/service/seed.service.ts | 7 + apps/vault/test/nock.util.ts | 66 +++ package-lock.json | 407 ++++++++++++++++++ package.json | 1 + .../src/lib/module/http/http.module.ts | 21 +- .../src/lib/module/logger/logger.constant.ts | 3 +- 51 files changed, 3103 insertions(+), 250 deletions(-) create mode 100644 apps/vault/src/broker/__test__/e2e/proxy.spec.ts create mode 100644 apps/vault/src/broker/core/exception/connection-invalid.exception.ts create mode 100644 apps/vault/src/broker/core/exception/model-invalid.exception.ts create mode 100644 apps/vault/src/broker/core/exception/proxy-request.exception.ts create mode 100644 apps/vault/src/broker/core/exception/url-parser.exception.ts create mode 100644 apps/vault/src/broker/core/lib/__test__/unit/anchorage-request-builder.spec.ts create mode 100644 apps/vault/src/broker/core/lib/anchorage-request-builder.ts create mode 100644 apps/vault/src/broker/core/service/__test__/integration/anchorage-sync.service.spec.ts create mode 100644 apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/handlers.ts create mode 100644 apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/vaults-addresses-ok.json create mode 100644 apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/vaults-ok.json create mode 100644 apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/wallets-ok.json create mode 100644 apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/server.ts create mode 100644 apps/vault/src/broker/core/service/anchorage-sync.service.ts create mode 100644 apps/vault/src/broker/core/service/proxy.service.ts create mode 100644 apps/vault/src/broker/http/client/anchorage.client.ts create mode 100644 apps/vault/src/broker/http/rest/controller/proxy.controller.ts create mode 100644 apps/vault/src/broker/persistence/connection.seed.ts create mode 100644 apps/vault/src/shared/decorator/connection-id.decorator.ts create mode 100644 apps/vault/src/shared/module/persistence/schema/migrations/20241213123626_add_unique_constraint_on_provider_resource_tables/migration.sql create mode 100644 apps/vault/src/shared/module/persistence/service/seed.service.ts create mode 100644 apps/vault/test/nock.util.ts diff --git a/apps/policy-engine/src/engine/core/service/__test__/integration/data-store.service.spec.ts b/apps/policy-engine/src/engine/core/service/__test__/integration/data-store.service.spec.ts index 65a2b0da0..a858397c0 100644 --- a/apps/policy-engine/src/engine/core/service/__test__/integration/data-store.service.spec.ts +++ b/apps/policy-engine/src/engine/core/service/__test__/integration/data-store.service.spec.ts @@ -39,7 +39,7 @@ describe(DataStoreService.name, () => { beforeEach(async () => { const module = await Test.createTestingModule({ - imports: [HttpModule.forRoot(), LoggerModule.forTest()], + imports: [HttpModule.register(), LoggerModule.forTest()], providers: [DataStoreService, DataStoreRepositoryFactory, HttpDataStoreRepository, FileSystemDataStoreRepository] }).compile() diff --git a/apps/policy-engine/src/engine/engine.module.ts b/apps/policy-engine/src/engine/engine.module.ts index 7b52f6b29..ef91cfaad 100644 --- a/apps/policy-engine/src/engine/engine.module.ts +++ b/apps/policy-engine/src/engine/engine.module.ts @@ -26,7 +26,7 @@ import { HttpDataStoreRepository } from './persistence/repository/http-data-stor @Module({ imports: [ - HttpModule.forRoot(), + HttpModule.register(), KeyValueModule, EncryptionModule.registerAsync({ imports: [EngineModule], diff --git a/apps/policy-engine/src/engine/persistence/repository/__test__/integration/http-data-store.repository.spec.ts b/apps/policy-engine/src/engine/persistence/repository/__test__/integration/http-data-store.repository.spec.ts index 2cb5d08a3..58cd2f887 100644 --- a/apps/policy-engine/src/engine/persistence/repository/__test__/integration/http-data-store.repository.spec.ts +++ b/apps/policy-engine/src/engine/persistence/repository/__test__/integration/http-data-store.repository.spec.ts @@ -24,7 +24,7 @@ describe(HttpDataStoreRepository.name, () => { beforeEach(async () => { const module = await Test.createTestingModule({ - imports: [HttpModule.forRoot(), LoggerModule.forTest()], + imports: [HttpModule.register(), LoggerModule.forTest()], providers: [HttpDataStoreRepository] }).compile() diff --git a/apps/vault/.env.default b/apps/vault/.env.default index 8081558a9..d149782ba 100644 --- a/apps/vault/.env.default +++ b/apps/vault/.env.default @@ -50,3 +50,9 @@ OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf OTEL_LOGS_EXPORTER=otlp OTEL_LOG_LEVEL=error OTEL_RESOURCE_ATTRIBUTES=deployment.environment=local + +# === External Api Keys === + +# Used to generate a valid connection to Anchorage sandbox access using your credentials +ANCHORAGE_API_KEY= +ANCHORAGE_SECRET_KEY= \ No newline at end of file diff --git a/apps/vault/jest.setup.ts b/apps/vault/jest.setup.ts index 4fab91e6b..0e4f6088e 100644 --- a/apps/vault/jest.setup.ts +++ b/apps/vault/jest.setup.ts @@ -1,6 +1,6 @@ import dotenv from 'dotenv' import fs from 'fs' -import nock from 'nock' +// import { setupNock } from './test/nock.util' const testEnvFile = `${__dirname}/.env.test` @@ -22,28 +22,5 @@ for (const prop in process.env) { dotenv.config({ path: testEnvFile, override: true }) -// Disable outgoing HTTP requests to avoid flaky tests. -nock.disableNetConnect() - -// Enable outbound HTTP requests to 127.0.0.1 to allow E2E tests with -// supertestwith supertest to work. -const OUTBOUND_HTTP_ALLOWED_HOST = '127.0.0.1' - -nock.enableNetConnect(OUTBOUND_HTTP_ALLOWED_HOST) - -// Jest sometimes translates unmatched errors into obscure JSON circular -// dependency without a proper stack trace. This can lead to hours of -// debugging. To save time, this emitter will consistently log an unmatched -// event allowing engineers to quickly identify the source of the error. -nock.emitter.on('no match', (request) => { - if (request.host && request.host.includes(OUTBOUND_HTTP_ALLOWED_HOST)) { - return - } - - if (request.hostname && request.hostname.includes(OUTBOUND_HTTP_ALLOWED_HOST)) { - return - } - - // eslint-disable-next-line no-console - console.error('Nock: no match for request', request) -}) +// Temp disable it +// setupNock() diff --git a/apps/vault/src/broker/__test__/e2e/account.spec.ts b/apps/vault/src/broker/__test__/e2e/account.spec.ts index 720c8065a..e081d20b3 100644 --- a/apps/vault/src/broker/__test__/e2e/account.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/account.spec.ts @@ -171,7 +171,8 @@ describe('Account', () => { // Create a new account without addresses const accountWithoutAddresses = { ...TEST_ACCOUNTS[0], - id: 'account-without-addresses' + externalId: 'test-external-id', + id: 'test-account-without-addresses' } await testPrismaService.getClient().providerAccount.create({ data: accountWithoutAddresses diff --git a/apps/vault/src/broker/__test__/e2e/proxy.spec.ts b/apps/vault/src/broker/__test__/e2e/proxy.spec.ts new file mode 100644 index 000000000..2a771f1dd --- /dev/null +++ b/apps/vault/src/broker/__test__/e2e/proxy.spec.ts @@ -0,0 +1,223 @@ +import { ConfigModule } from '@narval/config-module' +import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' +import { Alg, generateJwk, privateKeyToHex } from '@narval/signature' +import { HttpStatus, INestApplication } from '@nestjs/common' +import { Test, TestingModule } from '@nestjs/testing' +import nock from 'nock' +import request from 'supertest' +import { load } from '../../../main.config' +import { REQUEST_HEADER_CONNECTION_ID } from '../../../shared/decorator/connection-id.decorator' +import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' +import { BrokerModule } from '../../broker.module' +import { ConnectionService } from '../../core/service/connection.service' +import { Provider } from '../../core/type/connection.type' + +describe('Proxy', () => { + let app: INestApplication + let module: TestingModule + let connectionService: ConnectionService + let testPrismaService: TestPrismaService + + const TEST_CLIENT_ID = 'test-client-id' + const TEST_CONNECTION_ID = 'test-connection-id' + const MOCK_API_URL = 'https://api.anchorage-staging.com' + + beforeAll(async () => { + module = await Test.createTestingModule({ + imports: [ + LoggerModule.forTest(), + ConfigModule.forRoot({ + load: [load], + isGlobal: true + }), + BrokerModule + ] + }).compile() + + app = module.createNestApplication() + + testPrismaService = module.get(TestPrismaService) + connectionService = module.get(ConnectionService) + + await testPrismaService.truncateAll() + await app.init() + }) + + afterAll(async () => { + await testPrismaService.truncateAll() + await module.close() + await app.close() + nock.cleanAll() + }) + + beforeEach(async () => { + await testPrismaService.truncateAll() + // Clean any pending nock interceptors + nock.cleanAll() + + // Create a test connection + await connectionService.create(TEST_CLIENT_ID, { + connectionId: TEST_CONNECTION_ID, + label: 'test connection', + provider: Provider.ANCHORAGE, + url: MOCK_API_URL, + credentials: { + apiKey: 'test-api-key', + privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) + } + }) + }) + + it('forwards GET request', async () => { + nock(MOCK_API_URL).get('/v2/vaults').reply(200, { data: 'mock response' }) + + const response = await request(app.getHttpServer()) + .get('/proxy/v2/vaults') + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set(REQUEST_HEADER_CONNECTION_ID, TEST_CONNECTION_ID) + .send() + + expect(response.body).toEqual({ data: 'mock response' }) + expect(response.status).toBe(HttpStatus.OK) + }) + + it('forwards POST request', async () => { + nock(MOCK_API_URL).post('/v2/wallets').reply(201, { data: 'mock response' }) + + const response = await request(app.getHttpServer()) + .post('/proxy/v2/wallets') + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set(REQUEST_HEADER_CONNECTION_ID, TEST_CONNECTION_ID) + .send({ test: 'data' }) + + expect(response.body).toEqual({ data: 'mock response' }) + expect(response.status).toBe(HttpStatus.CREATED) + }) + + it('forwards DELETE request', async () => { + nock(MOCK_API_URL).delete('/v2/vaults').reply(204) + + const response = await request(app.getHttpServer()) + .delete('/proxy/v2/vaults') + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set(REQUEST_HEADER_CONNECTION_ID, TEST_CONNECTION_ID) + .send() + + expect(response.status).toBe(HttpStatus.NO_CONTENT) + }) + + it('forwards PUT request', async () => { + nock(MOCK_API_URL).put('/v2/vaults').reply(200, { data: 'mock response' }) + + const response = await request(app.getHttpServer()) + .put('/proxy/v2/vaults') + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set(REQUEST_HEADER_CONNECTION_ID, TEST_CONNECTION_ID) + .send({ test: 'data' }) + + expect(response.body).toEqual({ data: 'mock response' }) + expect(response.status).toBe(HttpStatus.OK) + }) + + it('forwards PATCH request', async () => { + nock(MOCK_API_URL).patch('/v2/vaults').reply(200, { data: 'mock response' }) + + const response = await request(app.getHttpServer()) + .patch('/proxy/v2/vaults') + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set(REQUEST_HEADER_CONNECTION_ID, TEST_CONNECTION_ID) + .send({ test: 'data' }) + + expect(response.body).toEqual({ data: 'mock response' }) + expect(response.status).toBe(HttpStatus.OK) + }) + + it('adds api-key header', async () => { + let capturedHeaders: Record = {} + + nock(MOCK_API_URL) + .get('/v2/vaults') + .reply(function () { + capturedHeaders = this.req.headers + return [200, { data: 'mock response' }] + }) + + await request(app.getHttpServer()) + .get('/proxy/v2/vaults') + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set(REQUEST_HEADER_CONNECTION_ID, TEST_CONNECTION_ID) + .send() + + expect(capturedHeaders['api-access-key']).toBe('test-api-key') + }) + + it(`doesn't leak client-id header`, async () => { + let capturedHeaders: Record = {} + + nock(MOCK_API_URL) + .get('/v2/vaults') + .reply(function () { + capturedHeaders = this.req.headers + return [200, { data: 'mock response' }] + }) + + await request(app.getHttpServer()) + .get('/v1/proxy/v2/vaults') + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set(REQUEST_HEADER_CONNECTION_ID, TEST_CONNECTION_ID) + .send() + + expect(capturedHeaders[REQUEST_HEADER_CLIENT_ID.toLowerCase()]).toBeUndefined() + }) + + it(`doesn't leak connection-id header`, async () => { + let capturedHeaders: Record = {} + + nock(MOCK_API_URL) + .get('/v2/vaults') + .reply(function () { + capturedHeaders = this.req.headers + return [200, { data: 'mock response' }] + }) + + await request(app.getHttpServer()) + .get('/v1/proxy/v2/vaults') + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set(REQUEST_HEADER_CONNECTION_ID, TEST_CONNECTION_ID) + .send() + + expect(capturedHeaders[REQUEST_HEADER_CONNECTION_ID.toLowerCase()]).toBeUndefined() + }) + + it(`doesn't tamper with the error response`, async () => { + nock(MOCK_API_URL).get('/v2/vaults').reply(512, { error: 'mock error' }, { 'x-custom-header': 'custom value' }) + + const response = await request(app.getHttpServer()) + .get('/proxy/v2/vaults') + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set(REQUEST_HEADER_CONNECTION_ID, TEST_CONNECTION_ID) + .send() + + expect(response.body).toEqual({ error: 'mock error' }) + expect(response.status).toBe(512) + expect(response.header['x-custom-header']).toBe('custom value') + }) + + it('throws a connection invalid exception when the connection is not active', async () => { + await connectionService.revoke(TEST_CLIENT_ID, TEST_CONNECTION_ID) + + const response = await request(app.getHttpServer()) + .get('/proxy/v2/vaults') + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set(REQUEST_HEADER_CONNECTION_ID, TEST_CONNECTION_ID) + .send() + + expect(response.body).toEqual({ + message: 'Connection is not active', + context: { connectionId: TEST_CONNECTION_ID, clientId: TEST_CLIENT_ID, status: 'revoked' }, + stack: expect.any(String), + statusCode: HttpStatus.UNPROCESSABLE_ENTITY + }) + expect(response.status).toBe(HttpStatus.UNPROCESSABLE_ENTITY) + }) +}) diff --git a/apps/vault/src/broker/__test__/e2e/sync.spec.ts b/apps/vault/src/broker/__test__/e2e/sync.spec.ts index d47832afe..d8cfed059 100644 --- a/apps/vault/src/broker/__test__/e2e/sync.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/sync.spec.ts @@ -3,14 +3,21 @@ import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' import { Alg, generateJwk, privateKeyToHex } from '@narval/signature' import { HttpStatus, INestApplication } from '@nestjs/common' import { Test, TestingModule } from '@nestjs/testing' +import { MockProxy, mock } from 'jest-mock-extended' import request from 'supertest' import { v4 as uuid } from 'uuid' import { load } from '../../../main.config' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { BrokerModule } from '../../broker.module' +import { + ANCHORAGE_TEST_API_BASE_URL, + setupMockServer +} from '../../core/service/__test__/integration/mocks/anchorage/server' +import { AnchorageSyncService } from '../../core/service/anchorage-sync.service' import { ConnectionService } from '../../core/service/connection.service' import { SyncService } from '../../core/service/sync.service' import { ActiveConnection, PendingConnection, Provider } from '../../core/type/connection.type' +import { SyncStatus } from '../../core/type/sync.type' describe('Sync', () => { let app: INestApplication @@ -18,20 +25,30 @@ describe('Sync', () => { let syncService: SyncService let connectionService: ConnectionService let testPrismaService: TestPrismaService + let anchorageSyncServiceMock: MockProxy - let activeConnectionOne: ActiveConnection - // eslint-disable-next-line @typescript-eslint/no-unused-vars - let activeConnectionTwo: ActiveConnection + let activeConnection: ActiveConnection // eslint-disable-next-line @typescript-eslint/no-unused-vars let pendingConnection: PendingConnection - const url = 'http://provider.narval.xyz' + const url = ANCHORAGE_TEST_API_BASE_URL const apiKey = 'test-api-key' const clientId = uuid() + setupMockServer() + beforeAll(async () => { + // We mock the provider's sync service here to prevent race conditions + // during testing. This is because the SyncService sends a promise to start + // the sync but does not wait for it to complete. + // + // NOTE: The sync logic is tested in the provider's sync service + // integration tests. + anchorageSyncServiceMock = mock() + anchorageSyncServiceMock.sync.mockResolvedValue() + module = await Test.createTestingModule({ imports: [ LoggerModule.forTest(), @@ -41,7 +58,10 @@ describe('Sync', () => { }), BrokerModule ] - }).compile() + }) + .overrideProvider(AnchorageSyncService) + .useValue(anchorageSyncServiceMock) + .compile() app = module.createNestApplication() @@ -63,17 +83,7 @@ describe('Sync', () => { beforeEach(async () => { await testPrismaService.truncateAll() - activeConnectionOne = await connectionService.create(clientId, { - connectionId: uuid(), - provider: Provider.ANCHORAGE, - url, - credentials: { - apiKey, - privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) - } - }) - - activeConnectionTwo = await connectionService.create(clientId, { + activeConnection = await connectionService.create(clientId, { connectionId: uuid(), provider: Provider.ANCHORAGE, url, @@ -90,6 +100,17 @@ describe('Sync', () => { }) describe('POST /syncs', () => { + // This test ensures that the sync process is correctly wired. + // Since the mock is created in the `beforeAll` block, it maintains a + // single state throughout the entire test lifecycle. Therefore, changing + // the order of this test will affect how many times the `sync` function is + // called. + it('dispatches the sync to the provider specific service', async () => { + await request(app.getHttpServer()).post('/syncs').set(REQUEST_HEADER_CLIENT_ID, clientId).send() + + expect(anchorageSyncServiceMock.sync).toHaveBeenCalledTimes(1) + }) + it('starts a sync on every active connection', async () => { const { status, body } = await request(app.getHttpServer()) .post('/syncs') @@ -97,51 +118,44 @@ describe('Sync', () => { .send() const syncs = await syncService.findAllPaginated(clientId) - const [syncOne, syncTwo] = syncs.data + const [sync] = syncs.data expect(body).toMatchObject({ started: true, syncs: [ { - clientId: syncOne.clientId, - connectionId: syncOne.connectionId, - createdAt: syncOne.createdAt.toISOString(), - syncId: syncOne.syncId, - status: syncOne.status - }, - { - clientId: syncTwo.clientId, - connectionId: syncTwo.connectionId, - createdAt: syncTwo.createdAt.toISOString(), - syncId: syncTwo.syncId, - status: syncTwo.status + clientId: sync.clientId, + connectionId: sync.connectionId, + createdAt: sync.createdAt.toISOString(), + syncId: sync.syncId, + status: SyncStatus.PROCESSING } ] }) expect(status).toEqual(HttpStatus.CREATED) - expect(syncs.data.length).toEqual(2) + expect(syncs.data.length).toEqual(1) }) it('starts a sync on the given connection', async () => { const { status, body } = await request(app.getHttpServer()) .post('/syncs') .set(REQUEST_HEADER_CLIENT_ID, clientId) - .send({ connectionId: activeConnectionOne.connectionId }) + .send({ connectionId: activeConnection.connectionId }) const syncs = await syncService.findAllPaginated(clientId) - const [syncOne] = syncs.data + const [sync] = syncs.data expect(body).toEqual({ started: true, syncs: [ { - clientId: syncOne.clientId, - connectionId: activeConnectionOne.connectionId, - createdAt: syncOne.createdAt.toISOString(), - syncId: syncOne.syncId, - status: syncOne.status + clientId: sync.clientId, + connectionId: activeConnection.connectionId, + createdAt: sync.createdAt.toISOString(), + syncId: sync.syncId, + status: SyncStatus.PROCESSING } ] }) @@ -156,7 +170,7 @@ describe('Sync', () => { it('responds with the specific sync', async () => { const { syncs } = await syncService.start({ clientId, - connectionId: activeConnectionOne.connectionId + connectionId: activeConnection.connectionId }) const [sync] = syncs @@ -170,7 +184,9 @@ describe('Sync', () => { connectionId: sync.connectionId, createdAt: sync.createdAt.toISOString(), syncId: sync.syncId, - status: sync.status + // In between the calling `start` and sending the request, the sync + // status changed from `processing` to `success`. + status: SyncStatus.SUCCESS }) expect(status).toEqual(HttpStatus.OK) @@ -180,7 +196,7 @@ describe('Sync', () => { describe('GET /syncs', () => { it('responds with a list of syncs', async () => { const { syncs } = await syncService.start({ clientId }) - const [syncOne, syncTwo] = syncs + const [sync] = syncs const { status, body } = await request(app.getHttpServer()) .get('/syncs') @@ -190,25 +206,20 @@ describe('Sync', () => { expect(body).toMatchObject({ syncs: [ { - clientId: syncOne.clientId, - connectionId: syncOne.connectionId, - createdAt: syncOne.createdAt.toISOString(), - syncId: syncOne.syncId, - status: syncOne.status - }, - { - clientId: syncTwo.clientId, - connectionId: syncTwo.connectionId, - createdAt: syncTwo.createdAt.toISOString(), - syncId: syncTwo.syncId, - status: syncTwo.status + clientId: sync.clientId, + connectionId: sync.connectionId, + createdAt: sync.createdAt.toISOString(), + syncId: sync.syncId, + // In between the calling `start` and sending the request, the sync + // status changed from `processing` to `success`. + status: SyncStatus.SUCCESS } ] }) expect(status).toEqual(HttpStatus.OK) - expect(body.syncs.length).toEqual(2) + expect(body.syncs.length).toEqual(1) }) it('responds with the specific sync filter by connection', async () => { @@ -228,7 +239,7 @@ describe('Sync', () => { connectionId: sync.connectionId, createdAt: sync.createdAt.toISOString(), syncId: sync.syncId, - status: sync.status + status: SyncStatus.SUCCESS } ] }) diff --git a/apps/vault/src/broker/__test__/util/map-db-to-returned.ts b/apps/vault/src/broker/__test__/util/map-db-to-returned.ts index 1ad916425..7240ba3ba 100644 --- a/apps/vault/src/broker/__test__/util/map-db-to-returned.ts +++ b/apps/vault/src/broker/__test__/util/map-db-to-returned.ts @@ -1,3 +1,5 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ + import { ProviderAccount, ProviderAddress, ProviderConnection, ProviderWallet } from '@prisma/client/vault' import { PublicConnection } from '../../core/type/connection.type' import { TEST_ACCOUNTS, TEST_ADDRESSES, TEST_CONNECTIONS, TEST_WALLET_CONNECTIONS } from './mock-data' diff --git a/apps/vault/src/broker/broker.module.ts b/apps/vault/src/broker/broker.module.ts index a1a10fa82..d35f42c13 100644 --- a/apps/vault/src/broker/broker.module.ts +++ b/apps/vault/src/broker/broker.module.ts @@ -1,3 +1,4 @@ +import { HttpModule, OpenTelemetryModule } from '@narval/nestjs-shared' import { Module } from '@nestjs/common' import { DEFAULT_HTTP_MODULE_PROVIDERS } from '../shared/constant' import { PersistenceModule } from '../shared/module/persistence/persistence.module' @@ -6,14 +7,19 @@ import { EncryptionKeyRepository } from '../transit-encryption/persistence/encry import { TransitEncryptionModule } from '../transit-encryption/transit-encryption.module' import { AccountService } from './core/service/account.service' import { AddressService } from './core/service/address.service' +import { AnchorageSyncService } from './core/service/anchorage-sync.service' import { ConnectionService } from './core/service/connection.service' +import { ProxyService } from './core/service/proxy.service' import { SyncService } from './core/service/sync.service' import { WalletService } from './core/service/wallet.service' +import { AnchorageClient } from './http/client/anchorage.client' import { AccountController } from './http/rest/controller/account.controller' import { AddressController } from './http/rest/controller/address.controller' import { ConnectionController } from './http/rest/controller/connection.controller' +import { ProxyController } from './http/rest/controller/proxy.controller' import { SyncController } from './http/rest/controller/sync.controller' import { WalletController } from './http/rest/controller/wallet.controller' +import { ConnectionSeedService } from './persistence/connection.seed' import { AccountRepository } from './persistence/repository/account.repository' import { AddressRepository } from './persistence/repository/address.repository' import { ConnectionRepository } from './persistence/repository/connection.repository' @@ -21,18 +27,38 @@ import { SyncRepository } from './persistence/repository/sync.repository' import { WalletRepository } from './persistence/repository/wallet.repository' @Module({ - imports: [PersistenceModule, TransitEncryptionModule], - controllers: [ConnectionController, WalletController, AccountController, AddressController, SyncController], + imports: [ + PersistenceModule, + TransitEncryptionModule, + OpenTelemetryModule.forRoot(), + HttpModule.register({ + retry: { + retries: 3 + } + }) + ], + controllers: [ + ConnectionController, + WalletController, + AccountController, + AddressController, + SyncController, + ProxyController + ], providers: [ ...DEFAULT_HTTP_MODULE_PROVIDERS, AccountRepository, AccountService, AddressRepository, AddressService, + AnchorageClient, + AnchorageSyncService, ConnectionRepository, + ConnectionSeedService, ConnectionService, EncryptionKeyRepository, EncryptionKeyService, + ProxyService, SyncRepository, SyncService, WalletRepository, diff --git a/apps/vault/src/broker/core/exception/connection-invalid.exception.ts b/apps/vault/src/broker/core/exception/connection-invalid.exception.ts new file mode 100644 index 000000000..1cc48107a --- /dev/null +++ b/apps/vault/src/broker/core/exception/connection-invalid.exception.ts @@ -0,0 +1,13 @@ +import { HttpStatus } from '@nestjs/common' +import { ApplicationExceptionParams } from '../../../shared/exception/application.exception' +import { BrokerException } from './broker.exception' + +export class ConnectionInvalidException extends BrokerException { + constructor(params?: Partial) { + super({ + message: params?.message || 'Invalid connection', + suggestedHttpStatusCode: params?.suggestedHttpStatusCode || HttpStatus.UNPROCESSABLE_ENTITY, + ...params + }) + } +} diff --git a/apps/vault/src/broker/core/exception/model-invalid.exception.ts b/apps/vault/src/broker/core/exception/model-invalid.exception.ts new file mode 100644 index 000000000..28ac1a27f --- /dev/null +++ b/apps/vault/src/broker/core/exception/model-invalid.exception.ts @@ -0,0 +1,11 @@ +import { HttpStatus } from '@nestjs/common' +import { BrokerException } from './broker.exception' + +export class ModelInvalidException extends BrokerException { + constructor() { + super({ + message: 'Invalid model', + suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR + }) + } +} diff --git a/apps/vault/src/broker/core/exception/proxy-request.exception.ts b/apps/vault/src/broker/core/exception/proxy-request.exception.ts new file mode 100644 index 000000000..bef47c9c1 --- /dev/null +++ b/apps/vault/src/broker/core/exception/proxy-request.exception.ts @@ -0,0 +1,30 @@ +import { BrokerException } from './broker.exception' + +export class ProxyRequestException extends BrokerException { + public data: any + public code: number + public headers: Record + + constructor({ + data, + status, + message, + headers, + context + }: { + data: any + status: number + message: string + headers: Record + context: Record + }) { + super({ + message: message ? message : 'Provider request failed', + suggestedHttpStatusCode: status, + context + }) + this.data = data + this.code = status + this.headers = headers + } +} diff --git a/apps/vault/src/broker/core/exception/url-parser.exception.ts b/apps/vault/src/broker/core/exception/url-parser.exception.ts new file mode 100644 index 000000000..c1a439202 --- /dev/null +++ b/apps/vault/src/broker/core/exception/url-parser.exception.ts @@ -0,0 +1,12 @@ +import { HttpStatus } from '@nestjs/common' +import { BrokerException } from './broker.exception' + +export class UrlParserException extends BrokerException { + constructor({ url, message }: { url: string; message?: string }) { + super({ + message: message || `Cannot parse url`, + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, + context: { url } + }) + } +} diff --git a/apps/vault/src/broker/core/lib/__test__/unit/anchorage-request-builder.spec.ts b/apps/vault/src/broker/core/lib/__test__/unit/anchorage-request-builder.spec.ts new file mode 100644 index 000000000..eae22d2a2 --- /dev/null +++ b/apps/vault/src/broker/core/lib/__test__/unit/anchorage-request-builder.spec.ts @@ -0,0 +1,149 @@ +import { Alg, privateKeyToJwk } from '@narval/signature' +import * as nobleEd25519 from '@noble/ed25519' +import { UrlParserException } from '../../../exception/url-parser.exception' +import { HttpMethod, buildAnchorageSignedRequest, parseUrl, serializePayload } from '../../anchorage-request-builder' + +const ED25519_PRIVATE_KEY = '0xe6ad32d225c16074bd4a3b62e28c99dd26136ef341e6368ca05227d1e13822d9' + +describe('Anchorage Request Builder', () => { + const mockTime = new Date(1234567890) + + const privateKey = privateKeyToJwk(ED25519_PRIVATE_KEY, Alg.EDDSA) + + describe('parseUrl', () => { + it('extracts version path from valid URLs', () => { + const testCases = [ + { + input: 'https://api.anchorage.com/v2/accounts', + expected: '/v2/accounts' + }, + { + input: 'https://api.anchorage.com/v1/trading/quotes', + expected: '/v1/trading/quotes' + }, + { + input: 'https://api.anchorage.com/v3/something/nested/path', + expected: '/v3/something/nested/path' + }, + { + input: 'https://api.anchorage.com/v4/something/nested/path?query=param&another=param&yetAnother=param', + expected: '/v4/something/nested/path?query=param&another=param&yetAnother=param' + } + ] + testCases.forEach(({ input, expected }) => { + expect(parseUrl(input)).toBe(expected) + }) + }) + + it('throws UrlParserException for invalid URLs', () => { + const invalidUrls = [ + 'https://api.anchorage.com/accounts', + 'https://api.anchorage.com/invalidv1/', + 'not-even-a-url' + ] + + invalidUrls.forEach((url) => expect(() => parseUrl(url)).toThrow(UrlParserException)) + }) + }) + + describe('serializePayload', () => { + it('serializes GET requests without body', () => { + const result = serializePayload(mockTime.getTime(), 'GET', '/v2/accounts', { some: 'data' }) + expect(result).toBe(`${mockTime.getTime()}GET/v2/accounts`) + }) + + it('serializes POST requests with body', () => { + const body = { some: 'data' } + const result = serializePayload(mockTime.getTime(), 'POST', '/v2/accounts', body) + expect(result).toBe(`${mockTime.getTime()}POST/v2/accounts${JSON.stringify(body)}`) + }) + + it('handles undefined body for non-GET requests', () => { + const result = serializePayload(mockTime.getTime(), 'POST', '/v2/accounts', undefined) + expect(result).toBe(`${mockTime.getTime()}POST/v2/accounts`) + }) + + it('formats payloads for all HTTP methods', () => { + const methods: HttpMethod[] = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'] + const body = { test: 'data' } + + methods.forEach((method) => { + const result = serializePayload(mockTime.getTime(), method, '/v2/test', body) + const expected = `${mockTime.getTime()}${method}/v2/test${method === 'GET' ? '' : JSON.stringify(body)}` + expect(result).toBe(expected) + }) + }) + }) + + describe('buildAnchorageSignedRequest', () => { + const defaultParams = { + url: 'https://api.anchorage.com/v2/accounts', + method: 'GET' as const, + apiKey: 'test-api-key', + signKey: privateKey, + body: undefined, + now: mockTime + } + + it('builds GET request config', async () => { + jest.spyOn(nobleEd25519, 'sign') + + const config = await buildAnchorageSignedRequest(defaultParams) + + expect(config).toEqual({ + url: defaultParams.url, + method: defaultParams.method, + headers: { + 'Api-Access-Key': defaultParams.apiKey, + 'Api-Signature': + '6b312c48285544422dc7f4bc44a8f094094453d74fb83f5419c99a2ce1ce79133034b561838b1312d257eb7af5ac8582bfdad319f602f3ff81c484c5a147c50e', + 'Api-Timestamp': Math.floor(mockTime.getTime() / 1000), + 'Content-Type': 'application/json' + }, + data: undefined + }) + + expect(nobleEd25519.sign).toHaveBeenCalledWith( + expect.any(String), + // We need to slice the '0x' prefix from the hex key + ED25519_PRIVATE_KEY.slice(2) + ) + }) + + it('builds POST request config with body', async () => { + const params = { + ...defaultParams, + method: 'POST' as HttpMethod, + body: { test: 'data' } + } + + const config = await buildAnchorageSignedRequest(params) + + expect(config).toEqual({ + url: params.url, + method: params.method, + headers: { + 'Api-Access-Key': params.apiKey, + 'Api-Signature': + '51f1feffab30a8e8bbad75cb85e99a945db0f71ca0e2dfc9b8f7be0f6ec65b9d5274d1e8eac283be9370a4c6d16bbab84049b58feadfcbcbc499bb816195420d', + 'Api-Timestamp': Math.floor(mockTime.getTime() / 1000), + 'Content-Type': 'application/json' + }, + data: params.body + }) + }) + + it('supports all HTTP methods with appropriate body handling', async () => { + const methods: HttpMethod[] = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'] + const body = { test: 'data' } + + for (const method of methods) { + const params = { ...defaultParams, method, body } + const config = await buildAnchorageSignedRequest(params) + + expect(config.method).toBe(method) + expect(config.data).toBe(method === 'GET' ? undefined : body) + } + }) + }) +}) diff --git a/apps/vault/src/broker/core/lib/anchorage-request-builder.ts b/apps/vault/src/broker/core/lib/anchorage-request-builder.ts new file mode 100644 index 000000000..b6b1e8651 --- /dev/null +++ b/apps/vault/src/broker/core/lib/anchorage-request-builder.ts @@ -0,0 +1,80 @@ +import { Ed25519PrivateKey, privateKeyToHex } from '@narval/signature' +import { sign } from '@noble/ed25519' +import { AxiosRequestConfig } from 'axios' +import { z } from 'zod' +import { UrlParserException } from '../exception/url-parser.exception' + +export const HttpMethod = z.union([ + z.literal('GET'), + z.literal('POST'), + z.literal('PATCH'), + z.literal('PUT'), + z.literal('DELETE') +]) +export type HttpMethod = z.infer + +export type BuildAnchorageRequestParams = { + url: string + method: HttpMethod + body?: unknown + apiKey: string + signKey: Ed25519PrivateKey + now?: Date +} + +export const parseUrl = (url: string): string => { + const regex = /(\/v\d+(?:\/.*)?)$/ + const match = url.match(regex) + + if (!match) { + throw new UrlParserException({ + message: 'No version pattern found in the URL', + url + }) + } + + return match[1] +} + +export const serializePayload = (time: number, method: HttpMethod, endpoint: string, body: unknown): string => { + return `${time}${method}${endpoint}${body && method !== 'GET' ? JSON.stringify(body) : ''}` +} + +export const buildAnchorageSignedRequest = async ({ + url, + method, + body, + apiKey, + signKey, + now +}: BuildAnchorageRequestParams): Promise => { + const timestamp = now ? now.getTime() : new Date().getTime() + const time = Math.floor(timestamp / 1000) + + const endpoint = parseUrl(url) + const serializedPayload = serializePayload(time, method, endpoint, body) + + const signatureRequest = Buffer.from(serializedPayload, 'utf8').toString('hex') + + const signHexKey = await privateKeyToHex(signKey) + const hexSignature = await sign(signatureRequest, signHexKey.slice(2)) + const signature = Buffer.from(hexSignature).toString('hex') + + const headers = { + 'Api-Access-Key': apiKey, + 'Api-Signature': signature, + 'Api-Timestamp': time, + 'Content-Type': 'application/json' + } + + const data = body && method !== 'GET' ? body : undefined + + const config: AxiosRequestConfig = { + url, + method, + headers, + data + } + + return config +} diff --git a/apps/vault/src/broker/core/service/__test__/integration/anchorage-sync.service.spec.ts b/apps/vault/src/broker/core/service/__test__/integration/anchorage-sync.service.spec.ts new file mode 100644 index 000000000..c65125f90 --- /dev/null +++ b/apps/vault/src/broker/core/service/__test__/integration/anchorage-sync.service.spec.ts @@ -0,0 +1,158 @@ +import { ConfigModule } from '@narval/config-module' +import { HttpModule, LoggerModule } from '@narval/nestjs-shared' +import { Alg, generateJwk, privateKeyToHex } from '@narval/signature' +import { Test } from '@nestjs/testing' +import { v4 as uuid } from 'uuid' +import { load } from '../../../../../main.config' +import { PersistenceModule } from '../../../../../shared/module/persistence/persistence.module' +import { TestPrismaService } from '../../../../../shared/module/persistence/service/test-prisma.service' +import { TransitEncryptionModule } from '../../../../../transit-encryption/transit-encryption.module' +import { AnchorageClient } from '../../../../http/client/anchorage.client' +import { AccountRepository } from '../../../../persistence/repository/account.repository' +import { AddressRepository } from '../../../../persistence/repository/address.repository' +import { ConnectionRepository } from '../../../../persistence/repository/connection.repository' +import { WalletRepository } from '../../../../persistence/repository/wallet.repository' +import { ActiveConnection, Provider } from '../../../type/connection.type' +import { Account } from '../../../type/indexed-resources.type' +import { AccountService } from '../../account.service' +import { AddressService } from '../../address.service' +import { AnchorageSyncService } from '../../anchorage-sync.service' +import { ConnectionService } from '../../connection.service' +import { WalletService } from '../../wallet.service' +import { ANCHORAGE_TEST_API_BASE_URL, setupMockServer } from './mocks/anchorage/server' + +describe(AnchorageSyncService.name, () => { + let testPrismaService: TestPrismaService + let anchorageSyncService: AnchorageSyncService + let connectionService: ConnectionService + let connection: ActiveConnection + let walletService: WalletRepository + let accountService: AccountService + let addressService: AddressService + + setupMockServer() + + const clientId = uuid() + + beforeEach(async () => { + const module = await Test.createTestingModule({ + imports: [ + PersistenceModule, + TransitEncryptionModule, + HttpModule.register(), + LoggerModule.forTest(), + ConfigModule.forRoot({ + load: [load], + isGlobal: true + }) + ], + providers: [ + AnchorageSyncService, + AnchorageClient, + ConnectionService, + ConnectionRepository, + WalletService, + WalletRepository, + AccountService, + AccountRepository, + AddressService, + AddressRepository + ] + }).compile() + + testPrismaService = module.get(TestPrismaService) + anchorageSyncService = module.get(AnchorageSyncService) + connectionService = module.get(ConnectionService) + walletService = module.get(WalletService) + accountService = module.get(AccountService) + addressService = module.get(AddressService) + + await testPrismaService.truncateAll() + + connection = await connectionService.create(clientId, { + connectionId: uuid(), + provider: Provider.ANCHORAGE, + url: ANCHORAGE_TEST_API_BASE_URL, + credentials: { + apiKey: 'test-api-key', + privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) + } + }) + }) + + describe('syncWallets', () => { + it('fetches anchorage vaults and persist them as wallets', async () => { + const syncedWallets = await anchorageSyncService.syncWallets(connection) + + const wallets = await walletService.findAll(connection.clientId) + + expect(syncedWallets).toEqual(wallets) + }) + + it('does not duplicate wallets', async () => { + const [first, second] = await Promise.all([ + await anchorageSyncService.syncWallets(connection), + await anchorageSyncService.syncWallets(connection) + ]) + + expect(first.length).toEqual(2) + expect(second.length).toEqual(0) + }) + }) + + describe('syncAccounts', () => { + const sortByExternalId = (a: Account, b: Account) => a.externalId.localeCompare(b.externalId) + + it('fetches anchorage wallets and persist them as accounts', async () => { + await anchorageSyncService.syncWallets(connection) + + const syncedAccounts = await anchorageSyncService.syncAccounts(connection) + + const accounts = await accountService.findAll(connection.clientId) + + expect(syncedAccounts.sort(sortByExternalId)).toEqual(accounts.sort(sortByExternalId)) + }) + + it('does not duplicate accounts', async () => { + await anchorageSyncService.syncWallets(connection) + + const [first, second] = await Promise.all([ + await anchorageSyncService.syncAccounts(connection), + await anchorageSyncService.syncAccounts(connection) + ]) + + expect(first.length).toEqual(18) + expect(second.length).toEqual(0) + }) + }) + + describe('syncAddresses', () => { + beforeEach(async () => { + await anchorageSyncService.syncWallets(connection) + await anchorageSyncService.syncAccounts(connection) + }) + + it('fetches anchorage addresses and persist them as addresses', async () => { + const syncedAddresses = await anchorageSyncService.syncAddresses(connection) + + const addresses = await addressService.findAll(connection.clientId) + + expect(syncedAddresses).toEqual( + addresses.map((address) => ({ + ...address, + addressId: expect.any(String) + })) + ) + }) + + it('does not duplicate addresses', async () => { + const [first, second] = await Promise.all([ + await anchorageSyncService.syncAddresses(connection), + await anchorageSyncService.syncAddresses(connection) + ]) + + expect(first.length).toEqual(1) + expect(second.length).toEqual(0) + }) + }) +}) diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/handlers.ts b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/handlers.ts new file mode 100644 index 000000000..6e089fe81 --- /dev/null +++ b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/handlers.ts @@ -0,0 +1,18 @@ +import { HttpResponse, http } from 'msw' +import vaultAddressesOk from './response/vaults-addresses-ok.json' +import vaultsOk from './response/vaults-ok.json' +import walletsOk from './response/wallets-ok.json' + +export const getHandlers = (baseUrl: string) => [ + http.get(`${baseUrl}/v2/vaults/:vaultId/addresses`, () => { + return new HttpResponse(JSON.stringify(vaultAddressesOk)) + }), + + http.get(`${baseUrl}/v2/vaults`, () => { + return new HttpResponse(JSON.stringify(vaultsOk)) + }), + + http.get(`${baseUrl}/v2/wallets`, () => { + return new HttpResponse(JSON.stringify(walletsOk)) + }) +] diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/vaults-addresses-ok.json b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/vaults-addresses-ok.json new file mode 100644 index 000000000..2252961c4 --- /dev/null +++ b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/vaults-addresses-ok.json @@ -0,0 +1,14 @@ +{ + "data": [ + { + "address": "2N18VkRep3F2z7Ggm8W94nkKdARMfEM3EWa", + "addressId": "96bf95f1b59d50d9d1149057e8c0f9fd", + "addressSignaturePayload": "7b225465787441646472657373223a22324e3138566b5265703346327a3747676d385739346e6b4b6441524d66454d33455761227d", + "signature": "95c4ae4f5ab905bea2d385da09cb87c45bc0be138ba624d06e65ffa7468fd21220c63535abf2e8723ede3e649be65a4a69b183b7cd7d6a592b452f4b9d0ea603", + "walletId": "6a46a1977959e0529f567e8e927e3895" + } + ], + "page": { + "next": null + } +} diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/vaults-ok.json b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/vaults-ok.json new file mode 100644 index 000000000..f78c97c44 --- /dev/null +++ b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/vaults-ok.json @@ -0,0 +1,61 @@ +{ + "data": [ + { + "accountName": "Narval Account 1", + "assets": [ + { + "assetType": "BTC_S", + "availableBalance": { + "assetType": "BTC_S", + "currentPrice": "100571.636951942", + "currentUSDValue": "502.86", + "quantity": "0.005" + }, + "totalBalance": { + "assetType": "BTC_S", + "currentPrice": "100571.636951942", + "currentUSDValue": "502.86", + "quantity": "0.005" + }, + "vaultId": "084ff57c0984420efac31723579c94fc", + "vaultName": "Vault 1", + "walletId": "6a46a1977959e0529f567e8e927e3895" + } + ], + "description": "", + "name": "Vault 1", + "type": "VAULT", + "vaultId": "084ff57c0984420efac31723579c94fc" + }, + { + "accountName": "Narval Account 1", + "assets": [ + { + "assetType": "ETHHOL", + "availableBalance": { + "assetType": "ETHHOL", + "currentPrice": "3801.93297363249", + "currentUSDValue": "3798.13", + "quantity": "0.998998527910122" + }, + "totalBalance": { + "assetType": "ETHHOL", + "currentPrice": "3801.93297363249", + "currentUSDValue": "3798.13", + "quantity": "0.998998527910122" + }, + "vaultId": "62547351cea99e827bcd43a513c40e7c", + "vaultName": "Vault 2", + "walletId": "ec9a04d05472e417ceb06e32c66834d1" + } + ], + "description": "Test", + "name": "Vault 2", + "type": "VAULT", + "vaultId": "62547351cea99e827bcd43a513c40e7c" + } + ], + "page": { + "next": null + } +} diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/wallets-ok.json b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/wallets-ok.json new file mode 100644 index 000000000..3e1faa25d --- /dev/null +++ b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/wallets-ok.json @@ -0,0 +1,363 @@ +{ + "data": [ + { + "assets": [], + "depositAddress": { + "address": "3Hy7Mb34EoXmdVQwdhAj1QZqD5kpH1voR8", + "addressId": "0ba932183dea75b8edef26c8fa806d04", + "addressSignaturePayload": "7b225465787441646472657373223a22334879374d623334456f586d645651776468416a31515a7144356b704831766f5238227d", + "addressID": "0ba932183dea75b8edef26c8fa806d04", + "signature": "0d6648a227057244b287240b385227f4c2220a61504801074b9f3be4a9a1ec07fc452fe958cc70b6bd2e3f83fb013808237aeaa761c3b078330d8a659004fd0c" + }, + "isArchived": false, + "isDefault": false, + "networkId": "BTC", + "type": "WALLET", + "vaultId": "084ff57c0984420efac31723579c94fc", + "vaultName": "Vault 1", + "walletId": "145ff5b10e0e208b9c3adab0a9531f0c", + "walletName": "secondWalletThroughApi!" + }, + { + "assets": [], + "depositAddress": { + "address": "0x81a1e40F018E411063768B04695Fd1a3c4CE11fD", + "addressId": "952837ceae2e623bc2ff0bb747887acf", + "addressSignaturePayload": "7b225465787441646472657373223a22307838316131653430463031384534313130363337363842303436393546643161336334434531316644227d", + "addressID": "952837ceae2e623bc2ff0bb747887acf", + "signature": "a1f5d2f5724fd83d4cbbcd4873ce3fef3ec6911255069ead07eaf4ff24200c214fd08e39ba17d67b88b4ba362219a79d5669719e7ae9797ec660188dcee4e20f" + }, + "isArchived": false, + "isDefault": true, + "networkId": "ETH_ZKSYNC_T", + "type": "WALLET", + "vaultId": "084ff57c0984420efac31723579c94fc", + "vaultName": "Vault 1", + "walletId": "234963c4c39cb528ac3b8fa9c9db5280", + "walletName": "ZKsync Sepolia Testnet Wallet 1" + }, + { + "assets": [], + "depositAddress": { + "address": "3FNGj14FtsLZxyUXhogb5gofi28Ft22Y22", + "addressId": "5b3d879c618ff14796b7b96351c862f2", + "addressSignaturePayload": "7b225465787441646472657373223a2233464e476a31344674734c5a78795558686f676235676f6669323846743232593232227d", + "addressID": "5b3d879c618ff14796b7b96351c862f2", + "signature": "25e229c81fc671d046bf205053061a2755d8ab2102ce5150b8a2c59e45dade12a5967d2029fea0717cf599eb4a56ef27be1c20f84bb76ae98d0df02b0a0cd806" + }, + "isArchived": false, + "isDefault": false, + "networkId": "BTC", + "type": "WALLET", + "vaultId": "084ff57c0984420efac31723579c94fc", + "vaultName": "Vault 1", + "walletId": "307258c6006b367a7aa3d5d3665c64b0", + "walletName": "secondWalletThroughApi!" + }, + { + "assets": [], + "depositAddress": { + "address": "0x81a1e40F018E411063768B04695Fd1a3c4CE11fD", + "addressId": "6e4c8306027028ad0d35248059e0eac7", + "addressSignaturePayload": "7b225465787441646472657373223a22307838316131653430463031384534313130363337363842303436393546643161336334434531316644227d", + "addressID": "6e4c8306027028ad0d35248059e0eac7", + "signature": "a1f5d2f5724fd83d4cbbcd4873ce3fef3ec6911255069ead07eaf4ff24200c214fd08e39ba17d67b88b4ba362219a79d5669719e7ae9797ec660188dcee4e20f" + }, + "isArchived": false, + "isDefault": true, + "networkId": "ETH_ARBITRUM_T", + "type": "WALLET", + "vaultId": "084ff57c0984420efac31723579c94fc", + "vaultName": "Vault 1", + "walletId": "655d4d4524bbd1cefbf2c0cdd9ebdece", + "walletName": "Arbitrum Sepolia Testnet Wallet 1" + }, + { + "assets": [ + { + "assetType": "BTC_S", + "availableBalance": { + "assetType": "BTC_S", + "currentPrice": "100571.636951942", + "currentUSDValue": "502.86", + "quantity": "0.005" + }, + "totalBalance": { + "assetType": "BTC_S", + "currentPrice": "100571.636951942", + "currentUSDValue": "502.86", + "quantity": "0.005" + } + } + ], + "depositAddress": { + "address": "2N18VkRep3F2z7Ggm8W94nkKdARMfEM3EWa", + "addressId": "96bf95f1b59d50d9d1149057e8c0f9fd", + "addressSignaturePayload": "7b225465787441646472657373223a22324e3138566b5265703346327a3747676d385739346e6b4b6441524d66454d33455761227d", + "addressID": "96bf95f1b59d50d9d1149057e8c0f9fd", + "signature": "95c4ae4f5ab905bea2d385da09cb87c45bc0be138ba624d06e65ffa7468fd21220c63535abf2e8723ede3e649be65a4a69b183b7cd7d6a592b452f4b9d0ea603" + }, + "isArchived": false, + "isDefault": true, + "networkId": "BTC_S", + "type": "WALLET", + "vaultId": "084ff57c0984420efac31723579c94fc", + "vaultName": "Vault 1", + "walletId": "6a46a1977959e0529f567e8e927e3895", + "walletName": "Bitcoin Signet Wallet 1" + }, + { + "assets": [], + "depositAddress": { + "address": "0x27211c05145FDc3c916e3377DB1a257364c5380B", + "addressId": "e2a48a472cf729eb8874fc518a8e4cbd", + "addressSignaturePayload": "7b225465787441646472657373223a22307832373231316330353134354644633363393136653333373744423161323537333634633533383042227d", + "addressID": "e2a48a472cf729eb8874fc518a8e4cbd", + "signature": "55ab7af2138ada8bb2bbc7a57a219e0d45f92317d949ac508f3890a57057b15c9b83c0d39c96633bea5916668460f191a2f63b452a6b7e5c409e0e010b92b20c" + }, + "isArchived": false, + "isDefault": true, + "networkId": "ETH", + "type": "WALLET", + "vaultId": "084ff57c0984420efac31723579c94fc", + "vaultName": "Vault 1", + "walletId": "7f81de30acbe98e3f6895eb12ab7d16f", + "walletName": "Ethereum Wallet 1" + }, + { + "assets": [], + "depositAddress": { + "address": "3DbSPwCQF9kWqpCHWjHuTY8uBu9PqHStUr", + "addressId": "a569b247f3dfa59fbd4df08d4814132c", + "addressSignaturePayload": "7b225465787441646472657373223a22334462535077435146396b5771704348576a48755459387542753950714853745572227d", + "addressID": "a569b247f3dfa59fbd4df08d4814132c", + "signature": "b4d92f68663365a9931d2ca934635ac6c844e0a73b45c8f25779f6bd330ea6700807fb6c72014d159534902219924586b28db6fabcd982caf73bd533f11b3802" + }, + "isArchived": false, + "isDefault": true, + "networkId": "BTC", + "type": "WALLET", + "vaultId": "084ff57c0984420efac31723579c94fc", + "vaultName": "Vault 1", + "walletId": "97f83a7fae3563895f50e2cbe4b9906c", + "walletName": "firstWalletThroughApi!" + }, + { + "assets": [], + "depositAddress": { + "address": "0x27211c05145FDc3c916e3377DB1a257364c5380B", + "addressId": "e49984c07576e86c622fd28fe44537ee", + "addressSignaturePayload": "7b225465787441646472657373223a22307832373231316330353134354644633363393136653333373744423161323537333634633533383042227d", + "addressID": "e49984c07576e86c622fd28fe44537ee", + "signature": "55ab7af2138ada8bb2bbc7a57a219e0d45f92317d949ac508f3890a57057b15c9b83c0d39c96633bea5916668460f191a2f63b452a6b7e5c409e0e010b92b20c" + }, + "isArchived": false, + "isDefault": true, + "networkId": "POL_POLYGON", + "type": "WALLET", + "vaultId": "084ff57c0984420efac31723579c94fc", + "vaultName": "Vault 1", + "walletId": "aba218a001728a6dd12b71cff2f8b5c0", + "walletName": "Polygon Wallet 1" + }, + { + "assets": [], + "depositAddress": { + "address": "3MeQ1PQZhnsJQUfHydE4dtpkri36gvrb8y", + "addressId": "9f5fe77af96429160103d24a61f9c4cb", + "addressSignaturePayload": "7b225465787441646472657373223a22334d65513150515a686e734a51556648796445346474706b72693336677672623879227d", + "addressID": "9f5fe77af96429160103d24a61f9c4cb", + "signature": "046642e46ba6d34c6318ecc25bb7b09f45d36a6ea352302b61ecbb3ef78c527aa33f47a886df351ccbb5cfcf40feb62b21d890c71e66babfd5d5bfe77556410c" + }, + "isArchived": false, + "isDefault": false, + "networkId": "BTC", + "type": "WALLET", + "vaultId": "084ff57c0984420efac31723579c94fc", + "vaultName": "Vault 1", + "walletId": "ae7abb325366f0623f9e192cd491436f", + "walletName": "secondWalletThroughApi!" + }, + { + "assets": [], + "depositAddress": { + "address": "3299b5fNXQortckqRRo7sAa7mgQcVotYPT", + "addressId": "6639c74804e5599860e9f5d8d55c03fb", + "addressSignaturePayload": "7b225465787441646472657373223a22333239396235664e58516f7274636b7152526f37734161376d675163566f74595054227d", + "addressID": "6639c74804e5599860e9f5d8d55c03fb", + "signature": "f295be507f3dcae9aa8a83b2e39b0341c6db16759f2e14bf9067aaf1714db76f61ff97119c032b085b737cfae438548880fbe6ff789b314415f1ca228e5b410d" + }, + "isArchived": false, + "isDefault": false, + "networkId": "BTC", + "type": "WALLET", + "vaultId": "084ff57c0984420efac31723579c94fc", + "vaultName": "Vault 1", + "walletId": "bf4538760915a5022d23f64b988cfedd", + "walletName": "secondWalletThroughApi!" + }, + { + "assets": [], + "depositAddress": { + "address": "3N86DziokoWESv1ZmEVC5ZCYVUnmhFhBNp", + "addressId": "7421b5541e928fe2dc35e5f95453c330", + "addressSignaturePayload": "7b225465787441646472657373223a22334e3836447a696f6b6f57455376315a6d455643355a435956556e6d684668424e70227d", + "addressID": "7421b5541e928fe2dc35e5f95453c330", + "signature": "a42054cfea8d836d93643538ba087c248a973b6fb0c490453d29f0e2b7e8b2a264a063097382a9085836d975fd0eb6770e61fdf3203f12b44573dc55fbb0cf09" + }, + "isArchived": false, + "isDefault": false, + "networkId": "BTC", + "type": "WALLET", + "vaultId": "084ff57c0984420efac31723579c94fc", + "vaultName": "Vault 1", + "walletId": "c3753da1db3d040f2ee295f6f3a91e0c", + "walletName": "firstWalletThroughApi!" + }, + { + "assets": [], + "depositAddress": { + "address": "0x6F28B85E1246ce5A4af89c5C94C0C661D6Cd031a", + "addressId": "f031997f52f848838b1f3b4eb1aa83fa", + "addressSignaturePayload": "7b225465787441646472657373223a22307836463238423835453132343663653541346166383963354339344330433636314436436430333161227d", + "addressID": "f031997f52f848838b1f3b4eb1aa83fa", + "signature": "f3197acd348734317a1b9fa0817f533d93ed2407545cd5606e6c95046ecc0bb4d719d54404fe94a02bd57def3add81cdee9547d93515f32913242e6f26937a0a" + }, + "isArchived": false, + "isDefault": false, + "networkId": "POL_POLYGON", + "type": "WALLET", + "vaultId": "084ff57c0984420efac31723579c94fc", + "vaultName": "Vault 1", + "walletId": "c4e5e0936fc1bd3646c3b0af9b2e729b", + "walletName": "Polygon Wallet 2" + }, + { + "assets": [], + "depositAddress": { + "address": "3FGW9JswZNkrLtSfkqfVMekNg1T7tuAkxe", + "addressId": "99a5dc014105cc59304813f8540ccc56", + "addressSignaturePayload": "7b225465787441646472657373223a2233464757394a73775a4e6b724c7453666b7166564d656b4e673154377475416b7865227d", + "addressID": "99a5dc014105cc59304813f8540ccc56", + "signature": "ba0044130fb6668c3bdb24eb51c21ff956829f65b14cd43e7ae288fb20aeb6dce65cb86fbee18cbc92da8f9215630f7c916227f473fa9103edef30020f0d5a08" + }, + "isArchived": false, + "isDefault": false, + "networkId": "BTC", + "type": "WALLET", + "vaultId": "084ff57c0984420efac31723579c94fc", + "vaultName": "Vault 1", + "walletId": "c8e6f9f5e09aeb4f5bbf43bf34ba909e", + "walletName": "firstWalletThroughApi!" + }, + { + "assets": [], + "depositAddress": { + "address": "0x81a1e40F018E411063768B04695Fd1a3c4CE11fD", + "addressId": "6d58eaac11543ba7477294d6981cf897", + "addressSignaturePayload": "7b225465787441646472657373223a22307838316131653430463031384534313130363337363842303436393546643161336334434531316644227d", + "addressID": "6d58eaac11543ba7477294d6981cf897", + "signature": "a1f5d2f5724fd83d4cbbcd4873ce3fef3ec6911255069ead07eaf4ff24200c214fd08e39ba17d67b88b4ba362219a79d5669719e7ae9797ec660188dcee4e20f" + }, + "isArchived": false, + "isDefault": true, + "networkId": "ETHSEP", + "type": "WALLET", + "vaultId": "084ff57c0984420efac31723579c94fc", + "vaultName": "Vault 1", + "walletId": "d30a5c8cb83f0be46d7669f81d776a62", + "walletName": "Ethereum Sepolia Wallet 1" + }, + { + "assets": [], + "depositAddress": { + "address": "0x6F28B85E1246ce5A4af89c5C94C0C661D6Cd031a", + "addressId": "4407a91a23f49ca8160af0708373c53a", + "addressSignaturePayload": "7b225465787441646472657373223a22307836463238423835453132343663653541346166383963354339344330433636314436436430333161227d", + "addressID": "4407a91a23f49ca8160af0708373c53a", + "signature": "f3197acd348734317a1b9fa0817f533d93ed2407545cd5606e6c95046ecc0bb4d719d54404fe94a02bd57def3add81cdee9547d93515f32913242e6f26937a0a" + }, + "isArchived": false, + "isDefault": false, + "networkId": "ETH", + "type": "WALLET", + "vaultId": "084ff57c0984420efac31723579c94fc", + "vaultName": "Vault 1", + "walletId": "daa5ead0f7f164d2de3c2fb83610f447", + "walletName": "Ethereum Wallet 2" + }, + { + "assets": [], + "depositAddress": { + "address": "3FWW3qkJjpdMZLHc1TDpbaNhYDxW3oYpdA", + "addressId": "dea22db33e3a40784a75971b73558258", + "addressSignaturePayload": "7b225465787441646472657373223a223346575733716b4a6a70644d5a4c48633154447062614e6859447857336f59706441227d", + "addressID": "dea22db33e3a40784a75971b73558258", + "signature": "abbfe2b34c8980b8c6bef797095afbaa9a62cd9197eaaf72a84bfbca755645a04c9d547862e66fdc72a07c9db24edd8c9f99f7fbceb7fe9cd06bdefe74203103" + }, + "isArchived": false, + "isDefault": false, + "networkId": "BTC", + "type": "WALLET", + "vaultId": "084ff57c0984420efac31723579c94fc", + "vaultName": "Vault 1", + "walletId": "fa2d82db5fab74ed0c1eec3e57eba2fb", + "walletName": "secondWalletThroughApi!" + }, + { + "assets": [], + "depositAddress": { + "address": "DDzPFiqWrHHYFRQQnh9ka83PYaVrn5zSsE", + "addressId": "59ec6d5ed7be498d54f8cb268011846b", + "addressSignaturePayload": "7b225465787441646472657373223a2244447a504669715772484859465251516e68396b61383350596156726e357a537345227d", + "addressID": "59ec6d5ed7be498d54f8cb268011846b", + "signature": "7b122a9c5b2579b74db77262bc66e2a52e68f5d7246cd94f3f1bb9e381661d8ba5023f32b3d5cc0b04f7dfa3aaaa52fba91c080777b9396f2e314e70c52c8f05" + }, + "isArchived": false, + "isDefault": true, + "networkId": "DOGE", + "type": "WALLET", + "vaultId": "084ff57c0984420efac31723579c94fc", + "vaultName": "Vault 1", + "walletId": "fdd93f7a1f41b98bd6672edfa301803c", + "walletName": "Doge" + }, + { + "assets": [ + { + "assetType": "ETHHOL", + "availableBalance": { + "assetType": "ETHHOL", + "currentPrice": "3801.93297363249", + "currentUSDValue": "3798.13", + "quantity": "0.998998527910122" + }, + "totalBalance": { + "assetType": "ETHHOL", + "currentPrice": "3801.93297363249", + "currentUSDValue": "3798.13", + "quantity": "0.998998527910122" + } + } + ], + "depositAddress": { + "address": "0x4BB7c65f821Ffcd1CAFEF3276E8eDa44474A08D3", + "addressId": "3d3b31a695fcbdf1c8a16c5df62c6516", + "addressSignaturePayload": "7b225465787441646472657373223a22307834424237633635663832314666636431434146454633323736453865446134343437344130384433227d", + "addressID": "3d3b31a695fcbdf1c8a16c5df62c6516", + "signature": "68a971bec8f22480202413fef93e0b0cbc7b6daf43c4c17cc1ed1948dd97742ec9a1a28336f2eaa95c32fd8ce342f00b62fefae00cf7d6a609d1bb21646a9e0d" + }, + "isArchived": false, + "isDefault": true, + "networkId": "ETHHOL", + "type": "WALLET", + "vaultId": "62547351cea99e827bcd43a513c40e7c", + "vaultName": "Vault 2", + "walletId": "ec9a04d05472e417ceb06e32c66834d1", + "walletName": "Ethereum Holešky Wallet 1" + } + ], + "page": { + "next": null + } +} diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/server.ts b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/server.ts new file mode 100644 index 000000000..ab1381de6 --- /dev/null +++ b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/server.ts @@ -0,0 +1,55 @@ +import { afterAll, afterEach, beforeAll } from '@jest/globals' +import { SetupServerApi, setupServer } from 'msw/node' +import { disableNockProtection, restoreNockProtection } from '../../../../../../../../test/nock.util' +import { getHandlers } from './handlers' + +export const ANCHORAGE_TEST_API_BASE_URL = 'https://test-mock-api.anchorage.com' + +export const getMockServer = () => setupServer(...getHandlers(ANCHORAGE_TEST_API_BASE_URL)) + +const attachToJestTestLifecycle = (server: SetupServerApi): SetupServerApi => { + beforeAll(() => { + // Disable nock net protection to allow requests to the mock server. + disableNockProtection() + server.listen({ + // IMPORTANT: Allow requests to 127.0.0.1 to pass through to support + // end-to-end testing with supertest because it boots a local server and + // helps send requests from the test to the server. + onUnhandledRequest: (req) => { + if (req.url.includes('127.0.0.1')) { + return 'bypass' + } + + return 'error' + } + }) + }) + + afterEach(() => server.resetHandlers()) + + afterAll(() => { + restoreNockProtection() + server.close() + }) + + return server +} + +/** + * Sets up a mock server and integrates it with Jest's test lifecycle. + * + * - The server starts on `beforeAll`. + * - HTTP handlers are reset on `afterEach` + * - The server is closed on `afterAll` + * + * IMPORTANT: This function should be used within a test block, such as + * `describe` or `it`. If you only need the server instance without attaching + * it to the test lifecycle, use `getMockServer` instead. + */ +export const setupMockServer = (server?: SetupServerApi): SetupServerApi => { + if (server) { + return attachToJestTestLifecycle(server) + } + + return attachToJestTestLifecycle(getMockServer()) +} diff --git a/apps/vault/src/broker/core/service/account.service.ts b/apps/vault/src/broker/core/service/account.service.ts index 3eaf0a6dd..c0e267497 100644 --- a/apps/vault/src/broker/core/service/account.service.ts +++ b/apps/vault/src/broker/core/service/account.service.ts @@ -1,18 +1,22 @@ import { PaginatedResult, PaginationOptions } from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' -import { AccountRepository } from '../../persistence/repository/account.repository' +import { + AccountRepository, + FindAllOptions, + FindAllPaginatedOptions +} from '../../persistence/repository/account.repository' import { Account, Address } from '../type/indexed-resources.type' @Injectable() export class AccountService { - constructor(private readonly AccountRepository: AccountRepository) {} + constructor(private readonly accountRepository: AccountRepository) {} async getAccounts(clientId: string, options: PaginationOptions): Promise> { - return this.AccountRepository.findByClientId(clientId, options) + return this.accountRepository.findByClientId(clientId, options) } async getAccount(clientId: string, AccountId: string): Promise { - return this.AccountRepository.findById(clientId, AccountId) + return this.accountRepository.findById(clientId, AccountId) } async getAccountAddresses( @@ -20,6 +24,18 @@ export class AccountService { AccountId: string, options: PaginationOptions ): Promise> { - return this.AccountRepository.findAddressesByAccountId(clientId, AccountId, options) + return this.accountRepository.findAddressesByAccountId(clientId, AccountId, options) + } + + async findAllPaginated(clientId: string, options?: FindAllPaginatedOptions): Promise> { + return this.accountRepository.findAllPaginated(clientId, options) + } + + async bulkCreate(accounts: Account[]): Promise { + return this.accountRepository.bulkCreate(accounts) + } + + async findAll(clientId: string, options?: FindAllOptions): Promise { + return this.accountRepository.findAll(clientId, options) } } diff --git a/apps/vault/src/broker/core/service/address.service.ts b/apps/vault/src/broker/core/service/address.service.ts index c070821d0..83ea49343 100644 --- a/apps/vault/src/broker/core/service/address.service.ts +++ b/apps/vault/src/broker/core/service/address.service.ts @@ -1,17 +1,25 @@ import { PaginatedResult, PaginationOptions } from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' -import { AddressRepository } from '../../persistence/repository/address.repository' +import { AddressRepository, FindAllFilters } from '../../persistence/repository/address.repository' import { Address } from '../type/indexed-resources.type' @Injectable() export class AddressService { - constructor(private readonly AddressRepository: AddressRepository) {} + constructor(private readonly addressRepository: AddressRepository) {} async getAddresses(clientId: string, options?: PaginationOptions): Promise> { - return this.AddressRepository.findByClientId(clientId, options) + return this.addressRepository.findByClientId(clientId, options) } async getAddress(clientId: string, AddressId: string): Promise
{ - return this.AddressRepository.findById(clientId, AddressId) + return this.addressRepository.findById(clientId, AddressId) + } + + async bulkCreate(addresses: Address[]): Promise { + return this.addressRepository.bulkCreate(addresses) + } + + async findAll(clientId: string, opts?: FindAllFilters): Promise { + return this.addressRepository.findAll(clientId, opts) } } diff --git a/apps/vault/src/broker/core/service/anchorage-sync.service.ts b/apps/vault/src/broker/core/service/anchorage-sync.service.ts new file mode 100644 index 000000000..57c8b41f9 --- /dev/null +++ b/apps/vault/src/broker/core/service/anchorage-sync.service.ts @@ -0,0 +1,274 @@ +import { LoggerService } from '@narval/nestjs-shared' +import { Ed25519PrivateKey } from '@narval/signature' +import { HttpStatus, Injectable } from '@nestjs/common' +import { uniq } from 'lodash' +import { v4 as uuid } from 'uuid' +import { AnchorageClient } from '../../http/client/anchorage.client' +import { BrokerException } from '../exception/broker.exception' +import { ConnectionInvalidException } from '../exception/connection-invalid.exception' +import { ActiveConnection, Provider } from '../type/connection.type' +import { Account, Address, Wallet } from '../type/indexed-resources.type' +import { AccountService } from './account.service' +import { AddressService } from './address.service' +import { WalletService } from './wallet.service' + +@Injectable() +export class AnchorageSyncService { + constructor( + private readonly anchorageClient: AnchorageClient, + private readonly walletService: WalletService, + private readonly accountService: AccountService, + private readonly addressService: AddressService, + private readonly logger: LoggerService + ) {} + + async sync(connection: ActiveConnection): Promise { + await this.syncWallets(connection) + await this.syncAccounts(connection) + await this.syncAddresses(connection) + } + + async syncWallets(connection: ActiveConnection) { + this.logger.log('Sync Anchorage wallets', { + connectionId: connection.credentials, + clientId: connection.clientId, + url: connection.url + }) + + this.validateConnection(connection) + + const anchorageVaults = await this.anchorageClient.getVaults({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey + }) + + const existingWallets = await this.walletService.findAll(connection.clientId, { + filters: { + externalIds: anchorageVaults.map((vault) => vault.vaultId) + } + }) + + const existingWalletByExternalId = new Map(existingWallets.map((wallet) => [wallet.externalId, wallet])) + + const missingAnchorageVaults = anchorageVaults.filter( + (anchorageVault) => !existingWalletByExternalId.has(anchorageVault.vaultId) + ) + + const now = new Date() + + const wallets: Wallet[] = missingAnchorageVaults.map((vault) => ({ + accounts: [], + clientId: connection.clientId, + connections: [connection], + createdAt: now, + externalId: vault.vaultId, + label: vault.name, + provider: Provider.ANCHORAGE, + updatedAt: now, + walletId: uuid() + })) + + await this.walletService.bulkCreate(wallets) + + return wallets + } + + async syncAccounts(connection: ActiveConnection) { + this.logger.log('Sync Anchorage accounts', { + connectionId: connection.credentials, + clientId: connection.clientId, + url: connection.url + }) + + this.validateConnection(connection) + + const now = new Date() + + const anchorageWallets = await this.anchorageClient.getWallets({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey + }) + + const walletExternalIds = uniq(anchorageWallets.map(({ vaultId }) => vaultId)) + + const existingWallets = await this.walletService.findAll(connection.clientId, { + filters: { + externalIds: walletExternalIds + } + }) + + const existingAccounts = await this.accountService.findAll(connection.clientId, { + filters: { + externalIds: uniq(anchorageWallets.map((wallet) => wallet.walletId)) + } + }) + + const existingAccountsByExternalId = new Map(existingAccounts.map((account) => [account.externalId, account])) + + const missingAnchorageWallets = anchorageWallets.filter( + (anchorageVault) => !existingAccountsByExternalId.has(anchorageVault.walletId) + ) + + const walletsIndexedByExternalId = existingWallets.reduce( + (idx, wallet) => idx.set(wallet.externalId, wallet), + new Map() + ) + + const accounts: Account[] = missingAnchorageWallets.map((anchorageWallet) => { + const wallet = walletsIndexedByExternalId.get(anchorageWallet.vaultId) + + if (!wallet) { + throw new BrokerException({ + message: 'Parent wallet for account not found', + suggestedHttpStatusCode: HttpStatus.NOT_FOUND, + context: { + walletExternalId: anchorageWallet.vaultId, + accountExternalId: anchorageWallet.walletId + } + }) + } + + return { + accountId: uuid(), + walletId: wallet?.walletId, + label: anchorageWallet.walletName, + clientId: connection.clientId, + provider: Provider.ANCHORAGE, + addresses: [], + externalId: anchorageWallet.walletId, + createdAt: now, + updatedAt: now, + // TODO: Map their networkId to SLIP 44 format. + networkId: anchorageWallet.networkId + } + }) + + await this.accountService.bulkCreate(accounts) + + return accounts + } + + async syncAddresses(connection: ActiveConnection) { + this.logger.log('Sync Anchorage addresses', { + connectionId: connection.credentials, + clientId: connection.clientId, + url: connection.url + }) + + this.validateConnection(connection) + + const now = new Date() + + const signKey = connection.credentials.privateKey + + const anchorageVaults = await this.anchorageClient.getVaults({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey + }) + + const getVaultAddressesRequests = anchorageVaults.flatMap((anchorageVault) => + anchorageVault.assets.map((asset) => ({ + signKey, + apiKey: connection.credentials.apiKey, + assetType: asset.assetType, + url: connection.url, + vaultId: anchorageVault.vaultId + })) + ) + + const anchorageAddresses = ( + await Promise.all(getVaultAddressesRequests.map((request) => this.anchorageClient.getVaultAddresses(request))) + ).flat() + + // Query existing accounts to associate them with their children addresses. + const existingAccounts = await this.accountService.findAll(connection.clientId, { + filters: { + externalIds: anchorageAddresses.map((anchorageAddress) => anchorageAddress.walletId) + } + }) + + const existingAccountsByExternalId = new Map(existingAccounts.map((account) => [account.externalId, account])) + + const existingAddresses = await this.addressService.findAll(connection.clientId, { + filters: { + externalIds: anchorageAddresses.map((anchorageAddress) => anchorageAddress.addressId) + } + }) + + const existingAddressesByExternalId = new Map(existingAddresses.map((address) => [address.externalId, address])) + + const uniqueAnchorageAddresses = Array.from( + new Map(anchorageAddresses.map((anchorageAddress) => [anchorageAddress.addressId, anchorageAddress])).values() + ) + + const missingAnchorageAddresses = uniqueAnchorageAddresses.filter( + (anchorageAddress) => !existingAddressesByExternalId.has(anchorageAddress.addressId) + ) + + const addresses: Address[] = missingAnchorageAddresses.map((anchorageAddress) => { + const account = existingAccountsByExternalId.get(anchorageAddress.walletId) + + if (account) { + return { + accountId: account.accountId, + address: anchorageAddress.address, + addressId: uuid(), + clientId: connection.clientId, + createdAt: now, + externalId: anchorageAddress.addressId, + provider: Provider.ANCHORAGE, + updatedAt: now + } satisfies Address + } + + throw new BrokerException({ + message: 'Anchorage address parent account not found', + suggestedHttpStatusCode: HttpStatus.NOT_FOUND + }) + }) + + await this.addressService.bulkCreate(addresses) + + return addresses + } + + private validateConnection(connection: ActiveConnection): asserts connection is ActiveConnection & { + url: string + credentials: { + apiKey: string + privateKey: Ed25519PrivateKey + } + } { + const context = { + clientId: connection.clientId, + connectionId: connection.connectionId, + provider: connection.provider, + status: connection.status, + url: connection.url + } + + if (connection.provider !== Provider.ANCHORAGE) { + throw new ConnectionInvalidException({ + message: 'Invalid connection provider for Anchorage', + context + }) + } + + if (!connection.url) { + throw new ConnectionInvalidException({ + message: 'Cannot sync without a connection URL', + context + }) + } + + if (!connection.credentials.apiKey && !connection.credentials.privateKey) { + throw new ConnectionInvalidException({ + message: 'Cannot sync without API key and/or signing key', + context + }) + } + } +} diff --git a/apps/vault/src/broker/core/service/connection.service.ts b/apps/vault/src/broker/core/service/connection.service.ts index 422d9bb90..513c57067 100644 --- a/apps/vault/src/broker/core/service/connection.service.ts +++ b/apps/vault/src/broker/core/service/connection.service.ts @@ -1,4 +1,4 @@ -import { PaginatedResult, PaginationOptions } from '@narval/nestjs-shared' +import { PaginatedResult } from '@narval/nestjs-shared' import { Alg, Ed25519PrivateKey, @@ -12,13 +12,11 @@ import { Injectable, NotImplementedException } from '@nestjs/common' import { SetRequired } from 'type-fest' import { v4 as uuid } from 'uuid' import { EncryptionKeyService } from '../../../transit-encryption/core/service/encryption-key.service' -import { AccountRepository } from '../../persistence/repository/account.repository' import { ConnectionRepository, FilterOptions, FindAllPaginatedOptions } from '../../persistence/repository/connection.repository' -import { WalletRepository } from '../../persistence/repository/wallet.repository' import { ConnectionInvalidCredentialsException } from '../exception/connection-invalid-credentials.exception' import { ConnectionInvalidPrivateKeyException } from '../exception/connection-invalid-private-key.exception' import { ConnectionInvalidStatusException } from '../exception/connection-invalid-status.exception' @@ -39,15 +37,12 @@ import { isPendingConnection, isRevokedConnection } from '../type/connection.type' -import { Wallet } from '../type/indexed-resources.type' @Injectable() export class ConnectionService { constructor( private readonly connectionRepository: ConnectionRepository, - private readonly encryptionKeyService: EncryptionKeyService, - private readonly walletRepository: WalletRepository, - private readonly accountRepository: AccountRepository + private readonly encryptionKeyService: EncryptionKeyService ) {} async initiate(clientId: string, input: InitiateConnection): Promise { @@ -367,32 +362,4 @@ export class ConnectionService { throw new NotFoundException({ context: { clientId, connectionId } }) } - - async findWallets( - clientId: string, - connectionId: string, - options: PaginationOptions - ): Promise> { - return this.walletRepository.findAll( - clientId, - { - connectionId - }, - options - ) - } - - async findAccounts( - clientId: string, - connectionId: string, - options: PaginationOptions - ): Promise> { - return this.accountRepository.findAll( - clientId, - { - connectionId - }, - options - ) - } } diff --git a/apps/vault/src/broker/core/service/proxy.service.ts b/apps/vault/src/broker/core/service/proxy.service.ts new file mode 100644 index 000000000..34ede96f3 --- /dev/null +++ b/apps/vault/src/broker/core/service/proxy.service.ts @@ -0,0 +1,49 @@ +import { HttpStatus, Injectable } from '@nestjs/common' +import { AnchorageClient } from '../../http/client/anchorage.client' +import { ConnectionRepository } from '../../persistence/repository/connection.repository' +import { ConnectionInvalidException } from '../exception/connection-invalid.exception' +import { HttpMethod } from '../lib/anchorage-request-builder' +import { ConnectionStatus } from '../type/connection.type' + +type RawRequestOptions = { + connectionId: string + body?: any + endpoint: string + method: HttpMethod +} +@Injectable() +export class ProxyService { + constructor( + private readonly anchorageClient: AnchorageClient, + private readonly connectionRepository: ConnectionRepository + ) {} + + async rawRequest( + clientId: string, + { connectionId, body, endpoint, method }: RawRequestOptions + ): Promise<{ data: any; code: HttpStatus; headers: Record }> { + const connection = await this.connectionRepository.findById(clientId, connectionId) + if (connection.status !== ConnectionStatus.ACTIVE) { + throw new ConnectionInvalidException({ + message: 'Connection is not active', + context: { connectionId, clientId, status: connection.status } + }) + } + + const { url, credentials } = connection + const { apiKey, privateKey } = credentials + + const fullUrl = `${url}${endpoint}` + + const response = await this.anchorageClient.forward({ + url: fullUrl, + method, + body, + apiKey, + signKey: privateKey + }) + + const { status: code, headers, data } = response + return { data, code, headers } + } +} diff --git a/apps/vault/src/broker/core/service/sync.service.ts b/apps/vault/src/broker/core/service/sync.service.ts index 9beea6425..cb4c59b68 100644 --- a/apps/vault/src/broker/core/service/sync.service.ts +++ b/apps/vault/src/broker/core/service/sync.service.ts @@ -1,16 +1,19 @@ -import { PaginatedResult } from '@narval/nestjs-shared' -import { Injectable } from '@nestjs/common/decorators' +import { PaginatedResult, TraceService } from '@narval/nestjs-shared' +import { Inject, Injectable } from '@nestjs/common/decorators' import { v4 as uuid } from 'uuid' import { FindAllPaginatedOptions, SyncRepository } from '../../persistence/repository/sync.repository' -import { ConnectionStatus } from '../type/connection.type' +import { ConnectionStatus, isActiveConnection } from '../type/connection.type' import { StartSync, Sync, SyncStatus } from '../type/sync.type' +import { AnchorageSyncService } from './anchorage-sync.service' import { ConnectionService } from './connection.service' @Injectable() export class SyncService { constructor( private readonly syncRepository: SyncRepository, - private readonly connectionService: ConnectionService + private readonly connectionService: ConnectionService, + private readonly anchorageSyncService: AnchorageSyncService, + @Inject(TraceService) private readonly traceService: TraceService ) {} async start(input: StartSync): Promise<{ @@ -21,18 +24,31 @@ export class SyncService { if (input.connectionId) { const syncId = uuid() + const connection = await this.connectionService.findById(input.clientId, input.connectionId) + const sync = await this.syncRepository.create( this.toProcessingSync({ ...input, - connectionId: input.connectionId, + connectionId: connection.connectionId, createdAt: now, syncId }) ) - // TODO: (@wcalderipe, 10/12/24): Sync connection + if (isActiveConnection(connection)) { + this.anchorageSyncService + .sync(connection) + .then(async () => { + await this.complete(sync) + }) + .catch(async (error) => { + await this.fail(sync, error) + }) + + return { started: true, syncs: [sync] } + } - return { started: true, syncs: [sync] } + return { started: false, syncs: [] } } const connections = await this.connectionService.findAll(input.clientId, { @@ -52,7 +68,17 @@ export class SyncService { ) ) - // TODO: (@wcalderipe, 10/12/24): Sync connections + await Promise.allSettled( + connections.filter(isActiveConnection).map((connection) => { + this.anchorageSyncService.sync(connection) + }) + ) + .then(async () => { + await Promise.all(syncs.map((sync) => this.complete(sync))) + }) + .catch(async (error) => { + await Promise.all(syncs.map((sync) => this.fail(sync, error))) + }) return { started: true, syncs } } @@ -75,4 +101,33 @@ export class SyncService { async findById(clientId: string, syncId: string): Promise { return this.syncRepository.findById(clientId, syncId) } + + async complete(sync: Sync): Promise { + const completedSync = { + ...sync, + status: SyncStatus.SUCCESS, + completedAt: sync.completedAt || new Date() + } + + await this.syncRepository.update(completedSync) + + return completedSync + } + + async fail(sync: Sync, error: Error): Promise { + const failedSync = { + ...sync, + status: SyncStatus.FAILED, + error: { + name: error.name, + message: error.message, + traceId: this.traceService.getActiveSpan()?.spanContext().traceId + }, + completedAt: sync.completedAt || new Date() + } + + await this.syncRepository.update(failedSync) + + return failedSync + } } diff --git a/apps/vault/src/broker/core/service/wallet.service.ts b/apps/vault/src/broker/core/service/wallet.service.ts index 66cebca3e..88ff5f05a 100644 --- a/apps/vault/src/broker/core/service/wallet.service.ts +++ b/apps/vault/src/broker/core/service/wallet.service.ts @@ -1,15 +1,15 @@ import { PaginatedResult, PaginationOptions } from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' -import { AccountRepository } from '../../persistence/repository/account.repository' -import { WalletRepository } from '../../persistence/repository/wallet.repository' -import { Account, Wallet } from '../type/indexed-resources.type' +import { + FindAllOptions, + FindAllPaginatedOptions, + WalletRepository +} from '../../persistence/repository/wallet.repository' +import { Wallet } from '../type/indexed-resources.type' @Injectable() export class WalletService { - constructor( - private readonly walletRepository: WalletRepository, - private readonly accountRepository: AccountRepository - ) {} + constructor(private readonly walletRepository: WalletRepository) {} async getWallets(clientId: string, options: PaginationOptions): Promise> { return this.walletRepository.findByClientId(clientId, options) @@ -19,11 +19,15 @@ export class WalletService { return this.walletRepository.findById(clientId, walletId) } - async getWalletAccounts( - clientId: string, - walletId: string, - options: PaginationOptions - ): Promise> { - return this.accountRepository.findAll(clientId, { walletId }, options) + async bulkCreate(wallets: Wallet[]): Promise { + return this.walletRepository.bulkCreate(wallets) + } + + async findAllPaginated(clientId: string, options?: FindAllPaginatedOptions): Promise> { + return this.walletRepository.findAllPaginated(clientId, options) + } + + async findAll(clientId: string, options?: FindAllOptions): Promise { + return this.walletRepository.findAll(clientId, options) } } diff --git a/apps/vault/src/broker/core/type/connection.type.ts b/apps/vault/src/broker/core/type/connection.type.ts index 2d1250c02..4e0482c95 100644 --- a/apps/vault/src/broker/core/type/connection.type.ts +++ b/apps/vault/src/broker/core/type/connection.type.ts @@ -22,6 +22,7 @@ export const BaseConnection = z.object({ integrity: z.string(), label: z.string().optional(), provider: z.nativeEnum(Provider), + revokedAt: z.date().optional(), status: z.nativeEnum(ConnectionStatus).default(ConnectionStatus.ACTIVE), updatedAt: z.date(), url: z.string().url().optional() @@ -34,10 +35,16 @@ export const AnchorageCredentials = z.object({ }) export type AnchorageCredentials = z.infer -const ActiveConnection = BaseConnection.extend({ +export const ActiveAnchorageCredentials = AnchorageCredentials.extend({ + apiKey: z.string() +}) +export type ActiveAnchorageCredentials = z.infer + +export const ActiveConnection = BaseConnection.extend({ status: z.literal(ConnectionStatus.ACTIVE), provider: z.literal(Provider.ANCHORAGE), - credentials: AnchorageCredentials + credentials: ActiveAnchorageCredentials, + url: z.string().url() }) export type ActiveConnection = z.infer diff --git a/apps/vault/src/broker/core/type/indexed-resources.type.ts b/apps/vault/src/broker/core/type/indexed-resources.type.ts index a714b6a14..f97ae1dd9 100644 --- a/apps/vault/src/broker/core/type/indexed-resources.type.ts +++ b/apps/vault/src/broker/core/type/indexed-resources.type.ts @@ -19,7 +19,7 @@ export const Account = z.object({ label: z.string().nullable().optional(), addresses: z.array(Address).optional(), clientId: z.string(), - provider: z.string(), + provider: z.nativeEnum(Provider), externalId: z.string(), walletId: z.string(), networkId: z.string(), @@ -31,10 +31,10 @@ export type Account = z.infer export const Wallet = z.object({ walletId: z.string(), accounts: z.array(Account).optional(), - connections: z.array(BaseConnection).optional(), + connections: z.array(BaseConnection), label: z.string().nullable().optional(), clientId: z.string(), - provider: z.string(), + provider: z.nativeEnum(Provider), externalId: z.string(), createdAt: z.date(), updatedAt: z.date() diff --git a/apps/vault/src/broker/http/client/anchorage.client.ts b/apps/vault/src/broker/http/client/anchorage.client.ts new file mode 100644 index 000000000..7447b51e7 --- /dev/null +++ b/apps/vault/src/broker/http/client/anchorage.client.ts @@ -0,0 +1,315 @@ +import { LoggerService } from '@narval/nestjs-shared' +import { Ed25519PrivateKey } from '@narval/signature' +import { HttpService } from '@nestjs/axios' +import { Injectable } from '@nestjs/common' +import axios, { AxiosRequestConfig, AxiosResponse } from 'axios' +import { EMPTY, Observable, catchError, expand, lastValueFrom, map, reduce, tap } from 'rxjs' +import { z } from 'zod' +import { ProxyRequestException } from '../../core/exception/proxy-request.exception' +import { BuildAnchorageRequestParams, buildAnchorageSignedRequest } from '../../core/lib/anchorage-request-builder' + +const Amount = z.object({ + quantity: z.string(), + assetType: z.string(), + currentPrice: z.string(), + currentUSDValue: z.string() +}) + +const DepositAddress = z.object({ + address: z.string(), + addressId: z.string(), + addressSignaturePayload: z.string(), + signature: z.string() +}) + +const VaultAsset = z.object({ + walletId: z.string(), + assetType: z.string(), + availableBalance: Amount.optional(), + totalBalance: Amount.optional(), + stakedBalance: Amount.optional(), + unclaimedBalance: Amount.optional(), + vaultId: z.string(), + vaultName: z.string() +}) + +const Vault = z.object({ + vaultId: z.string(), + name: z.string(), + description: z.string(), + type: z.literal('VAULT'), + accountName: z.string(), + assets: z.array(VaultAsset) +}) +type Vault = z.infer + +const WalletAsset = z.object({ + assetType: z.string(), + availableBalance: Amount.optional(), + totalBalance: Amount.optional(), + stakedBalance: Amount.optional(), + unclaimedBalance: Amount.optional() +}) + +const Wallet = z.object({ + walletId: z.string(), + walletName: z.string(), + depositAddress: DepositAddress, + assets: z.array(WalletAsset), + vaultId: z.string(), + vaultName: z.string(), + isDefault: z.boolean(), + isArchived: z.boolean(), + networkId: z.string(), + type: z.literal('WALLET') +}) +type Wallet = z.infer + +const Address = z.object({ + address: z.string(), + addressId: z.string(), + addressSignaturePayload: z.string(), + signature: z.string(), + walletId: z.string() +}) +type Address = z.infer + +const GetVaultsResponse = z.object({ + data: z.array(Vault), + page: z.object({ + next: z.string().nullish() + }) +}) +type GetVaultsResponse = z.infer + +const GetWalletsResponse = z.object({ + data: z.array(Wallet), + page: z.object({ + next: z.string().nullish() + }) +}) +type GetWalletsResponse = z.infer + +const GetVaultAddressesResponse = z.object({ + data: z.array(Address), + page: z.object({ + next: z.string().nullish() + }) +}) +type GetVaultAddressesResponse = z.infer + +interface RequestOptions { + url: string + apiKey: string + signKey: Ed25519PrivateKey + limit?: number +} + +@Injectable() +export class AnchorageClient { + constructor( + private readonly httpService: HttpService, + private readonly logger: LoggerService + ) {} + + async forward({ url, method, body, apiKey, signKey }: BuildAnchorageRequestParams): Promise { + const request = await buildAnchorageSignedRequest({ + url, + method, + body, + apiKey, + signKey + }) + + try { + const response = await axios(request) + return response + } catch (error) { + throw new ProxyRequestException({ + message: 'Anchorage request failed', + status: error.response?.status, + data: error.response?.data, + headers: error.response?.headers, + context: { url, method, body } + }) + } + } + + async getVaults(opts: RequestOptions): Promise { + this.logger.log('Requesting Anchorage vaults page', { + url: opts.url, + limit: opts.limit + }) + + const request = await buildAnchorageSignedRequest({ + url: `${opts.url}/v2/vaults`, + method: 'GET', + apiKey: opts.apiKey, + signKey: opts.signKey + }) + + return lastValueFrom( + this.getVaultsPage(request).pipe( + expand((response) => + response.page.next + ? // TODO: Use the signed request + this.getVaultsPage({ + ...opts, + url: response.page.next + }) + : EMPTY + ), + tap((response) => { + if (response.page.next) { + this.logger.log('Requesting Anchorage vaults next page', { + url: response.page.next, + limit: opts.limit + }) + } else { + this.logger.log('Reached Anchorage vaults last page') + } + }), + reduce((vaults: Vault[], response) => [...vaults, ...response.data], []), + tap((vaults) => { + this.logger.log('Completed fetching all vaults', { + vaultsCount: vaults.length, + url: opts.url + }) + }), + catchError((error) => { + this.logger.error('Failed to get Anchorage vaults', { error }) + + throw error + }) + ) + ) + } + + private getVaultsPage(request: AxiosRequestConfig): Observable { + return this.httpService.request(request).pipe( + tap((response) => { + this.logger.log('Received Anchorage vaults page', { + data: response.data + }) + }), + map((response) => GetVaultsResponse.parse(response.data)) + ) + } + + async getWallets(opts: RequestOptions): Promise { + const request = await buildAnchorageSignedRequest({ + url: `${opts.url}/v2/wallets`, + method: 'GET', + apiKey: opts.apiKey, + signKey: opts.signKey + }) + + return lastValueFrom( + this.getWalletsPage(request).pipe( + expand((response) => + response.page.next + ? // TODO: use signed request + this.getWalletsPage({ + ...opts, + url: response.page.next + }) + : EMPTY + ), + tap((response) => { + if (response.page.next) { + this.logger.log('Requesting Anchorage wallets next page', { + url: response.page.next, + limit: opts.limit + }) + } else { + this.logger.log('Reached Anchorage wallets last page') + } + }), + reduce((wallets: Wallet[], response) => [...wallets, ...response.data], []), + tap((wallets) => { + this.logger.log('Completed fetching all wallets', { + walletsCount: wallets.length, + url: opts.url + }) + }), + catchError((error) => { + this.logger.error('Failed to get Anchorage wallets', { error }) + + throw error + }) + ) + ) + } + + private getWalletsPage(request: AxiosRequestConfig): Observable { + return this.httpService.request(request).pipe( + tap((response) => { + this.logger.log('Received Anchorage wallets page', { + data: response.data + }) + }), + map((response) => GetWalletsResponse.parse(response.data)) + ) + } + + async getVaultAddresses(opts: RequestOptions & { vaultId: string; assetType: string }): Promise { + const request = await buildAnchorageSignedRequest({ + url: `${opts.url}/v2/vaults/${opts.vaultId}/addresses`, + method: 'GET', + apiKey: opts.apiKey, + signKey: opts.signKey + }) + + return lastValueFrom( + this.getVaultAddressesPage({ + ...request, + params: { + assetType: opts.assetType + } + }).pipe( + expand((response) => + response.page.next + ? // TODO: Use the signed request + this.getVaultAddressesPage({ + ...opts, + url: response.page.next + }) + : EMPTY + ), + tap((response) => { + if (response.page.next) { + this.logger.log('Requesting Anchorage vault addresses next page', { + url: response.page.next, + limit: opts.limit + }) + } else { + this.logger.log('Reached Anchorage vault addresses last page') + } + }), + reduce((addresses: Address[], response) => [...addresses, ...response.data], []), + tap((vaults) => { + this.logger.log('Completed fetching all vault addresses', { + vaultsCount: vaults.length, + url: opts.url + }) + }), + catchError((error) => { + this.logger.error('Failed to get Anchorage vault addresses', { error }) + + throw error + }) + ) + ) + } + + private getVaultAddressesPage(request: AxiosRequestConfig): Observable { + return this.httpService.request(request).pipe( + tap((response) => { + this.logger.log('Received Anchorage vaults addresses page', { + data: response.data + }) + }), + map((response) => GetVaultAddressesResponse.parse(response.data)) + ) + } +} diff --git a/apps/vault/src/broker/http/rest/controller/connection.controller.ts b/apps/vault/src/broker/http/rest/controller/connection.controller.ts index b36706472..d0ae2b36b 100644 --- a/apps/vault/src/broker/http/rest/controller/connection.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/connection.controller.ts @@ -2,7 +2,9 @@ import { Paginated, PaginationOptions, PaginationParam } from '@narval/nestjs-sh import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Patch, Post } from '@nestjs/common' import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../shared/decorator/client-id.decorator' +import { AccountService } from '../../../core/service/account.service' import { ConnectionService } from '../../../core/service/connection.service' +import { WalletService } from '../../../core/service/wallet.service' import { CreateConnectionDto } from '../dto/request/create-connection.dto' import { InitiateConnectionDto } from '../dto/request/initiate-connection.dto' import { UpdateConnectionDto } from '../dto/request/update-connection.dto' @@ -19,7 +21,11 @@ import { PendingConnectionDto } from '../dto/response/pending-connection.dto' }) @ApiTags('Provider Connection') export class ConnectionController { - constructor(private readonly connectionService: ConnectionService) {} + constructor( + private readonly connectionService: ConnectionService, + private readonly walletService: WalletService, + private readonly accountService: AccountService + ) {} @Post('/initiate') @ApiOperation({ @@ -149,7 +155,10 @@ export class ConnectionController { @Param('connectionId') connectionId: string, @PaginationParam() options: PaginationOptions ): Promise { - const { data, page } = await this.connectionService.findWallets(clientId, connectionId, options) + const { data, page } = await this.walletService.findAllPaginated(clientId, { + ...options, + filters: { connectionId } + }) return PaginatedWalletsDto.create({ wallets: data, page }) } @@ -168,7 +177,11 @@ export class ConnectionController { @Param('connectionId') connectionId: string, @PaginationParam() options: PaginationOptions ): Promise { - const { data, page } = await this.connectionService.findAccounts(clientId, connectionId, options) + // TODO: Move the method from the connection service to accounts. + const { data, page } = await this.accountService.findAllPaginated(clientId, { + ...options, + filters: { connectionId } + }) return PaginatedAccountsDto.create({ accounts: data, page }) } diff --git a/apps/vault/src/broker/http/rest/controller/proxy.controller.ts b/apps/vault/src/broker/http/rest/controller/proxy.controller.ts new file mode 100644 index 000000000..d8eec99a4 --- /dev/null +++ b/apps/vault/src/broker/http/rest/controller/proxy.controller.ts @@ -0,0 +1,65 @@ +import { All, Body, Controller, HttpStatus, Param, Req, Res } from '@nestjs/common' +import { ApiHeader, ApiOperation, ApiParam, ApiResponse } from '@nestjs/swagger' +import { Request, Response } from 'express' +import { ClientId } from '../../../../shared/decorator/client-id.decorator' +import { ConnectionId } from '../../../../shared/decorator/connection-id.decorator' +import { ProxyRequestException } from '../../../core/exception/proxy-request.exception' +import { HttpMethod } from '../../../core/lib/anchorage-request-builder' +import { ProxyService } from '../../../core/service/proxy.service' + +@Controller({ + path: 'proxy', + version: '1' +}) +export class ProxyController { + constructor(private readonly proxyService: ProxyService) {} + + @All(':endpoint(*)') + @ApiHeader({ + name: 'x-connection-id', + required: true, + description: 'The connection ID used to forward request to provider' + }) + @ApiOperation({ + summary: 'Forward request to provider', + description: + 'This endpoint uses the connection specified in the header to sign and forward the request in the path to the provider.' + }) + @ApiParam({ + name: 'endpoint', + required: true, + description: 'The raw endpoint path in the provider' + }) + @ApiResponse({ + status: HttpStatus.PROXY_AUTHENTICATION_REQUIRED, + description: 'Requested connection is not active' + }) + async proxyRequest( + @ClientId() clientId: string, + @ConnectionId() connectionId: string, + @Param('endpoint') endpoint: string, + @Body() body: unknown, + @Req() request: Request, + @Res() res: Response + ) { + const queryString = new URLSearchParams(request.query as Record).toString() + const sanitizedEndpoint = queryString ? `/${endpoint}?${queryString}` : `/${endpoint}` + + try { + const response = await this.proxyService.rawRequest(clientId, { + connectionId, + endpoint: sanitizedEndpoint, + method: HttpMethod.parse(request.method), + body + }) + + res.status(response.code).set(response.headers).send(response.data) + } catch (error) { + if (error instanceof ProxyRequestException) { + res.status(error.code).set(error.headers).send(error.data) + } else { + throw error + } + } + } +} diff --git a/apps/vault/src/broker/http/rest/controller/wallet.controller.ts b/apps/vault/src/broker/http/rest/controller/wallet.controller.ts index cec3dd9cb..b93abf402 100644 --- a/apps/vault/src/broker/http/rest/controller/wallet.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/wallet.controller.ts @@ -1,19 +1,23 @@ import { Paginated, PaginationOptions, PaginationParam } from '@narval/nestjs-shared' import { Controller, Get, HttpStatus, Param } from '@nestjs/common' import { ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger' - import { ClientId } from '../../../../shared/decorator/client-id.decorator' +import { AccountService } from '../../../core/service/account.service' import { WalletService } from '../../../core/service/wallet.service' import { PaginatedAccountsDto } from '../dto/response/paginated-accounts.dto' import { PaginatedWalletsDto } from '../dto/response/paginated-wallets.dto' import { WalletDto } from '../dto/response/wallet.dto' + @Controller({ path: 'wallets', version: '1' }) @ApiTags('Provider Wallet') export class WalletController { - constructor(private readonly walletService: WalletService) {} + constructor( + private readonly walletService: WalletService, + private readonly accountService: AccountService + ) {} @Get() @ApiOperation({ @@ -77,7 +81,11 @@ export class WalletController { @Param('walletId') walletId: string, @PaginationParam() options: PaginationOptions ): Promise { - const { data, page } = await this.walletService.getWalletAccounts(clientId, walletId, options) + const { data, page } = await this.accountService.findAllPaginated(clientId, { + ...options, + filters: { walletId } + }) + return PaginatedAccountsDto.create({ accounts: data, page diff --git a/apps/vault/src/broker/persistence/connection.seed.ts b/apps/vault/src/broker/persistence/connection.seed.ts new file mode 100644 index 000000000..1bf540b0c --- /dev/null +++ b/apps/vault/src/broker/persistence/connection.seed.ts @@ -0,0 +1,48 @@ +import { LoggerService } from '@narval/nestjs-shared' +import { hexSchema } from '@narval/policy-engine-shared' +import { privateKeyToJwk } from '@narval/signature' +import { Injectable } from '@nestjs/common' +import { ed25519PublicKeySchema } from 'packages/signature/src/lib/schemas' +import { SeedService } from '../../shared/module/persistence/service/seed.service' +import { Connection } from '../core/type/connection.type' +import { ConnectionRepository } from './repository/connection.repository' + +const NARVAL_DEV_CLIENT = 'narval-dev-client' + +@Injectable() +export class ConnectionSeedService extends SeedService { + constructor( + private logger: LoggerService, + private connectionRepository: ConnectionRepository + ) { + super() + } + + async createConnection(connection: Connection) { + const createdConnection = await this.connectionRepository.create(connection) + return createdConnection + } + + async createNarvalDevConnection() { + if (process.env.ANCHORAGE_API_KEY && process.env.ANCHORAGE_SECRET_KEY) { + const privateKey = privateKeyToJwk(hexSchema.parse(process.env.ANCHORAGE_SECRET_KEY), 'EDDSA') + const publicKey = ed25519PublicKeySchema.parse(privateKey) + await this.connectionRepository.create({ + clientId: NARVAL_DEV_CLIENT, + connectionId: '13198cdc-e508-4be5-9a5e-141a1a6e3526', + credentials: { + apiKey: process.env.ANCHORAGE_API_KEY, + privateKey, + publicKey + }, + integrity: 'sample-integrity-hash', + label: 'Anchorage Staging - Narval Dev Client', + provider: 'anchorage', + url: 'https://api.anchorage-staging.com', + createdAt: new Date(), + updatedAt: new Date(), + status: 'active' + }) + } + } +} diff --git a/apps/vault/src/broker/persistence/repository/account.repository.ts b/apps/vault/src/broker/persistence/repository/account.repository.ts index 9f48ae4a4..386b65c29 100644 --- a/apps/vault/src/broker/persistence/repository/account.repository.ts +++ b/apps/vault/src/broker/persistence/repository/account.repository.ts @@ -10,10 +10,18 @@ type ProviderAccountAndRelations = ProviderAccount & { addresses: ProviderAddress[] } -type AccountFilters = { - connectionId?: string - walletId?: string +type FindAllFilters = { + filters?: { + connectionId?: string + walletId?: string + externalIds?: string[] + } } + +export type FindAllPaginatedOptions = PaginationOptions & FindAllFilters + +export type FindAllOptions = FindAllFilters + @Injectable() export class AccountRepository { constructor(private prismaService: PrismaService) {} @@ -22,11 +30,27 @@ export class AccountRepository { return ['createdAt'] } - static parseModel(account: ProviderAccountAndRelations): Account { + static parseModel(model: ProviderAccountAndRelations): Account { + const { id, ...rest } = model + + return Account.parse({ + ...rest, + accountId: id, + addresses: model.addresses.map(AddressRepository.parseModel) + }) + } + + static parseEntity(account: Account): ProviderAccount { return { - ...account, - accountId: account.id, - addresses: account.addresses.map(AddressRepository.map) + clientId: account.clientId, + createdAt: account.createdAt, + externalId: account.externalId, + id: account.accountId, + label: account.label || null, + networkId: account.networkId, + provider: account.provider, + updatedAt: account.updatedAt, + walletId: account.walletId } } @@ -86,25 +110,21 @@ export class AccountRepository { } const { data, page } = getPaginatedResult({ items: account.addresses, options: pagination }) return { - data: data.map(AddressRepository.map), + data: data.map(AddressRepository.parseModel), page } } - async findAll( - clientId: string, - filters?: AccountFilters, - options?: PaginationOptions - ): Promise> { + async findAllPaginated(clientId: string, options?: FindAllPaginatedOptions): Promise> { const pagination = getPaginationQuery({ options, cursorOrderColumns: AccountRepository.getCursorOrderColumns() }) const result = await this.prismaService.providerAccount.findMany({ where: { clientId, - walletId: filters?.walletId, + walletId: options?.filters?.walletId, wallet: { connections: { some: { - connectionId: filters?.connectionId + connectionId: options?.filters?.connectionId } } } @@ -121,4 +141,40 @@ export class AccountRepository { page } } + + async bulkCreate(accounts: Account[]): Promise { + await this.prismaService.providerAccount.createMany({ + data: accounts.map(AccountRepository.parseEntity) + }) + + return accounts + } + + async findAll(clientId: string, options?: FindAllOptions): Promise { + const models = await this.prismaService.providerAccount.findMany({ + where: { + clientId, + walletId: options?.filters?.walletId, + wallet: { + connections: { + some: { + connectionId: options?.filters?.connectionId + } + } + }, + ...(options?.filters?.externalIds + ? { + externalId: { + in: options.filters.externalIds + } + } + : {}) + }, + include: { + addresses: true + } + }) + + return models.map(AccountRepository.parseModel) + } } diff --git a/apps/vault/src/broker/persistence/repository/address.repository.ts b/apps/vault/src/broker/persistence/repository/address.repository.ts index 434a37940..8429959aa 100644 --- a/apps/vault/src/broker/persistence/repository/address.repository.ts +++ b/apps/vault/src/broker/persistence/repository/address.repository.ts @@ -7,6 +7,12 @@ import { NotFoundException } from '../../core/exception/not-found.exception' import { Provider } from '../../core/type/connection.type' import { Address } from '../../core/type/indexed-resources.type' +export type FindAllFilters = { + filters?: { + externalIds?: string[] + } +} + @Injectable() export class AddressRepository { constructor(private prismaService: PrismaService) {} @@ -15,11 +21,26 @@ export class AddressRepository { return ['createdAt'] } - static map(address: ProviderAddress): Address { + static parseModel(model: ProviderAddress): Address { + const { id, ...rest } = model + + return { + ...rest, + addressId: id, + provider: z.nativeEnum(Provider).parse(model.provider) + } + } + + static parseEntity(entity: Address): ProviderAddress { return { - ...address, - provider: z.nativeEnum(Provider).parse(address.provider), - addressId: address.id + accountId: entity.accountId, + address: entity.address, + clientId: entity.clientId, + createdAt: entity.createdAt, + externalId: entity.externalId, + id: entity.addressId, + provider: entity.provider, + updatedAt: entity.updatedAt } } @@ -33,7 +54,7 @@ export class AddressRepository { const { data, page } = getPaginatedResult({ items: result, options: pagination }) return { - data: data.map(AddressRepository.map), + data: data.map(AddressRepository.parseModel), page } } @@ -49,6 +70,31 @@ export class AddressRepository { }) } - return AddressRepository.map(address) + return AddressRepository.parseModel(address) + } + + async findAll(clientId: string, opts?: FindAllFilters): Promise { + const models = await this.prismaService.providerAddress.findMany({ + where: { + clientId, + ...(opts?.filters?.externalIds + ? { + externalId: { + in: opts.filters.externalIds + } + } + : {}) + } + }) + + return models.map(AddressRepository.parseModel) + } + + async bulkCreate(addresses: Address[]): Promise { + await this.prismaService.providerAddress.createMany({ + data: addresses.map(AddressRepository.parseEntity) + }) + + return addresses } } diff --git a/apps/vault/src/broker/persistence/repository/connection.repository.ts b/apps/vault/src/broker/persistence/repository/connection.repository.ts index cec4b4b20..bafe39cab 100644 --- a/apps/vault/src/broker/persistence/repository/connection.repository.ts +++ b/apps/vault/src/broker/persistence/repository/connection.repository.ts @@ -57,6 +57,22 @@ export class ConnectionRepository { }) } + static parseEntity(entity: Connection): ProviderConnection { + return { + clientId: entity.clientId, + createdAt: entity.createdAt, + credentials: entity.credentials ? entity.credentials : Prisma.JsonNull, + id: entity.connectionId, + integrity: entity.integrity, + label: entity.label || null, + provider: entity.provider, + revokedAt: entity.revokedAt || null, + status: entity.status, + updatedAt: entity.updatedAt, + url: entity.url || null + } + } + async create(connection: Connection): Promise { const data = { clientId: connection.clientId, diff --git a/apps/vault/src/broker/persistence/repository/sync.repository.ts b/apps/vault/src/broker/persistence/repository/sync.repository.ts index 1a1fffa2d..8f07bb165 100644 --- a/apps/vault/src/broker/persistence/repository/sync.repository.ts +++ b/apps/vault/src/broker/persistence/repository/sync.repository.ts @@ -2,6 +2,7 @@ import { PaginatedResult, PaginationOptions, getPaginatedResult, getPaginationQu import { Injectable } from '@nestjs/common/decorators' import { ProviderSync } from '@prisma/client/vault' import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' +import { ModelInvalidException } from '../../core/exception/model-invalid.exception' import { NotFoundException } from '../../core/exception/not-found.exception' import { Sync, SyncStatus } from '../../core/type/sync.type' @@ -12,27 +13,47 @@ export type FindAllPaginatedOptions = PaginationOptions & { } } +export type UpdateSync = { + clientId: string + syncId: string + completedAt?: Date + status?: SyncStatus + error?: Sync['error'] +} + +const parseErrorEntity = (error: Sync['error']): Pick => ({ + errorName: error?.name || null, + errorMessage: error?.message || null, + errorTraceId: error?.traceId || null +}) + @Injectable() export class SyncRepository { constructor(private readonly prismaService: PrismaService) {} static parseModel(model?: ProviderSync | null): Sync { - return Sync.parse({ - ...model, - syncId: model?.id, - // Prisma always returns null for optional fields that don't have a - // value, rather than undefined. This is actually by design and aligns - // with how NULL values work in databases. - completedAt: model?.completedAt || undefined, - error: - model?.errorName || model?.errorMessage || model?.errorTraceId - ? { - name: model?.errorName || undefined, - message: model?.errorMessage || undefined, - traceId: model?.errorTraceId || undefined - } - : undefined - }) + if (model) { + const { id, ...rest } = model + + return Sync.parse({ + ...rest, + syncId: id, + // Prisma always returns null for optional fields that don't have a + // value, rather than undefined. This is actually by design and aligns + // with how NULL values work in databases. + completedAt: model.completedAt || undefined, + error: + model.errorName || model.errorMessage || model.errorTraceId + ? { + name: model.errorName || undefined, + message: model.errorMessage || undefined, + traceId: model.errorTraceId || undefined + } + : undefined + }) + } + + throw new ModelInvalidException() } static parseEntity(entity: Sync): ProviderSync { @@ -42,10 +63,8 @@ export class SyncRepository { completedAt: entity.completedAt || null, connectionId: entity.connectionId, createdAt: entity.createdAt, - errorName: entity.error?.name || null, - errorMessage: entity.error?.message || null, - errorTraceId: entity.error?.traceId || null, - status: entity.status + status: entity.status, + ...parseErrorEntity(entity.error) } } @@ -69,6 +88,22 @@ export class SyncRepository { return syncs } + async update(updateSync: UpdateSync): Promise { + await this.prismaService.providerSync.update({ + where: { + id: updateSync.syncId, + clientId: updateSync.clientId + }, + data: { + completedAt: updateSync.completedAt, + status: updateSync.status, + ...(updateSync.error ? parseErrorEntity(updateSync.error) : {}) + } + }) + + return true + } + async findById(clientId: string, syncId: string): Promise { const model = await this.prismaService.providerSync.findUnique({ where: { diff --git a/apps/vault/src/broker/persistence/repository/wallet.repository.ts b/apps/vault/src/broker/persistence/repository/wallet.repository.ts index f677df6a8..93f823961 100644 --- a/apps/vault/src/broker/persistence/repository/wallet.repository.ts +++ b/apps/vault/src/broker/persistence/repository/wallet.repository.ts @@ -1,6 +1,12 @@ import { PaginatedResult, PaginationOptions, getPaginatedResult, getPaginationQuery } from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' -import { ProviderAccount, ProviderAddress, ProviderConnection, ProviderWallet } from '@prisma/client/vault' +import { + ProviderAccount, + ProviderAddress, + ProviderConnection, + ProviderWallet, + ProviderWalletConnection +} from '@prisma/client/vault' import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' import { NotFoundException } from '../../core/exception/not-found.exception' import { Account, Wallet } from '../../core/type/indexed-resources.type' @@ -16,10 +22,18 @@ type ProviderWalletsAndRelations = ProviderWallet & { > } -type WalletFilters = { - connectionId: string +type FindAllFilters = { + filters?: { + connectionId?: string + walletIds?: string[] + externalIds?: string[] + } } +export type FindAllOptions = FindAllFilters + +export type FindAllPaginatedOptions = PaginationOptions & FindAllFilters + @Injectable() export class WalletRepository { constructor(private prismaService: PrismaService) {} @@ -39,11 +53,23 @@ export class WalletRepository { return AccountRepository.parseModel(account) }) - return { + return Wallet.parse({ ...walletData, walletId: id, accounts: mappedAccounts, connections: validConnections + }) + } + + static parseEntity(entity: Wallet): ProviderWallet { + return { + id: entity.walletId, + clientId: entity.clientId, + externalId: entity.externalId, + label: entity.label || null, + createdAt: entity.createdAt, + updatedAt: entity.updatedAt, + provider: entity.provider } } @@ -99,20 +125,27 @@ export class WalletRepository { return WalletRepository.parseModel(wallet) } - async findAll( - clientId: string, - filters: WalletFilters, - options: PaginationOptions - ): Promise> { + async findAllPaginated(clientId: string, options?: FindAllPaginatedOptions): Promise> { const pagination = getPaginationQuery({ options, cursorOrderColumns: WalletRepository.getCursorOrderColumns() }) const result = await this.prismaService.providerWallet.findMany({ where: { clientId, - connections: { - some: { - connectionId: filters.connectionId - } - } + ...(options?.filters?.walletIds + ? { + id: { + in: options.filters.walletIds + } + } + : {}), + ...(options?.filters?.connectionId + ? { + connections: { + some: { + connectionId: options.filters.connectionId + } + } + } + : {}) }, include: { accounts: { @@ -136,6 +169,51 @@ export class WalletRepository { } } + async findAll(clientId: string, options?: FindAllOptions): Promise { + const models = await this.prismaService.providerWallet.findMany({ + where: { + clientId, + ...(options?.filters?.connectionId + ? { + connections: { + some: { + connectionId: options.filters.connectionId + } + } + } + : {}), + ...(options?.filters?.walletIds + ? { + id: { + in: options.filters.walletIds + } + } + : {}), + ...(options?.filters?.externalIds + ? { + externalId: { + in: options.filters.externalIds + } + } + : {}) + }, + include: { + accounts: { + include: { + addresses: true + } + }, + connections: { + include: { + connection: true + } + } + } + }) + + return models.map(WalletRepository.parseModel) + } + async findAccountsByWalletId( clientId: string, walletId: string, @@ -168,4 +246,34 @@ export class WalletRepository { page } } + + async bulkCreate(wallets: Wallet[]): Promise { + const providerWallets: ProviderWallet[] = wallets.map(WalletRepository.parseEntity) + const providerWalletConnections: ProviderWalletConnection[] = wallets.flatMap(this.getWalletConnectionModel) + + await this.prismaService.$transaction(async (tx) => { + await tx.providerWallet.createMany({ + data: providerWallets, + skipDuplicates: true + }) + + await tx.providerWalletConnection.createMany({ + data: providerWalletConnections, + skipDuplicates: true + }) + }) + + return wallets + } + + private getWalletConnectionModel(wallet: Wallet): ProviderWalletConnection[] { + return wallet.connections.map((connection) => { + return { + clientId: wallet.clientId, + walletId: wallet.walletId, + connectionId: connection.connectionId, + createdAt: wallet.createdAt + } + }) + } } diff --git a/apps/vault/src/shared/decorator/connection-id.decorator.ts b/apps/vault/src/shared/decorator/connection-id.decorator.ts new file mode 100644 index 000000000..df7f8b3f4 --- /dev/null +++ b/apps/vault/src/shared/decorator/connection-id.decorator.ts @@ -0,0 +1,12 @@ +import { createParamDecorator, ExecutionContext, UnprocessableEntityException } from '@nestjs/common' + +export const REQUEST_HEADER_CONNECTION_ID = 'x-connection-id' +export const ConnectionId = createParamDecorator((_data: unknown, context: ExecutionContext): string => { + const req = context.switchToHttp().getRequest() + const connectionId = req.headers[REQUEST_HEADER_CONNECTION_ID] + if (!connectionId || typeof connectionId !== 'string') { + throw new UnprocessableEntityException(`Missing or invalid ${REQUEST_HEADER_CONNECTION_ID} header`) + } + + return connectionId +}) diff --git a/apps/vault/src/shared/module/persistence/schema/migrations/20241213123626_add_unique_constraint_on_provider_resource_tables/migration.sql b/apps/vault/src/shared/module/persistence/schema/migrations/20241213123626_add_unique_constraint_on_provider_resource_tables/migration.sql new file mode 100644 index 000000000..3352e92e8 --- /dev/null +++ b/apps/vault/src/shared/module/persistence/schema/migrations/20241213123626_add_unique_constraint_on_provider_resource_tables/migration.sql @@ -0,0 +1,20 @@ +/* + Warnings: + + - A unique constraint covering the columns `[client_id,external_id]` on the table `provider_account` will be added. If there are existing duplicate values, this will fail. + - A unique constraint covering the columns `[client_id,external_id]` on the table `provider_address` will be added. If there are existing duplicate values, this will fail. + - A unique constraint covering the columns `[client_id,external_id]` on the table `provider_known_destination` will be added. If there are existing duplicate values, this will fail. + - A unique constraint covering the columns `[client_id,external_id]` on the table `provider_wallet` will be added. If there are existing duplicate values, this will fail. + +*/ +-- CreateIndex +CREATE UNIQUE INDEX "provider_account_client_id_external_id_key" ON "provider_account"("client_id", "external_id"); + +-- CreateIndex +CREATE UNIQUE INDEX "provider_address_client_id_external_id_key" ON "provider_address"("client_id", "external_id"); + +-- CreateIndex +CREATE UNIQUE INDEX "provider_known_destination_client_id_external_id_key" ON "provider_known_destination"("client_id", "external_id"); + +-- CreateIndex +CREATE UNIQUE INDEX "provider_wallet_client_id_external_id_key" ON "provider_wallet"("client_id", "external_id"); diff --git a/apps/vault/src/shared/module/persistence/schema/schema.prisma b/apps/vault/src/shared/module/persistence/schema/schema.prisma index 46160f5f8..b573bd7ae 100644 --- a/apps/vault/src/shared/module/persistence/schema/schema.prisma +++ b/apps/vault/src/shared/module/persistence/schema/schema.prisma @@ -56,6 +56,8 @@ model ProviderWallet { connections ProviderWalletConnection[] sourceTransfers ProviderTransfer[] @relation("SourceWallet") + @@unique([clientId, externalId]) + @@map("provider_wallet") } @@ -75,6 +77,8 @@ model ProviderAccount { sourceTransfers ProviderTransfer[] @relation("SourceAccount") + @@unique([clientId, externalId]) + @@map("provider_account") } @@ -92,6 +96,8 @@ model ProviderAddress { sourceTransfers ProviderTransfer[] @relation("SourceAddress") + @@unique([clientId, externalId]) + @@map("provider_address") } @@ -110,6 +116,8 @@ model ProviderKnownDestination { connection ProviderConnection @relation(fields: [connectionId], references: [id]) + @@unique([clientId, externalId]) + @@map("provider_known_destination") } diff --git a/apps/vault/src/shared/module/persistence/seed.ts b/apps/vault/src/shared/module/persistence/seed.ts index c8279e957..38b4d6297 100644 --- a/apps/vault/src/shared/module/persistence/seed.ts +++ b/apps/vault/src/shared/module/persistence/seed.ts @@ -1,30 +1,57 @@ /* eslint-disable */ +import { ConfigService } from '@narval/config-module' import { LoggerService } from '@narval/nestjs-shared' +import { ed25519PrivateKeySchema, ed25519PublicKeySchema } from '@narval/signature' import { PrismaClient } from '@prisma/client/vault' +import { ConnectionStatus, Provider } from 'apps/vault/src/broker/core/type/connection.type' +import { ConnectionSeedService } from 'apps/vault/src/broker/persistence/connection.seed' +import { ConnectionRepository } from 'apps/vault/src/broker/persistence/repository/connection.repository' +import { Config, load } from 'apps/vault/src/main.config' import { v4 } from 'uuid' +import { PrismaService } from './service/prisma.service' const prisma = new PrismaClient() const clientId = 'client-1' +const privateKey = ed25519PrivateKeySchema.parse({ + kty: 'OKP', + crv: 'Ed25519', + alg: 'EDDSA', + kid: '0x64c3fa0c628c59c5795782356161bbe5bde6507f92d17256c174bfd19ed9a9bb', + x: 'wl2BAebjqX4_tvZcZo_VK3ZSxWZ-9-CGKe-3E9rlvB0', + d: 'A3imDr5aM3N1Iy2AMqn46PUsiiM2R4mRyj42yt3OAXM' +}) +const publicKey = ed25519PublicKeySchema.parse(privateKey) + +const privateKey2 = ed25519PrivateKeySchema.parse({ + kty: 'OKP', + crv: 'Ed25519', + alg: 'EDDSA', + kid: '0x5594dd8a27608b37a496787df068bc7843ec55322f54c8cd0d32ac4361caba58', + x: 'qQoqY2hWQ9c2CgnTE7TALK8ogWe2PBl3SrEH_ADihMY', + d: '4VBMwn8ZPV8c9E9Evv6yx_b71HjESKMaElXmbOcfMtU' +}) + +const publicKey2 = ed25519PublicKeySchema.parse(privateKey2) // Organize all data by connection const ANCHORAGE_CONNECTIONS = [ { connection: { - id: 'connection-1', + connectionId: 'connection-1', clientId, - provider: 'anchorage', + provider: Provider.ANCHORAGE, integrity: 'sample-integrity-hash', - url: 'https://api.anchorage-staging.com/v2', + url: 'https://api.anchorage-staging.com', label: 'Anchorage Staging - SubCustomer 1', credentials: { apiKey: 'sample-api-key', - secretKey: 'sample-secret-key' + privateKey, + publicKey }, createdAt: new Date(), updatedAt: new Date(), - revokedAt: null, - status: 'active' + status: ConnectionStatus.ACTIVE }, wallets: [ { @@ -107,20 +134,20 @@ const ANCHORAGE_CONNECTIONS = [ }, { connection: { - id: 'connection-2', + connectionId: 'connection-2', clientId, - provider: 'anchorage', + provider: Provider.ANCHORAGE, integrity: 'sample-integrity-hash-2', - url: 'https://api.anchorage-staging.com/v2', + url: 'https://api.anchorage-staging.com', label: 'Anchorage Staging - SubCustomer 2', credentials: { apiKey: 'sample-api-key-2', - secretKey: 'sample-secret-key-2' + privateKey: privateKey2, + publicKey: publicKey2 }, createdAt: new Date(), updatedAt: new Date(), - revokedAt: null, - status: 'active' + status: ConnectionStatus.ACTIVE }, wallets: [ { @@ -162,18 +189,22 @@ const ANCHORAGE_CONNECTIONS = [ async function main() { const logger = new LoggerService() + const config = new ConfigService(load()) + const prismaService = new PrismaService(config, logger) + const connRepository = new ConnectionRepository(prismaService) + const connSeed = new ConnectionSeedService(logger, connRepository) + logger.log('Seeding Vault database with Anchorage provider data') + if (process.env.NODE_ENV === 'development') { + await connSeed.createNarvalDevConnection() + } + await prisma.$transaction(async (txn) => { // Process each connection group for (const group of ANCHORAGE_CONNECTIONS) { // Create connection - const connection = await txn.providerConnection.create({ - data: { - ...group.connection, - credentials: group.connection.credentials as any - } - }) + const connection = await connSeed.createConnection(group.connection) const wallets = group.wallets.map((wallet) => ({ id: wallet.id, @@ -187,7 +218,7 @@ async function main() { const providerWalletConnection = wallets.map((wallet) => ({ clientId: wallet.clientId, - connectionId: connection.id, + connectionId: connection.connectionId, walletId: wallet.id })) @@ -222,13 +253,13 @@ async function main() { const knownDestinations = group.knownDestinations.map((dest) => ({ ...dest, - connectionId: group.connection.id + connectionId: group.connection.connectionId })) const sync = { id: v4(), clientId, - connectionId: group.connection.id, + connectionId: group.connection.connectionId, status: 'success' } @@ -257,7 +288,6 @@ async function main() { }) } }) - logger.log('Vault database germinated 🌱') } diff --git a/apps/vault/src/shared/module/persistence/service/seed.service.ts b/apps/vault/src/shared/module/persistence/service/seed.service.ts new file mode 100644 index 000000000..194bdce1d --- /dev/null +++ b/apps/vault/src/shared/module/persistence/service/seed.service.ts @@ -0,0 +1,7 @@ +import { NotImplementedException } from '@nestjs/common' + +export abstract class SeedService { + germinate(): Promise { + throw new NotImplementedException() + } +} diff --git a/apps/vault/test/nock.util.ts b/apps/vault/test/nock.util.ts new file mode 100644 index 000000000..b769afb2d --- /dev/null +++ b/apps/vault/test/nock.util.ts @@ -0,0 +1,66 @@ +import nock from 'nock' + +type Matcher = string | RegExp | ((host: string) => boolean) + +// Enable outbound HTTP requests to 127.0.0.1 to allow E2E tests with +// supertestwith supertest to work. +let allowedOutboundHttp: Matcher = '127.0.0.1' + +let originalAllowedOutboundHttp: Matcher + +// Store the original state to restore it later. +let originalNetConnect: boolean + +export const getAllowedOutboundHttp = () => allowedOutboundHttp + +export const setAllowedOutboundHttp = (matcher: Matcher) => (allowedOutboundHttp = matcher) + +export const setupNock = () => { + // Disable outgoing HTTP requests to avoid flaky tests. + nock.disableNetConnect() + + nock.enableNetConnect(getAllowedOutboundHttp()) + + // Jest sometimes translates unmatched errors into obscure JSON circular + // dependency without a proper stack trace. This can lead to hours of + // debugging. To save time, this emitter will consistently log an unmatched + // event allowing engineers to quickly identify the source of the error. + nock.emitter.on('no match', (request) => { + if (request.host && request.host.includes(getAllowedOutboundHttp())) { + return + } + + if (request.hostname && request.hostname.includes(getAllowedOutboundHttp())) { + return + } + + // eslint-disable-next-line no-console + console.error('Nock: no match for request', request) + }) +} + +export const disableNockProtection = () => { + // Store original state + originalNetConnect = nock.isActive() + originalAllowedOutboundHttp = getAllowedOutboundHttp() + + // Disable nock restrictions + nock.cleanAll() + nock.restore() + nock.enableNetConnect() +} + +export const restoreNockProtection = () => { + // Clean up any pending nocks + nock.cleanAll() + + // Restore original state + if (originalNetConnect) { + nock.activate() + nock.disableNetConnect() + nock.enableNetConnect(originalAllowedOutboundHttp) + } + + // Re-run the original setup + setupNock() +} diff --git a/package-lock.json b/package-lock.json index 69be3ea34..16324fb0b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -138,6 +138,7 @@ "jest-environment-node": "29.7.0", "jest-mock-extended": "3.0.5", "lint-staged": "15.2.0", + "msw": "^2.6.8", "nock": "13.5.4", "nx": "19.4.4", "postcss": "8.4.47", @@ -3444,6 +3445,47 @@ "@bull-board/api": "5.20.1" } }, + "node_modules/@bundled-es-modules/cookie": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/cookie/-/cookie-2.0.1.tgz", + "integrity": "sha512-8o+5fRPLNbjbdGRRmJj3h6Hh1AQJf2dk3qQ/5ZFb+PXkRNiSoMGGUKlsgLfrxneb72axVJyIYji64E2+nNfYyw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cookie": "^0.7.2" + } + }, + "node_modules/@bundled-es-modules/cookie/node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@bundled-es-modules/statuses": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/statuses/-/statuses-1.0.1.tgz", + "integrity": "sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==", + "dev": true, + "license": "ISC", + "dependencies": { + "statuses": "^2.0.1" + } + }, + "node_modules/@bundled-es-modules/tough-cookie": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/tough-cookie/-/tough-cookie-0.1.6.tgz", + "integrity": "sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw==", + "dev": true, + "license": "ISC", + "dependencies": { + "@types/tough-cookie": "^4.0.5", + "tough-cookie": "^4.1.4" + } + }, "node_modules/@coinbase/wallet-sdk": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/@coinbase/wallet-sdk/-/wallet-sdk-4.2.3.tgz", @@ -4823,6 +4865,147 @@ "deprecated": "Use @eslint/object-schema instead", "devOptional": true }, + "node_modules/@inquirer/confirm": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.0.tgz", + "integrity": "sha512-osaBbIMEqVFjTX5exoqPXs6PilWQdjaLhGtMDXMXg/yxkHXNq43GlxGyTA35lK2HpzUgDN+Cjh/2AmqCN0QJpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.1", + "@inquirer/type": "^3.0.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/core": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.1.tgz", + "integrity": "sha512-rmZVXy9iZvO3ZStEe/ayuuwIJ23LSF13aPMlLMTQARX6lGUBDHGV8UB5i9MRrfy0+mZwt5/9bdy8llszSD3NQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/figures": "^1.0.8", + "@inquirer/type": "^3.0.1", + "ansi-escapes": "^4.3.2", + "cli-width": "^4.1.0", + "mute-stream": "^2.0.0", + "signal-exit": "^4.1.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/core/node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 12" + } + }, + "node_modules/@inquirer/core/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@inquirer/core/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/core/node_modules/mute-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", + "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@inquirer/core/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@inquirer/core/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/core/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/figures": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.8.tgz", + "integrity": "sha512-tKd+jsmhq21AP1LhexC0pPwsCxEhGgAkg28byjJAd+xhmIs8LUX8JbUc3vBf3PhLxWiB5EvyBE5X7JSPAqMAqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/type": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.1.tgz", + "integrity": "sha512-+ksJMIy92sOAiAccGpcKZUc3bYO07cADnscIxHBknEm3uNts3movSmBofc1908BNy5edKscxYeAdaX1NXkHS6A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, "node_modules/@ioredis/commands": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", @@ -6254,6 +6437,24 @@ "win32" ] }, + "node_modules/@mswjs/interceptors": { + "version": "0.37.3", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.37.3.tgz", + "integrity": "sha512-USvgCL/uOGFtVa6SVyRrC8kIAedzRohxIXN5LISlg5C5vLZCn7dgMFVSNhSF9cuBEFrm/O2spDWEZeMnw4ZXYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@open-draft/deferred-promise": "^2.2.0", + "@open-draft/logger": "^0.3.0", + "@open-draft/until": "^2.0.0", + "is-node-process": "^1.2.0", + "outvariant": "^1.4.3", + "strict-event-emitter": "^0.5.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@napi-rs/wasm-runtime": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.4.tgz", @@ -12193,6 +12394,31 @@ "node": ">=12" } }, + "node_modules/@open-draft/deferred-promise": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", + "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@open-draft/logger": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz", + "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-node-process": "^1.2.0", + "outvariant": "^1.4.0" + } + }, + "node_modules/@open-draft/until": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz", + "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", + "dev": true, + "license": "MIT" + }, "node_modules/@open-policy-agent/opa-wasm": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/@open-policy-agent/opa-wasm/-/opa-wasm-1.9.0.tgz", @@ -19519,6 +19745,13 @@ "@types/node": "*" } }, + "node_modules/@types/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/cookiejar": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.5.tgz", @@ -19973,6 +20206,13 @@ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==" }, + "node_modules/@types/statuses": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.5.tgz", + "integrity": "sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/superagent": { "version": "8.1.7", "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.7.tgz", @@ -28354,6 +28594,16 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "devOptional": true }, + "node_modules/graphql": { + "version": "16.9.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.9.0.tgz", + "integrity": "sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, "node_modules/gray-matter": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", @@ -28752,6 +29002,13 @@ "he": "bin/he" } }, + "node_modules/headers-polyfill": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-4.0.3.tgz", + "integrity": "sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==", + "dev": true, + "license": "MIT" + }, "node_modules/hermes-estree": { "version": "0.23.1", "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.23.1.tgz", @@ -30083,6 +30340,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-node-process": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz", + "integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==", + "dev": true, + "license": "MIT" + }, "node_modules/is-npm": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-6.0.0.tgz", @@ -36143,6 +36407,122 @@ "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" } }, + "node_modules/msw": { + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/msw/-/msw-2.6.8.tgz", + "integrity": "sha512-nxXxnH6WALZ9a7rsQp4HU2AaD4iGAiouMmE/MY4al7pXTibgA6OZOuKhmN2WBIM6w9qMKwRtX8p2iOb45B2M/Q==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@bundled-es-modules/cookie": "^2.0.1", + "@bundled-es-modules/statuses": "^1.0.1", + "@bundled-es-modules/tough-cookie": "^0.1.6", + "@inquirer/confirm": "^5.0.0", + "@mswjs/interceptors": "^0.37.0", + "@open-draft/deferred-promise": "^2.2.0", + "@open-draft/until": "^2.1.0", + "@types/cookie": "^0.6.0", + "@types/statuses": "^2.0.4", + "chalk": "^4.1.2", + "graphql": "^16.8.1", + "headers-polyfill": "^4.0.2", + "is-node-process": "^1.2.0", + "outvariant": "^1.4.3", + "path-to-regexp": "^6.3.0", + "strict-event-emitter": "^0.5.1", + "type-fest": "^4.26.1", + "yargs": "^17.7.2" + }, + "bin": { + "msw": "cli/index.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mswjs" + }, + "peerDependencies": { + "typescript": ">= 4.8.x" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/msw/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/msw/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/msw/node_modules/path-to-regexp": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/msw/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/msw/node_modules/type-fest": { + "version": "4.30.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.30.0.tgz", + "integrity": "sha512-G6zXWS1dLj6eagy6sVhOMQiLtJdxQBHIA9Z6HFUNLOlr6MFOgzV8wvmidtPONfPtEUv0uZsy77XJNzTAfwPDaA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/msw/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/multer": { "version": "1.4.4-lts.1", "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4-lts.1.tgz", @@ -37175,6 +37555,13 @@ "node": ">=0.10.0" } }, + "node_modules/outvariant": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz", + "integrity": "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==", + "dev": true, + "license": "MIT" + }, "node_modules/oxc-resolver": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/oxc-resolver/-/oxc-resolver-1.10.2.tgz", @@ -41995,6 +42382,13 @@ "node": ">=10.0.0" } }, + "node_modules/strict-event-emitter": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz", + "integrity": "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==", + "dev": true, + "license": "MIT" + }, "node_modules/strict-uri-encode": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", @@ -45672,6 +46066,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/yoctocolors-cjs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz", + "integrity": "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/zod": { "version": "3.23.8", "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", diff --git a/package.json b/package.json index 2a1af667d..a148f6821 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ "jest-environment-node": "29.7.0", "jest-mock-extended": "3.0.5", "lint-staged": "15.2.0", + "msw": "^2.6.8", "nock": "13.5.4", "nx": "19.4.4", "postcss": "8.4.47", diff --git a/packages/nestjs-shared/src/lib/module/http/http.module.ts b/packages/nestjs-shared/src/lib/module/http/http.module.ts index 80a2d3a44..cf2a3ca5d 100644 --- a/packages/nestjs-shared/src/lib/module/http/http.module.ts +++ b/packages/nestjs-shared/src/lib/module/http/http.module.ts @@ -1,35 +1,36 @@ import { HttpService, HttpModule as NestHttpModule } from '@nestjs/axios' -import { DynamicModule, Global, Module } from '@nestjs/common' +import { DynamicModule } from '@nestjs/common' import axios, { AxiosRequestConfig } from 'axios' import axiosRetry, { DEFAULT_OPTIONS, IAxiosRetryConfig } from 'axios-retry' interface AxiosRetryOptions { - axiosConfig?: AxiosRequestConfig - axiosRetryConfig?: IAxiosRetryConfig + config?: AxiosRequestConfig + retry?: IAxiosRetryConfig } /** * A module that provides retry functionality for Axios HTTP requests. - * This module can be imported in a NestJS application to enable automatic retry of failed requests. + * + * This module can be imported in a NestJS application to enable automatic + * retry of failed requests. */ -@Global() -@Module({}) export class HttpModule { /** * Creates a dynamic module for the AxiosRetryModule. + * * @param options - Optional configuration options for the retry behavior. * @returns A dynamic module that can be imported in a NestJS application. */ - static forRoot( + static register( options: AxiosRetryOptions = { - axiosRetryConfig: { + retry: { ...DEFAULT_OPTIONS, retries: 0 // Default never retries } } ): DynamicModule { - const axiosInstance = axios.create(options.axiosConfig) - axiosRetry(axiosInstance, options.axiosRetryConfig) + const axiosInstance = axios.create(options.config) + axiosRetry(axiosInstance, options.retry) const axiosProvider = { provide: HttpService, diff --git a/packages/nestjs-shared/src/lib/module/logger/logger.constant.ts b/packages/nestjs-shared/src/lib/module/logger/logger.constant.ts index fc91dfb99..b03c59846 100644 --- a/packages/nestjs-shared/src/lib/module/logger/logger.constant.ts +++ b/packages/nestjs-shared/src/lib/module/logger/logger.constant.ts @@ -6,7 +6,8 @@ export const REDACT_KEYS = [ /^pass$/i, /secret/i, /token/i, - /api[-._]?key/i + /api[-._]?key/i, + /access[-._]?key/i ] export const REDACT_REPLACE = '[REDACTED]' From 492d6640d7a12dc71020f9a7275c3fadcbb89ec4 Mon Sep 17 00:00:00 2001 From: Matt Schoch Date: Tue, 17 Dec 2024 09:22:13 +0100 Subject: [PATCH 031/120] Declarative config file for App & Client configs, switching to relational db model for them (#13) * Declarative config file for App & Client configs, switching to relational db model for them * Fixing tests * Migrating v1 client data to normalized table * Cleaning up module dependency resolution * Adding auth disabled options & variations to AuthorizationGuard, adding tests * Cleanup * DB Encryption + Permissions (#24) * core encryption, rebase * Fixed connection service & tests, only returning Credentials in specific queries * Updating all tests to use encryption/integrity & permissionsGuard --- .husky/pre-commit | 3 - .prettierrc | 11 +- apps/vault/.env.default | 5 + apps/vault/.env.test.default | 2 + apps/vault/src/app.repository.ts | 86 ++++ apps/vault/src/app.service.ts | 74 +++ .../src/broker/__test__/e2e/account.spec.ts | 180 ++++++-- .../src/broker/__test__/e2e/address.spec.ts | 131 ++++-- .../broker/__test__/e2e/connection.spec.ts | 311 ++++++++++--- .../src/broker/__test__/e2e/proxy.spec.ts | 158 +++++-- .../src/broker/__test__/e2e/sync.spec.ts | 143 ++++-- .../src/broker/__test__/e2e/wallet.spec.ts | 203 +++++++-- .../__test__/util/map-db-to-returned.ts | 8 +- .../src/broker/__test__/util/mock-data.ts | 98 +++- apps/vault/src/broker/broker.module.ts | 4 +- .../anchorage-sync.service.spec.ts | 86 ++-- .../core/service/anchorage-sync.service.ts | 18 +- .../broker/core/service/connection.service.ts | 55 ++- .../src/broker/core/service/proxy.service.ts | 2 +- .../src/broker/core/service/sync.service.ts | 13 +- .../src/broker/core/type/connection.type.ts | 27 +- .../rest/controller/account.controller.ts | 5 + .../rest/controller/address.controller.ts | 4 + .../rest/controller/connection.controller.ts | 10 + .../http/rest/controller/proxy.controller.ts | 3 + .../http/rest/controller/sync.controller.ts | 5 + .../http/rest/controller/wallet.controller.ts | 5 + .../rest/dto/response/connection-list.dto.ts | 4 +- .../http/rest/dto/response/connection.dto.ts | 2 +- .../dto/response/paginated-connections.dto.ts | 2 +- .../src/broker/persistence/connection.seed.ts | 5 +- .../repository/connection.repository.ts | 102 +++-- .../repository/wallet.repository.ts | 28 +- .../src/client/__test__/e2e/client.spec.ts | 34 +- apps/vault/src/client/client.module.ts | 8 +- .../__test__/unit/client.service.spec.ts | 45 +- .../client/core/service/bootstrap.service.ts | 56 ++- .../src/client/core/service/client.service.ts | 77 +++- .../http/rest/controller/client.controller.ts | 37 +- .../__test__/unit/client.repository.spec.ts | 65 --- .../repository/client.repository.ts | 190 +++++++- apps/vault/src/main.config.ts | 322 ++++++++++++-- apps/vault/src/main.module.ts | 43 +- apps/vault/src/provision.service.ts | 119 +++++ .../decorator/permission-guard.decorator.ts | 6 +- .../encryption-module-option.factory.ts | 10 +- .../__test__/unit/admin-api-key.guard.spec.ts | 9 +- .../__test__/unit/authorization.guard.spec.ts | 421 ++++++++++++++++++ .../src/shared/guard/admin-api-key.guard.ts | 4 +- .../src/shared/guard/authorization.guard.ts | 177 +++++--- .../module/key-value/key-value.module.ts | 10 +- .../module/persistence/persistence.module.ts | 45 +- .../migration.sql | 60 +++ .../migration.sql | 6 + .../module/persistence/schema/schema.prisma | 71 ++- .../persistence/service/prisma.service.ts | 253 ++++++++++- .../service/test-prisma.service.ts | 12 +- apps/vault/src/shared/type/domain.type.ts | 69 ++- .../encryption-key.service.spec.ts | 17 +- .../persistence/encryption-key.repository.ts | 11 +- .../src/vault/__test__/e2e/account.spec.ts | 78 ++-- .../vault/__test__/e2e/encryption-key.spec.ts | 65 ++- .../src/vault/__test__/e2e/provision.spec.ts | 90 ---- .../vault/src/vault/__test__/e2e/sign.spec.ts | 106 +++-- .../src/vault/__test__/e2e/wallet.spec.ts | 68 +-- .../__test__/integration/app.service.spec.ts | 70 --- .../unit/key-generation.service.spec.ts | 26 +- .../__test__/unit/provision.service.spec.ts | 64 +-- .../src/vault/core/service/app.service.ts | 47 -- .../core/service/key-generation.service.ts | 7 +- .../vault/core/service/provision.service.ts | 91 ---- .../rest/controller/provision.controller.ts | 47 -- .../__test__/unit/app.repository.spec.ts | 53 --- .../persistence/repository/app.repository.ts | 37 -- apps/vault/src/vault/vault.module.ts | 40 +- apps/vault/src/vault/vault.service.ts | 12 - config/vault-config.local.yml | 145 ++++++ config/vault-config.template.yml | 155 +++++++ package-lock.json | 95 +++- package.json | 1 + packages/signature/src/lib/types.ts | 2 +- packages/signature/src/lib/verify.ts | 2 +- 82 files changed, 3967 insertions(+), 1304 deletions(-) create mode 100644 apps/vault/src/app.repository.ts create mode 100644 apps/vault/src/app.service.ts delete mode 100644 apps/vault/src/client/persistence/repository/__test__/unit/client.repository.spec.ts create mode 100644 apps/vault/src/provision.service.ts create mode 100644 apps/vault/src/shared/guard/__test__/unit/authorization.guard.spec.ts create mode 100644 apps/vault/src/shared/module/persistence/schema/migrations/20241206135505_normalize_client_and_app/migration.sql create mode 100644 apps/vault/src/shared/module/persistence/schema/migrations/20241212175217_encrypted_json_is_stringified/migration.sql delete mode 100644 apps/vault/src/vault/__test__/e2e/provision.spec.ts delete mode 100644 apps/vault/src/vault/core/service/__test__/integration/app.service.spec.ts delete mode 100644 apps/vault/src/vault/core/service/app.service.ts delete mode 100644 apps/vault/src/vault/core/service/provision.service.ts delete mode 100644 apps/vault/src/vault/http/rest/controller/provision.controller.ts delete mode 100644 apps/vault/src/vault/persistence/repository/__test__/unit/app.repository.spec.ts delete mode 100644 apps/vault/src/vault/persistence/repository/app.repository.ts delete mode 100644 apps/vault/src/vault/vault.service.ts create mode 100644 config/vault-config.local.yml create mode 100644 config/vault-config.template.yml diff --git a/.husky/pre-commit b/.husky/pre-commit index 36af21989..2312dc587 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" - npx lint-staged diff --git a/.prettierrc b/.prettierrc index c42708dec..2f3b81abc 100644 --- a/.prettierrc +++ b/.prettierrc @@ -6,5 +6,14 @@ "singleQuote": true, "tabWidth": 2, "trailingComma": "none", - "useTabs": false + "useTabs": false, + "overrides": [ + { + "files": ["*.yml", "*.yaml"], + "options": { + "singleQuote": false, + "quoteProps": "preserve" + } + } + ] } diff --git a/apps/vault/.env.default b/apps/vault/.env.default index d149782ba..8f718ea0a 100644 --- a/apps/vault/.env.default +++ b/apps/vault/.env.default @@ -4,6 +4,9 @@ PORT=3011 APP_UID=local-dev-vault-instance-1 +# Absolute path to the config file, otherwise defaults to project root `./config/vault-config.yml` +# CONFIG_FILE="/config/vault-config.yml" + # OPTIONAL: Sets the admin API key instead of generating a new one during the # provision. # @@ -36,6 +39,8 @@ MASTER_PASSWORD=unsafe-local-dev-master-password # If using awskms keyring, provide the ARN of the KMS encryption key instead of a master password MASTER_AWS_KMS_ARN= +HMAC_SECRET=unsafe-local-dev-hmac-secret + # Base URL where the Vault is deployed. Will be used to verify jwsd request # signatures. BASE_URL=http://localhost:3011 diff --git a/apps/vault/.env.test.default b/apps/vault/.env.test.default index bf8094b29..590577911 100644 --- a/apps/vault/.env.test.default +++ b/apps/vault/.env.test.default @@ -11,6 +11,8 @@ APP_UID="local-dev-vault-instance-1" MASTER_PASSWORD="unsafe-local-test-master-password" +HMAC_SECRET="unsafe-local-test-hmac-secret" + KEYRING_TYPE="raw" # MASTER_AWS_KMS_ARN="arn:aws:kms:us-east-2:728783560968:key/f6aa3ddb-47c3-4f31-977d-b93205bb23d1" diff --git a/apps/vault/src/app.repository.ts b/apps/vault/src/app.repository.ts new file mode 100644 index 000000000..27246f7fa --- /dev/null +++ b/apps/vault/src/app.repository.ts @@ -0,0 +1,86 @@ +import { coerce } from '@narval/nestjs-shared' +import { Injectable } from '@nestjs/common' +import { KeyMetadata } from './shared/module/key-value/core/repository/key-value.repository' +import { KeyValueService } from './shared/module/key-value/core/service/key-value.service' +import { PrismaService } from './shared/module/persistence/service/prisma.service' +import { App, AppV1, Collection } from './shared/type/domain.type' + +@Injectable() +export class AppRepository { + constructor( + private keyValueService: KeyValueService, + private prismaService: PrismaService + ) {} + + private KEY_PREFIX = Collection.APP + + /** @deprecated */ + getMetadata(): KeyMetadata { + return { + collection: Collection.APP + } + } + + /** @deprecated */ + async findByIdV1(id: string): Promise { + const value = await this.keyValueService.get(this.getKey(id)) + + if (value) { + return coerce.decode(AppV1, value) + } + + return null + } + + async findById(id: string): Promise { + const value = await this.prismaService.vault.findUnique({ where: { id } }) + + if (value) { + return App.parse(value) + } + + return null + } + + async findAll(): Promise { + const values = await this.prismaService.vault.findMany() + + return values.map((value) => App.parse(value)) + } + + /** @deprecated */ + async saveV1(app: AppV1): Promise { + await this.keyValueService.set(this.getKey(app.id), coerce.encode(AppV1, app), this.getMetadata()) + + return app + } + + async save(app: App): Promise { + const appData = { + id: app.id, + encryptionKeyringType: app.encryptionKeyringType, + encryptionMasterKey: app.encryptionMasterKey, + encryptionMasterAwsKmsArn: app.encryptionMasterAwsKmsArn, + authDisabled: app.authDisabled, + adminApiKeyHash: app.adminApiKeyHash + } + + // You cannot update the encryption details; that will cause data corruption. + // Key rotation must be a separate process. + await this.prismaService.vault.upsert({ + where: { id: app.id }, + update: { + authDisabled: app.authDisabled, + adminApiKeyHash: app.adminApiKeyHash + }, + create: appData + }) + + return app + } + + /** @deprecated */ + getKey(id: string): string { + return `${this.KEY_PREFIX}:${id}` + } +} diff --git a/apps/vault/src/app.service.ts b/apps/vault/src/app.service.ts new file mode 100644 index 000000000..7a152af25 --- /dev/null +++ b/apps/vault/src/app.service.ts @@ -0,0 +1,74 @@ +import { ConfigService } from '@narval/config-module' +import { LoggerService } from '@narval/nestjs-shared' +import { Injectable } from '@nestjs/common' +import { AppRepository } from './app.repository' +import { Config } from './main.config' +import { App } from './shared/type/domain.type' +import { AppNotProvisionedException } from './vault/core/exception/app-not-provisioned.exception' +import { ProvisionException } from './vault/core/exception/provision.exception' + +@Injectable() +export class AppService { + constructor( + private configService: ConfigService, + private appRepository: AppRepository, + private logger: LoggerService + ) {} + + async getAppOrThrow(): Promise { + const app = await this.getApp() + + if (app) { + return app + } + + throw new AppNotProvisionedException() + } + + async getApp(): Promise { + // Find all & throw if more than one. Only 1 instance is supported. + const apps = await this.appRepository.findAll() + const app = apps?.find((app) => app.id === this.getId()) + if (apps?.length && apps.length > 1) { + throw new ProvisionException('Multiple app instances found; this can lead to data corruption') + } + + if (app) { + return app + } + + return null + } + + // IMPORTANT: The admin API key is hashed by the caller not the service. That + // allows us to have a declarative configuration file which is useful for + // automations like development or cloud set up. + async save(app: App): Promise { + await this.appRepository.save(app) + + return app + } + + private getId(): string { + return this.configService.get('app.id') + } + + /** Temporary migration function, converting the key-value format of the App config into the table format */ + async migrateV1Data(): Promise { + const appV1 = await this.appRepository.findByIdV1(this.getId()) + if (appV1) { + this.logger.log('Migrating App V1 data to V2') + const keyring = this.configService.get('keyring') + const app = App.parse({ + id: appV1.id, + adminApiKeyHash: appV1.adminApiKey, + encryptionMasterKey: appV1.masterKey, + encryptionKeyringType: appV1.masterKey ? 'raw' : 'awskms', + encryptionMasterAwsKmsArn: keyring.type === 'awskms' ? keyring.encryptionMasterAwsKmsArn : null, + authDisabled: false + }) + await this.appRepository.save(app) + this.logger.log('App V1 data migrated to V2 Successfully') + } + } +} diff --git a/apps/vault/src/broker/__test__/e2e/account.spec.ts b/apps/vault/src/broker/__test__/e2e/account.spec.ts index e081d20b3..3eeedabc7 100644 --- a/apps/vault/src/broker/__test__/e2e/account.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/account.spec.ts @@ -1,32 +1,40 @@ -import { ConfigModule } from '@narval/config-module' import { EncryptionModuleOptionProvider } from '@narval/encryption-module' import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' import { HttpStatus, INestApplication } from '@nestjs/common' import { Test, TestingModule } from '@nestjs/testing' import request from 'supertest' -import { load } from '../../../main.config' +import { ClientService } from '../../../client/core/service/client.service' +import { MainModule } from '../../../main.module' +import { ProvisionService } from '../../../provision.service' +import { KeyValueRepository } from '../../../shared/module/key-value/core/repository/key-value.repository' +import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' -import { BrokerModule } from '../../broker.module' import { getExpectedAccount, getExpectedAddress } from '../util/map-db-to-returned' -import { TEST_ACCOUNTS, TEST_ADDRESSES, TEST_CLIENT_ID } from '../util/mock-data' +import { + TEST_ACCOUNTS, + TEST_ADDRESSES, + TEST_CLIENT_ID, + getJwsd, + testClient, + testUserPrivateJwk +} from '../util/mock-data' describe('Account', () => { let app: INestApplication let module: TestingModule let testPrismaService: TestPrismaService + let provisionService: ProvisionService + let clientService: ClientService beforeAll(async () => { module = await Test.createTestingModule({ - imports: [ - LoggerModule.forTest(), - ConfigModule.forRoot({ - load: [load], - isGlobal: true - }), - BrokerModule - ] + imports: [MainModule] }) + .overrideModule(LoggerModule) + .useModule(LoggerModule.forTest()) + .overrideProvider(KeyValueRepository) + .useValue(new InMemoryKeyValueRepository()) .overrideProvider(EncryptionModuleOptionProvider) .useValue({ keyring: getTestRawAesKeyring() @@ -35,13 +43,9 @@ describe('Account', () => { app = module.createNestApplication() testPrismaService = module.get(TestPrismaService) - - await app.init() - }) - - beforeEach(async () => { + provisionService = module.get(ProvisionService) + clientService = module.get(ClientService) await testPrismaService.truncateAll() - await testPrismaService.seedBrokerTestData() }) afterAll(async () => { @@ -50,9 +54,30 @@ describe('Account', () => { await app.close() }) + beforeEach(async () => { + await testPrismaService.truncateAll() + await provisionService.provision() + + await clientService.save(testClient) + await testPrismaService.seedBrokerTestData() + + await app.init() + }) + describe('GET /accounts', () => { it('returns the list of accounts with addresses for the client', async () => { - const response = await request(app.getHttpServer()).get('/accounts').set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + const response = await request(app.getHttpServer()) + .get('/provider/accounts') + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/accounts', + payload: {}, + htm: 'GET' + }) + ) expect(response.status).toEqual(HttpStatus.OK) expect(response.body).toEqual({ @@ -65,14 +90,18 @@ describe('Account', () => { it('returns empty list for unknown client', async () => { const response = await request(app.getHttpServer()) - .get('/accounts') + .get('/provider/accounts') .set(REQUEST_HEADER_CLIENT_ID, 'unknown-client') - expect(response.status).toEqual(HttpStatus.OK) - - expect(response.body).toEqual({ - accounts: [], - page: { next: null } - }) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/accounts', + payload: {}, + htm: 'GET' + }) + ) + expect(response.status).toEqual(HttpStatus.NOT_FOUND) }) }) @@ -80,8 +109,17 @@ describe('Account', () => { it('returns limited number of accounts when limit parameter is provided', async () => { const limit = 1 const response = await request(app.getHttpServer()) - .get(`/accounts?limit=${limit}`) + .get(`/provider/accounts?limit=${limit}`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: `/provider/accounts?limit=${limit}`, + payload: {}, + htm: 'GET' + }) + ) expect(response.status).toEqual(HttpStatus.OK) expect(response.body.accounts).toHaveLength(limit) @@ -91,8 +129,17 @@ describe('Account', () => { it('returns next page of results using cursor', async () => { // First request const firstResponse = await request(app.getHttpServer()) - .get('/accounts?limit=1') + .get('/provider/accounts?limit=1') .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/accounts?limit=1', + payload: {}, + htm: 'GET' + }) + ) expect(firstResponse.status).toEqual(HttpStatus.OK) const cursor = firstResponse.body.page?.next @@ -100,8 +147,17 @@ describe('Account', () => { // Second request using the cursor const secondResponse = await request(app.getHttpServer()) - .get(`/accounts?cursor=${cursor}&limit=1`) + .get(`/provider/accounts?cursor=${cursor}&limit=1`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: `/provider/accounts?cursor=${cursor}&limit=1`, + payload: {}, + htm: 'GET' + }) + ) expect(secondResponse.status).toEqual(HttpStatus.OK) expect(secondResponse.body.accounts).toHaveLength(1) @@ -110,8 +166,17 @@ describe('Account', () => { it('handles descending orderBy createdAt parameter correctly', async () => { const response = await request(app.getHttpServer()) - .get(`/accounts?orderBy=createdAt&desc=true`) + .get(`/provider/accounts?orderBy=createdAt&desc=true`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/accounts?orderBy=createdAt&desc=true', + payload: {}, + htm: 'GET' + }) + ) expect(response.status).toEqual(HttpStatus.OK) const returnedAccounts = response.body.accounts @@ -126,8 +191,17 @@ describe('Account', () => { it('returns the account details with addresses', async () => { const account = TEST_ACCOUNTS[0] const response = await request(app.getHttpServer()) - .get(`/accounts/${account.id}`) + .get(`/provider/accounts/${account.id}`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: `/provider/accounts/${account.id}`, + payload: {}, + htm: 'GET' + }) + ) expect(response.status).toEqual(HttpStatus.OK) expect(response.body).toEqual({ account: getExpectedAccount(account) @@ -136,15 +210,33 @@ describe('Account', () => { it('returns 404 with proper error message for non-existent account', async () => { const response = await request(app.getHttpServer()) - .get(`/accounts/non-existent`) + .get(`/provider/accounts/non-existent`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: `/provider/accounts/non-existent`, + payload: {}, + htm: 'GET' + }) + ) expect(response.status).toEqual(HttpStatus.NOT_FOUND) }) it('returns 404 when accessing account from unknown client', async () => { const response = await request(app.getHttpServer()) - .get(`/accounts/${TEST_ACCOUNTS[0].id}`) + .get(`/provider/accounts/${TEST_ACCOUNTS[0].id}`) .set(REQUEST_HEADER_CLIENT_ID, 'unknown-client') + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: `/provider/accounts/${TEST_ACCOUNTS[0].id}`, + payload: {}, + htm: 'GET' + }) + ) expect(response.status).toEqual(HttpStatus.NOT_FOUND) }) }) @@ -155,8 +247,17 @@ describe('Account', () => { const addresses = TEST_ADDRESSES.filter((addr) => addr.accountId === account.id) const response = await request(app.getHttpServer()) - .get(`/accounts/${account.id}/addresses`) + .get(`/provider/accounts/${account.id}/addresses`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: `/provider/accounts/${account.id}/addresses`, + payload: {}, + htm: 'GET' + }) + ) expect(response.status).toEqual(HttpStatus.OK) expect(response.body).toEqual({ @@ -179,8 +280,17 @@ describe('Account', () => { }) const response = await request(app.getHttpServer()) - .get(`/accounts/${accountWithoutAddresses.id}/addresses`) + .get(`/provider/accounts/${accountWithoutAddresses.id}/addresses`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: `/provider/accounts/${accountWithoutAddresses.id}/addresses`, + payload: {}, + htm: 'GET' + }) + ) expect(response.status).toEqual(HttpStatus.OK) expect(response.body).toEqual({ addresses: [], diff --git a/apps/vault/src/broker/__test__/e2e/address.spec.ts b/apps/vault/src/broker/__test__/e2e/address.spec.ts index d1348bdcf..4209c9bd3 100644 --- a/apps/vault/src/broker/__test__/e2e/address.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/address.spec.ts @@ -1,32 +1,33 @@ -import { ConfigModule } from '@narval/config-module' import { EncryptionModuleOptionProvider } from '@narval/encryption-module' import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' import { HttpStatus, INestApplication } from '@nestjs/common' import { Test, TestingModule } from '@nestjs/testing' import request from 'supertest' -import { load } from '../../../main.config' +import { ClientService } from '../../../client/core/service/client.service' +import { MainModule } from '../../../main.module' +import { ProvisionService } from '../../../provision.service' +import { KeyValueRepository } from '../../../shared/module/key-value/core/repository/key-value.repository' +import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' -import { BrokerModule } from '../../broker.module' import { getExpectedAddress } from '../util/map-db-to-returned' -import { TEST_ADDRESSES, TEST_CLIENT_ID } from '../util/mock-data' +import { TEST_ADDRESSES, TEST_CLIENT_ID, getJwsd, testClient, testUserPrivateJwk } from '../util/mock-data' describe('Address', () => { let app: INestApplication let module: TestingModule let testPrismaService: TestPrismaService + let provisionService: ProvisionService + let clientService: ClientService beforeAll(async () => { module = await Test.createTestingModule({ - imports: [ - LoggerModule.forTest(), - ConfigModule.forRoot({ - load: [load], - isGlobal: true - }), - BrokerModule - ] + imports: [MainModule] }) + .overrideModule(LoggerModule) + .useModule(LoggerModule.forTest()) + .overrideProvider(KeyValueRepository) + .useValue(new InMemoryKeyValueRepository()) .overrideProvider(EncryptionModuleOptionProvider) .useValue({ keyring: getTestRawAesKeyring() @@ -35,13 +36,9 @@ describe('Address', () => { app = module.createNestApplication() testPrismaService = module.get(TestPrismaService) - - await app.init() - }) - - beforeEach(async () => { + provisionService = module.get(ProvisionService) + clientService = module.get(ClientService) await testPrismaService.truncateAll() - await testPrismaService.seedBrokerTestData() }) afterAll(async () => { @@ -50,11 +47,30 @@ describe('Address', () => { await app.close() }) + beforeEach(async () => { + await testPrismaService.truncateAll() + await provisionService.provision() + + await clientService.save(testClient) + await testPrismaService.seedBrokerTestData() + + await app.init() + }) + describe('GET /addresses', () => { it('returns the list of addresses for the client', async () => { const response = await request(app.getHttpServer()) - .get(`/addresses`) + .get(`/provider/addresses`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/addresses', + payload: {}, + htm: 'GET' + }) + ) expect(response.status).toEqual(HttpStatus.OK) expect(response.body).toEqual({ @@ -70,8 +86,17 @@ describe('Address', () => { it('returns limited number of addresses when limit parameter is provided', async () => { const limit = 1 const response = await request(app.getHttpServer()) - .get(`/addresses?limit=${limit}`) + .get(`/provider/addresses?limit=${limit}`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: `/provider/addresses?limit=${limit}`, + payload: {}, + htm: 'GET' + }) + ) expect(response.body.addresses).toHaveLength(limit) expect(response.body.page).toHaveProperty('next') @@ -80,8 +105,17 @@ describe('Address', () => { it('returns next page of results using cursor', async () => { // First request const firstResponse = await request(app.getHttpServer()) - .get('/addresses?limit=1') + .get('/provider/addresses?limit=1') .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/addresses?limit=1', + payload: {}, + htm: 'GET' + }) + ) .expect(HttpStatus.OK) const cursor = firstResponse.body.page?.next @@ -89,8 +123,17 @@ describe('Address', () => { // Second request using the cursor const secondResponse = await request(app.getHttpServer()) - .get(`/addresses?cursor=${cursor}&limit=1`) + .get(`/provider/addresses?cursor=${cursor}&limit=1`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: `/provider/addresses?cursor=${cursor}&limit=1`, + payload: {}, + htm: 'GET' + }) + ) .expect(HttpStatus.OK) expect(secondResponse.body.addresses).toHaveLength(1) @@ -99,8 +142,17 @@ describe('Address', () => { it('handles descending orderBy createdAt parameter correctly', async () => { const response = await request(app.getHttpServer()) - .get('/addresses?orderBy=createdAt&desc=true') + .get('/provider/addresses?orderBy=createdAt&desc=true') .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/addresses?orderBy=createdAt&desc=true', + payload: {}, + htm: 'GET' + }) + ) .expect(HttpStatus.OK) const returnedAddresses = response.body.addresses @@ -115,8 +167,17 @@ describe('Address', () => { it('returns the address details', async () => { const address = TEST_ADDRESSES[0] const response = await request(app.getHttpServer()) - .get(`/addresses/${address.id}`) + .get(`/provider/addresses/${address.id}`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: `/provider/addresses/${address.id}`, + payload: {}, + htm: 'GET' + }) + ) expect(response.body).toEqual({ address: getExpectedAddress(address) @@ -126,16 +187,34 @@ describe('Address', () => { it('returns 404 with proper error message for non-existent address', async () => { const response = await request(app.getHttpServer()) - .get('/addresses/non-existent') + .get('/provider/addresses/non-existent') .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/addresses/non-existent', + payload: {}, + htm: 'GET' + }) + ) expect(response.status).toBe(HttpStatus.NOT_FOUND) }) it('returns 404 when accessing address from different client', async () => { const response = await request(app.getHttpServer()) - .get(`/addresses/${TEST_ADDRESSES[0].id}`) + .get(`/provider/addresses/${TEST_ADDRESSES[0].id}`) .set(REQUEST_HEADER_CLIENT_ID, 'different-client') + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: `/provider/addresses/${TEST_ADDRESSES[0].id}`, + payload: {}, + htm: 'GET' + }) + ) expect(response.status).toBe(HttpStatus.NOT_FOUND) }) diff --git a/apps/vault/src/broker/__test__/e2e/connection.spec.ts b/apps/vault/src/broker/__test__/e2e/connection.spec.ts index fff629072..44caf2f83 100644 --- a/apps/vault/src/broker/__test__/e2e/connection.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/connection.spec.ts @@ -1,4 +1,4 @@ -import { ConfigModule } from '@narval/config-module' +import { EncryptionModuleOptionProvider } from '@narval/encryption-module' import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' import { Alg, @@ -16,25 +16,25 @@ import { times } from 'lodash' import request from 'supertest' import { v4 as uuid } from 'uuid' import { ZodSchema } from 'zod' -import { load } from '../../../main.config' +import { ClientService } from '../../../client/core/service/client.service' +import { MainModule } from '../../../main.module' +import { ProvisionService } from '../../../provision.service' +import { KeyValueRepository } from '../../../shared/module/key-value/core/repository/key-value.repository' +import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' +import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' import { EncryptionKeyService } from '../../../transit-encryption/core/service/encryption-key.service' -import { BrokerModule } from '../../broker.module' import { ConnectionService } from '../../core/service/connection.service' -import { - ActiveConnection, - ConnectionStatus, - Provider, - isActiveConnection, - isRevokedConnection -} from '../../core/type/connection.type' +import { ConnectionStatus, Provider, isActiveConnection, isRevokedConnection } from '../../core/type/connection.type' import { getExpectedAccount, getExpectedWallet } from '../util/map-db-to-returned' import { TEST_ACCOUNTS, - TEST_CLIENT_ID, TEST_CONNECTIONS, TEST_WALLETS, - TEST_WALLET_CONNECTIONS + TEST_WALLET_CONNECTIONS, + getJwsd, + testClient, + testUserPrivateJwk } from '../util/mock-data' const toMatchZodSchema = (received: unknown, schema: ZodSchema): void => { @@ -61,32 +61,38 @@ describe('Connection', () => { let connectionService: ConnectionService let encryptionKeyService: EncryptionKeyService let testPrismaService: TestPrismaService + let provisionService: ProvisionService + let clientService: ClientService const url = 'http://provider.narval.xyz' - const clientId = TEST_CLIENT_ID + const userPrivateJwk = testUserPrivateJwk + const client = testClient + const clientId = testClient.clientId beforeAll(async () => { module = await Test.createTestingModule({ - imports: [ - LoggerModule.forTest(), - ConfigModule.forRoot({ - load: [load], - isGlobal: true - }), - BrokerModule - ] - }).compile() + imports: [MainModule] + }) + .overrideModule(LoggerModule) + .useModule(LoggerModule.forTest()) + .overrideProvider(KeyValueRepository) + .useValue(new InMemoryKeyValueRepository()) + .overrideProvider(EncryptionModuleOptionProvider) + .useValue({ + keyring: getTestRawAesKeyring() + }) + .compile() app = module.createNestApplication() testPrismaService = module.get(TestPrismaService) connectionService = module.get(ConnectionService) encryptionKeyService = module.get(EncryptionKeyService) + provisionService = module.get(ProvisionService) + clientService = module.get(ClientService) await testPrismaService.truncateAll() - - await app.init() }) afterAll(async () => { @@ -97,6 +103,11 @@ describe('Connection', () => { beforeEach(async () => { await testPrismaService.truncateAll() + await provisionService.provision() + + await clientService.save(client) + + await app.init() }) describe('POST /connections/initiate', () => { @@ -108,8 +119,16 @@ describe('Connection', () => { } const { status, body } = await request(app.getHttpServer()) - .post('/connections/initiate') + .post('/provider/connections/initiate') .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk, + requestUrl: '/provider/connections/initiate', + payload: connection + }) + ) .send(connection) expect(body).toMatchObject({ @@ -128,7 +147,7 @@ describe('Connection', () => { }) }) - describe('POST /connections', () => { + describe('POST /provider/connections', () => { it('creates a new connection to anchorage with plain credentials', async () => { const privateKey = await generateJwk(Alg.EDDSA) const privateKeyHex = await privateKeyToHex(privateKey) @@ -145,18 +164,25 @@ describe('Connection', () => { } const { status, body } = await request(app.getHttpServer()) - .post('/connections') + .post('/provider/connections') .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk, + requestUrl: '/provider/connections', + payload: connection + }) + ) .send(connection) - const createdConnection = await connectionService.findById(clientId, connection.connectionId) + const createdConnection = await connectionService.findById(clientId, connection.connectionId, true) expect(body).toEqual({ clientId, connectionId, url, createdAt: expect.any(String), - integrity: expect.any(String), label: connection.label, provider: connection.provider, status: ConnectionStatus.ACTIVE, @@ -174,7 +200,6 @@ describe('Connection', () => { }, createdAt: expect.any(Date), connectionId, - integrity: expect.any(String), label: connection.label, provider: connection.provider, status: ConnectionStatus.ACTIVE, @@ -190,13 +215,35 @@ describe('Connection', () => { const credentials = { apiKey: 'test-api-key' } const { body: pendingConnection } = await request(app.getHttpServer()) - .post('/connections/initiate') + .post('/provider/connections/initiate') .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk, + requestUrl: '/provider/connections/initiate', + payload: { connectionId, provider } + }) + ) .send({ connectionId, provider }) const { status, body } = await request(app.getHttpServer()) - .post('/connections') + .post('/provider/connections') .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk, + requestUrl: '/provider/connections', + payload: { + connectionId, + credentials, + label, + provider, + url + } + }) + ) .send({ connectionId, credentials, @@ -212,13 +259,12 @@ describe('Connection', () => { provider, url, createdAt: expect.any(String), - integrity: 'TODO ACTIVATE CONNECTION', status: ConnectionStatus.ACTIVE, updatedAt: expect.any(String) }) expect(status).toEqual(HttpStatus.CREATED) - const createdConnection = await connectionService.findById(clientId, connectionId) + const createdConnection = await connectionService.findById(clientId, connectionId, true) expect(createdConnection).toMatchObject({ clientId, @@ -227,7 +273,6 @@ describe('Connection', () => { provider, url, createdAt: expect.any(Date), - integrity: expect.any(String), status: ConnectionStatus.ACTIVE, updatedAt: expect.any(Date) }) @@ -251,15 +296,37 @@ describe('Connection', () => { } const { body: pendingConnection } = await request(app.getHttpServer()) - .post('/connections/initiate') + .post('/provider/connections/initiate') .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk, + requestUrl: '/provider/connections/initiate', + payload: { connectionId, provider } + }) + ) .send({ connectionId, provider }) const encryptedCredentials = await rsaEncrypt(JSON.stringify(credentials), pendingConnection.encryptionPublicKey) const { status, body } = await request(app.getHttpServer()) - .post('/connections') + .post('/provider/connections') .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk, + requestUrl: '/provider/connections', + payload: { + provider, + connectionId, + label, + url, + encryptedCredentials + } + }) + ) .send({ provider, connectionId, @@ -275,13 +342,12 @@ describe('Connection', () => { provider, url, createdAt: expect.any(String), - integrity: 'TODO ACTIVATE CONNECTION', status: ConnectionStatus.ACTIVE, updatedAt: expect.any(String) }) expect(status).toEqual(HttpStatus.CREATED) - const createdConnection = await connectionService.findById(clientId, connectionId) + const createdConnection = await connectionService.findById(clientId, connectionId, true) expect(createdConnection).toMatchObject({ clientId, @@ -290,7 +356,6 @@ describe('Connection', () => { provider, url, createdAt: expect.any(Date), - integrity: expect.any(String), status: ConnectionStatus.ACTIVE, updatedAt: expect.any(Date) }) @@ -306,7 +371,7 @@ describe('Connection', () => { }) }) - describe('DELETE /connections/:id', () => { + describe('DELETE /provider/connections/:id', () => { it('revokes an existing connection', async () => { const connection = await connectionService.create(clientId, { connectionId: uuid(), @@ -320,13 +385,22 @@ describe('Connection', () => { }) const { status } = await request(app.getHttpServer()) - .delete(`/connections/${connection.connectionId}`) + .delete(`/provider/connections/${connection.connectionId}`) .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk, + requestUrl: `/provider/connections/${connection.connectionId}`, + payload: {}, + htm: 'DELETE' + }) + ) .send() expect(status).toEqual(HttpStatus.NO_CONTENT) - const updatedConnection = await connectionService.findById(clientId, connection.connectionId) + const updatedConnection = await connectionService.findById(clientId, connection.connectionId, true) if (isRevokedConnection(updatedConnection)) { expect(updatedConnection.credentials).toEqual(null) @@ -337,7 +411,7 @@ describe('Connection', () => { }) }) - describe('GET /connections', () => { + describe('GET /provider/connections', () => { beforeEach(async () => { await Promise.all( times(3, async () => @@ -357,8 +431,17 @@ describe('Connection', () => { it('responds with connections from the given client', async () => { const { status, body } = await request(app.getHttpServer()) - .get('/connections') + .get('/provider/connections') .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk, + requestUrl: '/provider/connections', + payload: {}, + htm: 'GET' + }) + ) .send() expect(body.connections.length).toEqual(3) @@ -368,7 +451,6 @@ describe('Connection', () => { url, connectionId: expect.any(String), createdAt: expect.any(String), - integrity: expect.any(String), label: expect.any(String), provider: Provider.ANCHORAGE, updatedAt: expect.any(String) @@ -380,34 +462,73 @@ describe('Connection', () => { it('responds with limited number of syncs when limit is given', async () => { const { body } = await request(app.getHttpServer()) - .get('/connections') + .get('/provider/connections') .query({ limit: 1 }) .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk, + requestUrl: '/provider/connections?limit=1', + payload: {}, + htm: 'GET' + }) + ) + .send() expect(body.connections.length).toEqual(1) expect(body.page).toHaveProperty('next') }) - it('responds the next page of results when cursos is given', async () => { + it('responds the next page of results when cursors is given', async () => { const { body: pageOne } = await request(app.getHttpServer()) - .get('/connections') + .get('/provider/connections') .query({ limit: 1 }) .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk, + requestUrl: '/provider/connections?limit=1', + payload: {}, + htm: 'GET' + }) + ) + .send() const { body: pageTwo } = await request(app.getHttpServer()) - .get('/connections') + .get('/provider/connections') .query({ limit: 1, cursor: pageOne.page.next }) .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk, + requestUrl: `/provider/connections?limit=1&cursor=${pageOne.page.next}`, + payload: {}, + htm: 'GET' + }) + ) + .send() expect(pageTwo.connections.length).toEqual(1) expect(pageTwo.page).toHaveProperty('next') }) + + it('throws error if the request was not signed', async () => { + const { status } = await request(app.getHttpServer()) + .get('/provider/connections') + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .send() + + expect(status).toEqual(HttpStatus.UNAUTHORIZED) + }) }) - describe('GET /connections/:connectionId', () => { + describe('GET /provider/connections/:connectionId', () => { it('responds with the specific connection', async () => { const connection = await connectionService.create(clientId, { connectionId: uuid(), @@ -421,13 +542,21 @@ describe('Connection', () => { }) const { status, body } = await request(app.getHttpServer()) - .get(`/connections/${connection.connectionId}`) + .get(`/provider/connections/${connection.connectionId}`) .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk, + requestUrl: `/provider/connections/${connection.connectionId}`, + payload: {}, + htm: 'GET' + }) + ) .send() expect(body).toMatchObject({ connectionId: expect.any(String), - integrity: expect.any(String), clientId, createdAt: expect.any(String), updatedAt: expect.any(String), @@ -441,7 +570,7 @@ describe('Connection', () => { }) }) - describe('PATCH /connections/:connectionId', () => { + describe('PATCH /provider/connections/:connectionId', () => { it('updates the given connection', async () => { const connection = await connectionService.create(clientId, { connectionId: uuid(), @@ -462,8 +591,20 @@ describe('Connection', () => { const encryptedCredentials = await rsaEncrypt(JSON.stringify(newCredentials), encryptionKey.publicKey) const { status, body } = await request(app.getHttpServer()) - .patch(`/connections/${connection.connectionId}`) + .patch(`/provider/connections/${connection.connectionId}`) .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk, + requestUrl: `/provider/connections/${connection.connectionId}`, + payload: { + label: 'new label', + encryptedCredentials + }, + htm: 'PATCH' + }) + ) .send({ label: 'new label', encryptedCredentials @@ -474,24 +615,30 @@ describe('Connection', () => { expect(status).toEqual(HttpStatus.OK) - const updatedConnection = (await connectionService.findById( - clientId, - connection.connectionId - )) as ActiveConnection + const updatedConnection = await connectionService.findById(clientId, connection.connectionId, true) - expect(updatedConnection.credentials.apiKey).toEqual(newCredentials.apiKey) - expect(updatedConnection.credentials.privateKey).toEqual(newPrivateKey) - expect(updatedConnection.credentials.publicKey).toEqual(getPublicKey(newPrivateKey as Ed25519PrivateKey)) + expect(updatedConnection.credentials?.apiKey).toEqual(newCredentials.apiKey) + expect(updatedConnection.credentials?.privateKey).toEqual(newPrivateKey) + expect(updatedConnection.credentials?.publicKey).toEqual(getPublicKey(newPrivateKey as Ed25519PrivateKey)) }) }) - describe('GET /connections/:connectionId/wallets', () => { + describe('GET /provider/connections/:connectionId/wallets', () => { it('responds with wallets for the specific connection', async () => { await testPrismaService.seedBrokerTestData() const { status, body } = await request(app.getHttpServer()) - .get(`/connections/${TEST_CONNECTIONS[0].id}/wallets`) + .get(`/provider/connections/${TEST_CONNECTIONS[0].id}/wallets`) .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk, + requestUrl: `/provider/connections/${TEST_CONNECTIONS[0].id}/wallets`, + payload: {}, + htm: 'GET' + }) + ) .send() expect(status).toEqual(HttpStatus.OK) @@ -516,8 +663,17 @@ describe('Connection', () => { }) const { status, body } = await request(app.getHttpServer()) - .get(`/connections/${connection.connectionId}/wallets`) + .get(`/provider/connections/${connection.connectionId}/wallets`) .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk, + requestUrl: `/provider/connections/${connection.connectionId}/wallets`, + payload: {}, + htm: 'GET' + }) + ) .send() expect(status).toEqual(HttpStatus.OK) @@ -528,8 +684,9 @@ describe('Connection', () => { }) }) - describe('GET /connections/:connectionId/accounts', () => { + describe('GET /provider/connections/:connectionId/accounts', () => { it('responds with accounts for the specific connection', async () => { + expect.assertions(2) await testPrismaService.seedBrokerTestData() // Assume connection[0] has some wallets which in turn have accounts. @@ -541,8 +698,17 @@ describe('Connection', () => { const accountsForConnection = TEST_ACCOUNTS.filter((account) => walletsForConnection.includes(account.walletId)) const { status, body } = await request(app.getHttpServer()) - .get(`/connections/${connectionId}/accounts`) + .get(`/provider/connections/${connectionId}/accounts`) .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk, + requestUrl: `/provider/connections/${connectionId}/accounts`, + payload: {}, + htm: 'GET' + }) + ) .send() expect(status).toEqual(HttpStatus.OK) @@ -568,8 +734,17 @@ describe('Connection', () => { }) const { status, body } = await request(app.getHttpServer()) - .get(`/connections/${connection.connectionId}/accounts`) + .get(`/provider/connections/${connection.connectionId}/accounts`) .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk, + requestUrl: `/provider/connections/${connection.connectionId}/accounts`, + payload: {}, + htm: 'GET' + }) + ) .send() expect(status).toEqual(HttpStatus.OK) diff --git a/apps/vault/src/broker/__test__/e2e/proxy.spec.ts b/apps/vault/src/broker/__test__/e2e/proxy.spec.ts index 2a771f1dd..d77b25b7d 100644 --- a/apps/vault/src/broker/__test__/e2e/proxy.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/proxy.spec.ts @@ -1,22 +1,29 @@ -import { ConfigModule } from '@narval/config-module' import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' import { Alg, generateJwk, privateKeyToHex } from '@narval/signature' import { HttpStatus, INestApplication } from '@nestjs/common' import { Test, TestingModule } from '@nestjs/testing' import nock from 'nock' +import { EncryptionModuleOptionProvider } from 'packages/encryption-module/src/lib/encryption.module' import request from 'supertest' -import { load } from '../../../main.config' +import { ClientService } from '../../../client/core/service/client.service' +import { MainModule } from '../../../main.module' +import { ProvisionService } from '../../../provision.service' import { REQUEST_HEADER_CONNECTION_ID } from '../../../shared/decorator/connection-id.decorator' +import { KeyValueRepository } from '../../../shared/module/key-value/core/repository/key-value.repository' +import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' -import { BrokerModule } from '../../broker.module' +import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' import { ConnectionService } from '../../core/service/connection.service' import { Provider } from '../../core/type/connection.type' +import { getJwsd, testClient, testUserPrivateJwk } from '../util/mock-data' describe('Proxy', () => { let app: INestApplication let module: TestingModule let connectionService: ConnectionService let testPrismaService: TestPrismaService + let provisionService: ProvisionService + let clientService: ClientService const TEST_CLIENT_ID = 'test-client-id' const TEST_CONNECTION_ID = 'test-connection-id' @@ -24,23 +31,24 @@ describe('Proxy', () => { beforeAll(async () => { module = await Test.createTestingModule({ - imports: [ - LoggerModule.forTest(), - ConfigModule.forRoot({ - load: [load], - isGlobal: true - }), - BrokerModule - ] - }).compile() + imports: [MainModule] + }) + .overrideModule(LoggerModule) + .useModule(LoggerModule.forTest()) + .overrideProvider(KeyValueRepository) + .useValue(new InMemoryKeyValueRepository()) + .overrideProvider(EncryptionModuleOptionProvider) + .useValue({ + keyring: getTestRawAesKeyring() + }) + .compile() app = module.createNestApplication() - testPrismaService = module.get(TestPrismaService) - connectionService = module.get(ConnectionService) - + provisionService = module.get(ProvisionService) + clientService = module.get(ClientService) await testPrismaService.truncateAll() - await app.init() + connectionService = module.get(ConnectionService) }) afterAll(async () => { @@ -55,6 +63,9 @@ describe('Proxy', () => { // Clean any pending nock interceptors nock.cleanAll() + await provisionService.provision() + await clientService.save(testClient) + // Create a test connection await connectionService.create(TEST_CLIENT_ID, { connectionId: TEST_CONNECTION_ID, @@ -66,28 +77,47 @@ describe('Proxy', () => { privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) } }) + + await app.init() }) it('forwards GET request', async () => { nock(MOCK_API_URL).get('/v2/vaults').reply(200, { data: 'mock response' }) const response = await request(app.getHttpServer()) - .get('/proxy/v2/vaults') + .get('/provider/proxy/v2/vaults') .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set(REQUEST_HEADER_CONNECTION_ID, TEST_CONNECTION_ID) - .send() + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/proxy/v2/vaults', + payload: {}, + htm: 'GET' + }) + ) - expect(response.body).toEqual({ data: 'mock response' }) expect(response.status).toBe(HttpStatus.OK) + expect(response.body).toEqual({ data: 'mock response' }) }) it('forwards POST request', async () => { nock(MOCK_API_URL).post('/v2/wallets').reply(201, { data: 'mock response' }) const response = await request(app.getHttpServer()) - .post('/proxy/v2/wallets') + .post('/provider/proxy/v2/wallets') .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set(REQUEST_HEADER_CONNECTION_ID, TEST_CONNECTION_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/proxy/v2/wallets', + payload: { test: 'data' }, + htm: 'POST' + }) + ) .send({ test: 'data' }) expect(response.body).toEqual({ data: 'mock response' }) @@ -98,9 +128,18 @@ describe('Proxy', () => { nock(MOCK_API_URL).delete('/v2/vaults').reply(204) const response = await request(app.getHttpServer()) - .delete('/proxy/v2/vaults') + .delete('/provider/proxy/v2/vaults') .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set(REQUEST_HEADER_CONNECTION_ID, TEST_CONNECTION_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/proxy/v2/vaults', + payload: {}, + htm: 'DELETE' + }) + ) .send() expect(response.status).toBe(HttpStatus.NO_CONTENT) @@ -110,9 +149,18 @@ describe('Proxy', () => { nock(MOCK_API_URL).put('/v2/vaults').reply(200, { data: 'mock response' }) const response = await request(app.getHttpServer()) - .put('/proxy/v2/vaults') + .put('/provider/proxy/v2/vaults') .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set(REQUEST_HEADER_CONNECTION_ID, TEST_CONNECTION_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/proxy/v2/vaults', + payload: { test: 'data' }, + htm: 'PUT' + }) + ) .send({ test: 'data' }) expect(response.body).toEqual({ data: 'mock response' }) @@ -123,9 +171,18 @@ describe('Proxy', () => { nock(MOCK_API_URL).patch('/v2/vaults').reply(200, { data: 'mock response' }) const response = await request(app.getHttpServer()) - .patch('/proxy/v2/vaults') + .patch('/provider/proxy/v2/vaults') .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set(REQUEST_HEADER_CONNECTION_ID, TEST_CONNECTION_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/proxy/v2/vaults', + payload: { test: 'data' }, + htm: 'PATCH' + }) + ) .send({ test: 'data' }) expect(response.body).toEqual({ data: 'mock response' }) @@ -143,9 +200,18 @@ describe('Proxy', () => { }) await request(app.getHttpServer()) - .get('/proxy/v2/vaults') + .get('/provider/proxy/v2/vaults') .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set(REQUEST_HEADER_CONNECTION_ID, TEST_CONNECTION_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/proxy/v2/vaults', + payload: {}, + htm: 'GET' + }) + ) .send() expect(capturedHeaders['api-access-key']).toBe('test-api-key') @@ -162,9 +228,18 @@ describe('Proxy', () => { }) await request(app.getHttpServer()) - .get('/v1/proxy/v2/vaults') + .get('/provider/proxy/v2/vaults') .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set(REQUEST_HEADER_CONNECTION_ID, TEST_CONNECTION_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/proxy/v2/vaults', + payload: {}, + htm: 'GET' + }) + ) .send() expect(capturedHeaders[REQUEST_HEADER_CLIENT_ID.toLowerCase()]).toBeUndefined() @@ -181,9 +256,18 @@ describe('Proxy', () => { }) await request(app.getHttpServer()) - .get('/v1/proxy/v2/vaults') + .get('/provider/proxy/v2/vaults') .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set(REQUEST_HEADER_CONNECTION_ID, TEST_CONNECTION_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/proxy/v2/vaults', + payload: {}, + htm: 'GET' + }) + ) .send() expect(capturedHeaders[REQUEST_HEADER_CONNECTION_ID.toLowerCase()]).toBeUndefined() @@ -193,9 +277,18 @@ describe('Proxy', () => { nock(MOCK_API_URL).get('/v2/vaults').reply(512, { error: 'mock error' }, { 'x-custom-header': 'custom value' }) const response = await request(app.getHttpServer()) - .get('/proxy/v2/vaults') + .get('/provider/proxy/v2/vaults') .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set(REQUEST_HEADER_CONNECTION_ID, TEST_CONNECTION_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/proxy/v2/vaults', + payload: {}, + htm: 'GET' + }) + ) .send() expect(response.body).toEqual({ error: 'mock error' }) @@ -207,9 +300,18 @@ describe('Proxy', () => { await connectionService.revoke(TEST_CLIENT_ID, TEST_CONNECTION_ID) const response = await request(app.getHttpServer()) - .get('/proxy/v2/vaults') + .get('/provider/proxy/v2/vaults') .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set(REQUEST_HEADER_CONNECTION_ID, TEST_CONNECTION_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/proxy/v2/vaults', + payload: {}, + htm: 'GET' + }) + ) .send() expect(response.body).toEqual({ diff --git a/apps/vault/src/broker/__test__/e2e/sync.spec.ts b/apps/vault/src/broker/__test__/e2e/sync.spec.ts index d8cfed059..b11013b72 100644 --- a/apps/vault/src/broker/__test__/e2e/sync.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/sync.spec.ts @@ -1,4 +1,4 @@ -import { ConfigModule } from '@narval/config-module' +import { EncryptionModuleOptionProvider } from '@narval/encryption-module' import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' import { Alg, generateJwk, privateKeyToHex } from '@narval/signature' import { HttpStatus, INestApplication } from '@nestjs/common' @@ -6,9 +6,13 @@ import { Test, TestingModule } from '@nestjs/testing' import { MockProxy, mock } from 'jest-mock-extended' import request from 'supertest' import { v4 as uuid } from 'uuid' -import { load } from '../../../main.config' +import { ClientService } from '../../../client/core/service/client.service' +import { MainModule } from '../../../main.module' +import { ProvisionService } from '../../../provision.service' +import { KeyValueRepository } from '../../../shared/module/key-value/core/repository/key-value.repository' +import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' -import { BrokerModule } from '../../broker.module' +import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' import { ANCHORAGE_TEST_API_BASE_URL, setupMockServer @@ -18,6 +22,7 @@ import { ConnectionService } from '../../core/service/connection.service' import { SyncService } from '../../core/service/sync.service' import { ActiveConnection, PendingConnection, Provider } from '../../core/type/connection.type' import { SyncStatus } from '../../core/type/sync.type' +import { getJwsd, testClient, testUserPrivateJwk } from '../util/mock-data' describe('Sync', () => { let app: INestApplication @@ -26,6 +31,8 @@ describe('Sync', () => { let connectionService: ConnectionService let testPrismaService: TestPrismaService let anchorageSyncServiceMock: MockProxy + let provisionService: ProvisionService + let clientService: ClientService let activeConnection: ActiveConnection // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -35,7 +42,7 @@ describe('Sync', () => { const apiKey = 'test-api-key' - const clientId = uuid() + const clientId = testClient.clientId setupMockServer() @@ -48,17 +55,17 @@ describe('Sync', () => { // integration tests. anchorageSyncServiceMock = mock() anchorageSyncServiceMock.sync.mockResolvedValue() - module = await Test.createTestingModule({ - imports: [ - LoggerModule.forTest(), - ConfigModule.forRoot({ - load: [load], - isGlobal: true - }), - BrokerModule - ] + imports: [MainModule] }) + .overrideModule(LoggerModule) + .useModule(LoggerModule.forTest()) + .overrideProvider(KeyValueRepository) + .useValue(new InMemoryKeyValueRepository()) + .overrideProvider(EncryptionModuleOptionProvider) + .useValue({ + keyring: getTestRawAesKeyring() + }) .overrideProvider(AnchorageSyncService) .useValue(anchorageSyncServiceMock) .compile() @@ -66,12 +73,12 @@ describe('Sync', () => { app = module.createNestApplication() testPrismaService = module.get(TestPrismaService) + provisionService = module.get(ProvisionService) + clientService = module.get(ClientService) syncService = module.get(SyncService) connectionService = module.get(ConnectionService) await testPrismaService.truncateAll() - - await app.init() }) afterAll(async () => { @@ -83,6 +90,9 @@ describe('Sync', () => { beforeEach(async () => { await testPrismaService.truncateAll() + await provisionService.provision() + await clientService.save(testClient) + activeConnection = await connectionService.create(clientId, { connectionId: uuid(), provider: Provider.ANCHORAGE, @@ -97,6 +107,8 @@ describe('Sync', () => { connectionId: uuid(), provider: Provider.ANCHORAGE }) + + await app.init() }) describe('POST /syncs', () => { @@ -106,15 +118,36 @@ describe('Sync', () => { // the order of this test will affect how many times the `sync` function is // called. it('dispatches the sync to the provider specific service', async () => { - await request(app.getHttpServer()).post('/syncs').set(REQUEST_HEADER_CLIENT_ID, clientId).send() + await request(app.getHttpServer()) + .post('/provider/syncs') + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/syncs', + payload: {}, + htm: 'POST' + }) + ) + .send() expect(anchorageSyncServiceMock.sync).toHaveBeenCalledTimes(1) }) it('starts a sync on every active connection', async () => { const { status, body } = await request(app.getHttpServer()) - .post('/syncs') + .post('/provider/syncs') .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/syncs', + payload: {}, + htm: 'POST' + }) + ) .send() const syncs = await syncService.findAllPaginated(clientId) @@ -140,8 +173,17 @@ describe('Sync', () => { it('starts a sync on the given connection', async () => { const { status, body } = await request(app.getHttpServer()) - .post('/syncs') + .post('/provider/syncs') .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/syncs', + payload: { connectionId: activeConnection.connectionId }, + htm: 'POST' + }) + ) .send({ connectionId: activeConnection.connectionId }) const syncs = await syncService.findAllPaginated(clientId) @@ -175,8 +217,17 @@ describe('Sync', () => { const [sync] = syncs const { status, body } = await request(app.getHttpServer()) - .get(`/syncs/${sync.syncId}`) + .get(`/provider/syncs/${sync.syncId}`) .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: `/provider/syncs/${sync.syncId}`, + payload: {}, + htm: 'GET' + }) + ) .send() expect(body).toMatchObject({ @@ -199,8 +250,17 @@ describe('Sync', () => { const [sync] = syncs const { status, body } = await request(app.getHttpServer()) - .get('/syncs') + .get('/provider/syncs') .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/syncs', + payload: {}, + htm: 'GET' + }) + ) .send() expect(body).toMatchObject({ @@ -227,9 +287,18 @@ describe('Sync', () => { const [sync] = syncs const { status, body } = await request(app.getHttpServer()) - .get('/syncs') + .get('/provider/syncs') .query({ connectionId: sync.connectionId }) .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: `/provider/syncs?connectionId=${sync.connectionId}`, + payload: {}, + htm: 'GET' + }) + ) .send() expect(body).toMatchObject({ @@ -253,32 +322,22 @@ describe('Sync', () => { await syncService.start({ clientId }) const { body } = await request(app.getHttpServer()) - .get('/syncs') + .get('/provider/syncs') .query({ limit: 1 }) .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/syncs?limit=1', + payload: {}, + htm: 'GET' + }) + ) + .send() expect(body.syncs.length).toEqual(1) expect(body.page).toHaveProperty('next') }) - - it('responds the next page of results when cursos is given', async () => { - await syncService.start({ clientId }) - - const { body: pageOne } = await request(app.getHttpServer()) - .get('/syncs') - .query({ limit: 1 }) - .set(REQUEST_HEADER_CLIENT_ID, clientId) - - const { body: pageTwo } = await request(app.getHttpServer()) - .get('/syncs') - .query({ - limit: 1, - cursor: pageOne.page.next - }) - .set(REQUEST_HEADER_CLIENT_ID, clientId) - - expect(pageTwo.syncs.length).toEqual(1) - expect(pageTwo.page).toHaveProperty('next') - }) }) }) diff --git a/apps/vault/src/broker/__test__/e2e/wallet.spec.ts b/apps/vault/src/broker/__test__/e2e/wallet.spec.ts index b827b08d7..6297282ae 100644 --- a/apps/vault/src/broker/__test__/e2e/wallet.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/wallet.spec.ts @@ -1,32 +1,33 @@ -import { ConfigModule } from '@narval/config-module' import { EncryptionModuleOptionProvider } from '@narval/encryption-module' import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' import { HttpStatus, INestApplication } from '@nestjs/common' import { Test, TestingModule } from '@nestjs/testing' import request from 'supertest' -import { load } from '../../../main.config' +import { ClientService } from '../../../client/core/service/client.service' +import { MainModule } from '../../../main.module' +import { ProvisionService } from '../../../provision.service' +import { KeyValueRepository } from '../../../shared/module/key-value/core/repository/key-value.repository' +import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' -import { BrokerModule } from '../../broker.module' import { getExpectedAccount, getExpectedWallet } from '../util/map-db-to-returned' -import { TEST_ACCOUNTS, TEST_CLIENT_ID, TEST_WALLETS } from '../util/mock-data' +import { TEST_ACCOUNTS, TEST_CLIENT_ID, TEST_WALLETS, getJwsd, testClient, testUserPrivateJwk } from '../util/mock-data' describe('Wallet', () => { let app: INestApplication let module: TestingModule let testPrismaService: TestPrismaService + let provisionService: ProvisionService + let clientService: ClientService beforeAll(async () => { module = await Test.createTestingModule({ - imports: [ - LoggerModule.forTest(), - ConfigModule.forRoot({ - load: [load], - isGlobal: true - }), - BrokerModule - ] + imports: [MainModule] }) + .overrideModule(LoggerModule) + .useModule(LoggerModule.forTest()) + .overrideProvider(KeyValueRepository) + .useValue(new InMemoryKeyValueRepository()) .overrideProvider(EncryptionModuleOptionProvider) .useValue({ keyring: getTestRawAesKeyring() @@ -35,13 +36,9 @@ describe('Wallet', () => { app = module.createNestApplication() testPrismaService = module.get(TestPrismaService) - - await app.init() - }) - - beforeEach(async () => { + provisionService = module.get(ProvisionService) + clientService = module.get(ClientService) await testPrismaService.truncateAll() - await testPrismaService.seedBrokerTestData() }) afterAll(async () => { @@ -50,9 +47,30 @@ describe('Wallet', () => { await app.close() }) + beforeEach(async () => { + await testPrismaService.truncateAll() + await provisionService.provision() + + await clientService.save(testClient) + await testPrismaService.seedBrokerTestData() + + await app.init() + }) + describe('GET /wallets', () => { it('returns the list of wallets with accounts for the client', async () => { - const res = await request(app.getHttpServer()).get('/wallets').set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + const res = await request(app.getHttpServer()) + .get('/provider/wallets') + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/wallets', + payload: {}, + htm: 'GET' + }) + ) expect(res.status).toBe(HttpStatus.OK) expect(res.body).toEqual({ @@ -64,7 +82,18 @@ describe('Wallet', () => { }) it("doesn't return private connection information", async () => { - const res = await request(app.getHttpServer()).get('/wallets').set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + const res = await request(app.getHttpServer()) + .get('/provider/wallets') + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/wallets', + payload: {}, + htm: 'GET' + }) + ) expect(res.status).toBe(HttpStatus.OK) @@ -76,16 +105,26 @@ describe('Wallet', () => { } }) - it('returns empty list for unknown client', async () => { - const res = await request(app.getHttpServer()).get('/wallets').set(REQUEST_HEADER_CLIENT_ID, 'unknown-client') + it('returns 404 auth error for unknown client', async () => { + const res = await request(app.getHttpServer()) + .get('/provider/wallets') + .set(REQUEST_HEADER_CLIENT_ID, 'unknown-client') + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/wallets', + payload: {}, + htm: 'GET' + }) + ) + expect(res.status).toBe(HttpStatus.NOT_FOUND) expect(res.body).toEqual({ - wallets: [], - page: { - next: null - } + message: 'Client not found', + statusCode: HttpStatus.NOT_FOUND, + stack: expect.any(String) }) - expect(res.status).toBe(HttpStatus.OK) }) }) @@ -94,8 +133,17 @@ describe('Wallet', () => { // We have 2 wallets in TEST_WALLETS const limit = 1 const res = await request(app.getHttpServer()) - .get('/wallets?limit=1') + .get('/provider/wallets?limit=1') .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/wallets?limit=1', + payload: {}, + htm: 'GET' + }) + ) expect(res.body.wallets).toHaveLength(limit) expect(res.body.page).toHaveProperty('next') @@ -104,17 +152,35 @@ describe('Wallet', () => { it('returns next page of results using cursor', async () => { const firstResponse = await request(app.getHttpServer()) - .get(`/wallets?limit=1`) + .get(`/provider/wallets?limit=1`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/wallets?limit=1', + payload: {}, + htm: 'GET' + }) + ) expect(firstResponse.status).toBe(HttpStatus.OK) const cursor = firstResponse.body.page?.next expect(cursor).toBeDefined() const secondResponse = await request(app.getHttpServer()) - .get(`/wallets?cursor=${cursor}`) + .get(`/provider/wallets?cursor=${cursor}`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: `/provider/wallets?cursor=${cursor}`, + payload: {}, + htm: 'GET' + }) + ) expect(secondResponse.status).toBe(HttpStatus.OK) expect(secondResponse.body.wallets).toHaveLength(1) @@ -123,8 +189,17 @@ describe('Wallet', () => { }) it('handles descending orderBy createdAt parameter correctly', async () => { const res = await request(app.getHttpServer()) - .get('/wallets?orderBy=createdAt&desc=true') + .get('/provider/wallets?orderBy=createdAt&desc=true') .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/wallets?orderBy=createdAt&desc=true', + payload: {}, + htm: 'GET' + }) + ) // Check descending order by createdAt const returnedWallets = res.body.wallets @@ -139,8 +214,17 @@ describe('Wallet', () => { it('throws invalidField orderBy is not a valid field', async () => { const res = await request(app.getHttpServer()) - .get('/wallets?orderBy=invalid-field') + .get('/provider/wallets?orderBy=invalid-field') .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/wallets?orderBy=invalid-field', + payload: {}, + htm: 'GET' + }) + ) expect(res.status).toBe(HttpStatus.UNPROCESSABLE_ENTITY) }) @@ -150,8 +234,17 @@ describe('Wallet', () => { it('returns the wallet details with accounts and addresses', async () => { const wallet = TEST_WALLETS[0] const res = await request(app.getHttpServer()) - .get(`/wallets/${wallet.id}`) + .get(`/provider/wallets/${wallet.id}`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: `/provider/wallets/${wallet.id}`, + payload: {}, + htm: 'GET' + }) + ) expect(res.status).toBe(HttpStatus.OK) @@ -162,8 +255,17 @@ describe('Wallet', () => { it('returns 404 with proper error message for non-existent wallet', async () => { const res = await request(app.getHttpServer()) - .get(`/wallets/non-existent`) + .get(`/provider/wallets/non-existent`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: `/provider/wallets/non-existent`, + payload: {}, + htm: 'GET' + }) + ) expect(res.status).toBe(HttpStatus.NOT_FOUND) }) @@ -171,8 +273,17 @@ describe('Wallet', () => { it('returns 404 when accessing wallet from wrong client', async () => { const wallet = TEST_WALLETS[0] const res = await request(app.getHttpServer()) - .get(`/wallets/${wallet.id}`) + .get(`/provider/wallets/${wallet.id}`) .set(REQUEST_HEADER_CLIENT_ID, 'wrong-client') + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: `/provider/wallets/${wallet.id}`, + payload: {}, + htm: 'GET' + }) + ) expect(res.status).toBe(HttpStatus.NOT_FOUND) }) @@ -183,8 +294,17 @@ describe('Wallet', () => { const wallet = TEST_WALLETS[0] const accounts = TEST_ACCOUNTS.filter((acc) => acc.walletId === wallet.id) const res = await request(app.getHttpServer()) - .get(`/wallets/${wallet.id}/accounts`) + .get(`/provider/wallets/${wallet.id}/accounts`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: `/provider/wallets/${wallet.id}/accounts`, + payload: {}, + htm: 'GET' + }) + ) expect(res.status).toBe(HttpStatus.OK) expect(res.body).toEqual({ @@ -197,8 +317,17 @@ describe('Wallet', () => { it('returns empty accounts array for wallet with no accounts', async () => { const res = await request(app.getHttpServer()) - .get(`/wallets/${TEST_WALLETS[1].id}/accounts`) + .get(`/provider/wallets/${TEST_WALLETS[1].id}/accounts`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: `/provider/wallets/${TEST_WALLETS[1].id}/accounts`, + payload: {}, + htm: 'GET' + }) + ) expect(res.status).toBe(HttpStatus.OK) expect(res.body).toEqual({ diff --git a/apps/vault/src/broker/__test__/util/map-db-to-returned.ts b/apps/vault/src/broker/__test__/util/map-db-to-returned.ts index 7240ba3ba..7dcb27c2a 100644 --- a/apps/vault/src/broker/__test__/util/map-db-to-returned.ts +++ b/apps/vault/src/broker/__test__/util/map-db-to-returned.ts @@ -52,7 +52,13 @@ export const getExpectedAccount = (account: ProviderAccount) => { export const getExpectedWallet = (wallet: ProviderWallet) => { const accounts = TEST_ACCOUNTS.filter((acc) => acc.walletId === wallet.id) const walletConnections = TEST_WALLET_CONNECTIONS.filter((conn) => conn.walletId === wallet.id) - const connections = TEST_CONNECTIONS.filter((conn) => walletConnections.some((wc) => wc.connectionId === conn.id)) + const connections = TEST_CONNECTIONS.filter((conn) => + walletConnections.some((wc) => wc.connectionId === conn.id) + ).map((c) => ({ + ...c, + credentials: c.credentials ? JSON.stringify(c.credentials) : null, + integrity: null + })) const { id, ...walletWithoutId } = wallet return { diff --git a/apps/vault/src/broker/__test__/util/mock-data.ts b/apps/vault/src/broker/__test__/util/mock-data.ts index 114e88ce3..40b5f44dc 100644 --- a/apps/vault/src/broker/__test__/util/mock-data.ts +++ b/apps/vault/src/broker/__test__/util/mock-data.ts @@ -1,3 +1,17 @@ +import { + buildSignerEip191, + hash, + hexToBase64Url, + JwsdHeader, + PrivateKey, + privateKeyToHex, + secp256k1PrivateKeyToJwk, + secp256k1PrivateKeyToPublicJwk, + SigningAlg, + signJwsd +} from '@narval/signature' +import { Client } from '../../../shared/type/domain.type' + const privateKey = { kty: 'OKP', crv: 'Ed25519', @@ -11,6 +25,50 @@ const { d: _d, ...publicKey } = privateKey export const TEST_CLIENT_ID = 'test-client-id' +const PRIVATE_KEY = '0x7cfef3303797cbc7515d9ce22ffe849c701b0f2812f999b0847229c47951fca5' + +export const testUserPrivateJwk = secp256k1PrivateKeyToJwk(PRIVATE_KEY) +export const testUserPublicJWK = secp256k1PrivateKeyToPublicJwk(PRIVATE_KEY) +export const testClient: Client = { + clientId: TEST_CLIENT_ID, + auth: { + disabled: false, + local: { + jwsd: { + maxAge: 600, + requiredComponents: ['htm', 'uri', 'created', 'ath'] + }, + allowedUsersJwksUrl: null, + allowedUsers: [ + { + userId: 'user-1', + publicKey: testUserPublicJWK + } + ] + }, + tokenValidation: { + disabled: true, + url: null, + jwksUrl: null, + verification: { + audience: null, + issuer: 'https://armory.narval.xyz', + maxTokenAge: 300, + requireBoundTokens: false, // DO NOT REQUIRE BOUND TOKENS; we're testing both payload.cnf bound tokens and unbound here. + allowBearerTokens: false, + allowWildcard: [] + }, + pinnedPublicKey: null + } + }, + name: 'test-client', + configurationSource: 'dynamic', + backupPublicKey: null, + baseUrl: null, + createdAt: new Date(), + updatedAt: new Date() +} + export const TEST_CONNECTIONS = [ { id: 'connection-1', @@ -24,7 +82,6 @@ export const TEST_CONNECTIONS = [ publicKey }, status: 'active', - integrity: 'test-integrity-1', createdAt: new Date(), updatedAt: new Date(), revokedAt: null @@ -41,7 +98,6 @@ export const TEST_CONNECTIONS = [ publicKey }, status: 'active', - integrity: 'test-integrity-2', createdAt: new Date(), updatedAt: new Date(), revokedAt: null @@ -141,3 +197,41 @@ export const TEST_ADDRESSES = [ updatedAt: new Date() } ] + +export const getJwsd = async ({ + userPrivateJwk, + baseUrl, + requestUrl, + accessToken, + payload, + htm +}: { + userPrivateJwk: PrivateKey + baseUrl?: string + requestUrl: string + accessToken?: string + payload: object | string + htm?: string +}) => { + const now = Math.floor(Date.now() / 1000) + + const jwsdSigner = buildSignerEip191(await privateKeyToHex(userPrivateJwk)) + const jwsdHeader: JwsdHeader = { + alg: SigningAlg.EIP191, + kid: userPrivateJwk.kid, + typ: 'gnap-binding-jwsd', + htm: htm || 'POST', + uri: `${baseUrl || 'https://vault-test.narval.xyz'}${requestUrl}`, // matches the client baseUrl + request url + created: now, + ath: accessToken ? hexToBase64Url(hash(accessToken)) : undefined + } + + const jwsd = await signJwsd(payload, jwsdHeader, jwsdSigner).then((jws) => { + // Strip out the middle part for size + const parts = jws.split('.') + parts[1] = '' + return parts.join('.') + }) + + return jwsd +} diff --git a/apps/vault/src/broker/broker.module.ts b/apps/vault/src/broker/broker.module.ts index d35f42c13..8bfc7fcd7 100644 --- a/apps/vault/src/broker/broker.module.ts +++ b/apps/vault/src/broker/broker.module.ts @@ -1,5 +1,6 @@ import { HttpModule, OpenTelemetryModule } from '@narval/nestjs-shared' import { Module } from '@nestjs/common' +import { ClientModule } from '../client/client.module' import { DEFAULT_HTTP_MODULE_PROVIDERS } from '../shared/constant' import { PersistenceModule } from '../shared/module/persistence/persistence.module' import { EncryptionKeyService } from '../transit-encryption/core/service/encryption-key.service' @@ -35,7 +36,8 @@ import { WalletRepository } from './persistence/repository/wallet.repository' retry: { retries: 3 } - }) + }), + ClientModule ], controllers: [ ConnectionController, diff --git a/apps/vault/src/broker/core/service/__test__/integration/anchorage-sync.service.spec.ts b/apps/vault/src/broker/core/service/__test__/integration/anchorage-sync.service.spec.ts index c65125f90..df0fdd8a8 100644 --- a/apps/vault/src/broker/core/service/__test__/integration/anchorage-sync.service.spec.ts +++ b/apps/vault/src/broker/core/service/__test__/integration/anchorage-sync.service.spec.ts @@ -1,18 +1,19 @@ -import { ConfigModule } from '@narval/config-module' -import { HttpModule, LoggerModule } from '@narval/nestjs-shared' +import { EncryptionModuleOptionProvider } from '@narval/encryption-module' +import { LoggerModule } from '@narval/nestjs-shared' import { Alg, generateJwk, privateKeyToHex } from '@narval/signature' -import { Test } from '@nestjs/testing' +import { INestApplication } from '@nestjs/common' +import { Test, TestingModule } from '@nestjs/testing' import { v4 as uuid } from 'uuid' -import { load } from '../../../../../main.config' -import { PersistenceModule } from '../../../../../shared/module/persistence/persistence.module' +import { ClientService } from '../../../../../client/core/service/client.service' +import { MainModule } from '../../../../../main.module' +import { ProvisionService } from '../../../../../provision.service' +import { KeyValueRepository } from '../../../../../shared/module/key-value/core/repository/key-value.repository' +import { InMemoryKeyValueRepository } from '../../../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../../../shared/module/persistence/service/test-prisma.service' -import { TransitEncryptionModule } from '../../../../../transit-encryption/transit-encryption.module' -import { AnchorageClient } from '../../../../http/client/anchorage.client' -import { AccountRepository } from '../../../../persistence/repository/account.repository' -import { AddressRepository } from '../../../../persistence/repository/address.repository' -import { ConnectionRepository } from '../../../../persistence/repository/connection.repository' +import { getTestRawAesKeyring } from '../../../../../shared/testing/encryption.testing' +import { testClient } from '../../../../__test__/util/mock-data' import { WalletRepository } from '../../../../persistence/repository/wallet.repository' -import { ActiveConnection, Provider } from '../../../type/connection.type' +import { ActiveConnectionWithCredentials, Provider } from '../../../type/connection.type' import { Account } from '../../../type/indexed-resources.type' import { AccountService } from '../../account.service' import { AddressService } from '../../address.service' @@ -22,43 +23,37 @@ import { WalletService } from '../../wallet.service' import { ANCHORAGE_TEST_API_BASE_URL, setupMockServer } from './mocks/anchorage/server' describe(AnchorageSyncService.name, () => { + let app: INestApplication + let module: TestingModule let testPrismaService: TestPrismaService let anchorageSyncService: AnchorageSyncService let connectionService: ConnectionService - let connection: ActiveConnection + let connection: ActiveConnectionWithCredentials let walletService: WalletRepository let accountService: AccountService let addressService: AddressService + let provisionService: ProvisionService + let clientService: ClientService setupMockServer() const clientId = uuid() - beforeEach(async () => { - const module = await Test.createTestingModule({ - imports: [ - PersistenceModule, - TransitEncryptionModule, - HttpModule.register(), - LoggerModule.forTest(), - ConfigModule.forRoot({ - load: [load], - isGlobal: true - }) - ], - providers: [ - AnchorageSyncService, - AnchorageClient, - ConnectionService, - ConnectionRepository, - WalletService, - WalletRepository, - AccountService, - AccountRepository, - AddressService, - AddressRepository - ] - }).compile() + beforeAll(async () => { + module = await Test.createTestingModule({ + imports: [MainModule] + }) + .overrideModule(LoggerModule) + .useModule(LoggerModule.forTest()) + .overrideProvider(KeyValueRepository) + .useValue(new InMemoryKeyValueRepository()) + .overrideProvider(EncryptionModuleOptionProvider) + .useValue({ + keyring: getTestRawAesKeyring() + }) + .compile() + + app = module.createNestApplication() testPrismaService = module.get(TestPrismaService) anchorageSyncService = module.get(AnchorageSyncService) @@ -66,8 +61,23 @@ describe(AnchorageSyncService.name, () => { walletService = module.get(WalletService) accountService = module.get(AccountService) addressService = module.get(AddressService) + provisionService = module.get(ProvisionService) + clientService = module.get(ClientService) + + await testPrismaService.truncateAll() + }) + afterAll(async () => { await testPrismaService.truncateAll() + await module.close() + await app.close() + }) + + beforeEach(async () => { + await testPrismaService.truncateAll() + + await provisionService.provision() + await clientService.save(testClient) connection = await connectionService.create(clientId, { connectionId: uuid(), @@ -78,6 +88,8 @@ describe(AnchorageSyncService.name, () => { privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) } }) + + await app.init() }) describe('syncWallets', () => { diff --git a/apps/vault/src/broker/core/service/anchorage-sync.service.ts b/apps/vault/src/broker/core/service/anchorage-sync.service.ts index 57c8b41f9..ea2de0841 100644 --- a/apps/vault/src/broker/core/service/anchorage-sync.service.ts +++ b/apps/vault/src/broker/core/service/anchorage-sync.service.ts @@ -6,7 +6,7 @@ import { v4 as uuid } from 'uuid' import { AnchorageClient } from '../../http/client/anchorage.client' import { BrokerException } from '../exception/broker.exception' import { ConnectionInvalidException } from '../exception/connection-invalid.exception' -import { ActiveConnection, Provider } from '../type/connection.type' +import { ActiveConnection, ActiveConnectionWithCredentials, Provider } from '../type/connection.type' import { Account, Address, Wallet } from '../type/indexed-resources.type' import { AccountService } from './account.service' import { AddressService } from './address.service' @@ -22,13 +22,13 @@ export class AnchorageSyncService { private readonly logger: LoggerService ) {} - async sync(connection: ActiveConnection): Promise { + async sync(connection: ActiveConnectionWithCredentials): Promise { await this.syncWallets(connection) await this.syncAccounts(connection) await this.syncAddresses(connection) } - async syncWallets(connection: ActiveConnection) { + async syncWallets(connection: ActiveConnectionWithCredentials) { this.logger.log('Sync Anchorage wallets', { connectionId: connection.credentials, clientId: connection.clientId, @@ -60,7 +60,7 @@ export class AnchorageSyncService { const wallets: Wallet[] = missingAnchorageVaults.map((vault) => ({ accounts: [], clientId: connection.clientId, - connections: [connection], + connections: [ActiveConnection.parse(connection)], createdAt: now, externalId: vault.vaultId, label: vault.name, @@ -74,7 +74,7 @@ export class AnchorageSyncService { return wallets } - async syncAccounts(connection: ActiveConnection) { + async syncAccounts(connection: ActiveConnectionWithCredentials) { this.logger.log('Sync Anchorage accounts', { connectionId: connection.credentials, clientId: connection.clientId, @@ -150,7 +150,7 @@ export class AnchorageSyncService { return accounts } - async syncAddresses(connection: ActiveConnection) { + async syncAddresses(connection: ActiveConnectionWithCredentials) { this.logger.log('Sync Anchorage addresses', { connectionId: connection.credentials, clientId: connection.clientId, @@ -235,7 +235,9 @@ export class AnchorageSyncService { return addresses } - private validateConnection(connection: ActiveConnection): asserts connection is ActiveConnection & { + private validateConnection( + connection: ActiveConnectionWithCredentials + ): asserts connection is ActiveConnectionWithCredentials & { url: string credentials: { apiKey: string @@ -264,7 +266,7 @@ export class AnchorageSyncService { }) } - if (!connection.credentials.apiKey && !connection.credentials.privateKey) { + if (!connection.credentials?.apiKey && !connection.credentials?.privateKey) { throw new ConnectionInvalidException({ message: 'Cannot sync without API key and/or signing key', context diff --git a/apps/vault/src/broker/core/service/connection.service.ts b/apps/vault/src/broker/core/service/connection.service.ts index 513c57067..68cf21d11 100644 --- a/apps/vault/src/broker/core/service/connection.service.ts +++ b/apps/vault/src/broker/core/service/connection.service.ts @@ -23,14 +23,15 @@ import { ConnectionInvalidStatusException } from '../exception/connection-invali import { NotFoundException } from '../exception/not-found.exception' import { UpdateException } from '../exception/update.exception' import { - ActiveConnection, + ActiveConnectionWithCredentials, AnchorageCredentials, Connection, ConnectionStatus, + ConnectionWithCredentials, CreateConnection, CreateCredentials, InitiateConnection, - PendingConnection, + PendingConnectionWithCredentials, Provider, UpdateConnection, isActiveConnection, @@ -45,7 +46,7 @@ export class ConnectionService { private readonly encryptionKeyService: EncryptionKeyService ) {} - async initiate(clientId: string, input: InitiateConnection): Promise { + async initiate(clientId: string, input: InitiateConnection): Promise { const now = new Date() const privateKey = await this.generatePrivateKey() const encryptionKey = await this.encryptionKeyService.generate(clientId) @@ -61,9 +62,7 @@ export class ConnectionService { encryptionPublicKey: encryptionKey.publicKey, status: ConnectionStatus.PENDING, revokedAt: undefined, - updatedAt: now, - // TODO: (@wcalderipe, 05/12/24): HMAC hash and signature. - integrity: 'TODO INITIATE CONNECTION' + updatedAt: now } await this.connectionRepository.create(connection) @@ -71,7 +70,6 @@ export class ConnectionService { return { clientId: connection.clientId, connectionId: connection.connectionId, - integrity: connection.integrity, createdAt: connection.createdAt, updatedAt: connection.updatedAt, credentials: { @@ -89,7 +87,7 @@ export class ConnectionService { return await generateJwk(Alg.EDDSA) } - async create(clientId: string, input: CreateConnection): Promise { + async create(clientId: string, input: CreateConnection): Promise { // If a connection ID is provided, check if the connection already exists. // If it does, activate the connection. if (input.connectionId) { @@ -114,7 +112,10 @@ export class ConnectionService { throw new ConnectionInvalidCredentialsException() } - private async createActiveConnection(clientId: string, input: CreateConnection): Promise { + private async createActiveConnection( + clientId: string, + input: CreateConnection + ): Promise { // By this point, the credentials should have already been decrypted and // decoded. if (!input.credentials) { @@ -139,9 +140,7 @@ export class ConnectionService { url: input.url, revokedAt: undefined, status: ConnectionStatus.ACTIVE, - updatedAt: now, - // TODO: (@wcalderipe, 05/12/24): HMAC hash and signature. - integrity: 'TODO CREATE CONNECTION' + updatedAt: now } await this.connectionRepository.create(connection) @@ -152,33 +151,36 @@ export class ConnectionService { throw new ConnectionInvalidPrivateKeyException() } - async activate(clientId: string, input: SetRequired): Promise { - const pendingConnection = await this.connectionRepository.findById(clientId, input.connectionId) + async activate( + clientId: string, + input: SetRequired + ): Promise { + const pendingConnection = await this.connectionRepository.findById(clientId, input.connectionId, true) - if (isPendingConnection(pendingConnection)) { + if (isPendingConnection(pendingConnection) && pendingConnection.credentials) { // TODO: Ensure the connection status is pending. const now = new Date() const credentials = await this.getInputCredentials(clientId, input) - const connection = { + const connection: ActiveConnectionWithCredentials = { + ...pendingConnection, clientId, connectionId: input.connectionId, status: ConnectionStatus.ACTIVE, label: input.label, url: input.url, updatedAt: now, + createdAt: pendingConnection.createdAt, credentials: { ...pendingConnection.credentials, apiKey: credentials.apiKey - }, - // TODO: (@wcalderipe, 05/12/24): HMAC hash and signature. - integrity: 'TODO ACTIVATE CONNECTION' + } } await this.connectionRepository.update(connection) - return { ...pendingConnection, ...connection } + return connection } throw new ConnectionInvalidStatusException({ @@ -265,9 +267,11 @@ export class ConnectionService { } async update(input: UpdateConnection): Promise { - const connection = await this.connectionRepository.findById(input.clientId, input.connectionId) + const connection = await this.connectionRepository.findById(input.clientId, input.connectionId, true) const hasCredentials = input.credentials || input.encryptedCredentials const update = { + ...connection, + createdAt: connection.createdAt, // must include the existing createdAt value for integrity verification ...input, ...(hasCredentials ? { credentials: await this.parseInputCredentials(input.clientId, connection.provider, input) } @@ -324,8 +328,12 @@ export class ConnectionService { return false } - async findById(clientId: string, connectionId: string): Promise { - return this.connectionRepository.findById(clientId, connectionId) + async findById( + clientId: string, + connectionId: string, + includeCredentials?: T + ): Promise { + return this.connectionRepository.findById(clientId, connectionId, includeCredentials) } async findAll(clientId: string, options?: FilterOptions): Promise { @@ -350,6 +358,7 @@ export class ConnectionService { if (isActiveConnection(connection) || isPendingConnection(connection)) { await this.connectionRepository.update({ + ...connection, clientId, connectionId: connectionId, credentials: null, diff --git a/apps/vault/src/broker/core/service/proxy.service.ts b/apps/vault/src/broker/core/service/proxy.service.ts index 34ede96f3..2b4f6b532 100644 --- a/apps/vault/src/broker/core/service/proxy.service.ts +++ b/apps/vault/src/broker/core/service/proxy.service.ts @@ -22,7 +22,7 @@ export class ProxyService { clientId: string, { connectionId, body, endpoint, method }: RawRequestOptions ): Promise<{ data: any; code: HttpStatus; headers: Record }> { - const connection = await this.connectionRepository.findById(clientId, connectionId) + const connection = await this.connectionRepository.findById(clientId, connectionId, true) if (connection.status !== ConnectionStatus.ACTIVE) { throw new ConnectionInvalidException({ message: 'Connection is not active', diff --git a/apps/vault/src/broker/core/service/sync.service.ts b/apps/vault/src/broker/core/service/sync.service.ts index cb4c59b68..f8db74489 100644 --- a/apps/vault/src/broker/core/service/sync.service.ts +++ b/apps/vault/src/broker/core/service/sync.service.ts @@ -2,7 +2,7 @@ import { PaginatedResult, TraceService } from '@narval/nestjs-shared' import { Inject, Injectable } from '@nestjs/common/decorators' import { v4 as uuid } from 'uuid' import { FindAllPaginatedOptions, SyncRepository } from '../../persistence/repository/sync.repository' -import { ConnectionStatus, isActiveConnection } from '../type/connection.type' +import { ActiveConnectionWithCredentials, ConnectionStatus, isActiveConnection } from '../type/connection.type' import { StartSync, Sync, SyncStatus } from '../type/sync.type' import { AnchorageSyncService } from './anchorage-sync.service' import { ConnectionService } from './connection.service' @@ -24,7 +24,7 @@ export class SyncService { if (input.connectionId) { const syncId = uuid() - const connection = await this.connectionService.findById(input.clientId, input.connectionId) + const connection = await this.connectionService.findById(input.clientId, input.connectionId, true) const sync = await this.syncRepository.create( this.toProcessingSync({ @@ -69,8 +69,13 @@ export class SyncService { ) await Promise.allSettled( - connections.filter(isActiveConnection).map((connection) => { - this.anchorageSyncService.sync(connection) + connections.map(async (connection) => { + const connectionWithCredentials = await this.connectionService.findById( + input.clientId, + connection.connectionId, + true + ) + this.anchorageSyncService.sync(connectionWithCredentials as ActiveConnectionWithCredentials) }) ) .then(async () => { diff --git a/apps/vault/src/broker/core/type/connection.type.ts b/apps/vault/src/broker/core/type/connection.type.ts index 4e0482c95..e773babbc 100644 --- a/apps/vault/src/broker/core/type/connection.type.ts +++ b/apps/vault/src/broker/core/type/connection.type.ts @@ -18,8 +18,6 @@ export const BaseConnection = z.object({ clientId: z.string(), connectionId: z.string(), createdAt: z.date(), - credentials: z.unknown().nullish(), - integrity: z.string(), label: z.string().optional(), provider: z.nativeEnum(Provider), revokedAt: z.date().optional(), @@ -43,10 +41,13 @@ export type ActiveAnchorageCredentials = z.infer +export const ActiveConnectionWithCredentials = ActiveConnection.extend({ + credentials: ActiveAnchorageCredentials +}) +export type ActiveConnectionWithCredentials = z.infer const RevokedConnection = BaseConnection.extend({ status: z.literal(ConnectionStatus.REVOKED), @@ -54,17 +55,31 @@ const RevokedConnection = BaseConnection.extend({ revokedAt: z.date() }) export type RevokedConnection = z.infer +export const RevokedConnectionWithCredentials = RevokedConnection.extend({ + credentials: z.null() +}) +export type RevokedConnectionWithCredentials = z.infer export const PendingConnection = BaseConnection.extend({ status: z.literal(ConnectionStatus.PENDING), provider: z.literal(Provider.ANCHORAGE), - credentials: AnchorageCredentials, encryptionPublicKey: rsaPublicKeySchema.optional() }) export type PendingConnection = z.infer +export const PendingConnectionWithCredentials = PendingConnection.extend({ + credentials: AnchorageCredentials.nullable() +}) +export type PendingConnectionWithCredentials = z.infer export const Connection = z.discriminatedUnion('status', [ActiveConnection, RevokedConnection, PendingConnection]) export type Connection = z.infer +// This is the only type that should be including Credentials on it. The rest do not, so we don't accidentally use them. +export const ConnectionWithCredentials = z.discriminatedUnion('status', [ + ActiveConnectionWithCredentials, + RevokedConnectionWithCredentials, + PendingConnectionWithCredentials +]) +export type ConnectionWithCredentials = z.infer export const InitiateConnection = z.object({ connectionId: z.string().optional(), @@ -94,7 +109,6 @@ export const UpdateConnection = z.object({ connectionId: z.string(), credentials: CreateCredentials.nullish(), encryptedCredentials: z.string().optional().describe('RSA encrypted JSON string of the credentials'), - integrity: z.string().optional(), label: z.string().optional(), status: z.nativeEnum(ConnectionStatus).optional(), updatedAt: z.date().optional(), @@ -115,3 +129,6 @@ export const isRevokedConnection = (connection: Connection): connection is Revok } export const PublicConnection = BaseConnection.pick({ connectionId: true, status: true, label: true, provider: true }) export type PublicConnection = z.infer + +// Connection is "special". It has encrypted data that must be queried more specifically, therefore we will separate the +// types to have one that includes "encrypted" data and another that does not. diff --git a/apps/vault/src/broker/http/rest/controller/account.controller.ts b/apps/vault/src/broker/http/rest/controller/account.controller.ts index 3b59fa3b2..257d03646 100644 --- a/apps/vault/src/broker/http/rest/controller/account.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/account.controller.ts @@ -3,6 +3,8 @@ import { Controller, Get, HttpStatus, Param } from '@nestjs/common' import { ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../shared/decorator/client-id.decorator' +import { PermissionGuard } from '../../../../shared/decorator/permission-guard.decorator' +import { VaultPermission } from '../../../../shared/type/domain.type' import { AccountService } from '../../../core/service/account.service' import { AccountDto } from '../dto/response/account.dto' import { PaginatedAccountsDto } from '../dto/response/paginated-accounts.dto' @@ -17,6 +19,7 @@ export class AccountController { constructor(private readonly accountService: AccountService) {} @Get() + @PermissionGuard(VaultPermission.CONNECTION_READ) @ApiOperation({ summary: 'List the client accounts' }) @@ -37,6 +40,7 @@ export class AccountController { } @Get(':accountId') + @PermissionGuard(VaultPermission.CONNECTION_READ) @ApiOperation({ summary: 'Get a specific account by ID' }) @@ -58,6 +62,7 @@ export class AccountController { } @Get(':accountId/addresses') + @PermissionGuard(VaultPermission.CONNECTION_READ) @ApiOperation({ summary: 'List addresses for a specific account' }) diff --git a/apps/vault/src/broker/http/rest/controller/address.controller.ts b/apps/vault/src/broker/http/rest/controller/address.controller.ts index b14d70b43..d1fcdebf3 100644 --- a/apps/vault/src/broker/http/rest/controller/address.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/address.controller.ts @@ -2,6 +2,8 @@ import { Paginated, PaginationOptions, PaginationParam } from '@narval/nestjs-sh import { Controller, Get, HttpStatus, Param } from '@nestjs/common' import { ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../shared/decorator/client-id.decorator' +import { PermissionGuard } from '../../../../shared/decorator/permission-guard.decorator' +import { VaultPermission } from '../../../../shared/type/domain.type' import { AddressService } from '../../../core/service/address.service' import { AddressDto } from '../dto/response/address.dto' import { PaginatedAddressesDto } from '../dto/response/paginated-addresses.dto' @@ -15,6 +17,7 @@ export class AddressController { constructor(private readonly addressService: AddressService) {} @Get() + @PermissionGuard(VaultPermission.CONNECTION_READ) @ApiOperation({ summary: 'List the client addresss' }) @@ -35,6 +38,7 @@ export class AddressController { } @Get(':addressId') + @PermissionGuard(VaultPermission.CONNECTION_READ) @ApiOperation({ summary: 'Get a specific address by ID' }) diff --git a/apps/vault/src/broker/http/rest/controller/connection.controller.ts b/apps/vault/src/broker/http/rest/controller/connection.controller.ts index d0ae2b36b..7353f34f6 100644 --- a/apps/vault/src/broker/http/rest/controller/connection.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/connection.controller.ts @@ -2,6 +2,8 @@ import { Paginated, PaginationOptions, PaginationParam } from '@narval/nestjs-sh import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Patch, Post } from '@nestjs/common' import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../shared/decorator/client-id.decorator' +import { PermissionGuard } from '../../../../shared/decorator/permission-guard.decorator' +import { VaultPermission } from '../../../../shared/type/domain.type' import { AccountService } from '../../../core/service/account.service' import { ConnectionService } from '../../../core/service/connection.service' import { WalletService } from '../../../core/service/wallet.service' @@ -28,6 +30,7 @@ export class ConnectionController { ) {} @Post('/initiate') + @PermissionGuard(VaultPermission.CONNECTION_WRITE) @ApiOperation({ summary: 'Initiate a new provider connection', description: @@ -45,6 +48,7 @@ export class ConnectionController { } @Post() + @PermissionGuard(VaultPermission.CONNECTION_WRITE) @ApiOperation({ summary: 'Store a provider connection securely', description: @@ -62,6 +66,7 @@ export class ConnectionController { } @Delete(':connectionId') + @PermissionGuard(VaultPermission.CONNECTION_WRITE) @ApiOperation({ summary: 'Revoke an existing connection', description: @@ -77,6 +82,7 @@ export class ConnectionController { } @Get() + @PermissionGuard(VaultPermission.CONNECTION_READ) @ApiOperation({ summary: 'List all connections', description: 'This endpoint retrieves a list of all connections associated with the client.' @@ -100,6 +106,7 @@ export class ConnectionController { } @Get(':connectionId') + @PermissionGuard(VaultPermission.CONNECTION_READ) @ApiOperation({ summary: 'Retrieve a specific connection by ID', description: @@ -117,6 +124,7 @@ export class ConnectionController { } @Patch(':connectionId') + @PermissionGuard(VaultPermission.CONNECTION_WRITE) @ApiOperation({ summary: 'Update a specific connection by ID', description: @@ -142,6 +150,7 @@ export class ConnectionController { } @Get(':connectionId/wallets') + @PermissionGuard(VaultPermission.CONNECTION_READ) @ApiOperation({ summary: 'List wallets for a specific connection', description: 'This endpoint retrieves a list of wallets associated with a specific connection.' @@ -164,6 +173,7 @@ export class ConnectionController { } @Get(':connectionId/accounts') + @PermissionGuard(VaultPermission.CONNECTION_READ) @ApiOperation({ summary: 'List accounts for a specific connection', description: 'This endpoint retrieves a list of accounts associated with a specific connection.' diff --git a/apps/vault/src/broker/http/rest/controller/proxy.controller.ts b/apps/vault/src/broker/http/rest/controller/proxy.controller.ts index d8eec99a4..a45f8478b 100644 --- a/apps/vault/src/broker/http/rest/controller/proxy.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/proxy.controller.ts @@ -3,6 +3,8 @@ import { ApiHeader, ApiOperation, ApiParam, ApiResponse } from '@nestjs/swagger' import { Request, Response } from 'express' import { ClientId } from '../../../../shared/decorator/client-id.decorator' import { ConnectionId } from '../../../../shared/decorator/connection-id.decorator' +import { PermissionGuard } from '../../../../shared/decorator/permission-guard.decorator' +import { VaultPermission } from '../../../../shared/type/domain.type' import { ProxyRequestException } from '../../../core/exception/proxy-request.exception' import { HttpMethod } from '../../../core/lib/anchorage-request-builder' import { ProxyService } from '../../../core/service/proxy.service' @@ -15,6 +17,7 @@ export class ProxyController { constructor(private readonly proxyService: ProxyService) {} @All(':endpoint(*)') + @PermissionGuard(VaultPermission.CONNECTION_READ) @ApiHeader({ name: 'x-connection-id', required: true, diff --git a/apps/vault/src/broker/http/rest/controller/sync.controller.ts b/apps/vault/src/broker/http/rest/controller/sync.controller.ts index 696a5afb4..6d0fc3191 100644 --- a/apps/vault/src/broker/http/rest/controller/sync.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/sync.controller.ts @@ -2,6 +2,8 @@ import { Paginated, PaginationOptions, PaginationParam } from '@narval/nestjs-sh import { Body, Controller, Get, HttpStatus, Param, Post, Query } from '@nestjs/common' import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../shared/decorator/client-id.decorator' +import { PermissionGuard } from '../../../../shared/decorator/permission-guard.decorator' +import { VaultPermission } from '../../../../shared/type/domain.type' import { SyncService } from '../../../core/service/sync.service' import { StartSyncDto } from '../dto/request/start-sync.dto' import { PaginatedSyncsDto } from '../dto/response/paginated-syncs.dto' @@ -17,6 +19,7 @@ export class SyncController { constructor(private readonly syncService: SyncService) {} @Post() + @PermissionGuard(VaultPermission.CONNECTION_READ) // Sync is a read operation even though it's a POST. @ApiOperation({ summary: 'Start a synchronization process', description: 'This endpoint starts synchronization process for the client.' @@ -31,6 +34,7 @@ export class SyncController { } @Get(':syncId') + @PermissionGuard(VaultPermission.CONNECTION_READ) @ApiOperation({ summary: 'Retrieve a specific synchronization process by ID', description: @@ -48,6 +52,7 @@ export class SyncController { } @Get() + @PermissionGuard(VaultPermission.CONNECTION_READ) @ApiOperation({ summary: 'Retrieve a list of synchronization processes', description: diff --git a/apps/vault/src/broker/http/rest/controller/wallet.controller.ts b/apps/vault/src/broker/http/rest/controller/wallet.controller.ts index b93abf402..4d08f948f 100644 --- a/apps/vault/src/broker/http/rest/controller/wallet.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/wallet.controller.ts @@ -2,6 +2,8 @@ import { Paginated, PaginationOptions, PaginationParam } from '@narval/nestjs-sh import { Controller, Get, HttpStatus, Param } from '@nestjs/common' import { ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../shared/decorator/client-id.decorator' +import { PermissionGuard } from '../../../../shared/decorator/permission-guard.decorator' +import { VaultPermission } from '../../../../shared/type/domain.type' import { AccountService } from '../../../core/service/account.service' import { WalletService } from '../../../core/service/wallet.service' import { PaginatedAccountsDto } from '../dto/response/paginated-accounts.dto' @@ -20,6 +22,7 @@ export class WalletController { ) {} @Get() + @PermissionGuard(VaultPermission.CONNECTION_READ) @ApiOperation({ summary: 'List the client wallets' }) @@ -40,6 +43,7 @@ export class WalletController { } @Get(':walletId') + @PermissionGuard(VaultPermission.CONNECTION_READ) @ApiOperation({ summary: 'Get a specific wallet by ID' }) @@ -61,6 +65,7 @@ export class WalletController { } @Get(':walletId/accounts') + @PermissionGuard(VaultPermission.CONNECTION_READ) @ApiOperation({ summary: 'List accounts for a specific wallet' }) diff --git a/apps/vault/src/broker/http/rest/dto/response/connection-list.dto.ts b/apps/vault/src/broker/http/rest/dto/response/connection-list.dto.ts index ec52976a5..ee4ca2973 100644 --- a/apps/vault/src/broker/http/rest/dto/response/connection-list.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/connection-list.dto.ts @@ -2,6 +2,4 @@ import { createZodDto } from 'nestjs-zod' import { z } from 'zod' import { BaseConnection } from '../../../../core/type/connection.type' -export class ConnectionListDto extends createZodDto( - z.object({ connections: z.array(BaseConnection.omit({ credentials: true })) }) -) {} +export class ConnectionListDto extends createZodDto(z.object({ connections: z.array(BaseConnection) })) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/connection.dto.ts b/apps/vault/src/broker/http/rest/dto/response/connection.dto.ts index 4f6b7f0ec..cb861b25a 100644 --- a/apps/vault/src/broker/http/rest/dto/response/connection.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/connection.dto.ts @@ -1,4 +1,4 @@ import { createZodDto } from 'nestjs-zod' import { BaseConnection } from '../../../../core/type/connection.type' -export class ConnectionDto extends createZodDto(BaseConnection.omit({ credentials: true })) {} +export class ConnectionDto extends createZodDto(BaseConnection) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/paginated-connections.dto.ts b/apps/vault/src/broker/http/rest/dto/response/paginated-connections.dto.ts index f01f6e24d..d9bad9785 100644 --- a/apps/vault/src/broker/http/rest/dto/response/paginated-connections.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/paginated-connections.dto.ts @@ -5,7 +5,7 @@ import { BaseConnection } from '../../../../core/type/connection.type' export class PaginatedConnectionsDto extends createZodDto( z.object({ - connections: z.array(BaseConnection.omit({ credentials: true })), + connections: z.array(BaseConnection), page: Page }) ) {} diff --git a/apps/vault/src/broker/persistence/connection.seed.ts b/apps/vault/src/broker/persistence/connection.seed.ts index 1bf540b0c..1277fee00 100644 --- a/apps/vault/src/broker/persistence/connection.seed.ts +++ b/apps/vault/src/broker/persistence/connection.seed.ts @@ -4,7 +4,7 @@ import { privateKeyToJwk } from '@narval/signature' import { Injectable } from '@nestjs/common' import { ed25519PublicKeySchema } from 'packages/signature/src/lib/schemas' import { SeedService } from '../../shared/module/persistence/service/seed.service' -import { Connection } from '../core/type/connection.type' +import { ConnectionWithCredentials } from '../core/type/connection.type' import { ConnectionRepository } from './repository/connection.repository' const NARVAL_DEV_CLIENT = 'narval-dev-client' @@ -18,7 +18,7 @@ export class ConnectionSeedService extends SeedService { super() } - async createConnection(connection: Connection) { + async createConnection(connection: ConnectionWithCredentials) { const createdConnection = await this.connectionRepository.create(connection) return createdConnection } @@ -35,7 +35,6 @@ export class ConnectionSeedService extends SeedService { privateKey, publicKey }, - integrity: 'sample-integrity-hash', label: 'Anchorage Staging - Narval Dev Client', provider: 'anchorage', url: 'https://api.anchorage-staging.com', diff --git a/apps/vault/src/broker/persistence/repository/connection.repository.ts b/apps/vault/src/broker/persistence/repository/connection.repository.ts index bafe39cab..60faf64a3 100644 --- a/apps/vault/src/broker/persistence/repository/connection.repository.ts +++ b/apps/vault/src/broker/persistence/repository/connection.repository.ts @@ -1,22 +1,22 @@ import { PaginatedResult, PaginationOptions, getPaginatedResult, getPaginationQuery } from '@narval/nestjs-shared' import { HttpStatus, Injectable } from '@nestjs/common' -import { Prisma, ProviderConnection } from '@prisma/client/vault' -import { omit } from 'lodash' +import { ProviderConnection } from '@prisma/client/vault' import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' import { BrokerException } from '../../core/exception/broker.exception' import { ConnectionParseException } from '../../core/exception/connection-parse.exception' import { NotFoundException } from '../../core/exception/not-found.exception' -import { Connection, ConnectionStatus } from '../../core/type/connection.type' +import { Connection, ConnectionStatus, ConnectionWithCredentials } from '../../core/type/connection.type' export type UpdateConnection = { clientId: string connectionId: string credentials?: unknown | null - integrity?: string label?: string + provider?: string revokedAt?: Date status?: ConnectionStatus updatedAt?: Date + createdAt: Date url?: string } @@ -28,6 +28,20 @@ export type FilterOptions = { export type FindAllPaginatedOptions = PaginationOptions & FilterOptions +export const connectionSelectWithoutCredentials = { + id: true, + clientId: true, + provider: true, + url: true, + label: true, + credentials: false, // DO NOT INCLUDE CREDENTIALS + status: true, + integrity: true, + createdAt: true, + updatedAt: true, + revokedAt: true +} + @Injectable() export class ConnectionRepository { constructor(private prismaService: PrismaService) {} @@ -35,10 +49,13 @@ export class ConnectionRepository { static getCursorOrderColumns(): Array { return ['createdAt'] } - - static parseModel(model?: ProviderConnection | null): Connection { - const parse = Connection.safeParse({ + static parseModel( + model?: Partial | null, + includeCredentials?: T + ): T extends true ? ConnectionWithCredentials : Connection { + const connectionData = { ...model, + credentials: model?.credentials ? JSON.parse(model.credentials) : null, connectionId: model?.id, // Prisma always returns null for optional fields that don't have a // value, rather than undefined. This is actually by design and aligns @@ -46,10 +63,13 @@ export class ConnectionRepository { label: model?.label || undefined, revokedAt: model?.revokedAt || undefined, url: model?.url || undefined - }) + } + + const schema = includeCredentials ? ConnectionWithCredentials : Connection + const parse = schema.safeParse(connectionData) if (parse.success) { - return parse.data + return parse.data as T extends true ? ConnectionWithCredentials : Connection } throw new ConnectionParseException({ @@ -57,43 +77,26 @@ export class ConnectionRepository { }) } - static parseEntity(entity: Connection): ProviderConnection { - return { - clientId: entity.clientId, - createdAt: entity.createdAt, - credentials: entity.credentials ? entity.credentials : Prisma.JsonNull, - id: entity.connectionId, - integrity: entity.integrity, - label: entity.label || null, - provider: entity.provider, - revokedAt: entity.revokedAt || null, - status: entity.status, - updatedAt: entity.updatedAt, - url: entity.url || null - } - } - - async create(connection: Connection): Promise { + async create(connection: ConnectionWithCredentials): Promise { const data = { - clientId: connection.clientId, - createdAt: connection.createdAt, - credentials: connection.credentials !== null ? connection.credentials : Prisma.JsonNull, id: connection.connectionId, - integrity: connection.integrity, - label: connection.label, + clientId: connection.clientId, + credentials: connection.credentials !== null ? JSON.stringify(connection.credentials) : null, + label: connection.label || null, provider: connection.provider, status: connection.status, - updatedAt: connection.updatedAt, - url: connection.url + url: connection.url || null, + createdAt: connection.createdAt, + updatedAt: connection.updatedAt } await this.prismaService.providerConnection.upsert({ - where: { id: connection.connectionId }, + where: { id: data.id }, create: data, - update: omit(data, 'id') + update: data }) - return connection + return Connection.parse(connection) } async update(updateConnection: UpdateConnection): Promise { @@ -110,26 +113,33 @@ export class ConnectionRepository { clientId: updateConnection.clientId }, data: { - credentials: updateConnection.credentials !== null ? updateConnection.credentials : Prisma.JsonNull, - integrity: updateConnection.integrity, + id: updateConnection.connectionId, + clientId: updateConnection.clientId, + provider: updateConnection.provider, + url: updateConnection.url, label: updateConnection.label, - revokedAt: updateConnection.revokedAt, + credentials: updateConnection.credentials !== null ? JSON.stringify(updateConnection.credentials) : null, status: updateConnection.status, - updatedAt: updateConnection.updatedAt, - url: updateConnection.url + createdAt: updateConnection.createdAt, + revokedAt: updateConnection.revokedAt, + updatedAt: updateConnection.updatedAt } }) return true } - async findById(clientId: string, connectionId: string): Promise { + async findById( + clientId: string, + connectionId: string, + includeCredentials?: T + ): Promise { const model = await this.prismaService.providerConnection.findUnique({ where: { clientId, id: connectionId } }) if (model) { - return ConnectionRepository.parseModel(model) + return ConnectionRepository.parseModel(model, includeCredentials) } throw new NotFoundException({ context: { clientId, connectionId } }) @@ -137,13 +147,14 @@ export class ConnectionRepository { async findAll(clientId: string, options?: FilterOptions): Promise { const models = await this.prismaService.providerConnection.findMany({ + select: connectionSelectWithoutCredentials, where: { clientId, status: options?.filters?.status } }) - return models.map(ConnectionRepository.parseModel) + return models.map((model) => ConnectionRepository.parseModel(model, false)) } async findAllPaginated(clientId: string, options?: FindAllPaginatedOptions): Promise> { @@ -153,6 +164,7 @@ export class ConnectionRepository { }) const models = await this.prismaService.providerConnection.findMany({ + select: connectionSelectWithoutCredentials, where: { clientId, status: options?.filters?.status @@ -163,7 +175,7 @@ export class ConnectionRepository { const { data, page } = getPaginatedResult({ items: models, options: pagination }) return { - data: data.map(ConnectionRepository.parseModel), + data: data.map((model) => ConnectionRepository.parseModel(model, false)), page } } diff --git a/apps/vault/src/broker/persistence/repository/wallet.repository.ts b/apps/vault/src/broker/persistence/repository/wallet.repository.ts index 93f823961..9eca94498 100644 --- a/apps/vault/src/broker/persistence/repository/wallet.repository.ts +++ b/apps/vault/src/broker/persistence/repository/wallet.repository.ts @@ -11,10 +11,10 @@ import { PrismaService } from '../../../shared/module/persistence/service/prisma import { NotFoundException } from '../../core/exception/not-found.exception' import { Account, Wallet } from '../../core/type/indexed-resources.type' import { AccountRepository } from './account.repository' -import { ConnectionRepository } from './connection.repository' +import { ConnectionRepository, connectionSelectWithoutCredentials } from './connection.repository' type ProviderWalletsAndRelations = ProviderWallet & { - connections: { connection: ProviderConnection }[] + connections: { connection: Partial }[] accounts: Array< ProviderAccount & { addresses: ProviderAddress[] @@ -85,7 +85,9 @@ export class WalletRepository { }, connections: { include: { - connection: true + connection: { + select: connectionSelectWithoutCredentials + } } } }, @@ -110,7 +112,9 @@ export class WalletRepository { }, connections: { include: { - connection: true + connection: { + select: connectionSelectWithoutCredentials + } } } } @@ -155,7 +159,9 @@ export class WalletRepository { }, connections: { include: { - connection: true + connection: { + select: connectionSelectWithoutCredentials + } } } }, @@ -205,7 +211,9 @@ export class WalletRepository { }, connections: { include: { - connection: true + connection: { + select: connectionSelectWithoutCredentials + } } } } @@ -230,7 +238,13 @@ export class WalletRepository { }, ...pagination }, - connections: true + connections: { + include: { + connection: { + select: connectionSelectWithoutCredentials + } + } + } } }) if (!wallet) { diff --git a/apps/vault/src/client/__test__/e2e/client.spec.ts b/apps/vault/src/client/__test__/e2e/client.spec.ts index 9650f5bf9..50900972a 100644 --- a/apps/vault/src/client/__test__/e2e/client.spec.ts +++ b/apps/vault/src/client/__test__/e2e/client.spec.ts @@ -1,6 +1,5 @@ -import { ConfigModule, ConfigService } from '@narval/config-module' import { EncryptionModuleOptionProvider } from '@narval/encryption-module' -import { LoggerModule, secret } from '@narval/nestjs-shared' +import { LoggerModule } from '@narval/nestjs-shared' import { Alg, PrivateKey, @@ -13,12 +12,11 @@ import { HttpStatus, INestApplication } from '@nestjs/common' import { Test, TestingModule } from '@nestjs/testing' import request from 'supertest' import { v4 as uuid } from 'uuid' -import { Config, load } from '../../../main.config' +import { MainModule } from '../../../main.module' +import { ProvisionService } from '../../../provision.service' import { REQUEST_HEADER_API_KEY } from '../../../shared/constant' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' -import { AppService } from '../../../vault/core/service/app.service' -import { ClientModule } from '../../client.module' import { CreateClientDto } from '../../http/rest/dto/create-client.dto' import { ClientRepository } from '../../persistence/repository/client.repository' @@ -27,22 +25,16 @@ describe('Client', () => { let module: TestingModule let testPrismaService: TestPrismaService let clientRepository: ClientRepository - let appService: AppService - let configService: ConfigService + let provisionService: ProvisionService - const adminApiKey = 'test-admin-api-key' + const adminApiKey = 'test-vault-admin-api-key' beforeAll(async () => { module = await Test.createTestingModule({ - imports: [ - LoggerModule.forTest(), - ConfigModule.forRoot({ - load: [load], - isGlobal: true - }), - ClientModule - ] + imports: [MainModule] }) + .overrideModule(LoggerModule) + .useModule(LoggerModule.forTest()) .overrideProvider(EncryptionModuleOptionProvider) .useValue({ keyring: getTestRawAesKeyring() @@ -51,19 +43,13 @@ describe('Client', () => { app = module.createNestApplication() - appService = module.get(AppService) + provisionService = module.get(ProvisionService) clientRepository = module.get(ClientRepository) testPrismaService = module.get(TestPrismaService) - configService = module.get>(ConfigService) await testPrismaService.truncateAll() - await appService.save({ - id: configService.get('app.id'), - masterKey: 'test-master-key', - adminApiKey: secret.hash(adminApiKey) - }) - + await provisionService.provision() await app.init() }) diff --git a/apps/vault/src/client/client.module.ts b/apps/vault/src/client/client.module.ts index 4bc508a25..63386357d 100644 --- a/apps/vault/src/client/client.module.ts +++ b/apps/vault/src/client/client.module.ts @@ -1,18 +1,18 @@ import { HttpModule } from '@nestjs/axios' -import { Module, OnApplicationBootstrap, ValidationPipe, forwardRef } from '@nestjs/common' +import { forwardRef, Module, OnApplicationBootstrap, ValidationPipe } from '@nestjs/common' import { APP_PIPE } from '@nestjs/core' import { ZodValidationPipe } from 'nestjs-zod' +import { AppModule } from '../main.module' import { AdminApiKeyGuard } from '../shared/guard/admin-api-key.guard' import { KeyValueModule } from '../shared/module/key-value/key-value.module' -import { VaultModule } from '../vault/vault.module' +import { PersistenceModule } from '../shared/module/persistence/persistence.module' import { BootstrapService } from './core/service/bootstrap.service' import { ClientService } from './core/service/client.service' import { ClientController } from './http/rest/controller/client.controller' import { ClientRepository } from './persistence/repository/client.repository' @Module({ - // NOTE: The AdminApiKeyGuard is the only reason we need the VaultModule. - imports: [HttpModule, KeyValueModule, forwardRef(() => VaultModule)], + imports: [HttpModule, KeyValueModule, PersistenceModule, forwardRef(() => AppModule)], controllers: [ClientController], providers: [ AdminApiKeyGuard, diff --git a/apps/vault/src/client/core/service/__test__/unit/client.service.spec.ts b/apps/vault/src/client/core/service/__test__/unit/client.service.spec.ts index e6b31f083..c2780fedf 100644 --- a/apps/vault/src/client/core/service/__test__/unit/client.service.spec.ts +++ b/apps/vault/src/client/core/service/__test__/unit/client.service.spec.ts @@ -1,35 +1,57 @@ -import { EncryptionModule } from '@narval/encryption-module' +import { LoggerModule } from '@narval/nestjs-shared' import { Test } from '@nestjs/testing' +import { MockProxy, mock } from 'jest-mock-extended' import { KeyValueRepository } from '../../../../../shared/module/key-value/core/repository/key-value.repository' -import { EncryptKeyValueService } from '../../../../../shared/module/key-value/core/service/encrypt-key-value.service' import { InMemoryKeyValueRepository } from '../../../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' -import { getTestRawAesKeyring } from '../../../../../shared/testing/encryption.testing' import { Client } from '../../../../../shared/type/domain.type' import { ClientRepository } from '../../../../persistence/repository/client.repository' import { ClientService } from '../../client.service' describe(ClientService.name, () => { let clientService: ClientService + let clientRepositoryMock: MockProxy const clientId = 'test-client-id' const client: Client = { clientId, + auth: { + disabled: true, + local: null, + tokenValidation: { + disabled: true, + url: null, + jwksUrl: null, + verification: { + audience: null, + issuer: null, + maxTokenAge: null, + requireBoundTokens: false, + allowBearerTokens: false, + allowWildcard: null + }, + pinnedPublicKey: null + } + }, + name: 'test-client', + configurationSource: 'dynamic', + backupPublicKey: null, + baseUrl: null, createdAt: new Date(), updatedAt: new Date() } beforeEach(async () => { + clientRepositoryMock = mock() + const module = await Test.createTestingModule({ - imports: [ - EncryptionModule.register({ - keyring: getTestRawAesKeyring() - }) - ], + imports: [LoggerModule.forTest()], providers: [ ClientService, - ClientRepository, - EncryptKeyValueService, + { + provide: ClientRepository, + useValue: clientRepositoryMock + }, { provide: KeyValueRepository, useClass: InMemoryKeyValueRepository @@ -42,9 +64,12 @@ describe(ClientService.name, () => { describe('save', () => { it('saves the client', async () => { + clientRepositoryMock.save.mockResolvedValue(client) + const actualClient = await clientService.save(client) expect(actualClient).toEqual(client) + expect(clientRepositoryMock.save).toHaveBeenCalledWith(client, false) }) }) }) diff --git a/apps/vault/src/client/core/service/bootstrap.service.ts b/apps/vault/src/client/core/service/bootstrap.service.ts index a57454448..2a9c85885 100644 --- a/apps/vault/src/client/core/service/bootstrap.service.ts +++ b/apps/vault/src/client/core/service/bootstrap.service.ts @@ -1,20 +1,74 @@ +import { ConfigService } from '@narval/config-module' import { LoggerService } from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' +import { Config } from '../../../main.config' +import { Client } from '../../../shared/type/domain.type' import { ClientService } from './client.service' @Injectable() export class BootstrapService { constructor( + private configService: ConfigService, private clientService: ClientService, private logger: LoggerService ) {} async boot(): Promise { - this.logger.log('Start app bootstrap') + this.logger.log('Start client bootstrap') + + await this.persistDeclarativeClients() + + // TEMPORARY: Migrate the key-value format of the Client config into the table format. + // Can be removed once this runs once. + await this.clientService.migrateV1Data() await this.syncClients() } + private async persistDeclarativeClients(): Promise { + const clients = this.configService.get('clients') + if (!clients) return + + // Given ClientConfig type, build the Client type + const declarativeClients: Client[] = clients.map((client) => ({ + clientId: client.clientId, + name: client.name, + configurationSource: 'declarative', + backupPublicKey: client.backupPublicKey, + baseUrl: client.baseUrl, + auth: { + disabled: client.auth.disabled, + local: client.auth.local?.httpSigning?.methods?.jwsd + ? { + jwsd: client.auth.local?.httpSigning?.methods?.jwsd || null, + allowedUsersJwksUrl: client.auth.local?.httpSigning?.allowedUsersJwksUrl || null, + allowedUsers: client.auth.local?.httpSigning?.allowedUsers + } + : null, + tokenValidation: { + disabled: !!client.auth.tokenValidation?.disabled, + url: client.auth.tokenValidation?.url || null, + jwksUrl: client.auth.tokenValidation?.jwksUrl || null, + pinnedPublicKey: client.auth.tokenValidation?.publicKey || null, + verification: { + audience: client.auth.tokenValidation?.verification?.audience || null, + issuer: client.auth.tokenValidation?.verification?.issuer || null, + maxTokenAge: client.auth.tokenValidation?.verification?.maxTokenAge || null, + requireBoundTokens: !!client.auth.tokenValidation?.verification?.requireBoundTokens, + allowBearerTokens: !!client.auth.tokenValidation?.verification?.allowBearerTokens, + allowWildcard: client.auth.tokenValidation?.verification?.allowWildcard || null + } + } + }, + createdAt: new Date(), + updatedAt: new Date() + })) + + for (const client of declarativeClients) { + await this.clientService.save(client) + } + } + private async syncClients(): Promise { const clients = await this.clientService.findAll() diff --git a/apps/vault/src/client/core/service/client.service.ts b/apps/vault/src/client/core/service/client.service.ts index f25fc8792..0c02dc6f1 100644 --- a/apps/vault/src/client/core/service/client.service.ts +++ b/apps/vault/src/client/core/service/client.service.ts @@ -1,20 +1,75 @@ +import { LoggerService } from '@narval/nestjs-shared' import { HttpStatus, Injectable } from '@nestjs/common' +import { isDeepStrictEqual } from 'util' import { ApplicationException } from '../../../shared/exception/application.exception' import { Client } from '../../../shared/type/domain.type' import { ClientRepository } from '../../persistence/repository/client.repository' @Injectable() export class ClientService { - constructor(private clientRepository: ClientRepository) {} + constructor( + private clientRepository: ClientRepository, + private logger: LoggerService + ) {} + + // Temporary function to migrate data from V1 to V2 + async migrateV1Data(): Promise { + const clientsV1 = await this.clientRepository.findAllV1() + for (const clientV1 of clientsV1) { + const client: Client = { + clientId: clientV1.clientId, + name: clientV1.clientId, + configurationSource: 'dynamic', + backupPublicKey: clientV1.backupPublicKey || null, + baseUrl: clientV1.baseUrl || null, + auth: { + disabled: false, + local: { + jwsd: { + maxAge: 60, // 1 minute; this is seconds + requiredComponents: ['htm', 'uri', 'created', 'ath'] + }, + allowedUsersJwksUrl: null, + allowedUsers: null + }, + tokenValidation: { + disabled: false, + url: null, + jwksUrl: null, + pinnedPublicKey: clientV1.engineJwk || null, + verification: { + audience: clientV1.audience || null, + issuer: clientV1.issuer || null, + maxTokenAge: clientV1.maxTokenAge || null, + requireBoundTokens: true, + allowBearerTokens: false, + allowWildcard: [ + 'transactionRequest.maxPriorityFeePerGas', + 'transactionRequest.maxFeePerGas', + 'transactionRequest.gas', + 'transactionRequest.gasPrice', + 'transactionRequest.nonce' + ] + } + } + }, + createdAt: clientV1.createdAt, + updatedAt: clientV1.updatedAt + } + this.logger.info('Migrating client', { clientV1, client }) + await this.clientRepository.save(client) + await this.clientRepository.deleteV1(clientV1.clientId) + } + } async findById(clientId: string): Promise { return this.clientRepository.findById(clientId) } - async save(client: Client): Promise { + async save(client: Client, overwriteAllowedUsers = false): Promise { const exists = await this.clientRepository.findById(client.clientId) - if (exists) { + if (exists && exists.configurationSource === 'dynamic') { throw new ApplicationException({ message: 'client already exist', suggestedHttpStatusCode: HttpStatus.BAD_REQUEST, @@ -22,8 +77,22 @@ export class ClientService { }) } + // Validate the backupPublicKey is not being changed; it can be unset but not rotated here. + if ( + exists && + exists.backupPublicKey && + client.backupPublicKey && + !isDeepStrictEqual(exists.backupPublicKey, client.backupPublicKey) + ) { + throw new ApplicationException({ + message: 'Cannot change backupPublicKey', + suggestedHttpStatusCode: HttpStatus.BAD_REQUEST, + context: { clientId: client.clientId } + }) + } + try { - await this.clientRepository.save(client) + await this.clientRepository.save(client, overwriteAllowedUsers) return client } catch (error) { diff --git a/apps/vault/src/client/http/rest/controller/client.controller.ts b/apps/vault/src/client/http/rest/controller/client.controller.ts index eceb3ec53..d4dd3d3d6 100644 --- a/apps/vault/src/client/http/rest/controller/client.controller.ts +++ b/apps/vault/src/client/http/rest/controller/client.controller.ts @@ -31,14 +31,35 @@ export class ClientController { const client = await this.clientService.save({ clientId, - engineJwk, - audience: body.audience, - issuer: body.issuer, - maxTokenAge: body.maxTokenAge, - allowKeyExport: body.allowKeyExport, - allowWildcard: body.allowWildcard, - backupPublicKey: body.backupPublicKey, - baseUrl: body.baseUrl, + name: clientId, + backupPublicKey: null, + baseUrl: body.baseUrl || null, + configurationSource: 'dynamic', + auth: { + disabled: false, + local: { + jwsd: { + maxAge: 300, + requiredComponents: ['htm', 'uri', 'created', 'ath'] + }, + allowedUsersJwksUrl: null, + allowedUsers: null + }, + tokenValidation: { + disabled: false, + url: null, + jwksUrl: null, + pinnedPublicKey: engineJwk || null, + verification: { + audience: body.audience || null, + issuer: body.issuer || null, + maxTokenAge: body.maxTokenAge || null, + requireBoundTokens: true, + allowBearerTokens: false, + allowWildcard: body.allowWildcard || null + } + } + }, createdAt: now, updatedAt: now }) diff --git a/apps/vault/src/client/persistence/repository/__test__/unit/client.repository.spec.ts b/apps/vault/src/client/persistence/repository/__test__/unit/client.repository.spec.ts deleted file mode 100644 index d82e992b0..000000000 --- a/apps/vault/src/client/persistence/repository/__test__/unit/client.repository.spec.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { EncryptionModule } from '@narval/encryption-module' -import { Test } from '@nestjs/testing' -import { KeyValueRepository } from '../../../../../shared/module/key-value/core/repository/key-value.repository' -import { EncryptKeyValueService } from '../../../../../shared/module/key-value/core/service/encrypt-key-value.service' -import { KeyValueService } from '../../../../../shared/module/key-value/core/service/key-value.service' -import { InMemoryKeyValueRepository } from '../../../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' -import { getTestRawAesKeyring } from '../../../../../shared/testing/encryption.testing' -import { Client } from '../../../../../shared/type/domain.type' -import { ClientRepository } from '../../client.repository' - -describe(ClientRepository.name, () => { - let repository: ClientRepository - let inMemoryKeyValueRepository: InMemoryKeyValueRepository - - const clientId = 'test-client-id' - - beforeEach(async () => { - inMemoryKeyValueRepository = new InMemoryKeyValueRepository() - - const module = await Test.createTestingModule({ - imports: [ - EncryptionModule.register({ - keyring: getTestRawAesKeyring() - }) - ], - providers: [ - KeyValueService, - ClientRepository, - EncryptKeyValueService, - { - provide: KeyValueRepository, - useValue: inMemoryKeyValueRepository - } - ] - }).compile() - - repository = module.get(ClientRepository) - }) - - describe('save', () => { - const now = new Date() - - const client: Client = { - clientId, - createdAt: now, - updatedAt: now - } - - it('saves a new client', async () => { - await repository.save(client) - - const value = await inMemoryKeyValueRepository.get(repository.getKey(client.clientId)) - const actualClient = await repository.findById(client.clientId) - - expect(value).not.toEqual(null) - expect(client).toEqual(actualClient) - }) - - it('indexes the new client', async () => { - await repository.save(client) - - expect(await repository.getClientIndex()).toEqual([client.clientId]) - }) - }) -}) diff --git a/apps/vault/src/client/persistence/repository/client.repository.ts b/apps/vault/src/client/persistence/repository/client.repository.ts index 3a11b1d2b..fa32c79b8 100644 --- a/apps/vault/src/client/persistence/repository/client.repository.ts +++ b/apps/vault/src/client/persistence/repository/client.repository.ts @@ -1,33 +1,174 @@ import { coerce } from '@narval/nestjs-shared' +import { publicKeySchema, rsaPublicKeySchema } from '@narval/signature' import { Injectable } from '@nestjs/common' +import { Prisma } from '@prisma/client/vault' import { compact } from 'lodash/fp' import { z } from 'zod' import { KeyMetadata } from '../../../shared/module/key-value/core/repository/key-value.repository' import { EncryptKeyValueService } from '../../../shared/module/key-value/core/service/encrypt-key-value.service' -import { Client, Collection } from '../../../shared/type/domain.type' - +import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' +import { Client, ClientLocalAuthAllowedUser, ClientV1, Collection } from '../../../shared/type/domain.type' export const ClientIndex = z.array(z.string()) +export function clientObjectToPrisma(client: Client): Prisma.ClientCreateInput { + return { + clientId: client.clientId, + name: client.name, + configurationSource: client.configurationSource, + authDisabled: client.auth.disabled, + tokenValidationDisabled: client.auth.tokenValidation.disabled, + backupPublicKey: client.backupPublicKey ? JSON.stringify(client.backupPublicKey) : null, + baseUrl: client.baseUrl, + + // JWT Token Validation + authorizationServerUrl: client.auth.tokenValidation.url, + authorizationIssuer: client.auth.tokenValidation.verification.issuer, + authorizationAudience: client.auth.tokenValidation.verification.audience, + authorizationMaxTokenAge: client.auth.tokenValidation.verification.maxTokenAge, + authorizationJwksUrl: client.auth.tokenValidation.jwksUrl, + authorizationPinnedPublicKey: client.auth.tokenValidation.pinnedPublicKey + ? JSON.stringify(client.auth.tokenValidation.pinnedPublicKey) + : null, + authorizationRequireBoundTokens: client.auth.tokenValidation.verification.requireBoundTokens, + authorizationAllowBearerTokens: client.auth.tokenValidation.verification.allowBearerTokens, + authorizationAllowWildcards: client.auth.tokenValidation.verification.allowWildcard?.join(','), + + // Local Authentication Methods + localAuthAllowedUsersJwksUrl: client.auth.local?.allowedUsersJwksUrl || null, + localAuthJwsdEnabled: !!client.auth.local?.jwsd, + jwsdMaxAge: client.auth.local?.jwsd?.maxAge || null, + jwsdRequiredComponents: client.auth.local?.jwsd?.requiredComponents.join(',') || null, + + createdAt: client.createdAt, // Exclude the createdAt so the db generates it. + updatedAt: client.updatedAt + } +} + +function prismaToClientObject( + prismaClient: Prisma.ClientGetPayload<{ include: { localAuthAllowedUsers: true } }> +): Client { + return { + clientId: prismaClient.clientId, + name: prismaClient.name, + configurationSource: prismaClient.configurationSource as 'declarative' | 'dynamic', + backupPublicKey: prismaClient.backupPublicKey + ? rsaPublicKeySchema.parse(JSON.parse(prismaClient.backupPublicKey)) + : null, + baseUrl: prismaClient.baseUrl, + + auth: { + disabled: prismaClient.authDisabled, + local: prismaClient.localAuthJwsdEnabled + ? { + jwsd: { + maxAge: prismaClient.jwsdMaxAge ?? 0, + requiredComponents: prismaClient.jwsdRequiredComponents?.split(',') ?? [] + }, + allowedUsersJwksUrl: prismaClient.localAuthAllowedUsersJwksUrl, + allowedUsers: prismaClient.localAuthAllowedUsers?.length + ? prismaClient.localAuthAllowedUsers?.map((user) => ({ + userId: user.userId, + publicKey: publicKeySchema.parse(JSON.parse(user.publicKey)) + })) + : null + } + : null, + tokenValidation: { + disabled: prismaClient.tokenValidationDisabled, + url: prismaClient.authorizationServerUrl, + jwksUrl: prismaClient.authorizationJwksUrl, + pinnedPublicKey: prismaClient.authorizationPinnedPublicKey + ? publicKeySchema.parse(JSON.parse(prismaClient.authorizationPinnedPublicKey)) + : null, + verification: { + audience: prismaClient.authorizationAudience, + issuer: prismaClient.authorizationIssuer, + maxTokenAge: prismaClient.authorizationMaxTokenAge, + requireBoundTokens: prismaClient.authorizationRequireBoundTokens, + allowBearerTokens: prismaClient.authorizationAllowBearerTokens, + allowWildcard: prismaClient.authorizationAllowWildcards + ? prismaClient.authorizationAllowWildcards.split(',') + : null + } + } + }, + + createdAt: prismaClient.createdAt, + updatedAt: prismaClient.updatedAt + } +} + @Injectable() export class ClientRepository { - constructor(private encryptKeyValueService: EncryptKeyValueService) {} + constructor( + private encryptKeyValueService: EncryptKeyValueService, + private prismaService: PrismaService + ) {} private KEY_PREFIX = Collection.CLIENT async findById(clientId: string): Promise { - const value = await this.encryptKeyValueService.get(this.getKey(clientId)) + const value = await this.prismaService.client.findUnique({ + where: { clientId }, + include: { localAuthAllowedUsers: true } + }) if (value) { - return coerce.decode(Client, value) + return prismaToClientObject(value) } return null } + async findAll(): Promise { + const clients = await this.prismaService.client.findMany({ include: { localAuthAllowedUsers: true } }) + return clients.map(prismaToClientObject) + } + + async saveAllowedUsers( + clientId: string, + allowedUsers: ClientLocalAuthAllowedUser[], + overwrite: boolean + ): Promise { + const allowedUsersInput = allowedUsers.map((user) => ({ + id: `${clientId}:${user.userId}`, + userId: user.userId, + clientId: clientId, + publicKey: JSON.stringify(user.publicKey) + })) + + await this.prismaService.$transaction( + compact([ + overwrite ? this.prismaService.clientLocalAuthAllowedUser.deleteMany({ where: { clientId } }) : undefined, + allowedUsers.length > 0 + ? this.prismaService.clientLocalAuthAllowedUser.createMany({ + data: allowedUsersInput, + skipDuplicates: true + }) + : undefined + ]) + ) + } + + // Upsert the Client and any Allowed Users, optionally overwriting existing "allowedUsers" + async save(client: Client, overwriteAllowedUsers = false): Promise { + const clientData = clientObjectToPrisma(client) + + await this.prismaService.client.upsert({ + where: { clientId: client.clientId }, + update: { ...clientData, createdAt: undefined }, // Ensure we don't overwrite the createdAt + create: clientData + }) + + await this.saveAllowedUsers(client.clientId, client.auth.local?.allowedUsers ?? [], overwriteAllowedUsers) + + return client + } - async save(client: Client): Promise { + /** @deprecated */ + async saveV1(client: ClientV1): Promise { await this.encryptKeyValueService.set( this.getKey(client.clientId), - coerce.encode(Client, client), + coerce.encode(ClientV1, client), this.getMetadata(client.clientId) ) await this.index(client) @@ -35,6 +176,18 @@ export class ClientRepository { return client } + /** @deprecated */ + async findByIdV1(clientId: string): Promise { + const value = await this.encryptKeyValueService.get(this.getKey(clientId)) + + if (value) { + return coerce.decode(ClientV1, value) + } + + return null + } + + /** @deprecated */ async getClientIndex(): Promise { const index = await this.encryptKeyValueService.get(this.getIndexKey()) @@ -52,26 +205,31 @@ export class ClientRepository { // An option is to move these general queries `findBy`, findAll`, etc to the // KeyValeuRepository implementation letting each implementation pick the best // strategy to solve the problem (e.g. where query in SQL) - async findAll(): Promise { + /** @deprecated */ + async findAllV1(): Promise { const ids = await this.getClientIndex() - const clients = await Promise.all(ids.map((id) => this.findById(id))) + const clients = await Promise.all(ids.map((id) => this.findByIdV1(id))) return compact(clients) } + /** @deprecated */ getMetadata(clientId: string): KeyMetadata { return { collection: Collection.CLIENT, clientId } } + /** @deprecated */ getKey(clientId: string): string { return `${this.KEY_PREFIX}:${clientId}` } + /** @deprecated */ getIndexKey(): string { return `${this.KEY_PREFIX}:index` } - private async index(client: Client): Promise { + /** @deprecated */ + private async index(client: ClientV1): Promise { const currentIndex = await this.getClientIndex() await this.encryptKeyValueService.set( @@ -82,4 +240,16 @@ export class ClientRepository { return true } + async deleteV1(clientId: string): Promise { + await this.encryptKeyValueService.delete(this.getKey(clientId)) + // Remove the client from the index + const currentIndex = await this.getClientIndex() + + const newIndex = currentIndex.filter((id) => id !== clientId) + await this.encryptKeyValueService.set( + this.getIndexKey(), + coerce.encode(ClientIndex, newIndex), + this.getMetadata(clientId) // This is ignored on updates + ) + } } diff --git a/apps/vault/src/main.config.ts b/apps/vault/src/main.config.ts index bcd33739a..30788a33a 100644 --- a/apps/vault/src/main.config.ts +++ b/apps/vault/src/main.config.ts @@ -1,3 +1,8 @@ +import { LoggerService } from '@narval/nestjs-shared' +import { publicKeySchema, rsaPublicKeySchema } from '@narval/signature' +import fs from 'fs' +import path from 'path' +import { parse } from 'yaml' import { z } from 'zod' export enum Env { @@ -6,54 +11,295 @@ export enum Env { PRODUCTION = 'production' } -const configSchema = z.object({ - env: z.nativeEnum(Env), - port: z.coerce.number(), - cors: z.array(z.string()).optional(), - baseUrl: z.string().optional(), - database: z.object({ - url: z.string().startsWith('postgresql:') - }), - app: z.object({ - id: z.string(), - adminApiKeyHash: z.string().optional(), - masterKey: z.string().optional() +const CONFIG_VERSION_LATEST = '1' +const logger = new LoggerService() + +const JwsdMethodConfigSchema = z.object({ + maxAge: z.number(), + requiredComponents: z.array(z.string()) +}) + +const HttpSigningConfigSchema = z.object({ + methods: z.object({ + jwsd: JwsdMethodConfigSchema.nullable().optional() }), - keyring: z.union([ - z.object({ - type: z.literal('raw'), - masterPassword: z.string() - }), - z.object({ - type: z.literal('awskms'), - masterAwsKmsArn: z.string() + allowedUsersJwksUrl: z.string().nullable().optional(), + allowedUsers: z + .array( + z.object({ + userId: z.string(), + publicKey: publicKeySchema + }) + ) + .nullable() + .optional() +}) + +const LocalAuthConfigSchema = z.object({ + httpSigning: HttpSigningConfigSchema.nullable().optional() +}) + +const AppLocalAuthConfigSchema = z.object({ + adminApiKeyHash: z.string().nullable().optional() + // TODO: Add the app-level httpSigning section: + /** + # HTTP Signing configuration - this is for Service-level authentication. + # https://httpsig.org/ + httpSigning: + # Settings for when THIS service verifies incoming requests + verification: + maxAge: 300 # Reject signatures older than 5 minutes + requiredComponents: # Fail if these aren't included in signature + - "@method" + - "@target-uri" + - "content-digest" + + # [optional]: Known keys for pinning/offline validation + # If set, ONLY these keys will be accepted. + allowedUsers: + # Peer name + - name: armory + # [optional] URL of the peer's JWKS endpoint to verify signatures against. + jwksUrl: https://armory/.well-known/jwks.json + # [optional] Pin specific keys, instead of jwks endpoint + publicKeys: + - kid: "local-dev-armory-instance-1-2024-1" + kty: "EC" + crv: "secp256k1" + alg: "ES256K" + x: "..." + y: "..." + */ +}) + +const TokenValidationVerificationConfigSchema = z.object({ + audience: z.string().nullable().optional(), + issuer: z.string().nullable().optional(), + maxTokenAge: z.number().nullable().optional(), + requireBoundTokens: z.boolean().optional(), + allowBearerTokens: z.boolean().optional(), + allowWildcard: z.array(z.string()).nullable().optional() +}) + +const TokenValidationConfigSchema = z.object({ + disabled: z.boolean().nullable().optional(), + url: z.string().nullable().optional(), + jwksUrl: z.string().nullable().optional(), + publicKey: publicKeySchema.nullable().optional(), + verification: TokenValidationVerificationConfigSchema.nullable().optional() +}) + +const OIDCConfigSchema = z.any() // TODO: Define OIDC schema +const OutgoingAuthConfigSchema = z.any() // TODO: Define outgoing auth schema + +const AuthConfigSchema = z.object({ + disabled: z.boolean().optional(), + oidc: OIDCConfigSchema.nullable().optional(), + local: LocalAuthConfigSchema.nullable().optional(), + tokenValidation: TokenValidationConfigSchema.nullable().optional(), + outgoing: OutgoingAuthConfigSchema.nullable().optional() +}) + +const ClientConfigSchema = z.object({ + name: z.string(), + baseUrl: z.string().optional(), + auth: AuthConfigSchema, + backupPublicKey: rsaPublicKeySchema.optional() +}) +const VaultConfigSchema = z.object({ + version: z.coerce.string(), + env: z.nativeEnum(Env).nullish(), + port: z.coerce.number().nullish(), + cors: z.array(z.string()).nullable().optional(), + baseUrl: z.string().nullish(), + app: z + .object({ + id: z.string(), + auth: z.object({ + disabled: z.boolean(), + oidc: OIDCConfigSchema.nullable(), + local: AppLocalAuthConfigSchema.nullable(), + outgoing: OutgoingAuthConfigSchema.nullable() + }) }) - ]) + .nullish(), + database: z + .object({ + url: z.string() + }) + .nullish(), + keyring: z + .object({ + type: z.enum(['raw', 'awskms']), + encryptionMasterPassword: z.string().nullable().optional(), + encryptionMasterKey: z.string().nullable().optional(), + encryptionMasterAwsKmsArn: z.string().nullable().optional(), + hmacSecret: z.string().nullable().optional() + }) + .nullish(), + clients: z.record(z.string(), ClientConfigSchema).nullish() }) -export type Config = z.infer +const keyringSchema = z.union([ + z.object({ + type: z.literal('raw'), + encryptionMasterPassword: z.string(), + encryptionMasterKey: z.string().nullable(), + hmacSecret: z.string().nullable() + }), + z.object({ + type: z.literal('awskms'), + encryptionMasterAwsKmsArn: z.string(), + hmacSecret: z.string().nullable() + }) +]) + +const LoadConfig = VaultConfigSchema.transform((yaml, ctx) => { + const appId = process.env.APP_UID || yaml.app?.id + const databaseUrl = process.env.APP_DATABASE_URL || yaml.database?.url + const env = process.env.NODE_ENV || yaml.env + const port = process.env.PORT || yaml.port + const baseUrl = process.env.BASE_URL || yaml.baseUrl + if (!appId) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'APP_UID is required' + }) + return z.NEVER + } + if (!databaseUrl) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'APP_DATABASE_URL is required' + }) + return z.NEVER + } + if (!env) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'NODE_ENV is required' + }) + return z.NEVER + } + if (!port) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'PORT is required' + }) + return z.NEVER + } + if (!baseUrl) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'BASE_URL is required' + }) + return z.NEVER + } -export const load = (): Config => { - const result = configSchema.safeParse({ - env: process.env.NODE_ENV, - port: process.env.PORT, - cors: process.env.CORS ? process.env.CORS.split(',') : [], - // Such as "https://vault.narval.xyz" - baseUrl: process.env.BASE_URL, + const clients = Object.entries(yaml.clients || {}).map(([clientId, client]) => ({ + clientId, + name: client.name, + backupPublicKey: client.backupPublicKey || null, + baseUrl: client.baseUrl || null, + configurationSource: 'declarative', + auth: { + disabled: !!client.auth.disabled, + oidc: client.auth.oidc || null, + local: client.auth.local + ? { + httpSigning: client.auth.local.httpSigning + ? { + methods: { + jwsd: client.auth.local.httpSigning.methods.jwsd + ? { + maxAge: client.auth.local.httpSigning.methods.jwsd.maxAge, + requiredComponents: client.auth.local.httpSigning.methods.jwsd.requiredComponents + } + : null + }, + allowedUsersJwksUrl: client.auth.local.httpSigning.allowedUsersJwksUrl || null, + allowedUsers: client.auth.local.httpSigning.allowedUsers || null + } + : null + } + : null, + tokenValidation: client.auth.tokenValidation + ? { + disabled: !!client.auth.tokenValidation.disabled, + url: client.auth.tokenValidation.url || null, + jwksUrl: client.auth.tokenValidation.jwksUrl || null, + publicKey: client.auth.tokenValidation.publicKey || null, + verification: client.auth.tokenValidation.verification + ? { + audience: client.auth.tokenValidation.verification.audience || null, + issuer: client.auth.tokenValidation.verification.issuer || null, + maxTokenAge: client.auth.tokenValidation.verification.maxTokenAge || null, + requireBoundTokens: !!client.auth.tokenValidation.verification.requireBoundTokens, + allowBearerTokens: !!client.auth.tokenValidation.verification.allowBearerTokens, + allowWildcard: client.auth.tokenValidation.verification.allowWildcard || null + } + : null + } + : null, + outgoing: client.auth.outgoing || null + } + })) + + return { + version: yaml.version || CONFIG_VERSION_LATEST, + env, + port, + cors: z.array(z.string()).parse(process.env.CORS || yaml.cors || []), + baseUrl, database: { - url: process.env.APP_DATABASE_URL + url: databaseUrl }, + app: { - id: process.env.APP_UID, - adminApiKeyHash: process.env.ADMIN_API_KEY, - masterKey: process.env.MASTER_KEY + id: appId, + auth: { + disabled: yaml.app?.auth.disabled || false, + local: + yaml.app?.auth.local || process.env.ADMIN_API_KEY + ? { + adminApiKeyHash: yaml.app?.auth.local?.adminApiKeyHash || process.env.ADMIN_API_KEY || null + } + : null + // oidc: yaml.app.auth.oidc, + // outgoing: yaml.app.auth.outgoing, + } }, - keyring: { - type: process.env.KEYRING_TYPE, - masterAwsKmsArn: process.env.MASTER_AWS_KMS_ARN, - masterPassword: process.env.MASTER_PASSWORD + keyring: keyringSchema.parse({ + type: process.env.KEYRING_TYPE || yaml.keyring?.type, + encryptionMasterPassword: process.env.MASTER_PASSWORD || yaml.keyring?.encryptionMasterPassword || null, + encryptionMasterKey: process.env.MASTER_KEY || yaml.keyring?.encryptionMasterKey || null, + encryptionMasterAwsKmsArn: process.env.MASTER_AWS_KMS_ARN || yaml.keyring?.encryptionMasterAwsKmsArn || null, + hmacSecret: process.env.HMAC_SECRET || yaml.keyring?.hmacSecret || null + }), + clients + } +}) + +export type Config = z.output + +export const load = (): Config => { + const configFilePathEnv = process.env.CONFIG_FILE + const filePath = configFilePathEnv + ? path.resolve(configFilePathEnv) + : path.resolve(process.cwd(), 'config/vault-config.yml') + let yamlConfigRaw = {} + try { + if (fs.existsSync(filePath)) { + const fileContents = fs.readFileSync(filePath, 'utf8') + yamlConfigRaw = parse(fileContents) } - }) + // If file doesn't exist, we'll use empty object as default + } catch (error) { + logger.warn(`Warning: Could not read config file at ${filePath}: ${error.message}`) + // Continue with empty config + } + + const result = LoadConfig.safeParse(yamlConfigRaw) if (result.success) { return result.data diff --git a/apps/vault/src/main.module.ts b/apps/vault/src/main.module.ts index 2abf98230..e99616766 100644 --- a/apps/vault/src/main.module.ts +++ b/apps/vault/src/main.module.ts @@ -1,35 +1,50 @@ -import { ConfigModule, ConfigService } from '@narval/config-module' -import { EncryptionModule } from '@narval/encryption-module' +import { ConfigModule } from '@narval/config-module' +import { EncryptionService } from '@narval/encryption-module' import { HttpLoggerMiddleware, LoggerModule, OpenTelemetryModule } from '@narval/nestjs-shared' -import { MiddlewareConsumer, Module, NestModule, OnModuleInit, ValidationPipe, forwardRef } from '@nestjs/common' +import { MiddlewareConsumer, Module, NestModule, OnModuleInit, ValidationPipe } from '@nestjs/common' import { APP_PIPE, RouterModule } from '@nestjs/core' import { ZodValidationPipe } from 'nestjs-zod' +import { AppRepository } from './app.repository' +import { AppService } from './app.service' import { BrokerModule } from './broker/broker.module' import { ClientModule } from './client/client.module' import { load } from './main.config' -import { EncryptionModuleOptionFactory } from './shared/factory/encryption-module-option.factory' -import { AppService } from './vault/core/service/app.service' -import { ProvisionService } from './vault/core/service/provision.service' +import { ProvisionService } from './provision.service' +import { KeyValueModule } from './shared/module/key-value/key-value.module' +import { PersistenceModule } from './shared/module/persistence/persistence.module' import { VaultModule } from './vault/vault.module' const INFRASTRUCTURE_MODULES = [ LoggerModule, ConfigModule.forRoot({ load: [load], - isGlobal: true - }), - EncryptionModule.registerAsync({ - imports: [forwardRef(() => VaultModule)], - inject: [ConfigService, AppService], - useClass: EncryptionModuleOptionFactory + isGlobal: true, + cache: true }), OpenTelemetryModule.forRoot() ] @Module({ imports: [ - ...INFRASTRUCTURE_MODULES, + PersistenceModule.register({ + imports: [] // Specifically erase the imports, so we do NOT initialize the EncryptionModule + }), + KeyValueModule + ], + providers: [AppRepository, AppService, ProvisionService, { provide: EncryptionService, useValue: undefined }], + exports: [AppService, ProvisionService] +}) +export class AppModule implements NestModule { + configure(consumer: MiddlewareConsumer): void { + consumer.apply(HttpLoggerMiddleware).forRoutes('*') + } +} +@Module({ + imports: [ + ...INFRASTRUCTURE_MODULES, + AppModule, + PersistenceModule.forRoot(), // Domain VaultModule, ClientModule, @@ -70,7 +85,7 @@ export class MainModule implements NestModule { // context, dependencies requiring encryption will fail because the keyring was // already set as undefined. @Module({ - imports: [...INFRASTRUCTURE_MODULES, VaultModule] + imports: [...INFRASTRUCTURE_MODULES, AppModule] }) export class ProvisionModule implements OnModuleInit { constructor(private provisionService: ProvisionService) {} diff --git a/apps/vault/src/provision.service.ts b/apps/vault/src/provision.service.ts new file mode 100644 index 000000000..15cb2c8ea --- /dev/null +++ b/apps/vault/src/provision.service.ts @@ -0,0 +1,119 @@ +import { ConfigService } from '@narval/config-module' +import { decryptMasterKey, generateKeyEncryptionKey, generateMasterKey } from '@narval/encryption-module' +import { LoggerService } from '@narval/nestjs-shared' +import { toBytes } from '@narval/policy-engine-shared' +import { Injectable } from '@nestjs/common' +import { AppService } from './app.service' +import { Config } from './main.config' +import { App } from './shared/type/domain.type' +import { ProvisionException } from './vault/core/exception/provision.exception' + +@Injectable() +export class ProvisionService { + // IMPORTANT: The provision service establishes encryption. Therefore, you + // cannot have dependencies that rely on encryption to function. If you do, + // you'll ran into an error due to a missing keyring. + // Any process that requires encryption should be handled in the + // BootstrapService. + constructor( + private configService: ConfigService, + private appService: AppService, + private logger: LoggerService + ) {} + + // Provision the application if it's not already provisioned. + // Update configuration if needed. + // 1. Check if we have an App reference; App is initialized once. + // 2. Check if we have Encryption set up; Encryption is initialized once. + // 3. Auth can be updated, so change it if it's changed. + + // NOTE: The `adminApiKeyHash` argument is for test convinience in case it + // needs to provision the application. + async provision(adminApiKeyHash?: string): Promise { + // TEMPORARY: Migrate the key-value format of the App config into the table format. + // Can be removed once this runs once. + await this.appService.migrateV1Data() + + // Actually provision the new one; will not overwrite anything if this started from a migration + const app = await this.appService.getApp() + const keyring = this.configService.get('keyring') + + const thisApp: App = { ...(app || { id: this.getId(), encryptionKeyringType: keyring.type }) } + if (app && app.id !== this.getId()) { + throw new ProvisionException('App already provisioned with a different ID', { + current: this.getId(), + saved: app.id + }) + } + + // No encryption set up yet, so initialize encryption + if (!app?.encryptionKeyringType || (!app.encryptionMasterKey && !app.encryptionMasterAwsKmsArn)) { + thisApp.encryptionKeyringType = keyring.type + + if (keyring.type === 'awskms' && keyring.encryptionMasterAwsKmsArn) { + this.logger.log('Using AWS KMS for encryption') + thisApp.encryptionMasterAwsKmsArn = keyring.encryptionMasterAwsKmsArn + } else if (keyring.type === 'raw') { + // If we have the masterKey set in config, we'll save that. + // Otherwise, we'll generate a new one. + if (keyring.encryptionMasterKey) { + this.logger.log('Using provided master key') + thisApp.encryptionMasterKey = keyring.encryptionMasterKey + } else { + this.logger.log('Generating master encryption key') + const { encryptionMasterPassword } = keyring + const kek = generateKeyEncryptionKey(encryptionMasterPassword, thisApp.id) + const masterKey = await generateMasterKey(kek) // Encrypted master encryption key + thisApp.encryptionMasterKey = masterKey + } + } else { + throw new ProvisionException('Unsupported keyring type') + } + } + + // if raw encryption, verify the encryptionMasterPassword in config is the valid kek for the encryptionMasterKey + if (thisApp?.encryptionKeyringType === 'raw' && keyring.type === 'raw' && thisApp.encryptionMasterKey) { + try { + const kek = generateKeyEncryptionKey(keyring.encryptionMasterPassword, thisApp.id) + await decryptMasterKey(kek, toBytes(thisApp.encryptionMasterKey)) + this.logger.log('Master Encryption Key Verified') + } catch (error) { + this.logger.error( + 'Master Encryption Key Verification Failed; check the encryptionMasterPassword is the one that encrypted the masterKey', + { error } + ) + throw new ProvisionException('Master Encryption Key Verification Failed', { error }) + } + } + + // Now set the Auth if needed + thisApp.adminApiKeyHash = adminApiKeyHash || this.getAdminApiKeyHash() || null // fallback to null so we _unset_ it if it's not provided. + + // If we have an app already & the adminApiKeyHash has changed, just log that we're changing it. + if (app && thisApp.adminApiKeyHash !== app?.adminApiKeyHash) { + this.logger.log('Admin API Key has been changed', { + previous: app?.adminApiKeyHash, + current: thisApp.adminApiKeyHash + }) + } + + // Check if we disabled all auth + thisApp.authDisabled = this.configService.get('app.auth.disabled') + if (thisApp.authDisabled) { + thisApp.adminApiKeyHash = null + } + + this.logger.log('App configuration saved') + return this.appService.save(thisApp) + } + + private getAdminApiKeyHash(): string | null | undefined { + const localAuth = this.configService.get('app.auth.local') + + return localAuth?.adminApiKeyHash + } + + private getId(): string { + return this.configService.get('app.id') + } +} diff --git a/apps/vault/src/shared/decorator/permission-guard.decorator.ts b/apps/vault/src/shared/decorator/permission-guard.decorator.ts index dcc126b37..007900318 100644 --- a/apps/vault/src/shared/decorator/permission-guard.decorator.ts +++ b/apps/vault/src/shared/decorator/permission-guard.decorator.ts @@ -1,11 +1,11 @@ -import { Permission } from '@narval/armory-sdk' import { ApiGnapSecurity } from '@narval/nestjs-shared' import { UseGuards, applyDecorators } from '@nestjs/common' import { Reflector } from '@nestjs/core' import { AuthorizationGuard } from '../guard/authorization.guard' +import { VaultPermission } from '../type/domain.type' -const RequiredPermission = Reflector.createDecorator() +const RequiredPermission = Reflector.createDecorator() -export function PermissionGuard(...permissions: Permission[]) { +export function PermissionGuard(...permissions: VaultPermission[]) { return applyDecorators(RequiredPermission(permissions), UseGuards(AuthorizationGuard), ApiGnapSecurity(permissions)) } diff --git a/apps/vault/src/shared/factory/encryption-module-option.factory.ts b/apps/vault/src/shared/factory/encryption-module-option.factory.ts index 15a0d5eef..7888eba15 100644 --- a/apps/vault/src/shared/factory/encryption-module-option.factory.ts +++ b/apps/vault/src/shared/factory/encryption-module-option.factory.ts @@ -9,8 +9,8 @@ import { import { LoggerService } from '@narval/nestjs-shared' import { toBytes } from '@narval/policy-engine-shared' import { Injectable } from '@nestjs/common' +import { AppService } from '../../app.service' import { Config } from '../../main.config' -import { AppService } from '../../vault/core/service/app.service' import { ENCRYPTION_KEY_NAME, ENCRYPTION_KEY_NAMESPACE, ENCRYPTION_WRAPPING_SUITE } from '../constant' @Injectable() @@ -36,12 +36,12 @@ export class EncryptionModuleOptionFactory { } if (keyringConfig.type === 'raw') { - if (!app.masterKey) { + if (!app.encryptionMasterKey) { throw new Error('Master key not set') } - const kek = generateKeyEncryptionKey(keyringConfig.masterPassword, app.id) - const unencryptedMasterKey = await decryptMasterKey(kek, toBytes(app.masterKey)) + const kek = generateKeyEncryptionKey(keyringConfig.encryptionMasterPassword, app.id) + const unencryptedMasterKey = await decryptMasterKey(kek, toBytes(app.encryptionMasterKey)) return { keyring: new RawAesKeyringNode({ @@ -53,7 +53,7 @@ export class EncryptionModuleOptionFactory { } } else if (keyringConfig.type === 'awskms') { // We have AWS KMS config so we'll use that instead as the MasterKey, which means we don't need a KEK separately - const keyring = new KmsKeyringNode({ generatorKeyId: keyringConfig.masterAwsKmsArn }) + const keyring = new KmsKeyringNode({ generatorKeyId: keyringConfig.encryptionMasterAwsKmsArn }) return { keyring } } diff --git a/apps/vault/src/shared/guard/__test__/unit/admin-api-key.guard.spec.ts b/apps/vault/src/shared/guard/__test__/unit/admin-api-key.guard.spec.ts index 630b143f9..e79660d87 100644 --- a/apps/vault/src/shared/guard/__test__/unit/admin-api-key.guard.spec.ts +++ b/apps/vault/src/shared/guard/__test__/unit/admin-api-key.guard.spec.ts @@ -1,7 +1,7 @@ import { secret } from '@narval/nestjs-shared' import { ExecutionContext } from '@nestjs/common' import { mock } from 'jest-mock-extended' -import { AppService } from '../../../../vault/core/service/app.service' +import { AppService } from '../../../../app.service' import { REQUEST_HEADER_API_KEY } from '../../../constant' import { ApplicationException } from '../../../exception/application.exception' import { AdminApiKeyGuard } from '../../admin-api-key.guard' @@ -22,10 +22,11 @@ describe(AdminApiKeyGuard.name, () => { const mockAppService = (adminApiKey = 'test-admin-api-key') => { const app = { - adminApiKey: secret.hash(adminApiKey), + adminApiKeyHash: secret.hash(adminApiKey), id: 'test-app-id', - masterKey: 'test-master-key', - activated: true + encryptionMasterKey: 'test-master-key', + encryptionKeyringType: 'raw' as const, + authDisabled: false } const serviceMock = mock() diff --git a/apps/vault/src/shared/guard/__test__/unit/authorization.guard.spec.ts b/apps/vault/src/shared/guard/__test__/unit/authorization.guard.spec.ts new file mode 100644 index 000000000..6407c255b --- /dev/null +++ b/apps/vault/src/shared/guard/__test__/unit/authorization.guard.spec.ts @@ -0,0 +1,421 @@ +import { ConfigService } from '@narval/config-module' +import { LoggerService } from '@narval/nestjs-shared' +import { FIXTURE } from '@narval/policy-engine-shared' +import { + buildSignerEip191, + hash, + hexToBase64Url, + JwsdHeader, + Payload, + PrivateKey, + privateKeyToHex, + secp256k1PrivateKeyToJwk, + secp256k1PrivateKeyToPublicJwk, + secp256k1PublicKeyToJwk, + SigningAlg, + signJwsd, + signJwt +} from '@narval/signature' +import { ExecutionContext } from '@nestjs/common' +import { Reflector } from '@nestjs/core' +import { mock } from 'jest-mock-extended' +import { ZodError } from 'zod' +import { ClientService } from '../../../../client/core/service/client.service' +import { Config } from '../../../../main.config' +import { Client } from '../../../type/domain.type' +import { AuthorizationGuard } from '../../authorization.guard' + +const PRIVATE_KEY = '0x7cfef3303797cbc7515d9ce22ffe849c701b0f2812f999b0847229c47951fca5' +// Engine key used to sign the approval request +const enginePrivateJwk = secp256k1PrivateKeyToJwk(PRIVATE_KEY) +const pinnedPublicJWK = secp256k1PrivateKeyToPublicJwk(PRIVATE_KEY) + +const getBaseClient = (): Client => ({ + clientId: 'test-client', + auth: { + disabled: false, + local: { + jwsd: { + maxAge: 600, + requiredComponents: ['htm', 'uri', 'created', 'ath'] + }, + allowedUsersJwksUrl: null, + allowedUsers: null + }, + tokenValidation: { + disabled: false, + url: null, + jwksUrl: null, + verification: { + audience: null, + issuer: 'https://armory.narval.xyz', + maxTokenAge: 300, + requireBoundTokens: true, + allowBearerTokens: false, + allowWildcard: [ + 'path.to.allow', + 'transactionRequest.maxFeePerGas', + 'transactionRequest.maxPriorityFeePerGas', + 'transactionRequest.gas' + ] + }, + pinnedPublicKey: pinnedPublicJWK + } + }, + name: 'test-client', + configurationSource: 'dynamic', + backupPublicKey: null, + baseUrl: 'https://vault-test.narval.xyz', + createdAt: new Date(), + updatedAt: new Date() +}) + +const getJwsd = async ({ + userPrivateJwk, + baseUrl, + requestUrl, + accessToken, + payload +}: { + userPrivateJwk: PrivateKey + baseUrl?: string + requestUrl: string + accessToken?: string + payload: object | string +}) => { + const now = Math.floor(Date.now() / 1000) + + const jwsdSigner = buildSignerEip191(await privateKeyToHex(userPrivateJwk)) + const jwsdHeader: JwsdHeader = { + alg: SigningAlg.EIP191, + kid: userPrivateJwk.kid, + typ: 'gnap-binding-jwsd', + htm: 'POST', + uri: `${baseUrl || getBaseClient().baseUrl}${requestUrl}`, // matches the client baseUrl + request url + created: now, + ath: accessToken ? hexToBase64Url(hash(accessToken)) : undefined + } + + const jwsd = await signJwsd(payload, jwsdHeader, jwsdSigner).then((jws) => { + // Strip out the middle part for size + const parts = jws.split('.') + parts[1] = '' + return parts.join('.') + }) + + return jwsd +} + +const getAccessToken = async (request: unknown, opts: object = {}) => { + const payload: Payload = { + requestHash: hash(request), + sub: 'test-root-user-uid', + iss: 'https://armory.narval.xyz', + iat: Math.floor(Date.now() / 1000), + ...opts + } + const signer = buildSignerEip191(PRIVATE_KEY) + + return signJwt(payload, enginePrivateJwk, { alg: SigningAlg.EIP191 }, signer) +} + +describe('AuthorizationGuard', () => { + let mockClientService = mock() + let mockConfigService = mock>() + + let mockLogger = mock() + let mockReflector = mock() + + beforeEach(() => { + jest.resetAllMocks() + mockClientService = mock() + mockConfigService = mock>() + mockLogger = mock() + mockReflector = mock() + }) + + it('should be defined', () => { + const guard = new AuthorizationGuard(mockClientService, mockConfigService, mockReflector, mockLogger) + expect(guard).toBeDefined() + }) + + describe('canActivate', () => { + const mockExecutionContext = ({ request }: { request?: unknown } = {}) => { + const mockRequest = request || { + headers: {}, + body: {}, + url: '/test', + method: 'GET' + } + return { + switchToHttp: () => ({ + getRequest: () => mockRequest + }), + getHandler: jest.fn() + } as unknown as ExecutionContext + } + + it('should throw when client-id header is missing', async () => { + const guard = new AuthorizationGuard(mockClientService, mockConfigService, mockReflector, mockLogger) + await expect(guard.canActivate(mockExecutionContext())).rejects.toThrow('Missing or invalid x-client-id header') + }) + + it('should throw when client is not found', async () => { + const guard = new AuthorizationGuard(mockClientService, mockConfigService, mockReflector, mockLogger) + const mockRequest = { + headers: { 'x-client-id': 'client-that-does-not-exist' }, + body: {}, + url: '/test', + method: 'GET' + } + const context = mockExecutionContext({ request: mockRequest }) + + await expect(guard.canActivate(context)).rejects.toThrow('Client not found') + }) + + it('should pass when client auth is disabled', async () => { + const client = getBaseClient() + client.auth.disabled = true + mockClientService.findById.mockResolvedValue(client) + const guard = new AuthorizationGuard(mockClientService, mockConfigService, mockReflector, mockLogger) + + const mockRequest = { + headers: { 'x-client-id': 'test-client' }, + body: {}, + url: '/test', + method: 'GET' + } + const context = mockExecutionContext({ request: mockRequest }) + + await expect(guard.canActivate(context)).resolves.toEqual(true) + expect(mockLogger.warn).toHaveBeenCalled() + }) + + // For this scenario, we don't yet support JWKS, so if you disable tokenValidation you must pin the allowed users + it('should throw when client auth is enabled AND token validation is disabled AND no allowed users are configured', async () => { + const client = getBaseClient() + client.auth.tokenValidation.disabled = true + mockClientService.findById.mockResolvedValue(client) + const guard = new AuthorizationGuard(mockClientService, mockConfigService, mockReflector, mockLogger) + + const mockRequest = { + headers: { 'x-client-id': 'test-client' }, + body: {}, + url: '/test', + method: 'GET' + } + const context = mockExecutionContext({ request: mockRequest }) + + await expect(guard.canActivate(context)).rejects.toThrow('No allowed users configured for client') + expect(mockLogger.warn).toHaveBeenCalled() + }) + + it('should throw when client auth is enabled AND token validation is disabled AND invalid jwsd for allowedUsers', async () => { + const client = getBaseClient() + client.auth.tokenValidation.disabled = true + client.auth.local = { + jwsd: client.auth.local?.jwsd || { maxAge: 0, requiredComponents: [] }, // default needed to pass TS validation + allowedUsers: [ + { + userId: 'user-1', + publicKey: pinnedPublicJWK + } + ], + allowedUsersJwksUrl: null + } + mockClientService.findById.mockResolvedValue(client) + const guard = new AuthorizationGuard(mockClientService, mockConfigService, mockReflector, mockLogger) + + const mockRequest = { + headers: { 'x-client-id': 'test-client' }, + body: {}, + url: '/test', + method: 'GET' + } + const context = mockExecutionContext({ request: mockRequest }) + + await expect(guard.canActivate(context)).rejects.toThrow('Invalid request signature') + expect(mockLogger.warn).toHaveBeenCalled() + }) + + it('should pass when client auth is enabled AND token validation is disabled AND jwsd is valid for allowedUsers', async () => { + const userPrivateJwk = secp256k1PrivateKeyToJwk(FIXTURE.UNSAFE_PRIVATE_KEY.Alice) + const userJwk = secp256k1PublicKeyToJwk(FIXTURE.VIEM_ACCOUNT.Alice.publicKey) + const client = getBaseClient() + client.auth.tokenValidation.disabled = true + client.auth.local = { + jwsd: client.auth.local?.jwsd || { maxAge: 0, requiredComponents: [] }, // default needed to pass TS validation + allowedUsers: [ + { + userId: 'user-1', + publicKey: userJwk + } + ], + allowedUsersJwksUrl: null + } + mockClientService.findById.mockResolvedValue(client) + const guard = new AuthorizationGuard(mockClientService, mockConfigService, mockReflector, mockLogger) + const payload = { + value: 'test-value' + } + + const jwsd = await getJwsd({ + userPrivateJwk, + requestUrl: '/test', + payload + }) + + const mockRequest = { + headers: { 'x-client-id': 'test-client', 'detached-jws': jwsd }, + body: payload, + url: '/test', + method: 'POST' + } + const context = mockExecutionContext({ request: mockRequest }) + + await expect(guard.canActivate(context)).resolves.toEqual(true) + }) + + it('should throw when token validation is enabled and missing accessToken', async () => { + expect.assertions(2) + const client = getBaseClient() + mockClientService.findById.mockResolvedValue(client) + const guard = new AuthorizationGuard(mockClientService, mockConfigService, mockReflector, mockLogger) + const payload = { + value: 'test-value' + } + + const mockRequest = { + headers: { 'x-client-id': 'test-client' }, + body: payload, + url: '/test', + method: 'POST' + } + const context = mockExecutionContext({ request: mockRequest }) + + await expect(guard.canActivate(context)).rejects.toThrow(ZodError) + + const mockRequest2 = { + headers: { 'x-client-id': 'test-client', authorization: 'bearer 0000' }, + body: payload, + url: '/test', + method: 'POST' + } + const context2 = mockExecutionContext({ request: mockRequest2 }) + + await expect(guard.canActivate(context2)).rejects.toThrow( + 'Missing or invalid Access Token in Authorization header' + ) + }) + + // JWT Validation + it('should throw when no pinnedPublicKey is configured', async () => { + const client = getBaseClient() + client.auth.tokenValidation.pinnedPublicKey = null + mockClientService.findById.mockResolvedValue(client) + const guard = new AuthorizationGuard(mockClientService, mockConfigService, mockReflector, mockLogger) + const payload = { + value: 'test-value' + } + + const accessToken = await getAccessToken(payload) + + const mockRequest = { + headers: { 'x-client-id': 'test-client', authorization: `GNAP ${accessToken}` }, + body: payload, + url: '/test', + method: 'POST' + } + const context = mockExecutionContext({ request: mockRequest }) + + await expect(guard.canActivate(context)).rejects.toThrow('No engine key configured') + }) + + it('should throw when requieBoundTokens is true and token is not bound', async () => { + const userPrivateJwk = secp256k1PrivateKeyToJwk(FIXTURE.UNSAFE_PRIVATE_KEY.Alice) + const client = getBaseClient() + mockClientService.findById.mockResolvedValue(client) + const guard = new AuthorizationGuard(mockClientService, mockConfigService, mockReflector, mockLogger) + const payload = { + value: 'test-value' + } + + const accessToken = await getAccessToken(payload, { sub: 'user-1' }) + const jwsd = await getJwsd({ + userPrivateJwk, + requestUrl: '/test', + payload, + accessToken + }) + + const mockRequest = { + headers: { 'x-client-id': 'test-client', authorization: `GNAP ${accessToken}`, 'detached-jws': jwsd }, + body: payload, + url: '/test', + method: 'POST' + } + const context = mockExecutionContext({ request: mockRequest }) + + await expect(guard.canActivate(context)).rejects.toThrow( + 'Access Token must be bound to a key referenced in the cnf claim' + ) + }) + + it('should pass when token is bound but used by a different user', async () => { + const userJwk = secp256k1PublicKeyToJwk(FIXTURE.VIEM_ACCOUNT.Alice.publicKey) + const client = getBaseClient() + mockClientService.findById.mockResolvedValue(client) + const guard = new AuthorizationGuard(mockClientService, mockConfigService, mockReflector, mockLogger) + const payload = { + value: 'test-value' + } + + const accessToken = await getAccessToken(payload, { sub: 'user-1', cnf: userJwk }) + const jwsd = await getJwsd({ + userPrivateJwk: secp256k1PrivateKeyToJwk(FIXTURE.UNSAFE_PRIVATE_KEY.Bob), // DIFFERENT user key + requestUrl: '/test', + payload, + accessToken + }) + + const mockRequest = { + headers: { 'x-client-id': 'test-client', authorization: `GNAP ${accessToken}`, 'detached-jws': jwsd }, + body: payload, + url: '/test', + method: 'POST' + } + const context = mockExecutionContext({ request: mockRequest }) + + await expect(guard.canActivate(context)).rejects.toThrow('Invalid signature') + }) + + it('should pass when token is valid & request is bound with jwsd', async () => { + const userPrivateJwk = secp256k1PrivateKeyToJwk(FIXTURE.UNSAFE_PRIVATE_KEY.Alice) + const userJwk = secp256k1PublicKeyToJwk(FIXTURE.VIEM_ACCOUNT.Alice.publicKey) + const client = getBaseClient() + mockClientService.findById.mockResolvedValue(client) + const guard = new AuthorizationGuard(mockClientService, mockConfigService, mockReflector, mockLogger) + const payload = { + value: 'test-value' + } + + const accessToken = await getAccessToken(payload, { sub: 'user-1', cnf: userJwk }) + const jwsd = await getJwsd({ + userPrivateJwk, + requestUrl: '/test', + payload, + accessToken + }) + + const mockRequest = { + headers: { 'x-client-id': 'test-client', authorization: `GNAP ${accessToken}`, 'detached-jws': jwsd }, + body: payload, + url: '/test', + method: 'POST' + } + const context = mockExecutionContext({ request: mockRequest }) + + await expect(guard.canActivate(context)).resolves.toEqual(true) + }) + }) +}) diff --git a/apps/vault/src/shared/guard/admin-api-key.guard.ts b/apps/vault/src/shared/guard/admin-api-key.guard.ts index 41b9855a4..812fd3e5d 100644 --- a/apps/vault/src/shared/guard/admin-api-key.guard.ts +++ b/apps/vault/src/shared/guard/admin-api-key.guard.ts @@ -1,6 +1,6 @@ import { secret } from '@narval/nestjs-shared' import { CanActivate, ExecutionContext, HttpStatus, Injectable } from '@nestjs/common' -import { AppService } from '../../vault/core/service/app.service' +import { AppService } from '../../app.service' import { REQUEST_HEADER_API_KEY } from '../constant' import { ApplicationException } from '../exception/application.exception' @@ -21,6 +21,6 @@ export class AdminApiKeyGuard implements CanActivate { const app = await this.appService.getAppOrThrow() - return app.adminApiKey === secret.hash(apiKey) + return app.adminApiKeyHash === secret.hash(apiKey) } } diff --git a/apps/vault/src/shared/guard/authorization.guard.ts b/apps/vault/src/shared/guard/authorization.guard.ts index 95c7b0abc..9e1aa8d96 100644 --- a/apps/vault/src/shared/guard/authorization.guard.ts +++ b/apps/vault/src/shared/guard/authorization.guard.ts @@ -1,6 +1,6 @@ import { ConfigService } from '@narval/config-module' -import { REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' -import { JwtVerifyOptions, publicKeySchema, verifyJwsd, verifyJwt } from '@narval/signature' +import { LoggerService, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' +import { Jwsd, JwtVerifyOptions, PublicKey, publicKeySchema, verifyJwsd, verifyJwt } from '@narval/signature' import { CanActivate, ExecutionContext, HttpStatus, Injectable } from '@nestjs/common' import { Reflector } from '@nestjs/core' import { z } from 'zod' @@ -8,10 +8,14 @@ import { ClientService } from '../../client/core/service/client.service' import { Config } from '../../main.config' import { PermissionGuard } from '../decorator/permission-guard.decorator' import { ApplicationException } from '../exception/application.exception' -import { Client } from '../type/domain.type' +import { Client, VaultPermission } from '../type/domain.type' +// Option 2: Add validation with custom message const AuthorizationHeaderSchema = z.object({ - authorization: z.string() + authorization: z.string({ + required_error: 'Authorization header is required', + invalid_type_error: 'Authorization header must be a string' + }) }) const ONE_MINUTE = 60 @@ -21,7 +25,8 @@ export class AuthorizationGuard implements CanActivate { constructor( private clientService: ClientService, private configService: ConfigService, - private reflector: Reflector + private reflector: Reflector, + private logger: LoggerService ) {} async canActivate(context: ExecutionContext): Promise { @@ -35,6 +40,57 @@ export class AuthorizationGuard implements CanActivate { }) } + const client = await this.clientService.findById(clientId) + if (!client) { + throw new ApplicationException({ + message: 'Client not found', + suggestedHttpStatusCode: HttpStatus.NOT_FOUND + }) + } + + if (client?.auth.disabled) { + this.logger.warn('Client auth disabled -- all request will be permitted') + return true + } + + if (client?.auth.tokenValidation.disabled) { + this.logger.warn('Client token validation disabled -- auth tokens will not be required') + // TODO: should we not return, in case AuthN is used w/out validation? + + // TODO: add JWKS as an option instead of allowedUsers + const allowedUsers = client.auth.local?.allowedUsers + if (!allowedUsers?.length) { + // JWT Validation is disabled, but Auth is enabled; then we MUST have an allow-list of user keys + throw new ApplicationException({ + message: 'No allowed users configured for client', + suggestedHttpStatusCode: HttpStatus.UNAUTHORIZED + }) + } + + // Try each allowed user's public key until we find one that validates + let validJwsd: Jwsd | undefined + for (const user of allowedUsers) { + try { + validJwsd = await this.validateJwsdAuthentication(context, client, user.publicKey) + break + } catch (err) { + // Continue trying other keys + continue + } + } + + if (!validJwsd) { + throw new ApplicationException({ + message: 'Invalid request signature', + suggestedHttpStatusCode: HttpStatus.UNAUTHORIZED + }) + } + + return true + } + + // Validate the Access Token. + // Expect the header in the format "GNAP " const headers = AuthorizationHeaderSchema.parse(req.headers) const accessToken: string | undefined = headers.authorization.split('GNAP ')[1] @@ -46,17 +102,9 @@ export class AuthorizationGuard implements CanActivate { }) } - const client = await this.clientService.findById(clientId) - - if (!client) { - throw new ApplicationException({ - message: 'Client not found', - suggestedHttpStatusCode: HttpStatus.NOT_FOUND - }) - } - + // Get the Permissions (scopes) required from the request decorator, if it exists. const { request: requestHash } = req.body - const permissions = this.reflector.get(PermissionGuard, context.getHandler()) + const permissions: VaultPermission[] | undefined = this.reflector.get(PermissionGuard, context.getHandler()) const access = permissions && permissions.length > 0 ? [ @@ -68,10 +116,10 @@ export class AuthorizationGuard implements CanActivate { : undefined const opts: JwtVerifyOptions = { - audience: client.audience, - issuer: client.issuer, - maxTokenAge: client.maxTokenAge, - allowWildcard: client.allowWildcard, + audience: client.auth.tokenValidation.verification.audience, + issuer: client.auth.tokenValidation.url, + maxTokenAge: client.auth.tokenValidation.verification.maxTokenAge, + allowWildcard: client.auth.tokenValidation.verification.allowWildcard, ...(requestHash && { requestHash }), ...(access && { access }) } @@ -79,25 +127,65 @@ export class AuthorizationGuard implements CanActivate { return this.validateToken(context, client, accessToken, opts) } + private async validateJwsdAuthentication( + context: ExecutionContext, + client: Client, + publicKey: PublicKey, + accessToken?: string + ): Promise { + const req = context.switchToHttp().getRequest() + + // TODO: support httpsig proof + const jwsdHeader = req.headers['detached-jws'] + + if (!jwsdHeader) { + throw new ApplicationException({ + message: `Missing detached-jws header`, + suggestedHttpStatusCode: HttpStatus.FORBIDDEN + }) + } + + // Will throw if not valid + try { + // TODO: add optionality for requiredComponents; for now, we always require all the jwsd claims (htm, uri, created, ath) + const defaultBaseUrl = this.configService.get('baseUrl') + const jwsd = await verifyJwsd(jwsdHeader, publicKey, { + requestBody: req.body, // Verify the request body + accessToken, // Verify that the ATH matches the access token + uri: `${(client.baseUrl || defaultBaseUrl).replace(/\/+$/, '')}${req.url.replace(/^\/+/, '/')}`, // Verify the request URI; ensure proper url joining + htm: req.method, // Verify the request method + maxTokenAge: client.auth.local?.jwsd.maxAge || ONE_MINUTE + }) + + return jwsd + } catch (err) { + throw new ApplicationException({ + message: err.message, + origin: err, + suggestedHttpStatusCode: HttpStatus.FORBIDDEN + }) + } + } + private async validateToken( context: ExecutionContext, client: Client, token: string, opts: JwtVerifyOptions ): Promise { - const req = context.switchToHttp().getRequest() - - if (!client.engineJwk) { + if (!client.auth.tokenValidation.pinnedPublicKey) { + // TODO: check jwksUrl too + // TODO: check opaque token; ping the auth server to check validity throw new ApplicationException({ message: 'No engine key configured', suggestedHttpStatusCode: HttpStatus.UNAUTHORIZED }) } - const clientJwk = publicKeySchema.parse(client.engineJwk) + const pinnedPublicKey = publicKeySchema.parse(client.auth.tokenValidation.pinnedPublicKey) // Validate the JWT has a valid signature for the expected client key & the request matches - const { payload } = await verifyJwt(token, clientJwk, opts).catch((err) => { + const { payload } = await verifyJwt(token, pinnedPublicKey, opts).catch((err) => { throw new ApplicationException({ message: err.message, origin: err, @@ -105,35 +193,24 @@ export class AuthorizationGuard implements CanActivate { }) }) - // We want to also check the client key in cnf so we can optionally do bound requests + // Signed Request / Bound Token ->> + // If the client has `requireBoundTokens` set, OR if the token has a `cnf` field, the request MUST include a proof of key possession + // If `requireBoundTokens` is set but the token does not have a `cnf`, we consider this _invalid_, because we won't accept unbound tokens. + // This means that this server can only accept bound tokens, and/or the auth server can issue a bound token that shouldn't be accepted without proof. + + if (client.auth.tokenValidation.verification.requireBoundTokens && !payload.cnf) { + throw new ApplicationException({ + message: 'Access Token must be bound to a key referenced in the cnf claim', + suggestedHttpStatusCode: HttpStatus.FORBIDDEN + }) + } + + // We don't require it here, but if the token is bound (cnf claim) then we must verify the request includes a proof of key possession if (payload.cnf) { const boundKey = payload.cnf - const jwsdHeader = req.headers['detached-jws'] - if (!jwsdHeader) { - throw new ApplicationException({ - message: `Missing detached-jws header`, - suggestedHttpStatusCode: HttpStatus.FORBIDDEN - }) - } - - // Will throw if not valid - try { - const defaultBaseUrl = this.configService.get('baseUrl') - await verifyJwsd(jwsdHeader, boundKey, { - requestBody: req.body, // Verify the request body - accessToken: token, // Verify that the ATH matches the access token - uri: `${client.baseUrl || defaultBaseUrl}${req.url}`, // Verify the request URI - htm: req.method, // Verify the request method - maxTokenAge: ONE_MINUTE - }) - } catch (err) { - throw new ApplicationException({ - message: err.message, - origin: err, - suggestedHttpStatusCode: HttpStatus.FORBIDDEN - }) - } + await this.validateJwsdAuthentication(context, client, boundKey, token) + // Valid! } return true diff --git a/apps/vault/src/shared/module/key-value/key-value.module.ts b/apps/vault/src/shared/module/key-value/key-value.module.ts index 38067a354..e488b35bd 100644 --- a/apps/vault/src/shared/module/key-value/key-value.module.ts +++ b/apps/vault/src/shared/module/key-value/key-value.module.ts @@ -2,8 +2,8 @@ import { ConfigService } from '@narval/config-module' import { EncryptionModule } from '@narval/encryption-module' import { LoggerService } from '@narval/nestjs-shared' import { Module, forwardRef } from '@nestjs/common' -import { AppService } from '../../../vault/core/service/app.service' -import { VaultModule } from '../../../vault/vault.module' +import { AppService } from '../../../app.service' +import { AppModule } from '../../../main.module' import { EncryptionModuleOptionFactory } from '../../factory/encryption-module-option.factory' import { PersistenceModule } from '../persistence/persistence.module' import { KeyValueRepository } from './core/repository/key-value.repository' @@ -14,9 +14,11 @@ import { PrismaKeyValueRepository } from './persistence/repository/prisma-key-va @Module({ imports: [ - PersistenceModule, + PersistenceModule.register({ + imports: [] // Specifically erase the imports, so we do NOT initialize the EncryptionModule since KV will handle it's own encryption + }), EncryptionModule.registerAsync({ - imports: [forwardRef(() => VaultModule)], + imports: [forwardRef(() => AppModule)], inject: [ConfigService, AppService, LoggerService], useClass: EncryptionModuleOptionFactory }) diff --git a/apps/vault/src/shared/module/persistence/persistence.module.ts b/apps/vault/src/shared/module/persistence/persistence.module.ts index 95d5dcd4c..01c9fe22a 100644 --- a/apps/vault/src/shared/module/persistence/persistence.module.ts +++ b/apps/vault/src/shared/module/persistence/persistence.module.ts @@ -1,9 +1,42 @@ -import { Module } from '@nestjs/common' +import { ConfigService } from '@narval/config-module' +import { EncryptionModule } from '@narval/encryption-module' +import { LoggerService } from '@narval/nestjs-shared' +import { DynamicModule, forwardRef, ForwardReference, Module, Type } from '@nestjs/common' +import { AppService } from '../../../app.service' +import { AppModule } from '../../../main.module' +import { EncryptionModuleOptionFactory } from '../../factory/encryption-module-option.factory' import { PrismaService } from './service/prisma.service' import { TestPrismaService } from './service/test-prisma.service' -@Module({ - exports: [PrismaService, TestPrismaService], - providers: [PrismaService, TestPrismaService] -}) -export class PersistenceModule {} +@Module({}) +export class PersistenceModule { + static forRoot(): DynamicModule { + return { + module: PersistenceModule, + global: true, + imports: [ + EncryptionModule.registerAsync({ + imports: [forwardRef(() => AppModule)], + inject: [ConfigService, AppService, LoggerService], + useClass: EncryptionModuleOptionFactory + }) + ], + providers: [PrismaService, TestPrismaService], + exports: [PrismaService, TestPrismaService] + } + } + static register(config: { imports?: Array } = {}): DynamicModule { + return { + module: PersistenceModule, + imports: config.imports || [ + EncryptionModule.registerAsync({ + imports: [forwardRef(() => AppModule)], + inject: [ConfigService, AppService, LoggerService], + useClass: EncryptionModuleOptionFactory + }) + ], + providers: [PrismaService, TestPrismaService], + exports: [PrismaService, TestPrismaService] + } + } +} diff --git a/apps/vault/src/shared/module/persistence/schema/migrations/20241206135505_normalize_client_and_app/migration.sql b/apps/vault/src/shared/module/persistence/schema/migrations/20241206135505_normalize_client_and_app/migration.sql new file mode 100644 index 000000000..14ed084ed --- /dev/null +++ b/apps/vault/src/shared/module/persistence/schema/migrations/20241206135505_normalize_client_and_app/migration.sql @@ -0,0 +1,60 @@ +/* + Warnings: + + - You are about to drop the column `admin_api_key` on the `vault` table. All the data in the column will be lost. + - You are about to drop the column `master_key` on the `vault` table. All the data in the column will be lost. + - Added the required column `encryption_keyring_type` to the `vault` table without a default value. This is not possible if the table is not empty. + +*/ + +-- AlterTable +ALTER TABLE "vault" DROP COLUMN "admin_api_key", +DROP COLUMN "master_key", +ADD COLUMN "admin_api_key_hash" TEXT, +ADD COLUMN "auth_disabled" BOOLEAN, +ADD COLUMN "encryption_keyring_type" TEXT NOT NULL, +ADD COLUMN "encryption_master_aws_kms_arn" TEXT, +ADD COLUMN "enncryption_master_key" TEXT; + +-- CreateTable +CREATE TABLE "client" ( + "client_id" TEXT NOT NULL, + "name" TEXT NOT NULL, + "configuration_source" TEXT NOT NULL, + "auth_disabled" BOOLEAN NOT NULL, + "token_validation_disabled" BOOLEAN NOT NULL, + "backup_public_key" TEXT, + "base_url" TEXT, + "authorization_server_url" TEXT, + "authorization_issuer" TEXT, + "authorization_audience" TEXT, + "authorization_max_token_age" INTEGER, + "authorization_jwks_url" TEXT, + "authorization_pinned_public_key" TEXT, + "authorization_require_bound_tokens" BOOLEAN NOT NULL, + "authorization_allow_bearer_tokens" BOOLEAN NOT NULL, + "authorization_allow_wildcards" TEXT, + "local_auth_allowed_users_jwks_url" TEXT, + "local_auth_jwsd_enabled" BOOLEAN NOT NULL, + "jwsd_max_age" INTEGER, + "jwsd_required_components" TEXT, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "client_pkey" PRIMARY KEY ("client_id") +); + +-- CreateTable +CREATE TABLE "client_local_auth_allowed_user" ( + "id" TEXT NOT NULL, + "user_id" TEXT NOT NULL, + "client_id" TEXT NOT NULL, + "public_key" TEXT NOT NULL, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "client_local_auth_allowed_user_pkey" PRIMARY KEY ("id") +); + +-- AddForeignKey +ALTER TABLE "client_local_auth_allowed_user" ADD CONSTRAINT "client_local_auth_allowed_user_client_id_fkey" FOREIGN KEY ("client_id") REFERENCES "client"("client_id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/apps/vault/src/shared/module/persistence/schema/migrations/20241212175217_encrypted_json_is_stringified/migration.sql b/apps/vault/src/shared/module/persistence/schema/migrations/20241212175217_encrypted_json_is_stringified/migration.sql new file mode 100644 index 000000000..f92378e4d --- /dev/null +++ b/apps/vault/src/shared/module/persistence/schema/migrations/20241212175217_encrypted_json_is_stringified/migration.sql @@ -0,0 +1,6 @@ +-- AlterTable +ALTER TABLE "provider_connection" ALTER COLUMN "credentials" SET DATA TYPE TEXT; + +-- AlterTable +ALTER TABLE "transit_encryption_key" ALTER COLUMN "private_key" SET DATA TYPE TEXT, +ALTER COLUMN "public_key" SET DATA TYPE TEXT; diff --git a/apps/vault/src/shared/module/persistence/schema/schema.prisma b/apps/vault/src/shared/module/persistence/schema/schema.prisma index b573bd7ae..ce7b5212f 100644 --- a/apps/vault/src/shared/module/persistence/schema/schema.prisma +++ b/apps/vault/src/shared/module/persistence/schema/schema.prisma @@ -14,9 +14,14 @@ datasource db { } model Vault { - id String @id - masterKey String? @map("master_key") - adminApiKey String? @map("admin_api_key") + id String @id + // Encryption options, possibly set from Config file + encryptionKeyringType String @map("encryption_keyring_type") // raw | awskms + encryptionMasterKey String? @map("enncryption_master_key") /// @encrypted by masterPassword KEK + encryptionMasterAwsKmsArn String? @map("encryption_master_aws_kms_arn") // only if type = awskms + // Auth Options, set from Config file + authDisabled Boolean? @map("auth_disabled") + adminApiKeyHash String? @map("admin_api_key_hash") /// hash, not plaintext @@map("vault") } @@ -35,14 +40,62 @@ model KeyValue { model TransitEncryptionKey { id String @id @default(cuid()) clientId String @map("client_id") - privateKey Json @map("private_key") - publicKey Json @map("public_key") + privateKey String @map("private_key") // @encrypted stringified JSON + publicKey String @map("public_key") // stringified JSON createdAt DateTime @default(now()) @@map("transit_encryption_key") } +model Client { + clientId String @id @map("client_id") + name String @map("name") + configurationSource String @map("configuration_source") // declarative | dynamic + authDisabled Boolean @map("auth_disabled") + tokenValidationDisabled Boolean @map("token_validation_disabled") + backupPublicKey String? @map("backup_public_key") // Stringified JSON + baseUrl String? @map("base_url") // If you want to override the used for verifying jwsd/httpsig + + // JWT Token Validation + authorizationServerUrl String? @map("authorization_server_url") + authorizationIssuer String? @map("authorization_issuer") + authorizationAudience String? @map("authorization_audience") + authorizationMaxTokenAge Int? @map("authorization_max_token_age") + authorizationJwksUrl String? @map("authorization_jwks_url") + authorizationPinnedPublicKey String? @map("authorization_pinned_public_key") // Stringified JSON + authorizationRequireBoundTokens Boolean @map("authorization_require_bound_tokens") + authorizationAllowBearerTokens Boolean @map("authorization_allow_bearer_tokens") + authorizationAllowWildcards String? @map("authorization_allow_wildcards") + + // Local Authentication Methods + // Optionally restrict to specific user credentials from a JWKS endpoint + localAuthAllowedUsersJwksUrl String? @map("local_auth_allowed_users_jwks_url") + localAuthJwsdEnabled Boolean @map("local_auth_jwsd_enabled") // Do we allow JWSD? + jwsdMaxAge Int? @map("jwsd_max_age") + jwsdRequiredComponents String? @map("jwsd_required_components") // comma-separated list: htm,uri,ath,created + + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") + + localAuthAllowedUsers ClientLocalAuthAllowedUser[] + + @@map("client") +} + +model ClientLocalAuthAllowedUser { + id String @id // clientId:userId, to be globally unique + userId String @map("user_id") + clientId String @map("client_id") + publicKey String @map("public_key") // Stringified JSON + client Client @relation(fields: [clientId], references: [clientId]) + + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") + + @@map("client_local_auth_allowed_user") +} + model ProviderWallet { id String @id label String? @@ -57,7 +110,6 @@ model ProviderWallet { sourceTransfers ProviderTransfer[] @relation("SourceWallet") @@unique([clientId, externalId]) - @@map("provider_wallet") } @@ -78,7 +130,6 @@ model ProviderAccount { sourceTransfers ProviderTransfer[] @relation("SourceAccount") @@unique([clientId, externalId]) - @@map("provider_account") } @@ -97,7 +148,6 @@ model ProviderAddress { sourceTransfers ProviderTransfer[] @relation("SourceAddress") @@unique([clientId, externalId]) - @@map("provider_address") } @@ -117,7 +167,6 @@ model ProviderKnownDestination { connection ProviderConnection @relation(fields: [connectionId], references: [id]) @@unique([clientId, externalId]) - @@map("provider_known_destination") } @@ -127,9 +176,9 @@ model ProviderConnection { provider String url String? label String? - credentials Json? + credentials String? // @encrypted stringified JSON status String - integrity String @map("_integrity") + integrity String? @map("_integrity") // IMPORTANT: Don't default DateTime to `now()` on this table because the // integrity column needs to hash all data at the application level. createdAt DateTime @map("created_at") diff --git a/apps/vault/src/shared/module/persistence/service/prisma.service.ts b/apps/vault/src/shared/module/persistence/service/prisma.service.ts index e7a7ab672..fe8aa0f15 100644 --- a/apps/vault/src/shared/module/persistence/service/prisma.service.ts +++ b/apps/vault/src/shared/module/persistence/service/prisma.service.ts @@ -1,22 +1,265 @@ import { ConfigService } from '@narval/config-module' +import { EncryptionService } from '@narval/encryption-module' import { LoggerService } from '@narval/nestjs-shared' -import { Injectable, OnApplicationShutdown, OnModuleDestroy, OnModuleInit } from '@nestjs/common' -import { PrismaClient } from '@prisma/client/vault' +import { Injectable, OnApplicationShutdown, OnModuleDestroy, OnModuleInit, Optional } from '@nestjs/common' +import { hmac } from '@noble/hashes/hmac' +import { sha256 } from '@noble/hashes/sha2' +import { bytesToHex } from '@noble/hashes/utils' +import { Prisma, PrismaClient } from '@prisma/client/vault' +import { canonicalize } from 'packages/signature/src/lib/json.util' import { Config } from '../../../../main.config' +const ENCRYPTION_PREFIX = 'enc.v1.' // Version prefix helps with future encryption changes +const INTEGRITY_PREFIX = 'hmac.v1.' // Version prefix helps with future integrity changes + +/** + * To encrypt a field, simply reference the Model as the key, and the fields in an array. + * NOTE: encrypted fields MUST be of string type. JSON data should be stringified before/after encryption/decryption; this assumes Strings. + */ +const encryptedModelFields = { + Client: [], + ProviderConnection: [Prisma.ProviderConnectionScalarFieldEnum.credentials], + TransitEncryptionKey: [Prisma.TransitEncryptionKeyScalarFieldEnum.privateKey] +} + +const modelWithHmacIntegrity = { + ProviderConnection: { + [Prisma.ProviderConnectionScalarFieldEnum.id]: { + integrity: true, + nullable: false + }, + [Prisma.ProviderConnectionScalarFieldEnum.clientId]: { + integrity: true, + nullable: false + }, + [Prisma.ProviderConnectionScalarFieldEnum.provider]: { + integrity: true, + nullable: false + }, + [Prisma.ProviderConnectionScalarFieldEnum.url]: { + integrity: true, + nullable: true + }, + [Prisma.ProviderConnectionScalarFieldEnum.label]: { + integrity: true, + nullable: true + }, + [Prisma.ProviderConnectionScalarFieldEnum.credentials]: { + integrity: true, + nullable: true + }, + [Prisma.ProviderConnectionScalarFieldEnum.status]: { + integrity: true, + nullable: false + }, + [Prisma.ProviderConnectionScalarFieldEnum.createdAt]: { + integrity: true, + nullable: false + }, + [Prisma.ProviderConnectionScalarFieldEnum.updatedAt]: { + integrity: true, + nullable: false + }, + [Prisma.ProviderConnectionScalarFieldEnum.revokedAt]: { + integrity: true, + nullable: true + } + } +} + +const getHmac = (secret: string, value: Record) => { + const integrity = hmac(sha256, secret, canonicalize(value)) + return `${INTEGRITY_PREFIX}${bytesToHex(integrity)}` +} + +const buildEncryptionExtension = ( + configService: ConfigService, + logger: LoggerService, + encryptionService: EncryptionService +) => { + // Generate the hmac + const hmacSecret = configService.get('keyring.hmacSecret') + if (!hmacSecret) { + logger.error('HMAC secret is not set, integrity verification will not be performed') + throw new Error('HMAC secret is not set, integrity verification will not be performed') + } + + const encryptToString = async (value: string) => { + const encryptedBuffer = await encryptionService.encrypt(value) + const encryptedString = encryptedBuffer.toString('hex') + return `${ENCRYPTION_PREFIX}${encryptedString}` + } + + const decryptToString = async (value: string) => { + if (!value.startsWith(ENCRYPTION_PREFIX)) { + return value + } + const decryptedBuffer = await encryptionService.decrypt(Buffer.from(value.slice(ENCRYPTION_PREFIX.length), 'hex')) + return decryptedBuffer.toString() + } + + return Prisma.defineExtension({ + name: 'encryption', + query: { + async $allOperations({ model, operation, args, query }) { + logger.log('Extended ALL OPERATIONS method') + if (!model || !(model in encryptedModelFields)) { + return query(args) + } + const fields = encryptedModelFields[model as keyof typeof encryptedModelFields] + + // For write operations, encrypt. + const writeOps = ['create', 'upsert', 'update', 'updateMany', 'createMany'] + if (writeOps.includes(operation)) { + let dataToUpdate: Record[] = [] + if (operation === 'upsert') { + if (args.update) { + dataToUpdate.push(args.update) + } + if (args.create) { + dataToUpdate.push(args.create) + } + } else if (Array.isArray(args.data)) { + dataToUpdate = args.data + } else { + dataToUpdate = [args.data] + } + // For each field-to-encrypt, for each object being created, encrypt the field. + await Promise.all( + fields.map(async (field) => { + await Promise.all( + dataToUpdate.map(async (item: Record) => { + if (item[field] && typeof item[field] === 'string') { + item[field] = await encryptToString(item[field] as string) + } + }) + ) + }) + ) + // Data has been encrypted. + // Now, generate the _integrity hmac + // The data must include every field on the model; if not, we will reject this operation. + if (model in modelWithHmacIntegrity) { + const fields = modelWithHmacIntegrity[model as keyof typeof modelWithHmacIntegrity] + for (const data of dataToUpdate) { + // Create object to hold fields that should be covered by integrity + const integrityCovered: Record = {} + + // Iterate through all configured fields for this model + for (const [fieldName, fieldSettings] of Object.entries(fields)) { + // Check if field is required but missing + integrityCovered[fieldName] = data[fieldName] + if (!fieldSettings.nullable && data[fieldName] === undefined) { + logger.error(`Missing required field ${fieldName} in data, needed for integrity hmac`) + throw new Error(`Missing required field ${fieldName} in data, needed for integrity hmac`) + } + if (fieldSettings.nullable && !data[fieldName]) { + // Ensure we capture the null in the integrity object + integrityCovered[fieldName] = null + } + } + + const integrity = getHmac(hmacSecret, integrityCovered) + data.integrity = integrity + } + } + + return query(args) + } + + // For read operations, decrypt. + const readOps = ['findUnique', 'findMany', 'findUniqueOrThrow', 'findFirst', 'findFirstOrThrow'] as const + type ReadOp = (typeof readOps)[number] + + if (readOps.includes(operation as ReadOp)) { + const result = await query(args) + + // Handle non-record results + if (!result || typeof result === 'number' || 'count' in result) { + return result + } + + // Handle array or single result + const items = Array.isArray(result) ? result : [result] + + await Promise.all( + items.map(async (item: Record) => { + // If it has an `integrity` field, verify it's integrity + let skipIntegrityAndDecryption = false + if (model in modelWithHmacIntegrity) { + const fields = modelWithHmacIntegrity[model as keyof typeof modelWithHmacIntegrity] + // Create object to hold fields that should be covered by integrity + const integrityCovered: Record = {} + + // Iterate through all configured fields for this model + for (const [fieldName, fieldSettings] of Object.entries(fields)) { + integrityCovered[fieldName] = item[fieldName] + + // If there is an integrity field that is in args.select with `false` then skip integrity verification & decryption + if (fieldSettings.integrity && args.select && args.select[fieldName] === false) { + logger.log(`Skipping integrity verification & decryption due to subset of fields queried`) + skipIntegrityAndDecryption = true + return + } + + // Check if field is required but missing + if (!fieldSettings.nullable && item[fieldName] === undefined) { + logger.error( + `Missing required field ${fieldName} in data, needed for integrity hmac, did your query forget it?` + ) + throw new Error(`Missing required field ${fieldName} in data, needed for integrity hmac`) + } + } + + const integrityToVerify = getHmac(hmacSecret, integrityCovered) + if (integrityToVerify !== item.integrity) { + logger.error('Integrity verification failed', { + integrityToVerify, + item, + args + }) + throw new Error('Integrity verification failed') + } + } + // We passed integrity verification, so we can decrypt the fields + if (!skipIntegrityAndDecryption) { + await Promise.all( + fields.map(async (field) => { + if (item[field] && typeof item[field] === 'string') { + item[field] = await decryptToString(item[field] as string) + } + }) + ) + } + }) + ) + + return result + } + + return query(args) + } + } + }) +} + @Injectable() export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy, OnApplicationShutdown { constructor( configService: ConfigService, - private logger: LoggerService + private logger: LoggerService, + @Optional() encryptionService?: EncryptionService ) { const url = configService.get('database.url') - super({ datasources: { db: { url } } }) + if (encryptionService) { + logger.log('Instantiating Prisma encryption extension') + Object.assign(this, this.$extends(buildEncryptionExtension(configService, logger, encryptionService))) + } } async onModuleInit() { @@ -40,7 +283,7 @@ export class PrismaService extends PrismaClient implements OnModuleInit, OnModul onApplicationShutdown(signal: string) { this.logger.log('Disconnecting from Prisma on application shutdown', signal) - // The $disconnect method returns a promise, so idealy we should wait for it + // The $disconnect method returns a promise, so ideally we should wait for it // to finish. However, the onApplicationShutdown, returns `void` making it // impossible to ensure the database will be properly disconnected before // the shutdown. diff --git a/apps/vault/src/shared/module/persistence/service/test-prisma.service.ts b/apps/vault/src/shared/module/persistence/service/test-prisma.service.ts index 0f9b45051..514f2ddf4 100644 --- a/apps/vault/src/shared/module/persistence/service/test-prisma.service.ts +++ b/apps/vault/src/shared/module/persistence/service/test-prisma.service.ts @@ -39,12 +39,16 @@ export class TestPrismaService { async seedBrokerTestData(): Promise { const client = this.getClient() - await client.providerWallet.createMany({ - data: TEST_WALLETS - }) await client.providerConnection.createMany({ - data: TEST_CONNECTIONS + data: TEST_CONNECTIONS.map((connection) => ({ + ...connection, + credentials: JSON.stringify(connection.credentials) + })) + }) + + await client.providerWallet.createMany({ + data: TEST_WALLETS }) await client.providerWalletConnection.createMany({ diff --git a/apps/vault/src/shared/type/domain.type.ts b/apps/vault/src/shared/type/domain.type.ts index ee438f024..d39adcde0 100644 --- a/apps/vault/src/shared/type/domain.type.ts +++ b/apps/vault/src/shared/type/domain.type.ts @@ -1,3 +1,4 @@ +import { Permission } from '@narval/armory-sdk' import { addressSchema, hexSchema } from '@narval/policy-engine-shared' import { Alg, Curves, publicKeySchema, rsaPrivateKeySchema, rsaPublicKeySchema } from '@narval/signature' import { z } from 'zod' @@ -15,7 +16,7 @@ export const CreateClientInput = z.object({ }) export type CreateClientInput = z.infer -export const Client = z.object({ +export const ClientV1 = z.object({ clientId: z.string(), engineJwk: publicKeySchema.optional(), @@ -37,13 +38,70 @@ export const Client = z.object({ createdAt: z.coerce.date(), updatedAt: z.coerce.date() }) +export type ClientV1 = z.infer + +export const ClientLocalAuthAllowedUser = z.object({ + userId: z.string(), + publicKey: publicKeySchema +}) +export type ClientLocalAuthAllowedUser = z.infer + +export const Client = z.object({ + clientId: z.string(), + name: z.string(), + configurationSource: z.literal('declarative').or(z.literal('dynamic')), // Declarative = comes from config file, Dyanmic = created at runtime + backupPublicKey: rsaPublicKeySchema.nullable(), + // Override if you want to use a different baseUrl for a single client. + baseUrl: z.string().nullable(), + + auth: z.object({ + disabled: z.boolean(), + local: z + .object({ + jwsd: z.object({ + maxAge: z.number(), + requiredComponents: z.array(z.string()) + }), + allowedUsersJwksUrl: z.string().nullable(), + allowedUsers: z.array(ClientLocalAuthAllowedUser).nullable() + }) + .nullable(), + tokenValidation: z.object({ + disabled: z.boolean(), + url: z.string().nullable(), + jwksUrl: z.string().nullable(), + pinnedPublicKey: publicKeySchema.nullable(), + verification: z.object({ + audience: z.string().nullable(), + issuer: z.string().nullable(), + maxTokenAge: z.number().nullable(), + requireBoundTokens: z.boolean(), + allowBearerTokens: z.boolean(), + allowWildcard: z.array(z.string()).nullable() + }) + }) + }), + + createdAt: z.coerce.date(), + updatedAt: z.coerce.date() +}) export type Client = z.infer -export const App = z.object({ +export const AppV1 = z.object({ id: z.string().min(1), adminApiKey: z.string().min(1).optional(), masterKey: z.string().min(1).optional() }) +export type AppV1 = z.infer + +export const App = z.object({ + id: z.string().min(1), + adminApiKeyHash: z.string().min(1).nullish(), + encryptionMasterKey: z.string().min(1).nullish(), + encryptionKeyringType: z.literal('raw').or(z.literal('awskms')), + encryptionMasterAwsKmsArn: z.string().nullish(), + authDisabled: z.boolean().optional() +}) export type App = z.infer export const Origin = { @@ -132,3 +190,10 @@ export type Algorithm = z.infer export const Curve = z.union([z.literal(Curves.P256), z.literal(Curves.SECP256K1)]) export type Curve = z.infer + +export const VaultPermission = { + ...Permission, + CONNECTION_WRITE: 'connection:write', + CONNECTION_READ: 'connection:read' +} as const +export type VaultPermission = (typeof VaultPermission)[keyof typeof VaultPermission] diff --git a/apps/vault/src/transit-encryption/core/service/__test__/integration/encryption-key.service.spec.ts b/apps/vault/src/transit-encryption/core/service/__test__/integration/encryption-key.service.spec.ts index 36a0c232a..02c026b2b 100644 --- a/apps/vault/src/transit-encryption/core/service/__test__/integration/encryption-key.service.spec.ts +++ b/apps/vault/src/transit-encryption/core/service/__test__/integration/encryption-key.service.spec.ts @@ -1,4 +1,5 @@ import { ConfigModule } from '@narval/config-module' +import { EncryptionModuleOptionProvider } from '@narval/encryption-module' import { LoggerModule } from '@narval/nestjs-shared' import { Alg, @@ -17,7 +18,9 @@ import { Test } from '@nestjs/testing' import { omit } from 'lodash' import { v4 as uuid } from 'uuid' import { load } from '../../../../../main.config' +import { AppModule } from '../../../../../main.module' import { PersistenceModule } from '../../../../../shared/module/persistence/persistence.module' +import { getTestRawAesKeyring } from '../../../../../shared/testing/encryption.testing' import { EncryptionKeyRepository } from '../../../../persistence/encryption-key.repository' import { InvalidJweHeaderException } from '../../../exception/invalid-jwe-header.exception' import { NotFoundException } from '../../../exception/not-found.exception' @@ -36,18 +39,24 @@ describe(EncryptionKeyService.name, () => { const clientId = uuid() - beforeEach(async () => { + beforeAll(async () => { const module = await Test.createTestingModule({ imports: [ - PersistenceModule, LoggerModule.forTest(), ConfigModule.forRoot({ load: [load], isGlobal: true - }) + }), + AppModule, + PersistenceModule.forRoot() ], providers: [EncryptionKeyService, EncryptionKeyRepository] - }).compile() + }) + .overrideProvider(EncryptionModuleOptionProvider) + .useValue({ + keyring: getTestRawAesKeyring() + }) + .compile() encryptionKeyService = module.get(EncryptionKeyService) encryptionKeyRepository = module.get(EncryptionKeyRepository) diff --git a/apps/vault/src/transit-encryption/persistence/encryption-key.repository.ts b/apps/vault/src/transit-encryption/persistence/encryption-key.repository.ts index 89194f768..b63af9edf 100644 --- a/apps/vault/src/transit-encryption/persistence/encryption-key.repository.ts +++ b/apps/vault/src/transit-encryption/persistence/encryption-key.repository.ts @@ -12,8 +12,8 @@ export class EncryptionKeyRepository { data: { id: encryptionKey.privateKey.kid, clientId: encryptionKey.clientId, - privateKey: rsaPrivateKeySchema.parse(encryptionKey.privateKey), - publicKey: rsaPublicKeySchema.parse(encryptionKey.publicKey), + privateKey: JSON.stringify(rsaPrivateKeySchema.parse(encryptionKey.privateKey)), + publicKey: JSON.stringify(rsaPublicKeySchema.parse(encryptionKey.publicKey)), createdAt: encryptionKey.createdAt } }) @@ -27,7 +27,12 @@ export class EncryptionKeyRepository { }) if (encryptionKey) { - return EncryptionKey.parse(encryptionKey) + // TODO: we have stringified json, so make sure to handle errors + return EncryptionKey.parse({ + ...encryptionKey, + privateKey: JSON.parse(encryptionKey.privateKey), + publicKey: JSON.parse(encryptionKey.publicKey) + }) } return null diff --git a/apps/vault/src/vault/__test__/e2e/account.spec.ts b/apps/vault/src/vault/__test__/e2e/account.spec.ts index 47fa00208..85cc0f90d 100644 --- a/apps/vault/src/vault/__test__/e2e/account.spec.ts +++ b/apps/vault/src/vault/__test__/e2e/account.spec.ts @@ -1,7 +1,6 @@ import { Permission } from '@narval/armory-sdk' -import { ConfigModule, ConfigService } from '@narval/config-module' import { EncryptionModuleOptionProvider } from '@narval/encryption-module' -import { LoggerModule, REQUEST_HEADER_CLIENT_ID, secret } from '@narval/nestjs-shared' +import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' import { Payload, RsaPublicKey, @@ -17,13 +16,12 @@ import { HttpStatus, INestApplication } from '@nestjs/common' import { Test, TestingModule } from '@nestjs/testing' import request from 'supertest' import { v4 as uuid } from 'uuid' -import { ClientModule } from '../../../client/client.module' import { ClientService } from '../../../client/core/service/client.service' -import { Config, load } from '../../../main.config' +import { MainModule } from '../../../main.module' +import { ProvisionService } from '../../../provision.service' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' import { Client, Origin } from '../../../shared/type/domain.type' -import { AppService } from '../../core/service/app.service' const PRIVATE_KEY = '0x7cfef3303797cbc7515d9ce22ffe849c701b0f2812f999b0847229c47951fca5' @@ -31,9 +29,8 @@ describe('Accounts', () => { let app: INestApplication let module: TestingModule let testPrismaService: TestPrismaService - let appService: AppService + let provisionService: ProvisionService let clientService: ClientService - let configService: ConfigService const clientId = uuid() @@ -43,10 +40,44 @@ describe('Accounts', () => { const client: Client = { clientId, - engineJwk: clientPublicJWK, + auth: { + disabled: false, + local: { + jwsd: { + maxAge: 600, + requiredComponents: ['htm', 'uri', 'created', 'ath'] + }, + allowedUsersJwksUrl: null, + allowedUsers: null + }, + tokenValidation: { + disabled: false, + url: null, + jwksUrl: null, + verification: { + audience: null, + issuer: 'https://armory.narval.xyz', + maxTokenAge: 300, + requireBoundTokens: false, // DO NOT REQUIRE BOUND TOKENS; we're testing both payload.cnf bound tokens and unbound here. + allowBearerTokens: false, + allowWildcard: [ + 'path.to.allow', + 'transactionRequest.maxFeePerGas', + 'transactionRequest.maxPriorityFeePerGas', + 'transactionRequest.gas' + ] + }, + pinnedPublicKey: clientPublicJWK + } + }, + name: 'test-client', + configurationSource: 'dynamic', + backupPublicKey: null, + baseUrl: null, createdAt: new Date(), updatedAt: new Date() } + const getAccessToken = async (permissions: Permission[], opts: object = {}) => { const payload: Payload = { sub: 'test-root-user-uid', @@ -67,15 +98,10 @@ describe('Accounts', () => { beforeAll(async () => { module = await Test.createTestingModule({ - imports: [ - LoggerModule.forTest(), - ConfigModule.forRoot({ - load: [load], - isGlobal: true - }), - ClientModule - ] + imports: [MainModule] }) + .overrideModule(LoggerModule) + .useModule(LoggerModule.forTest()) .overrideProvider(EncryptionModuleOptionProvider) .useValue({ keyring: getTestRawAesKeyring() @@ -84,10 +110,9 @@ describe('Accounts', () => { app = module.createNestApplication({ logger: false }) - appService = module.get(AppService) + provisionService = module.get(ProvisionService) testPrismaService = module.get(TestPrismaService) clientService = module.get(ClientService) - configService = module.get>(ConfigService) await app.init() }) @@ -101,11 +126,7 @@ describe('Accounts', () => { beforeEach(async () => { await testPrismaService.truncateAll() - await appService.save({ - id: configService.get('app.id'), - masterKey: 'test-master-key', - adminApiKey: secret.hash('test-admin-api-key') - }) + await provisionService.provision() await clientService.save(client) }) @@ -113,12 +134,11 @@ describe('Accounts', () => { describe('GET /accounts', () => { it('list all accounts for a specific client', async () => { const secondClientId = uuid() - await clientService.save({ - clientId: secondClientId, - engineJwk: clientPublicJWK, - createdAt: new Date(), - updatedAt: new Date() - }) + const secondClient: Client = { + ...client, + clientId: secondClientId + } + await clientService.save(secondClient) const accessToken = await getAccessToken([Permission.WALLET_READ]) const { body: firstMnemonicRequest } = await request(app.getHttpServer()) diff --git a/apps/vault/src/vault/__test__/e2e/encryption-key.spec.ts b/apps/vault/src/vault/__test__/e2e/encryption-key.spec.ts index 785fb3279..788ef8b7d 100644 --- a/apps/vault/src/vault/__test__/e2e/encryption-key.spec.ts +++ b/apps/vault/src/vault/__test__/e2e/encryption-key.spec.ts @@ -1,5 +1,4 @@ import { Permission } from '@narval/armory-sdk' -import { ConfigModule, ConfigService } from '@narval/config-module' import { EncryptionModuleOptionProvider } from '@narval/encryption-module' import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' import { @@ -14,13 +13,12 @@ import { HttpStatus, INestApplication } from '@nestjs/common' import { Test, TestingModule } from '@nestjs/testing' import request from 'supertest' import { v4 as uuid } from 'uuid' -import { ClientModule } from '../../../client/client.module' import { ClientService } from '../../../client/core/service/client.service' -import { Config, load } from '../../../main.config' +import { MainModule } from '../../../main.module' +import { ProvisionService } from '../../../provision.service' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' import { Client } from '../../../shared/type/domain.type' -import { AppService } from '../../core/service/app.service' const PRIVATE_KEY = '0x7cfef3303797cbc7515d9ce22ffe849c701b0f2812f999b0847229c47951fca5' @@ -28,9 +26,8 @@ describe('Encryption-keys', () => { let app: INestApplication let module: TestingModule let testPrismaService: TestPrismaService - let appService: AppService + let provisionService: ProvisionService let clientService: ClientService - let configService: ConfigService const clientId = uuid() @@ -40,10 +37,44 @@ describe('Encryption-keys', () => { const client: Client = { clientId, - engineJwk: clientPublicJWK, + auth: { + disabled: false, + local: { + jwsd: { + maxAge: 600, + requiredComponents: ['htm', 'uri', 'created', 'ath'] + }, + allowedUsersJwksUrl: null, + allowedUsers: null + }, + tokenValidation: { + disabled: false, + url: null, + jwksUrl: null, + verification: { + audience: null, + issuer: 'https://armory.narval.xyz', + maxTokenAge: 300, + requireBoundTokens: false, // DO NOT REQUIRE BOUND TOKENS; we're testing both payload.cnf bound tokens and unbound here. + allowBearerTokens: false, + allowWildcard: [ + 'path.to.allow', + 'transactionRequest.maxFeePerGas', + 'transactionRequest.maxPriorityFeePerGas', + 'transactionRequest.gas' + ] + }, + pinnedPublicKey: clientPublicJWK + } + }, + name: 'test-client', + configurationSource: 'dynamic', + backupPublicKey: null, + baseUrl: null, createdAt: new Date(), updatedAt: new Date() } + const getAccessToken = async (permissions: Permission[], opts: object = {}) => { const payload: Payload = { sub: 'test-root-user-uid', @@ -64,15 +95,10 @@ describe('Encryption-keys', () => { beforeAll(async () => { module = await Test.createTestingModule({ - imports: [ - LoggerModule.forTest(), - ConfigModule.forRoot({ - load: [load], - isGlobal: true - }), - ClientModule - ] + imports: [MainModule] }) + .overrideModule(LoggerModule) + .useModule(LoggerModule.forTest()) .overrideProvider(EncryptionModuleOptionProvider) .useValue({ keyring: getTestRawAesKeyring() @@ -81,10 +107,9 @@ describe('Encryption-keys', () => { app = module.createNestApplication({ logger: false }) - appService = module.get(AppService) + provisionService = module.get(ProvisionService) testPrismaService = module.get(TestPrismaService) clientService = module.get(ClientService) - configService = module.get>(ConfigService) await app.init() }) @@ -98,11 +123,7 @@ describe('Encryption-keys', () => { beforeEach(async () => { await testPrismaService.truncateAll() - await appService.save({ - id: configService.get('app.id'), - masterKey: 'test-master-key', - adminApiKey: 'test-admin-api-key' - }) + await provisionService.provision() await clientService.save(client) }) diff --git a/apps/vault/src/vault/__test__/e2e/provision.spec.ts b/apps/vault/src/vault/__test__/e2e/provision.spec.ts deleted file mode 100644 index be6db53f9..000000000 --- a/apps/vault/src/vault/__test__/e2e/provision.spec.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { ConfigModule } from '@narval/config-module' -import { LoggerModule, secret } from '@narval/nestjs-shared' -import { INestApplication } from '@nestjs/common' -import { Test, TestingModule } from '@nestjs/testing' -import request from 'supertest' -import { Config, load } from '../../../main.config' -import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' -import { AppService } from '../../core/service/app.service' -import { ProvisionService } from '../../core/service/provision.service' -import { VaultModule } from '../../vault.module' - -const ENDPOINT = '/apps/activate' - -const testConfigLoad = (): Config => ({ - ...load(), - app: { - id: 'local-dev-vault-instance-1', - adminApiKeyHash: undefined - } -}) - -describe('Provision', () => { - let app: INestApplication - let module: TestingModule - let appService: AppService - let testPrismaService: TestPrismaService - let provisionService: ProvisionService - - beforeAll(async () => { - module = await Test.createTestingModule({ - imports: [ - LoggerModule.forTest(), - ConfigModule.forRoot({ - load: [testConfigLoad], - isGlobal: true - }), - VaultModule - ] - }).compile() - - app = module.createNestApplication() - - appService = app.get(AppService) - provisionService = app.get(ProvisionService) - testPrismaService = app.get(TestPrismaService) - - await app.init() - }) - - beforeEach(async () => { - await testPrismaService.truncateAll() - await provisionService.provision() - }) - - afterAll(async () => { - await testPrismaService.truncateAll() - await module.close() - await app.close() - }) - - describe(`POST ${ENDPOINT}`, () => { - it('responds with activated app state', async () => { - const { body } = await request(app.getHttpServer()).post(ENDPOINT).send() - - expect(body).toEqual({ - state: 'READY', - app: { - appId: 'local-dev-vault-instance-1', - adminApiKey: expect.any(String) - } - }) - }) - - it('responds already activated', async () => { - await request(app.getHttpServer()).post(ENDPOINT).send() - - const { body } = await request(app.getHttpServer()).post(ENDPOINT).send() - - expect(body).toEqual({ state: 'ACTIVATED' }) - }) - - it('does not respond with hashed admin API key', async () => { - const { body } = await request(app.getHttpServer()).post(ENDPOINT).send() - - const actualApp = await appService.getAppOrThrow() - - expect(secret.hash(body.app.adminApiKey)).toEqual(actualApp.adminApiKey) - }) - }) -}) diff --git a/apps/vault/src/vault/__test__/e2e/sign.spec.ts b/apps/vault/src/vault/__test__/e2e/sign.spec.ts index 7685a4c82..cd3af8065 100644 --- a/apps/vault/src/vault/__test__/e2e/sign.spec.ts +++ b/apps/vault/src/vault/__test__/e2e/sign.spec.ts @@ -1,4 +1,3 @@ -import { ConfigModule } from '@narval/config-module' import { EncryptionModuleOptionProvider } from '@narval/encryption-module' import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' import { Action, FIXTURE } from '@narval/policy-engine-shared' @@ -21,15 +20,14 @@ import request from 'supertest' import { v4 as uuid } from 'uuid' import { verifyMessage } from 'viem' import { ClientService } from '../../../client/core/service/client.service' -import { load } from '../../../main.config' +import { MainModule } from '../../../main.module' +import { ProvisionService } from '../../../provision.service' import { KeyValueRepository } from '../../../shared/module/key-value/core/repository/key-value.repository' import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' import { Client, Origin, PrivateAccount } from '../../../shared/type/domain.type' -import { AppService } from '../../core/service/app.service' import { AccountRepository } from '../../persistence/repository/account.repository' -import { VaultModule } from '../../vault.module' const PRIVATE_KEY = '0x7cfef3303797cbc7515d9ce22ffe849c701b0f2812f999b0847229c47951fca5' @@ -38,31 +36,83 @@ describe('Sign', () => { let module: TestingModule let testPrismaService: TestPrismaService - const adminApiKey = 'test-admin-api-key' - const clientId = uuid() const clientIdWithoutWildcard = uuid() // Engine key used to sign the approval request const enginePrivateJwk = secp256k1PrivateKeyToJwk(PRIVATE_KEY) const clientPublicJWK = secp256k1PrivateKeyToPublicJwk(PRIVATE_KEY) - const client: Client = { clientId, - engineJwk: clientPublicJWK, + auth: { + disabled: false, + local: { + jwsd: { + maxAge: 600, + requiredComponents: ['htm', 'uri', 'created', 'ath'] + }, + allowedUsersJwksUrl: null, + allowedUsers: null + }, + tokenValidation: { + disabled: false, + url: null, + jwksUrl: null, + verification: { + audience: null, + issuer: 'https://armory.narval.xyz', + maxTokenAge: 300, + requireBoundTokens: false, // DO NOT REQUIRE BOUND TOKENS; we're testing both payload.cnf bound tokens and unbound here. + allowBearerTokens: false, + allowWildcard: [ + 'path.to.allow', + 'transactionRequest.maxFeePerGas', + 'transactionRequest.maxPriorityFeePerGas', + 'transactionRequest.gas' + ] + }, + pinnedPublicKey: clientPublicJWK + } + }, + name: 'test-client', + configurationSource: 'dynamic', + backupPublicKey: null, + baseUrl: null, createdAt: new Date(), - updatedAt: new Date(), - allowWildcard: [ - 'path.to.allow', - 'transactionRequest.maxFeePerGas', - 'transactionRequest.maxPriorityFeePerGas', - 'transactionRequest.gas' - ] + updatedAt: new Date() } const clientWithoutWildcard: Client = { clientId: clientIdWithoutWildcard, - engineJwk: clientPublicJWK, + auth: { + disabled: false, + local: { + jwsd: { + maxAge: 600, + requiredComponents: ['htm', 'uri', 'created', 'ath'] + }, + allowedUsersJwksUrl: null, + allowedUsers: null + }, + tokenValidation: { + disabled: false, + url: null, + jwksUrl: null, + verification: { + audience: null, + issuer: 'https://armory.narval.xyz', + maxTokenAge: 300, + requireBoundTokens: true, + allowBearerTokens: false, + allowWildcard: null + }, + pinnedPublicKey: clientPublicJWK + } + }, + name: 'test-client', + configurationSource: 'dynamic', + backupPublicKey: null, + baseUrl: null, createdAt: new Date(), updatedAt: new Date() } @@ -109,15 +159,10 @@ describe('Sign', () => { beforeAll(async () => { module = await Test.createTestingModule({ - imports: [ - LoggerModule.forTest(), - ConfigModule.forRoot({ - load: [load], - isGlobal: true - }), - VaultModule - ] + imports: [MainModule] }) + .overrideModule(LoggerModule) + .useModule(LoggerModule.forTest()) .overrideProvider(KeyValueRepository) .useValue(new InMemoryKeyValueRepository()) .overrideProvider(EncryptionModuleOptionProvider) @@ -129,16 +174,13 @@ describe('Sign', () => { app = module.createNestApplication({ logger: false }) testPrismaService = module.get(TestPrismaService) - - const appService = module.get(AppService) + const provisionService = module.get(ProvisionService) const clientService = module.get(ClientService) const accountRepository = module.get(AccountRepository) - await appService.save({ - id: 'test-app', - masterKey: 'unsafe-test-master-key', - adminApiKey - }) + await testPrismaService.truncateAll() + + await provisionService.provision() await clientService.save(client) @@ -148,8 +190,6 @@ describe('Sign', () => { await accountRepository.save(clientIdWithoutWildcard, account) - await testPrismaService.truncateAll() - await app.init() }) diff --git a/apps/vault/src/vault/__test__/e2e/wallet.spec.ts b/apps/vault/src/vault/__test__/e2e/wallet.spec.ts index dfb10d4bc..86c5c22ed 100644 --- a/apps/vault/src/vault/__test__/e2e/wallet.spec.ts +++ b/apps/vault/src/vault/__test__/e2e/wallet.spec.ts @@ -1,7 +1,6 @@ import { Permission, resourceId } from '@narval/armory-sdk' -import { ConfigModule, ConfigService } from '@narval/config-module' import { EncryptionModuleOptionProvider } from '@narval/encryption-module' -import { LoggerModule, REQUEST_HEADER_CLIENT_ID, secret } from '@narval/nestjs-shared' +import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' import { Alg, Curves, @@ -25,13 +24,12 @@ import { generateMnemonic } from '@scure/bip39' import request from 'supertest' import { v4 as uuid } from 'uuid' import { english } from 'viem/accounts' -import { ClientModule } from '../../../client/client.module' import { ClientService } from '../../../client/core/service/client.service' -import { Config, load } from '../../../main.config' +import { MainModule } from '../../../main.module' +import { ProvisionService } from '../../../provision.service' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' import { Client, Origin } from '../../../shared/type/domain.type' -import { AppService } from '../../core/service/app.service' import { ImportService } from '../../core/service/import.service' import { KeyGenerationService } from '../../core/service/key-generation.service' @@ -41,10 +39,9 @@ describe('Generate', () => { let app: INestApplication let module: TestingModule let testPrismaService: TestPrismaService - let appService: AppService + let provisionService: ProvisionService let clientService: ClientService let keyGenService: KeyGenerationService - let configService: ConfigService let importService: ImportService const clientId = uuid() @@ -55,10 +52,39 @@ describe('Generate', () => { const client: Client = { clientId, - engineJwk: clientPublicJWK, + auth: { + disabled: false, + local: { + jwsd: { + maxAge: 600, + requiredComponents: ['htm', 'uri', 'created', 'ath'] + }, + allowedUsersJwksUrl: null, + allowedUsers: null + }, + tokenValidation: { + disabled: false, + url: null, + jwksUrl: null, + verification: { + audience: null, + issuer: 'https://armory.narval.xyz', + maxTokenAge: 300, + requireBoundTokens: false, // DO NOT REQUIRE BOUND TOKENS; we're testing both payload.cnf bound tokens and unbound here. + allowBearerTokens: false, + allowWildcard: null + }, + pinnedPublicKey: clientPublicJWK + } + }, + name: 'test-client', + configurationSource: 'dynamic', + backupPublicKey: null, + baseUrl: null, createdAt: new Date(), updatedAt: new Date() } + const getAccessToken = async (permissions: Permission[], opts: object = {}) => { const payload: Payload = { sub: 'test-root-user-uid', @@ -79,15 +105,10 @@ describe('Generate', () => { beforeAll(async () => { module = await Test.createTestingModule({ - imports: [ - LoggerModule.forTest(), - ConfigModule.forRoot({ - load: [load], - isGlobal: true - }), - ClientModule - ] + imports: [MainModule] }) + .overrideModule(LoggerModule) + .useModule(LoggerModule.forTest()) .overrideProvider(EncryptionModuleOptionProvider) .useValue({ keyring: getTestRawAesKeyring() @@ -96,12 +117,11 @@ describe('Generate', () => { app = module.createNestApplication({ logger: false }) - appService = module.get(AppService) testPrismaService = module.get(TestPrismaService) clientService = module.get(ClientService) - configService = module.get>(ConfigService) keyGenService = module.get(KeyGenerationService) importService = module.get(ImportService) + provisionService = module.get(ProvisionService) await app.init() }) @@ -115,11 +135,7 @@ describe('Generate', () => { beforeEach(async () => { await testPrismaService.truncateAll() - await appService.save({ - id: configService.get('app.id'), - masterKey: 'test-master-key', - adminApiKey: secret.hash('test-admin-api-key') - }) + await provisionService.provision() await clientService.save(client) }) @@ -129,10 +145,8 @@ describe('Generate', () => { const accessToken = await getAccessToken([Permission.WALLET_READ]) const secondClientId = uuid() await clientService.save({ - clientId: secondClientId, - engineJwk: clientPublicJWK, - createdAt: new Date(), - updatedAt: new Date() + ...client, + clientId: secondClientId }) const { keyId: firstKeyId } = await keyGenService.generateWallet(clientId, { diff --git a/apps/vault/src/vault/core/service/__test__/integration/app.service.spec.ts b/apps/vault/src/vault/core/service/__test__/integration/app.service.spec.ts deleted file mode 100644 index 9afe2ece6..000000000 --- a/apps/vault/src/vault/core/service/__test__/integration/app.service.spec.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { ConfigModule, ConfigService } from '@narval/config-module' -import { EncryptionModule } from '@narval/encryption-module' -import { secret } from '@narval/nestjs-shared' -import { Test } from '@nestjs/testing' -import { Config, load } from '../../../../../main.config' -import { KeyValueRepository } from '../../../../../shared/module/key-value/core/repository/key-value.repository' -import { KeyValueService } from '../../../../../shared/module/key-value/core/service/key-value.service' -import { InMemoryKeyValueRepository } from '../../../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' -import { getTestRawAesKeyring } from '../../../../../shared/testing/encryption.testing' -import { AppRepository } from '../../../../persistence/repository/app.repository' -import { AppService } from '../../app.service' - -describe(AppService.name, () => { - let appService: AppService - let configService: ConfigService - - const app = { - id: 'test-app-id', - masterKey: 'test-master-key', - adminApiKey: secret.hash('test-admin-api-key'), - activated: true - } - - beforeEach(async () => { - const module = await Test.createTestingModule({ - imports: [ - ConfigModule.forRoot({ - load: [load], - isGlobal: true - }), - EncryptionModule.register({ - keyring: getTestRawAesKeyring() - }) - ], - providers: [ - AppService, - AppRepository, - KeyValueService, - { - provide: KeyValueRepository, - useClass: InMemoryKeyValueRepository - } - ] - }).compile() - - appService = module.get(AppService) - configService = module.get>(ConfigService) - }) - - describe('save', () => { - it('returns the given secret key', async () => { - const actualApp = await appService.save(app) - - expect(actualApp.adminApiKey).toEqual(app.adminApiKey) - }) - - // IMPORTANT: The admin API key is hashed by the caller not the service. That - // allows us to have a determistic configuration file which is useful for - // automations like development or cloud set up. - it('does not hash the secret key', async () => { - jest.spyOn(configService, 'get').mockReturnValue(app.id) - - await appService.save(app) - - const actualApp = await appService.getApp() - - expect(actualApp?.adminApiKey).toEqual(app.adminApiKey) - }) - }) -}) diff --git a/apps/vault/src/vault/core/service/__test__/unit/key-generation.service.spec.ts b/apps/vault/src/vault/core/service/__test__/unit/key-generation.service.spec.ts index baa34bc03..e28dea318 100644 --- a/apps/vault/src/vault/core/service/__test__/unit/key-generation.service.spec.ts +++ b/apps/vault/src/vault/core/service/__test__/unit/key-generation.service.spec.ts @@ -27,12 +27,30 @@ const PRIVATE_KEY = '0x7cfef3303797cbc7515d9ce22ffe849c701b0f2812f999b0847229c47 const clientId = uuid() -// Engine key used to sign the approval request -const clientPublicJWK = secp256k1PrivateKeyToPublicJwk(PRIVATE_KEY) - const client: Client = { clientId, - engineJwk: clientPublicJWK, + auth: { + disabled: true, + local: null, + tokenValidation: { + disabled: true, + url: null, + jwksUrl: null, + verification: { + audience: null, + issuer: null, + maxTokenAge: null, + requireBoundTokens: false, + allowBearerTokens: false, + allowWildcard: null + }, + pinnedPublicKey: null + } + }, + name: 'test-client', + configurationSource: 'dynamic', + backupPublicKey: null, + baseUrl: null, createdAt: new Date(), updatedAt: new Date() } diff --git a/apps/vault/src/vault/core/service/__test__/unit/provision.service.spec.ts b/apps/vault/src/vault/core/service/__test__/unit/provision.service.spec.ts index f93f6c400..5e7ad02ec 100644 --- a/apps/vault/src/vault/core/service/__test__/unit/provision.service.spec.ts +++ b/apps/vault/src/vault/core/service/__test__/unit/provision.service.spec.ts @@ -2,20 +2,22 @@ import { ConfigService } from '@narval/config-module' import { LoggerModule, secret } from '@narval/nestjs-shared' import { Test, TestingModule } from '@nestjs/testing' import { MockProxy, mock } from 'jest-mock-extended' +import { AppService } from '../../../../../app.service' import { Config } from '../../../../../main.config' +import { ProvisionService } from '../../../../../provision.service' import { KeyValueRepository } from '../../../../../shared/module/key-value/core/repository/key-value.repository' import { KeyValueService } from '../../../../../shared/module/key-value/core/service/key-value.service' import { InMemoryKeyValueRepository } from '../../../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' -import { AppRepository } from '../../../../persistence/repository/app.repository' -import { AppService } from '../../app.service' -import { ProvisionService } from '../../provision.service' +import { ProvisionException } from '../../../exception/provision.exception' const mockConfigService = (config: { keyring: Config['keyring']; engineId: string; adminApiKeyHash?: string }) => { const m = mock>() m.get.calledWith('keyring').mockReturnValue(config.keyring) m.get.calledWith('app.id').mockReturnValue(config.engineId) - m.get.calledWith('app.adminApiKeyHash').mockReturnValue(config.adminApiKeyHash) + m.get + .calledWith('app.auth.local') + .mockReturnValue(config.adminApiKeyHash ? { adminApiKeyHash: config.adminApiKeyHash } : null) return m } @@ -23,26 +25,31 @@ const mockConfigService = (config: { keyring: Config['keyring']; engineId: strin describe(ProvisionService.name, () => { let module: TestingModule let provisionService: ProvisionService - let appService: AppService + let appServiceMock: MockProxy let configServiceMock: MockProxy> const config = { engineId: 'test-engine-id', keyring: { type: 'raw', - masterPassword: 'test-master-password' + encryptionMasterPassword: 'test-master-password', + encryptionMasterKey: null, + hmacSecret: 'test-hmac-secret' } satisfies Config['keyring'] } beforeEach(async () => { configServiceMock = mockConfigService(config) + appServiceMock = mock() module = await Test.createTestingModule({ imports: [LoggerModule.forTest()], providers: [ ProvisionService, - AppService, - AppRepository, + { + provide: AppService, + useValue: appServiceMock + }, KeyValueService, { provide: ConfigService, @@ -56,7 +63,6 @@ describe(ProvisionService.name, () => { }).compile() provisionService = module.get(ProvisionService) - appService = module.get(AppService) }) describe('on first boot', () => { @@ -64,18 +70,22 @@ describe(ProvisionService.name, () => { const adminApiKey = 'test-admin-api-key' beforeEach(async () => { - configServiceMock.get.calledWith('app.adminApiKeyHash').mockReturnValue(secret.hash(adminApiKey)) + configServiceMock.get + .calledWith('app.auth.local') + .mockReturnValue({ adminApiKeyHash: secret.hash(adminApiKey) }) + appServiceMock.getApp.mockResolvedValue(null) }) it('saves the activated app', async () => { await provisionService.provision() - const actualApp = await appService.getApp() - - expect(actualApp).toEqual({ + expect(appServiceMock.save).toHaveBeenCalledWith({ id: config.engineId, - adminApiKey: secret.hash(adminApiKey), - masterKey: expect.any(String) + encryptionKeyringType: 'raw', + encryptionMasterKey: expect.any(String), + encryptionMasterAwsKmsArn: undefined, + adminApiKeyHash: secret.hash(adminApiKey), + authDisabled: undefined }) }) }) @@ -84,27 +94,29 @@ describe(ProvisionService.name, () => { it('saves the provisioned app', async () => { await provisionService.provision() - const actualApp = await appService.getApp() - - expect(actualApp?.adminApiKey).toEqual(undefined) - expect(actualApp).toEqual({ + expect(appServiceMock.save).toHaveBeenCalledWith({ id: config.engineId, - masterKey: expect.any(String) + encryptionKeyringType: 'raw', + encryptionMasterKey: expect.any(String), + encryptionMasterAwsKmsArn: undefined, + adminApiKeyHash: null, + authDisabled: undefined }) }) }) }) describe('on boot', () => { - it('skips provision and returns the existing app', async () => { - const actualApp = await appService.save({ + it('fails when masterEncryptionKey is not valid', async () => { + await appServiceMock.getApp.mockResolvedValue({ id: config.engineId, - masterKey: 'test-master-key' + encryptionMasterKey: 'test-master-key', + encryptionKeyringType: 'raw', + encryptionMasterAwsKmsArn: null, + authDisabled: false }) - const engine = await provisionService.provision() - - expect(actualApp).toEqual(engine) + await expect(provisionService.provision()).rejects.toThrow(ProvisionException) }) }) }) diff --git a/apps/vault/src/vault/core/service/app.service.ts b/apps/vault/src/vault/core/service/app.service.ts deleted file mode 100644 index 45bf61e90..000000000 --- a/apps/vault/src/vault/core/service/app.service.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { ConfigService } from '@narval/config-module' -import { Injectable } from '@nestjs/common' -import { Config } from '../../../main.config' -import { App } from '../../../shared/type/domain.type' -import { AppRepository } from '../../persistence/repository/app.repository' -import { AppNotProvisionedException } from '../exception/app-not-provisioned.exception' - -@Injectable() -export class AppService { - constructor( - private configService: ConfigService, - private appRepository: AppRepository - ) {} - - async getAppOrThrow(): Promise { - const app = await this.getApp() - - if (app) { - return app - } - - throw new AppNotProvisionedException() - } - - async getApp(): Promise { - const app = await this.appRepository.findById(this.getId()) - - if (app) { - return app - } - - return null - } - - // IMPORTANT: The admin API key is hashed by the caller not the service. That - // allows us to have a declarative configuration file which is useful for - // automations like development or cloud set up. - async save(app: App): Promise { - await this.appRepository.save(app) - - return app - } - - private getId(): string { - return this.configService.get('app.id') - } -} diff --git a/apps/vault/src/vault/core/service/key-generation.service.ts b/apps/vault/src/vault/core/service/key-generation.service.ts index c2ba6d15b..085eb5ce9 100644 --- a/apps/vault/src/vault/core/service/key-generation.service.ts +++ b/apps/vault/src/vault/core/service/key-generation.service.ts @@ -96,7 +96,12 @@ export class KeyGenerationService { }) } - const backup = await this.#maybeEncryptAndSaveBackup(clientId, keyId, mnemonic, client?.backupPublicKey) + const backup = await this.#maybeEncryptAndSaveBackup( + clientId, + keyId, + mnemonic, + client?.backupPublicKey || undefined + ) await this.rootKeyRepository.save(clientId, { keyId, diff --git a/apps/vault/src/vault/core/service/provision.service.ts b/apps/vault/src/vault/core/service/provision.service.ts deleted file mode 100644 index 7bc0edd7d..000000000 --- a/apps/vault/src/vault/core/service/provision.service.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { ConfigService } from '@narval/config-module' -import { generateKeyEncryptionKey, generateMasterKey } from '@narval/encryption-module' -import { LoggerService } from '@narval/nestjs-shared' -import { Injectable } from '@nestjs/common' -import { Config } from '../../../main.config' -import { App } from '../../../shared/type/domain.type' -import { ProvisionException } from '../exception/provision.exception' -import { AppService } from './app.service' - -@Injectable() -export class ProvisionService { - // IMPORTANT: The provision service establishes encryption. Therefore, you - // cannot have dependencies that rely on encryption to function. If you do, - // you'll ran into an error due to a missing keyring. - // Any process that requires encryption should be handled in the - // BootstrapService. - constructor( - private configService: ConfigService, - private appService: AppService, - private logger: LoggerService - ) {} - - // NOTE: The `adminApiKeyHash` argument is for test convinience in case it - // needs to provision the application. - async provision(adminApiKeyHash?: string): Promise { - const app = await this.appService.getApp() - - const isNotProvisioned = !app || !app.adminApiKey - - if (isNotProvisioned) { - this.logger.log('Start app provision') - - const provisionedApp: App = await this.withMasterKey( - app || { - id: this.getId() - } - ) - - const apiKey = adminApiKeyHash || this.getAdminApiKeyHash() - - if (apiKey) { - this.logger.log('Import admin API key hash') - - return this.appService.save({ - ...provisionedApp, - adminApiKey: apiKey - }) - } - - return this.appService.save(provisionedApp) - } - - this.logger.log('App already provisioned') - - return app - } - - private async withMasterKey(app: App): Promise { - if (app.masterKey) { - this.logger.log('Skip master key set up because it already exists') - - return app - } - - const keyring = this.configService.get('keyring') - - if (keyring.type === 'raw') { - this.logger.log('Generate and save engine master key') - - const { masterPassword } = keyring - const kek = generateKeyEncryptionKey(masterPassword, this.getId()) - const masterKey = await generateMasterKey(kek) - - return { ...app, masterKey } - } else if (keyring.type === 'awskms' && keyring.masterAwsKmsArn) { - this.logger.log('Using AWS KMS for encryption') - - return app - } else { - throw new ProvisionException('Unsupported keyring type') - } - } - - private getAdminApiKeyHash(): string | undefined { - return this.configService.get('app.adminApiKeyHash') - } - - private getId(): string { - return this.configService.get('app.id') - } -} diff --git a/apps/vault/src/vault/http/rest/controller/provision.controller.ts b/apps/vault/src/vault/http/rest/controller/provision.controller.ts deleted file mode 100644 index 87d46ceb1..000000000 --- a/apps/vault/src/vault/http/rest/controller/provision.controller.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { secret } from '@narval/nestjs-shared' -import { Controller, Post } from '@nestjs/common' -import { ApiExcludeController } from '@nestjs/swagger' -import { AppService } from '../../../core/service/app.service' - -type Response = - | { state: 'ACTIVATED' } - | { - state: 'READY' - app: { - appId: string - adminApiKey?: string - } - } - -@Controller({ - path: '/apps/activate', - version: '1' -}) -@ApiExcludeController() -export class ProvisionController { - constructor(private appService: AppService) {} - - @Post() - async provision(): Promise { - const app = await this.appService.getAppOrThrow() - - if (app.adminApiKey) { - return { state: 'ACTIVATED' } - } - - const adminApiKey = secret.generate() - - await this.appService.save({ - ...app, - adminApiKey: secret.hash(adminApiKey) - }) - - return { - state: 'READY', - app: { - appId: app.id, - adminApiKey - } - } - } -} diff --git a/apps/vault/src/vault/persistence/repository/__test__/unit/app.repository.spec.ts b/apps/vault/src/vault/persistence/repository/__test__/unit/app.repository.spec.ts deleted file mode 100644 index e0b3c8286..000000000 --- a/apps/vault/src/vault/persistence/repository/__test__/unit/app.repository.spec.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { EncryptionModule } from '@narval/encryption-module' -import { Test } from '@nestjs/testing' -import { KeyValueRepository } from '../../../../../shared/module/key-value/core/repository/key-value.repository' -import { KeyValueService } from '../../../../../shared/module/key-value/core/service/key-value.service' -import { InMemoryKeyValueRepository } from '../../../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' -import { getTestRawAesKeyring } from '../../../../../shared/testing/encryption.testing' -import { App } from '../../../../../shared/type/domain.type' -import { AppRepository } from '../../app.repository' - -describe(AppRepository.name, () => { - let repository: AppRepository - let inMemoryKeyValueRepository: InMemoryKeyValueRepository - - beforeEach(async () => { - inMemoryKeyValueRepository = new InMemoryKeyValueRepository() - - const module = await Test.createTestingModule({ - imports: [ - EncryptionModule.register({ - keyring: getTestRawAesKeyring() - }) - ], - providers: [ - KeyValueService, - AppRepository, - { - provide: KeyValueRepository, - useValue: inMemoryKeyValueRepository - } - ] - }).compile() - - repository = module.get(AppRepository) - }) - - describe('save', () => { - const app: App = { - id: 'test-app-id', - adminApiKey: 'unsafe-test-admin-api-key', - masterKey: 'unsafe-test-master-key' - } - - it('saves a new app', async () => { - await repository.save(app) - - const value = await inMemoryKeyValueRepository.get(repository.getKey(app.id)) - const actualApp = await repository.findById(app.id) - - expect(value).not.toEqual(null) - expect(app).toEqual(actualApp) - }) - }) -}) diff --git a/apps/vault/src/vault/persistence/repository/app.repository.ts b/apps/vault/src/vault/persistence/repository/app.repository.ts deleted file mode 100644 index 11389f1d4..000000000 --- a/apps/vault/src/vault/persistence/repository/app.repository.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { coerce } from '@narval/nestjs-shared' -import { Injectable } from '@nestjs/common' -import { KeyMetadata } from '../../../shared/module/key-value/core/repository/key-value.repository' -import { KeyValueService } from '../../../shared/module/key-value/core/service/key-value.service' -import { App, Collection } from '../../../shared/type/domain.type' - -@Injectable() -export class AppRepository { - constructor(private keyValueService: KeyValueService) {} - - private KEY_PREFIX = Collection.APP - getMetadata(): KeyMetadata { - return { - collection: Collection.APP - } - } - - async findById(id: string): Promise { - const value = await this.keyValueService.get(this.getKey(id)) - - if (value) { - return coerce.decode(App, value) - } - - return null - } - - async save(app: App): Promise { - await this.keyValueService.set(this.getKey(app.id), coerce.encode(App, app), this.getMetadata()) - - return app - } - - getKey(id: string): string { - return `${this.KEY_PREFIX}:${id}` - } -} diff --git a/apps/vault/src/vault/vault.module.ts b/apps/vault/src/vault/vault.module.ts index d024d690c..4fea2a917 100644 --- a/apps/vault/src/vault/vault.module.ts +++ b/apps/vault/src/vault/vault.module.ts @@ -1,71 +1,43 @@ -import { ConfigService } from '@narval/config-module' -import { EncryptionModule } from '@narval/encryption-module' -import { LoggerService, OpenTelemetryModule, TrackClientIdMiddleware } from '@narval/nestjs-shared' +import { TrackClientIdMiddleware } from '@narval/nestjs-shared' import { HttpModule } from '@nestjs/axios' -import { MiddlewareConsumer, Module, ValidationPipe, forwardRef } from '@nestjs/common' +import { MiddlewareConsumer, Module, ValidationPipe } from '@nestjs/common' import { APP_FILTER, APP_PIPE } from '@nestjs/core' +import { AppRepository } from '../app.repository' import { ClientModule } from '../client/client.module' -import { EncryptionModuleOptionFactory } from '../shared/factory/encryption-module-option.factory' import { ApplicationExceptionFilter } from '../shared/filter/application-exception.filter' import { ZodExceptionFilter } from '../shared/filter/zod-exception.filter' import { NonceGuard } from '../shared/guard/nonce.guard' import { KeyValueModule } from '../shared/module/key-value/key-value.module' import { PersistenceModule } from '../shared/module/persistence/persistence.module' import { AdminService } from './core/service/admin.service' -import { AppService } from './core/service/app.service' import { ImportService } from './core/service/import.service' import { KeyGenerationService } from './core/service/key-generation.service' import { NonceService } from './core/service/nonce.service' -import { ProvisionService } from './core/service/provision.service' import { SigningService } from './core/service/signing.service' import { AccountController } from './http/rest/controller/account.controller' import { EncryptionKeyController } from './http/rest/controller/encryption-key.controller' -import { ProvisionController } from './http/rest/controller/provision.controller' import { SignController } from './http/rest/controller/sign.controller' import { WalletController } from './http/rest/controller/wallet.controller' import { AccountRepository } from './persistence/repository/account.repository' -import { AppRepository } from './persistence/repository/app.repository' import { BackupRepository } from './persistence/repository/backup.repository' import { ImportRepository } from './persistence/repository/import.repository' import { RootKeyRepository } from './persistence/repository/root-key.repository' import { VaultController } from './vault.controller' -import { VaultService } from './vault.service' @Module({ - imports: [ - HttpModule, - PersistenceModule, - forwardRef(() => KeyValueModule), - EncryptionModule.registerAsync({ - imports: [VaultModule], - inject: [ConfigService, AppService, LoggerService], - useClass: EncryptionModuleOptionFactory - }), - forwardRef(() => ClientModule), - OpenTelemetryModule.forRoot() - ], - controllers: [ - VaultController, - WalletController, - SignController, - ProvisionController, - AccountController, - EncryptionKeyController - ], + imports: [HttpModule, PersistenceModule, KeyValueModule, ClientModule], + controllers: [VaultController, WalletController, SignController, AccountController, EncryptionKeyController], providers: [ AppRepository, - AppService, AdminService, ImportRepository, ImportService, NonceGuard, NonceService, - ProvisionService, SigningService, KeyGenerationService, RootKeyRepository, BackupRepository, - VaultService, AccountRepository, { provide: APP_PIPE, @@ -80,7 +52,7 @@ import { VaultService } from './vault.service' useClass: ZodExceptionFilter } ], - exports: [AppService, ProvisionService] + exports: [] }) export class VaultModule { configure(consumer: MiddlewareConsumer): void { diff --git a/apps/vault/src/vault/vault.service.ts b/apps/vault/src/vault/vault.service.ts deleted file mode 100644 index 8993d3064..000000000 --- a/apps/vault/src/vault/vault.service.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { EvaluationResponse } from '@narval/policy-engine-shared' -import { Injectable } from '@nestjs/common' -import { SigningService } from './core/service/signing.service' - -@Injectable() -export class VaultService { - constructor(private signingService: SigningService) {} - - async sign(): Promise { - return null - } -} diff --git a/config/vault-config.local.yml b/config/vault-config.local.yml new file mode 100644 index 000000000..c64bd0204 --- /dev/null +++ b/config/vault-config.local.yml @@ -0,0 +1,145 @@ +# Vault config.yaml, v1 + +##### +# THIS FILE CONTAINS SECRETS; DO NOT COMMIT OUR CONFIG TO SOURCE CONTROL. +##### + +# Config File Version +version: "1" + +# Core service configuration +env: development # Enum: development, test, production +port: 3011 +cors: [] +# Base URL where the Vault is deployed. Used to verify jwsd request signatures. +baseUrl: http://localhost:3011 + +# Database configuration +database: + url: postgresql://postgres:postgres@localhost:5432/vault?schema=public + +# Application identity and security +app: + id: local-dev-vault-instance-1 + # OPTIONAL: Sets the admin API key instead of generating a new one during the provision. + + auth: + # Disable all auth; only useful in dev + disabled: false + # OIDC configuration to use an external auth provider + oidc: null + # Local authentication options, either signed requests or basic api key + local: + adminApiKeyHash: d4a6b4c1cb71dbdb68a1dd429ad737369f74b9e264b9dfa639258753987caaad + # Auth config for requests from this service + outgoing: null + +# Encryption Key management configuration +keyring: + # Either "raw" or "awskms" + type: raw + # If type=raw: + # A master password that uses PBKDF2 to derive the Key Encryption Key (KEK) used to encrypt the master key. + encryptionMasterPassword: unsafe-local-dev-master-password + # If type=raw, you can set the master key to be used here. + # It must be an AES-256 key encoded as a hex string, encrypted by the KEK derived from the masterPassword. Ensure you wrap the string in quotes otherwise it will be interpreted as a number. + # If not set, it will be generated during first-boot. + encryptionMasterKey: "0x020578c93e6e65c27de1dddd752a83c6f50a235d90243e15be346c360d2c9d9f64ba17009800030003617070001861726d6f72792e656e6372797074696f6e2d6d6f64756c6500156177732d63727970746f2d7075626c69632d6b6579004441364a5577556f6f6f63476e752b6e6a465477414d56576a516f304b72447a34615a325761515861375236354330464d6567352f69556e4a31386f6a7169533877413d3d0007707572706f7365000f646174612d656e6372797074696f6e000100146e617276616c2e61726d6f72792e656e67696e65002561726d6f72792e656e67696e652e6b656b000000800000000c8ea6c76bba04c350fdd918b50030f5de1f7910661ae891dd5ce7d3b2692c0ae51916e08bfe4125842f259ed5bf6a2c9d5e3ec06411fcbc840805623da471020000100077f11eac1ff728005f6870ffe8864c1618aacbc5cc35879a0a59cfdafac822e4c852bb9e4c70ce8c18f8f02067a5641dffffffff00000001000000000000000000000001000000202ed04425860a9f6645bcac8616979af1ff484edf661a2501c85e20126c1530750784fc11ca5f2e660b11930c500c3d870068306602310098765ed9afdba77cccc53d493a99b8553873511e904175dcda86007eccccf0b660273e451fc2b900f3e7a60133d08c14023100f196c9312409263a59ee9ca227698e819887ef53798bf74b523cf9d8ecf909ae32c8d4c055907b3051a810a45a0f6ff7" + + # If type=awskms: + # The ARN of the AWS KMS key used as the Master Key. + encryptionMasterAwsKmsArn: null + + # HMAC secret for integrity verification of data in the database. Ensure you wrap the string in quotes otherwise it will be interpreted as a number. + hmacSecret: "4ce6d3404a13c971202693b669668e49e2d6d7e190428d0edd99d1cec1536efb" + +# Declarative clients (tenants) +clients: + # Each key is the client ID + dev-client-1: + name: "Example Client" + # Override default baseUrl for this client, used for verifying jwsd/httpsig + baseUrl: "http://localhost:3011" # [optional] + + auth: + # Disable all auth; only useful in dev + disabled: true + # OIDC configuration to use an external auth provider + oidc: null # TODO: add OIDC + # Local authentication options, either signed requests or basic api key + local: + # HTTP Signing configuration - this is for Service-level authentication. + httpSigning: + # Settings for when THIS service verifies incoming requests + # List of accepted proof methods, supporting httpsig & jwsd. Set null if verification is disabled. + methods: + # Detached JWS + jwsd: + maxAge: 300 + requiredComponents: + - "htm" # HTTP method + - "uri" # Target URI + - "created" # Created timestamp + - "ath" # Authorization (accessToken) + + ## + # [optional]: Restrict to specific user credentials + # If set, ONLY these keys will be accepted. + # Otherwise, any key can authenticate if it matches the authorized credential in a bound token. + ## + # [optional] URL of the JWKS endpoint that includes any keys that are valid "users" + allowedUsersJwksUrl: https://armory/.well-known/jwks.json + # [optional]: List of allowed users, pinning specific keys instead of jwskUrl + allowedUsers: + - userId: armory + publicKey: + kid: "ZvO6VhPB2Ebe6qmk2RH5ly6qOb2O" # armory staging dev-client-1 + kty: "EC" + crv: "secp256k1" + alg: "ES256K" + x: "PismhbGayPpeTjyxi021v6Z3gwaVak1A7l8PQC337XM" + y: "I2pO8D3v9CFgcZo0ej9jhFHwI3QSVFlaw3l4Gx8QbGI" + + # Authorization options, typically this will be used to pin the policy engine's public signing key. + tokenValidation: + # (optional) if you want to disable authorization for this client. DO NOT USE IN PRODUCTION. + disabled: false + # The GNAP Authorization Server that issues tokens + url: "http://armory" + # [optional] JWKS endpoint for the auth server; used for jwt verification. Or you can pin the key. + # jwksUrl: https://policy-engine/.well-known/jwks.json + + # [optional] Pinned public key; used for jwt verification. + publicKey: + kid: "ZvO6VhPB2Ebe6qmk2RH5ly6qOb2O" # armory staging dev-client-1 + kty: "EC" + crv: "secp256k1" + alg: "ES256K" + x: "PismhbGayPpeTjyxi021v6Z3gwaVak1A7l8PQC337XM" + y: "I2pO8D3v9CFgcZo0ej9jhFHwI3QSVFlaw3l4Gx8QbGI" + + verification: + # JWT verification options + audience: null # [optional] Expected audience in JWTs + issuer: "dev-client-1.armory.narval.xyz" # [optional] Expected issuer in JWTs + maxTokenAge: 600 # [optional] Maximum age of JWTs in seconds + # Whether tokens must be bound to signing keys + requireBoundTokens: true + # Whether to accept bearer tokens + allowBearerTokens: false + # [optional] Paths that can be omitted from request hashing + allowWildcard: + - "transactionRequest.maxPriorityFeePerGas" + - "transactionRequest.maxFeePerGas" + - "transactionRequest.gas" + - "transactionRequest.gasPrice" + - "transactionRequest.nonce" + # Auth config for requests from this service + outgoing: null + + # # Backup key export options + # backupPublicKey: # [optional] RSA public key for backups + # kid: "backup-2024-1" + # kty: "RSA" + # n: "..." + # e: "AQAB" diff --git a/config/vault-config.template.yml b/config/vault-config.template.yml new file mode 100644 index 000000000..0244f871c --- /dev/null +++ b/config/vault-config.template.yml @@ -0,0 +1,155 @@ +# Vault config.yaml, v1 + +##### +# THIS FILE CONTAINS SECRETS; DO NOT COMMIT OUR CONFIG TO SOURCE CONTROL. +##### + +# Config File Version +version: "1" + +# Core service configuration +env: development # Enum: development, test, production +port: 3011 +cors: [] +# Base URL where the Vault is deployed. Used to verify jwsd request signatures. +baseUrl: http://localhost:3011 + +# Database configuration +database: + url: postgresql://postgres:postgres@localhost:5432/vault?schema=public + +# Application identity and security +app: + id: local-dev-vault-instance-1 + # OPTIONAL: Sets the admin API key instead of generating a new one during the provision. + + auth: + # Disable all auth; only useful in dev + disabled: false + # OIDC configuration to use an external auth provider + oidc: null + # Local authentication options, either signed requests or basic api key + local: + # [optional]: Sets the admin API key for client provisioning operations + # + # Key should be hashed, like this: `echo -n "my-api-key" | openssl dgst -sha256 | awk '{print $2}'` + # Plain text API key: vault-admin-api-key + adminApiKeyHash: d4a6b4c1cb71dbdb68a1dd429ad737369f74b9e264b9dfa639258753987caaad + # Auth config for requests from this service + outgoing: null + +# Encryption Key management configuration +keyring: + # Either "raw" or "awskms" + type: raw + # If type=raw: + # A master password that uses PBKDF2 to derive the Key Encryption Key (KEK) used to encrypt the master key. + encryptionMasterPassword: unsafe-local-dev-master-password + # Encryption master key: + # - Required if type=raw + # - Must be an AES-256 key encoded as hex string + # - Must be encrypted by KEK derived from masterPassword + # - Must be quoted to prevent number interpretation + # - Will auto-generate on first-boot if not set + # encryptionMasterKey: "0x020578c93e6e65c27de1dddd752a83c6f50a235d90243e15be346c360d2c9d9f64ba17009800030003617070001861726d6f72792e656e6372797074696f6e2d6d6f64756c6500156177732d63727970746f2d7075626c69632d6b6579004441364a5577556f6f6f63476e752b6e6a465477414d56576a516f304b72447a34615a325761515861375236354330464d6567352f69556e4a31386f6a7169533877413d3d0007707572706f7365000f646174612d656e6372797074696f6e000100146e617276616c2e61726d6f72792e656e67696e65002561726d6f72792e656e67696e652e6b656b000000800000000c8ea6c76bba04c350fdd918b50030f5de1f7910661ae891dd5ce7d3b2692c0ae51916e08bfe4125842f259ed5bf6a2c9d5e3ec06411fcbc840805623da471020000100077f11eac1ff728005f6870ffe8864c1618aacbc5cc35879a0a59cfdafac822e4c852bb9e4c70ce8c18f8f02067a5641dffffffff00000001000000000000000000000001000000202ed04425860a9f6645bcac8616979af1ff484edf661a2501c85e20126c1530750784fc11ca5f2e660b11930c500c3d870068306602310098765ed9afdba77cccc53d493a99b8553873511e904175dcda86007eccccf0b660273e451fc2b900f3e7a60133d08c14023100f196c9312409263a59ee9ca227698e819887ef53798bf74b523cf9d8ecf909ae32c8d4c055907b3051a810a45a0f6ff7" + + # If type=awskms: + # The ARN of the AWS KMS key used as the Master Key. + encryptionMasterAwsKmsArn: null + + # HMAC secret for integrity verification of data in the database. Ensure you wrap the string in quotes otherwise it will be interpreted as a number. + # If not set, will be generated during first boot. + hmacSecret: "4ce6d3404a13c971202693b669668e49e2d6d7e190428d0edd99d1cec1536efb" + +# Declarative clients (tenants) +clients: + # Each key is the client ID + dev-client-1: + name: "Example Client" + # Override default baseUrl for this client, used for verifying jwsd/httpsig + baseUrl: "http://localhost:3011" # [optional] + + auth: + # Disable all auth; only useful in dev + disabled: false + # OIDC configuration to use an external auth provider - NOT IMPLEMENTED YET + oidc: null + # Local authentication options, either signed requests or basic api key + local: + # HTTP Signing configuration - this is for Service-level authentication. + httpSigning: + # Settings for when THIS service verifies incoming requests + # List of accepted proof methods, supporting httpsig & jwsd. Set null if verification is disabled. + methods: + # Detached JWS + jwsd: + maxAge: 300 + requiredComponents: + - "htm" # HTTP method + - "uri" # Target URI + - "created" # Created timestamp + - "ath" # Authorization (accessToken) + + # [optional]: Restrict to specific user credentials + # - If set, ONLY these keys will be accepted. + # - Otherwise, any key can authenticate if it matches the authorized credential in a bound token. + # - # + # [optional] URL of the JWKS endpoint that includes any keys that are valid "users" + allowedUsersJwksUrl: https://armory/.well-known/jwks.json + # [optional]: List of allowed users, pinning specific keys instead of jwskUrl + allowedUsers: + - userId: admin-user-id-1 + publicKey: + kid: "user-credential-id" + kty: "EC" + crv: "secp256k1" + alg: "ES256K" + x: "..." + y: "..." + + # Authorization options, typically this will be used to pin the policy engine's public signing key. + tokenValidation: + # (optional) if you want to disable authorization for this client. DO NOT USE IN PRODUCTION. + disabled: false + # The GNAP Authorization Server that issues tokens + url: "http://armory" + # [optional] JWKS endpoint for the auth server; used for jwt verification. Or you can pin the key below. + # jwksUrl: https://policy-engine/.well-known/jwks.json + + # [optional] Pinned public key; used for jwt verification. Must have this OR jwksUrl. + publicKey: + kid: "policy-engine-client-key-id" + kty: "EC" + crv: "secp256k1" + alg: "ES256K" + x: "..." + y: "..." + + verification: + # JWT verification options + # [optional] Expected audience in JWTs + audience: null + # [optional] Expected issuer in JWTs + issuer: "dev-client-1.armory.narval.xyz" + # [optional] Maximum age of JWTs in seconds + maxTokenAge: 600 + # Whether tokens must be bound to signing keys + requireBoundTokens: true + # Whether to accept bearer tokens + allowBearerTokens: false + # [optional] Paths that can be omitted from request hashing, e.g. for authorizing txns with variable gas + allowWildcard: + - "transactionRequest.maxPriorityFeePerGas" + - "transactionRequest.maxFeePerGas" + - "transactionRequest.gas" + - "transactionRequest.gasPrice" + - "transactionRequest.nonce" + # Auth config for requests from this service + outgoing: null + + # # Backup key export options + # backupPublicKey: # [optional] RSA public key for backups + # kid: "backup-2024-1" + # kty: "RSA" + # n: "..." + # e: "AQAB" diff --git a/package-lock.json b/package-lock.json index 16324fb0b..3190e02b5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -85,6 +85,7 @@ "wagmi": "2.12.31", "winston": "3.14.2", "winston-transport": "4.7.0", + "yaml": "2.6.1", "zod": "3.23.8" }, "devDependencies": { @@ -10621,6 +10622,16 @@ "node": ">=8" } }, + "node_modules/@nx/next/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, "node_modules/@nx/next/node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", @@ -12004,6 +12015,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@nx/webpack/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, "node_modules/@nx/webpack/node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", @@ -12428,6 +12449,15 @@ "yaml": "^1.10.2" } }, + "node_modules/@open-policy-agent/opa-wasm/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, "node_modules/@openapitools/openapi-generator-cli": { "version": "2.15.3", "resolved": "https://registry.npmjs.org/@openapitools/openapi-generator-cli/-/openapi-generator-cli-2.15.3.tgz", @@ -22238,6 +22268,16 @@ "node": ">=8" } }, + "node_modules/babel-plugin-macros/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, "node_modules/babel-plugin-polyfill-corejs2": { "version": "0.4.11", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", @@ -28007,6 +28047,16 @@ "node": ">=10" } }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, "node_modules/form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -31020,6 +31070,18 @@ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true }, + "node_modules/jest-circus/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "license": "ISC", + "optional": true, + "peer": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/jest-cli": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", @@ -38526,18 +38588,6 @@ } } }, - "node_modules/postcss-load-config/node_modules/yaml": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", - "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", - "dev": true, - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/postcss-loader": { "version": "7.3.4", "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.4.tgz", @@ -39940,6 +39990,15 @@ "node": ">=6" } }, + "node_modules/react-dev-utils/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, "node_modules/react-devtools-core": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-5.3.2.tgz", @@ -45938,11 +45997,15 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz", + "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, "engines": { - "node": ">= 6" + "node": ">= 14" } }, "node_modules/yargs": { diff --git a/package.json b/package.json index a148f6821..735b20bb8 100644 --- a/package.json +++ b/package.json @@ -145,6 +145,7 @@ "wagmi": "2.12.31", "winston": "3.14.2", "winston-transport": "4.7.0", + "yaml": "2.6.1", "zod": "3.23.8" }, "optionalDependencies": { diff --git a/packages/signature/src/lib/types.ts b/packages/signature/src/lib/types.ts index 3cc446eea..614aa2d97 100644 --- a/packages/signature/src/lib/types.ts +++ b/packages/signature/src/lib/types.ts @@ -361,7 +361,7 @@ export type JwtVerifyOptions = { export type JwsdVerifyOptions = { requestBody: object - accessToken: string + accessToken?: string uri: string htm: string maxTokenAge: number diff --git a/packages/signature/src/lib/verify.ts b/packages/signature/src/lib/verify.ts index 621582f76..55614cfa8 100644 --- a/packages/signature/src/lib/verify.ts +++ b/packages/signature/src/lib/verify.ts @@ -415,7 +415,7 @@ export async function verifyJwsd(jws: string, jwk: PublicKey, opts: JwsdVerifyOp htm: opts.htm, uri: opts.uri, maxTokenAge: opts.maxTokenAge, - ath: hexToBase64Url(hash(opts.accessToken)) + ath: opts.accessToken ? hexToBase64Url(hash(opts.accessToken)) : undefined }) await verifySignature(jwsToVerify, key, header.alg) From 27e49958e86c2779cb7e2cd85690d8d60a181bf1 Mon Sep 17 00:00:00 2001 From: Matt Schoch Date: Tue, 17 Dec 2024 10:49:16 +0100 Subject: [PATCH 032/120] Revert nestjs/platform-express version bump because it breaks the npm ci for some reason --- deploy/vault.dockerfile | 6 +- package-lock.json | 213 +++------------------------------------- package.json | 2 +- 3 files changed, 16 insertions(+), 205 deletions(-) diff --git a/deploy/vault.dockerfile b/deploy/vault.dockerfile index 1ccaefa31..9a57da4f7 100644 --- a/deploy/vault.dockerfile +++ b/deploy/vault.dockerfile @@ -1,4 +1,4 @@ -FROM node:21 as build +FROM node:21 AS build # Set the working directory WORKDIR /usr/src/app @@ -19,7 +19,7 @@ RUN make vault/db/generate-types && \ make vault/build && \ rm -rf apps/ && rm -rf packages/ -FROM node:21-slim as final +FROM node:21-slim AS final WORKDIR /usr/src/app RUN apt-get update && apt-get install -y openssl && apt-get clean && rm -rf /var/lib/apt/lists/* @@ -32,7 +32,7 @@ RUN chmod +x ./db-migrator.sh # Copy built application, which includes a pruned package.json # Then install just the dependencies we need for that. COPY --from=build /usr/src/app/dist ./dist -RUN npm ci --prefix ./dist/apps/vault --only=production +RUN npm ci --prefix ./dist/apps/vault --omit=dev COPY --from=build /usr/src/app/node_modules/@prisma/client/vault ./dist/apps/vault/node_modules/@prisma/client/vault ENV NODE_ENV=production diff --git a/package-lock.json b/package-lock.json index 3190e02b5..e4684d34e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,7 @@ "@nestjs/common": "10.3.10", "@nestjs/config": "3.1.1", "@nestjs/core": "10.4.7", - "@nestjs/platform-express": "10.4.15", + "@nestjs/platform-express": "10.3.9", "@nestjs/swagger": "7.4.0", "@noble/curves": "1.6.0", "@noble/ed25519": "1.7.1", @@ -7038,15 +7038,16 @@ } }, "node_modules/@nestjs/platform-express": { - "version": "10.4.15", - "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.4.15.tgz", - "integrity": "sha512-63ZZPkXHjoDyO7ahGOVcybZCRa7/Scp6mObQKjcX/fTEq1YJeU75ELvMsuQgc8U2opMGOBD7GVuc4DV0oeDHoA==", + "version": "10.3.9", + "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.3.9.tgz", + "integrity": "sha512-si/UzobP6YUtYtCT1cSyQYHHzU3yseqYT6l7OHSMVvfG1+TqxaAqI6nmrix02LO+l1YntHRXEs3p+v9a7EfrSQ==", + "license": "MIT", "dependencies": { - "body-parser": "1.20.3", + "body-parser": "1.20.2", "cors": "2.8.5", - "express": "4.21.2", + "express": "4.19.2", "multer": "1.4.4-lts.1", - "tslib": "2.8.1" + "tslib": "2.6.2" }, "funding": { "type": "opencollective", @@ -7057,201 +7058,11 @@ "@nestjs/core": "^10.0.0" } }, - "node_modules/@nestjs/platform-express/node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/@nestjs/platform-express/node_modules/cookie": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", - "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@nestjs/platform-express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/@nestjs/platform-express/node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@nestjs/platform-express/node_modules/express": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", - "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.7.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.12", - "proxy-addr": "~2.0.7", - "qs": "6.13.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@nestjs/platform-express/node_modules/finalhandler": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@nestjs/platform-express/node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@nestjs/platform-express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/@nestjs/platform-express/node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" - }, - "node_modules/@nestjs/platform-express/node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "dependencies": { - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/@nestjs/platform-express/node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/@nestjs/platform-express/node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@nestjs/platform-express/node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "node_modules/@nestjs/platform-express/node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", - "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/@nestjs/platform-express/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "license": "0BSD" }, "node_modules/@nestjs/schematics": { "version": "9.2.0", diff --git a/package.json b/package.json index 735b20bb8..db068c093 100644 --- a/package.json +++ b/package.json @@ -87,7 +87,7 @@ "@nestjs/common": "10.3.10", "@nestjs/config": "3.1.1", "@nestjs/core": "10.4.7", - "@nestjs/platform-express": "10.4.15", + "@nestjs/platform-express": "10.3.9", "@nestjs/swagger": "7.4.0", "@noble/curves": "1.6.0", "@noble/ed25519": "1.7.1", From d61f0722e201eb5963301cd38af7204845093fa0 Mon Sep 17 00:00:00 2001 From: Matt Schoch Date: Tue, 17 Dec 2024 11:52:53 +0100 Subject: [PATCH 033/120] Fixing enncryption_master_key column spelling --- .../migration.sql | 9 +++++++++ .../src/shared/module/persistence/schema/schema.prisma | 3 ++- .../shared/module/persistence/service/prisma.service.ts | 1 - 3 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 apps/vault/src/shared/module/persistence/schema/migrations/20241217102422_encryption_master_key_spelling/migration.sql diff --git a/apps/vault/src/shared/module/persistence/schema/migrations/20241217102422_encryption_master_key_spelling/migration.sql b/apps/vault/src/shared/module/persistence/schema/migrations/20241217102422_encryption_master_key_spelling/migration.sql new file mode 100644 index 000000000..03b7f5c33 --- /dev/null +++ b/apps/vault/src/shared/module/persistence/schema/migrations/20241217102422_encryption_master_key_spelling/migration.sql @@ -0,0 +1,9 @@ +-- AlterTable +ALTER TABLE "provider_connection" ALTER COLUMN "_integrity" DROP NOT NULL; + +-- AlterTable +ALTER TABLE "vault" ADD COLUMN "encryption_master_key" TEXT; +-- Copy over the old spelling to the new spelling +UPDATE vault SET encryption_master_key = enncryption_master_key +WHERE enncryption_master_key IS NOT NULL; + diff --git a/apps/vault/src/shared/module/persistence/schema/schema.prisma b/apps/vault/src/shared/module/persistence/schema/schema.prisma index ce7b5212f..e9570b6cf 100644 --- a/apps/vault/src/shared/module/persistence/schema/schema.prisma +++ b/apps/vault/src/shared/module/persistence/schema/schema.prisma @@ -17,7 +17,8 @@ model Vault { id String @id // Encryption options, possibly set from Config file encryptionKeyringType String @map("encryption_keyring_type") // raw | awskms - encryptionMasterKey String? @map("enncryption_master_key") /// @encrypted by masterPassword KEK + encryptionMasterKeySpelling String? @map("enncryption_master_key") /// @encrypted by masterPassword KEK @ignore + encryptionMasterKey String? @map("encryption_master_key") /// @encrypted by masterPassword KEK encryptionMasterAwsKmsArn String? @map("encryption_master_aws_kms_arn") // only if type = awskms // Auth Options, set from Config file authDisabled Boolean? @map("auth_disabled") diff --git a/apps/vault/src/shared/module/persistence/service/prisma.service.ts b/apps/vault/src/shared/module/persistence/service/prisma.service.ts index fe8aa0f15..a3defb6c4 100644 --- a/apps/vault/src/shared/module/persistence/service/prisma.service.ts +++ b/apps/vault/src/shared/module/persistence/service/prisma.service.ts @@ -102,7 +102,6 @@ const buildEncryptionExtension = ( name: 'encryption', query: { async $allOperations({ model, operation, args, query }) { - logger.log('Extended ALL OPERATIONS method') if (!model || !(model in encryptedModelFields)) { return query(args) } From 30a6d7e43c543f26df137dbd2f67769957fcb6a0 Mon Sep 17 00:00:00 2001 From: Matt Schoch Date: Tue, 17 Dec 2024 13:34:46 +0100 Subject: [PATCH 034/120] Exposing new configuration options to POST /clients (#34) --- .../src/client/__test__/e2e/client.spec.ts | 74 ++++++++++++++++++- .../http/rest/controller/client.controller.ts | 37 +++++----- apps/vault/src/shared/type/domain.type.ts | 64 +++++++++++++--- 3 files changed, 144 insertions(+), 31 deletions(-) diff --git a/apps/vault/src/client/__test__/e2e/client.spec.ts b/apps/vault/src/client/__test__/e2e/client.spec.ts index 50900972a..1e6fc44cb 100644 --- a/apps/vault/src/client/__test__/e2e/client.spec.ts +++ b/apps/vault/src/client/__test__/e2e/client.spec.ts @@ -17,7 +17,6 @@ import { ProvisionService } from '../../../provision.service' import { REQUEST_HEADER_API_KEY } from '../../../shared/constant' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' -import { CreateClientDto } from '../../http/rest/dto/create-client.dto' import { ClientRepository } from '../../persistence/repository/client.repository' describe('Client', () => { @@ -62,7 +61,7 @@ describe('Client', () => { describe('POST /clients', () => { const clientId = uuid() - const payload: CreateClientDto = { + const payload = { clientId, audience: 'https://vault.narval.xyz', issuer: 'https://auth.narval.xyz', @@ -87,7 +86,7 @@ describe('Client', () => { }) it('creates a new client with Engine JWK', async () => { - const newPayload: CreateClientDto = { + const newPayload = { clientId: 'client-2', engineJwk: { kty: 'EC', @@ -147,7 +146,7 @@ describe('Client', () => { }) ) - const validClientPayload: CreateClientDto = { + const validClientPayload = { ...payload, clientId: uuid(), backupPublicKey: rsaBackupKey @@ -179,5 +178,72 @@ describe('Client', () => { expect(wrongKeyStatus).toEqual(HttpStatus.UNPROCESSABLE_ENTITY) }) + + it('creates a new client with token validation disabled & pinned user', async () => { + const newPayload = { + clientId: 'client-3', + name: 'Client 3', + auth: { + local: { + allowedUsers: [ + { + userId: 'user-1', + publicKey: { + kty: 'EC', + crv: 'secp256k1', + alg: 'ES256K', + kid: '0x73d3ed0e92ac09a45d9538980214abb1a36c4943d64ffa53a407683ddf567fc9', + x: 'sxT67JN5KJVnWYyy7xhFNUOk4buvPLrbElHBinuFwmY', + y: 'CzC7IHlsDg9wz-Gqhtc78eC0IEX75upMgrvmS3U6Ad4' + } + } + ] + }, + tokenValidation: { + disabled: true + } + } + } + const { status, body } = await request(app.getHttpServer()) + .post('/clients') + .set(REQUEST_HEADER_API_KEY, adminApiKey) + .send(newPayload) + + expect(status).toEqual(HttpStatus.CREATED) + expect(body).toEqual({ + clientId: newPayload.clientId, + name: newPayload.name, + baseUrl: null, + backupPublicKey: null, + configurationSource: 'dynamic', + auth: { + disabled: false, + local: { + jwsd: { + maxAge: 300, + requiredComponents: ['htm', 'uri', 'created', 'ath'] + }, + allowedUsersJwksUrl: null, + allowedUsers: newPayload.auth.local.allowedUsers + }, + tokenValidation: { + disabled: true, + url: null, + jwksUrl: null, + pinnedPublicKey: null, + verification: { + audience: null, + issuer: null, + maxTokenAge: null, + requireBoundTokens: true, + allowBearerTokens: false, + allowWildcard: null + } + } + }, + createdAt: expect.any(String), + updatedAt: expect.any(String) + }) + }) }) }) diff --git a/apps/vault/src/client/http/rest/controller/client.controller.ts b/apps/vault/src/client/http/rest/controller/client.controller.ts index d4dd3d3d6..2a6eaf3eb 100644 --- a/apps/vault/src/client/http/rest/controller/client.controller.ts +++ b/apps/vault/src/client/http/rest/controller/client.controller.ts @@ -26,37 +26,38 @@ export class ClientController { }) async create(@Body() body: CreateClientDto): Promise { const now = new Date() - const engineJwk = body.engineJwk ? publicKeySchema.parse(body.engineJwk) : undefined // Validate the JWK, instead of in DTO const clientId = body.clientId || uuid() + const pinnedPublicKeyRaw = body.auth.tokenValidation.pinnedPublicKey || body.engineJwk || undefined + const pinnedPublicKey = pinnedPublicKeyRaw ? publicKeySchema.parse(pinnedPublicKeyRaw) : undefined // Validate the JWK, instead of in DTO const client = await this.clientService.save({ clientId, - name: clientId, - backupPublicKey: null, + name: body.name || clientId, + backupPublicKey: body.backupPublicKey || null, baseUrl: body.baseUrl || null, configurationSource: 'dynamic', auth: { - disabled: false, + disabled: false, // We DO NOT allow dynamic clients to have no auth; use declarative client if you need a no-auth deployment local: { jwsd: { - maxAge: 300, - requiredComponents: ['htm', 'uri', 'created', 'ath'] + maxAge: body.auth.local?.jwsd?.maxAge || 300, + requiredComponents: body.auth.local?.jwsd?.requiredComponents || ['htm', 'uri', 'created', 'ath'] }, - allowedUsersJwksUrl: null, - allowedUsers: null + allowedUsersJwksUrl: null, // Not implemented, so we set to null + allowedUsers: body.auth.local?.allowedUsers || null }, tokenValidation: { - disabled: false, - url: null, - jwksUrl: null, - pinnedPublicKey: engineJwk || null, + disabled: body.auth.tokenValidation.disabled, + url: body.auth.tokenValidation.url || null, + jwksUrl: null, // Not implemented, so we set to null + pinnedPublicKey: pinnedPublicKey || null, verification: { - audience: body.audience || null, - issuer: body.issuer || null, - maxTokenAge: body.maxTokenAge || null, - requireBoundTokens: true, - allowBearerTokens: false, - allowWildcard: body.allowWildcard || null + audience: body.auth.tokenValidation.verification.audience || body.audience || null, + issuer: body.auth.tokenValidation.verification.issuer || body.issuer || null, + maxTokenAge: body.auth.tokenValidation.verification.maxTokenAge || body.maxTokenAge || null, + requireBoundTokens: body.auth.tokenValidation.verification.requireBoundTokens, // Default to True + allowBearerTokens: body.auth.tokenValidation.verification.allowBearerTokens, // Defaults to False + allowWildcard: body.auth.tokenValidation.verification.allowWildcard || body.allowWildcard || null } } }, diff --git a/apps/vault/src/shared/type/domain.type.ts b/apps/vault/src/shared/type/domain.type.ts index d39adcde0..fe1c735d4 100644 --- a/apps/vault/src/shared/type/domain.type.ts +++ b/apps/vault/src/shared/type/domain.type.ts @@ -3,16 +3,68 @@ import { addressSchema, hexSchema } from '@narval/policy-engine-shared' import { Alg, Curves, publicKeySchema, rsaPrivateKeySchema, rsaPublicKeySchema } from '@narval/signature' import { z } from 'zod' +export const ClientLocalAuthAllowedUser = z.object({ + userId: z.string(), + publicKey: publicKeySchema +}) +export type ClientLocalAuthAllowedUser = z.infer + export const CreateClientInput = z.object({ clientId: z.string().optional(), + name: z.string().optional(), + baseUrl: z.string().optional(), + backupPublicKey: rsaPublicKeySchema.optional(), + + // New auth options + auth: z + .object({ + local: z + .object({ + jwsd: z + .object({ + maxAge: z.number().default(300), + requiredComponents: z.array(z.string()).default(['htm', 'uri', 'created', 'ath']) + }) + .nullish(), + allowedUsers: z + .array(ClientLocalAuthAllowedUser) + .nullish() + .describe('Pin specific users to be authorized; if set, ONLY these users are allowed') + }) + .nullish(), + tokenValidation: z + .object({ + disabled: z.boolean().default(false), + url: z.string().nullish(), + pinnedPublicKey: publicKeySchema.nullish(), + verification: z + .object({ + audience: z.string().nullish(), + issuer: z.string().nullish(), + maxTokenAge: z.number().nullish(), + requireBoundTokens: z.boolean().default(true), + allowBearerTokens: z.boolean().default(false), + allowWildcard: z.array(z.string()).nullish() + }) + .default({}) + }) + .default({}) + }) + .default({}), + + /** @deprecated use auth.tokenValidation instead */ engineJwk: publicKeySchema.optional(), + /** @deprecated use auth.tokenValidation instead */ audience: z.string().optional(), + /** @deprecated use auth.tokenValidation instead */ issuer: z.string().optional(), + /** @deprecated use auth.tokenValidation instead */ maxTokenAge: z.number().optional(), - backupPublicKey: rsaPublicKeySchema.optional(), - allowKeyExport: z.boolean().optional(), + /** @deprecated use auth.tokenValidation instead */ allowWildcard: z.array(z.string()).optional(), - baseUrl: z.string().optional() + + /** @deprecated, this has not bee implemented */ + allowKeyExport: z.boolean().optional() }) export type CreateClientInput = z.infer @@ -40,12 +92,6 @@ export const ClientV1 = z.object({ }) export type ClientV1 = z.infer -export const ClientLocalAuthAllowedUser = z.object({ - userId: z.string(), - publicKey: publicKeySchema -}) -export type ClientLocalAuthAllowedUser = z.infer - export const Client = z.object({ clientId: z.string(), name: z.string(), From 6830e834f21438b74f6b281bb66654e42fdb44a5 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Tue, 17 Dec 2024 13:42:01 +0100 Subject: [PATCH 035/120] Refactor sync (#25) * Add SyncException * Refactor Anchorage signed request to the client * Refactor pending connection DTO to include other key formats * Fix connection controller * Add OpenAPI tags in the proxy controller * Sync on connection activation Add logs in the sync and connection service. * Handle connection sync on activation * Fix sign RS256 flaky test * Add event envelope * Fix E2E test --- .../broker/__test__/e2e/connection.spec.ts | 139 +++++++- .../src/broker/__test__/e2e/proxy.spec.ts | 6 + .../src/broker/__test__/e2e/sync.spec.ts | 25 +- apps/vault/src/broker/broker.module.ts | 4 + .../broker/core/exception/sync.exception.ts | 13 + .../unit/anchorage-request-builder.spec.ts | 149 --------- .../core/lib/anchorage-request-builder.ts | 80 ----- .../anchorage-sync.service.spec.ts | 6 + .../core/service/anchorage-sync.service.ts | 36 +- .../broker/core/service/connection.service.ts | 55 ++- .../src/broker/core/service/proxy.service.ts | 29 +- .../src/broker/core/service/sync.service.ts | 103 ++---- apps/vault/src/broker/core/type/sync.type.ts | 6 + .../handler/connection-sync.event-handler.ts | 23 ++ .../__test__/unit/anchorage.client.spec.ts | 219 ++++++++++++ .../broker/http/client/anchorage.client.ts | 316 ++++++++++++------ .../rest/controller/connection.controller.ts | 19 +- .../http/rest/controller/proxy.controller.ts | 10 +- .../http/rest/controller/sync.controller.ts | 25 +- .../dto/response/pending-connection.dto.ts | 14 +- .../repository/connection.repository.ts | 18 +- .../event/connection-activated.event.ts | 7 + package-lock.json | 16 +- package.json | 3 +- .../src/lib/__test__/unit/sign.spec.ts | 3 +- 25 files changed, 870 insertions(+), 454 deletions(-) create mode 100644 apps/vault/src/broker/core/exception/sync.exception.ts delete mode 100644 apps/vault/src/broker/core/lib/__test__/unit/anchorage-request-builder.spec.ts delete mode 100644 apps/vault/src/broker/core/lib/anchorage-request-builder.ts create mode 100644 apps/vault/src/broker/event/handler/connection-sync.event-handler.ts create mode 100644 apps/vault/src/broker/http/client/__test__/unit/anchorage.client.spec.ts create mode 100644 apps/vault/src/broker/shared/event/connection-activated.event.ts diff --git a/apps/vault/src/broker/__test__/e2e/connection.spec.ts b/apps/vault/src/broker/__test__/e2e/connection.spec.ts index 44caf2f83..6ddac4b42 100644 --- a/apps/vault/src/broker/__test__/e2e/connection.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/connection.spec.ts @@ -1,5 +1,6 @@ import { EncryptionModuleOptionProvider } from '@narval/encryption-module' import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' +import { hexSchema } from '@narval/policy-engine-shared' import { Alg, Ed25519PrivateKey, @@ -11,7 +12,9 @@ import { rsaPublicKeySchema } from '@narval/signature' import { HttpStatus, INestApplication } from '@nestjs/common' +import { EventEmitter2 } from '@nestjs/event-emitter' import { Test, TestingModule } from '@nestjs/testing' +import { MockProxy, mock } from 'jest-mock-extended' import { times } from 'lodash' import request from 'supertest' import { v4 as uuid } from 'uuid' @@ -25,7 +28,15 @@ import { TestPrismaService } from '../../../shared/module/persistence/service/te import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' import { EncryptionKeyService } from '../../../transit-encryption/core/service/encryption-key.service' import { ConnectionService } from '../../core/service/connection.service' -import { ConnectionStatus, Provider, isActiveConnection, isRevokedConnection } from '../../core/type/connection.type' +import { SyncService } from '../../core/service/sync.service' +import { + ActiveConnectionWithCredentials, + ConnectionStatus, + Provider, + isActiveConnection, + isRevokedConnection +} from '../../core/type/connection.type' +import { ConnectionActivatedEvent } from '../../shared/event/connection-activated.event' import { getExpectedAccount, getExpectedWallet } from '../util/map-db-to-returned' import { TEST_ACCOUNTS, @@ -63,6 +74,7 @@ describe('Connection', () => { let testPrismaService: TestPrismaService let provisionService: ProvisionService let clientService: ClientService + let eventEmitterMock: MockProxy const url = 'http://provider.narval.xyz' @@ -71,11 +83,24 @@ describe('Connection', () => { const clientId = testClient.clientId beforeAll(async () => { + // We mock the sync service here to prevent race conditions + // during the tests. This is because the ConnectionService sends a promise + // to start the sync but does not wait for it to complete. + const syncServiceMock = mock() + syncServiceMock.start.mockResolvedValue({ started: true, syncs: [] }) + + eventEmitterMock = mock() + eventEmitterMock.emit.mockReturnValue(true) + module = await Test.createTestingModule({ imports: [MainModule] }) .overrideModule(LoggerModule) .useModule(LoggerModule.forTest()) + .overrideProvider(SyncService) + .useValue(syncServiceMock) + .overrideProvider(EventEmitter2) + .useValue(eventEmitterMock) .overrideProvider(KeyValueRepository) .useValue(new InMemoryKeyValueRepository()) .overrideProvider(EncryptionModuleOptionProvider) @@ -138,16 +163,61 @@ describe('Connection', () => { status: ConnectionStatus.PENDING }) - expect(body.credentials.privateKey).toEqual(undefined) + // Ensure it doesn't leak the private key. + expect(body.credentials).toEqual(undefined) + expect(body.privateKey).toEqual(undefined) - toMatchZodSchema(body.credentials.publicKey, ed25519PublicKeySchema) - toMatchZodSchema(body.encryptionPublicKey, rsaPublicKeySchema) + // Ensure it doesn't leak a private key as JWK by including the `d` + // property. + toMatchZodSchema(body.publicKey.jwk, ed25519PublicKeySchema) + toMatchZodSchema(body.encryptionPublicKey.jwk, rsaPublicKeySchema) + + toMatchZodSchema(body.publicKey.hex, hexSchema) + + expect(body.publicKey.keyId).toEqual(expect.any(String)) + expect(body.encryptionPublicKey.keyId).toEqual(expect.any(String)) expect(status).toEqual(HttpStatus.CREATED) }) }) describe('POST /provider/connections', () => { + it('emits connection.activated event on connection create', async () => { + const privateKey = await generateJwk(Alg.EDDSA) + const privateKeyHex = await privateKeyToHex(privateKey) + const connectionId = uuid() + const connection = { + provider: Provider.ANCHORAGE, + connectionId, + label: 'Test Anchorage Connection', + url, + credentials: { + apiKey: 'test-api-key', + privateKey: privateKeyHex + } + } + + await request(app.getHttpServer()) + .post('/provider/connections') + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk, + requestUrl: '/provider/connections', + payload: connection + }) + ) + .send(connection) + + const createdConnection = await connectionService.findById(clientId, connection.connectionId, true) + + expect(eventEmitterMock.emit).toHaveBeenCalledWith( + 'connection.activated', + new ConnectionActivatedEvent(createdConnection as ActiveConnectionWithCredentials) + ) + }) + it('creates a new connection to anchorage with plain credentials', async () => { const privateKey = await generateJwk(Alg.EDDSA) const privateKeyHex = await privateKeyToHex(privateKey) @@ -208,6 +278,58 @@ describe('Connection', () => { }) }) + it('emits connection.activated on connection activation', async () => { + const connectionId = uuid() + const provider = Provider.ANCHORAGE + const label = 'Test Anchorage Connection' + const credentials = { apiKey: 'test-api-key' } + + await request(app.getHttpServer()) + .post('/provider/connections/initiate') + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk, + requestUrl: '/provider/connections/initiate', + payload: { connectionId, provider } + }) + ) + .send({ connectionId, provider }) + + await request(app.getHttpServer()) + .post('/provider/connections') + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk, + requestUrl: '/provider/connections', + payload: { + connectionId, + credentials, + label, + provider, + url + } + }) + ) + .send({ + connectionId, + credentials, + label, + provider, + url + }) + + const createdConnection = await connectionService.findById(clientId, connectionId, true) + + expect(eventEmitterMock.emit).toHaveBeenCalledWith( + 'connection.activated', + new ConnectionActivatedEvent(createdConnection as ActiveConnectionWithCredentials) + ) + }) + it('activates an anchorage pending connection with plain credentials', async () => { const connectionId = uuid() const provider = Provider.ANCHORAGE @@ -280,7 +402,7 @@ describe('Connection', () => { if (isActiveConnection(createdConnection)) { expect(createdConnection.credentials).toMatchObject({ apiKey: credentials.apiKey, - publicKey: pendingConnection.credentials.publicKey + publicKey: pendingConnection.publicKey.jwk }) } else { fail('expected an active connection') @@ -308,7 +430,10 @@ describe('Connection', () => { ) .send({ connectionId, provider }) - const encryptedCredentials = await rsaEncrypt(JSON.stringify(credentials), pendingConnection.encryptionPublicKey) + const encryptedCredentials = await rsaEncrypt( + JSON.stringify(credentials), + pendingConnection.encryptionPublicKey.jwk + ) const { status, body } = await request(app.getHttpServer()) .post('/provider/connections') @@ -363,7 +488,7 @@ describe('Connection', () => { if (isActiveConnection(createdConnection)) { expect(createdConnection.credentials).toMatchObject({ apiKey: credentials.apiKey, - publicKey: pendingConnection.credentials.publicKey + publicKey: pendingConnection.publicKey.jwk }) } else { fail('expected an active connection') diff --git a/apps/vault/src/broker/__test__/e2e/proxy.spec.ts b/apps/vault/src/broker/__test__/e2e/proxy.spec.ts index d77b25b7d..7a41a9033 100644 --- a/apps/vault/src/broker/__test__/e2e/proxy.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/proxy.spec.ts @@ -1,7 +1,9 @@ import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' import { Alg, generateJwk, privateKeyToHex } from '@narval/signature' import { HttpStatus, INestApplication } from '@nestjs/common' +import { EventEmitter2 } from '@nestjs/event-emitter' import { Test, TestingModule } from '@nestjs/testing' +import { mock } from 'jest-mock-extended' import nock from 'nock' import { EncryptionModuleOptionProvider } from 'packages/encryption-module/src/lib/encryption.module' import request from 'supertest' @@ -41,6 +43,10 @@ describe('Proxy', () => { .useValue({ keyring: getTestRawAesKeyring() }) + // Mock the event emitter because we don't want to send a + // connection.activated event after the creation. + .overrideProvider(EventEmitter2) + .useValue(mock()) .compile() app = module.createNestApplication() diff --git a/apps/vault/src/broker/__test__/e2e/sync.spec.ts b/apps/vault/src/broker/__test__/e2e/sync.spec.ts index b11013b72..e707dbf03 100644 --- a/apps/vault/src/broker/__test__/e2e/sync.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/sync.spec.ts @@ -2,6 +2,7 @@ import { EncryptionModuleOptionProvider } from '@narval/encryption-module' import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' import { Alg, generateJwk, privateKeyToHex } from '@narval/signature' import { HttpStatus, INestApplication } from '@nestjs/common' +import { EventEmitter2 } from '@nestjs/event-emitter' import { Test, TestingModule } from '@nestjs/testing' import { MockProxy, mock } from 'jest-mock-extended' import request from 'supertest' @@ -20,7 +21,7 @@ import { import { AnchorageSyncService } from '../../core/service/anchorage-sync.service' import { ConnectionService } from '../../core/service/connection.service' import { SyncService } from '../../core/service/sync.service' -import { ActiveConnection, PendingConnection, Provider } from '../../core/type/connection.type' +import { ActiveConnectionWithCredentials, PendingConnection, Provider } from '../../core/type/connection.type' import { SyncStatus } from '../../core/type/sync.type' import { getJwsd, testClient, testUserPrivateJwk } from '../util/mock-data' @@ -34,7 +35,7 @@ describe('Sync', () => { let provisionService: ProvisionService let clientService: ClientService - let activeConnection: ActiveConnection + let activeConnection: ActiveConnectionWithCredentials // eslint-disable-next-line @typescript-eslint/no-unused-vars let pendingConnection: PendingConnection @@ -48,13 +49,14 @@ describe('Sync', () => { beforeAll(async () => { // We mock the provider's sync service here to prevent race conditions - // during testing. This is because the SyncService sends a promise to start - // the sync but does not wait for it to complete. + // during the tests. This is because the SyncService sends a promise to + // start the sync but does not wait for it to complete. // // NOTE: The sync logic is tested in the provider's sync service // integration tests. anchorageSyncServiceMock = mock() anchorageSyncServiceMock.sync.mockResolvedValue() + module = await Test.createTestingModule({ imports: [MainModule] }) @@ -68,6 +70,10 @@ describe('Sync', () => { }) .overrideProvider(AnchorageSyncService) .useValue(anchorageSyncServiceMock) + // Mock the event emitter because we don't want to send a + // connection.activated event after the creation. + .overrideProvider(EventEmitter2) + .useValue(mock()) .compile() app = module.createNestApplication() @@ -210,10 +216,7 @@ describe('Sync', () => { describe('GET /syncs/:syncId', () => { it('responds with the specific sync', async () => { - const { syncs } = await syncService.start({ - clientId, - connectionId: activeConnection.connectionId - }) + const { syncs } = await syncService.start([activeConnection]) const [sync] = syncs const { status, body } = await request(app.getHttpServer()) @@ -246,7 +249,7 @@ describe('Sync', () => { describe('GET /syncs', () => { it('responds with a list of syncs', async () => { - const { syncs } = await syncService.start({ clientId }) + const { syncs } = await syncService.start([activeConnection]) const [sync] = syncs const { status, body } = await request(app.getHttpServer()) @@ -283,7 +286,7 @@ describe('Sync', () => { }) it('responds with the specific sync filter by connection', async () => { - const { syncs } = await syncService.start({ clientId }) + const { syncs } = await syncService.start([activeConnection]) const [sync] = syncs const { status, body } = await request(app.getHttpServer()) @@ -319,7 +322,7 @@ describe('Sync', () => { }) it('responds with limited number of syncs when limit is given', async () => { - await syncService.start({ clientId }) + await syncService.start([activeConnection]) const { body } = await request(app.getHttpServer()) .get('/provider/syncs') diff --git a/apps/vault/src/broker/broker.module.ts b/apps/vault/src/broker/broker.module.ts index 8bfc7fcd7..681d84ca4 100644 --- a/apps/vault/src/broker/broker.module.ts +++ b/apps/vault/src/broker/broker.module.ts @@ -1,5 +1,6 @@ import { HttpModule, OpenTelemetryModule } from '@narval/nestjs-shared' import { Module } from '@nestjs/common' +import { EventEmitterModule } from '@nestjs/event-emitter' import { ClientModule } from '../client/client.module' import { DEFAULT_HTTP_MODULE_PROVIDERS } from '../shared/constant' import { PersistenceModule } from '../shared/module/persistence/persistence.module' @@ -13,6 +14,7 @@ import { ConnectionService } from './core/service/connection.service' import { ProxyService } from './core/service/proxy.service' import { SyncService } from './core/service/sync.service' import { WalletService } from './core/service/wallet.service' +import { ConnectionSyncEventHandler } from './event/handler/connection-sync.event-handler' import { AnchorageClient } from './http/client/anchorage.client' import { AccountController } from './http/rest/controller/account.controller' import { AddressController } from './http/rest/controller/address.controller' @@ -31,6 +33,7 @@ import { WalletRepository } from './persistence/repository/wallet.repository' imports: [ PersistenceModule, TransitEncryptionModule, + EventEmitterModule.forRoot(), OpenTelemetryModule.forRoot(), HttpModule.register({ retry: { @@ -58,6 +61,7 @@ import { WalletRepository } from './persistence/repository/wallet.repository' ConnectionRepository, ConnectionSeedService, ConnectionService, + ConnectionSyncEventHandler, EncryptionKeyRepository, EncryptionKeyService, ProxyService, diff --git a/apps/vault/src/broker/core/exception/sync.exception.ts b/apps/vault/src/broker/core/exception/sync.exception.ts new file mode 100644 index 000000000..813d34b31 --- /dev/null +++ b/apps/vault/src/broker/core/exception/sync.exception.ts @@ -0,0 +1,13 @@ +import { HttpStatus } from '@nestjs/common' +import { ApplicationExceptionParams } from '../../../shared/exception/application.exception' +import { BrokerException } from './broker.exception' + +export class SyncException extends BrokerException { + constructor(params?: Partial) { + super({ + message: params?.message || 'Fail to sync provider connection', + suggestedHttpStatusCode: params?.suggestedHttpStatusCode || HttpStatus.UNPROCESSABLE_ENTITY, + ...params + }) + } +} diff --git a/apps/vault/src/broker/core/lib/__test__/unit/anchorage-request-builder.spec.ts b/apps/vault/src/broker/core/lib/__test__/unit/anchorage-request-builder.spec.ts deleted file mode 100644 index eae22d2a2..000000000 --- a/apps/vault/src/broker/core/lib/__test__/unit/anchorage-request-builder.spec.ts +++ /dev/null @@ -1,149 +0,0 @@ -import { Alg, privateKeyToJwk } from '@narval/signature' -import * as nobleEd25519 from '@noble/ed25519' -import { UrlParserException } from '../../../exception/url-parser.exception' -import { HttpMethod, buildAnchorageSignedRequest, parseUrl, serializePayload } from '../../anchorage-request-builder' - -const ED25519_PRIVATE_KEY = '0xe6ad32d225c16074bd4a3b62e28c99dd26136ef341e6368ca05227d1e13822d9' - -describe('Anchorage Request Builder', () => { - const mockTime = new Date(1234567890) - - const privateKey = privateKeyToJwk(ED25519_PRIVATE_KEY, Alg.EDDSA) - - describe('parseUrl', () => { - it('extracts version path from valid URLs', () => { - const testCases = [ - { - input: 'https://api.anchorage.com/v2/accounts', - expected: '/v2/accounts' - }, - { - input: 'https://api.anchorage.com/v1/trading/quotes', - expected: '/v1/trading/quotes' - }, - { - input: 'https://api.anchorage.com/v3/something/nested/path', - expected: '/v3/something/nested/path' - }, - { - input: 'https://api.anchorage.com/v4/something/nested/path?query=param&another=param&yetAnother=param', - expected: '/v4/something/nested/path?query=param&another=param&yetAnother=param' - } - ] - testCases.forEach(({ input, expected }) => { - expect(parseUrl(input)).toBe(expected) - }) - }) - - it('throws UrlParserException for invalid URLs', () => { - const invalidUrls = [ - 'https://api.anchorage.com/accounts', - 'https://api.anchorage.com/invalidv1/', - 'not-even-a-url' - ] - - invalidUrls.forEach((url) => expect(() => parseUrl(url)).toThrow(UrlParserException)) - }) - }) - - describe('serializePayload', () => { - it('serializes GET requests without body', () => { - const result = serializePayload(mockTime.getTime(), 'GET', '/v2/accounts', { some: 'data' }) - expect(result).toBe(`${mockTime.getTime()}GET/v2/accounts`) - }) - - it('serializes POST requests with body', () => { - const body = { some: 'data' } - const result = serializePayload(mockTime.getTime(), 'POST', '/v2/accounts', body) - expect(result).toBe(`${mockTime.getTime()}POST/v2/accounts${JSON.stringify(body)}`) - }) - - it('handles undefined body for non-GET requests', () => { - const result = serializePayload(mockTime.getTime(), 'POST', '/v2/accounts', undefined) - expect(result).toBe(`${mockTime.getTime()}POST/v2/accounts`) - }) - - it('formats payloads for all HTTP methods', () => { - const methods: HttpMethod[] = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'] - const body = { test: 'data' } - - methods.forEach((method) => { - const result = serializePayload(mockTime.getTime(), method, '/v2/test', body) - const expected = `${mockTime.getTime()}${method}/v2/test${method === 'GET' ? '' : JSON.stringify(body)}` - expect(result).toBe(expected) - }) - }) - }) - - describe('buildAnchorageSignedRequest', () => { - const defaultParams = { - url: 'https://api.anchorage.com/v2/accounts', - method: 'GET' as const, - apiKey: 'test-api-key', - signKey: privateKey, - body: undefined, - now: mockTime - } - - it('builds GET request config', async () => { - jest.spyOn(nobleEd25519, 'sign') - - const config = await buildAnchorageSignedRequest(defaultParams) - - expect(config).toEqual({ - url: defaultParams.url, - method: defaultParams.method, - headers: { - 'Api-Access-Key': defaultParams.apiKey, - 'Api-Signature': - '6b312c48285544422dc7f4bc44a8f094094453d74fb83f5419c99a2ce1ce79133034b561838b1312d257eb7af5ac8582bfdad319f602f3ff81c484c5a147c50e', - 'Api-Timestamp': Math.floor(mockTime.getTime() / 1000), - 'Content-Type': 'application/json' - }, - data: undefined - }) - - expect(nobleEd25519.sign).toHaveBeenCalledWith( - expect.any(String), - // We need to slice the '0x' prefix from the hex key - ED25519_PRIVATE_KEY.slice(2) - ) - }) - - it('builds POST request config with body', async () => { - const params = { - ...defaultParams, - method: 'POST' as HttpMethod, - body: { test: 'data' } - } - - const config = await buildAnchorageSignedRequest(params) - - expect(config).toEqual({ - url: params.url, - method: params.method, - headers: { - 'Api-Access-Key': params.apiKey, - 'Api-Signature': - '51f1feffab30a8e8bbad75cb85e99a945db0f71ca0e2dfc9b8f7be0f6ec65b9d5274d1e8eac283be9370a4c6d16bbab84049b58feadfcbcbc499bb816195420d', - 'Api-Timestamp': Math.floor(mockTime.getTime() / 1000), - 'Content-Type': 'application/json' - }, - data: params.body - }) - }) - - it('supports all HTTP methods with appropriate body handling', async () => { - const methods: HttpMethod[] = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'] - const body = { test: 'data' } - - for (const method of methods) { - const params = { ...defaultParams, method, body } - const config = await buildAnchorageSignedRequest(params) - - expect(config.method).toBe(method) - expect(config.data).toBe(method === 'GET' ? undefined : body) - } - }) - }) -}) diff --git a/apps/vault/src/broker/core/lib/anchorage-request-builder.ts b/apps/vault/src/broker/core/lib/anchorage-request-builder.ts deleted file mode 100644 index b6b1e8651..000000000 --- a/apps/vault/src/broker/core/lib/anchorage-request-builder.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { Ed25519PrivateKey, privateKeyToHex } from '@narval/signature' -import { sign } from '@noble/ed25519' -import { AxiosRequestConfig } from 'axios' -import { z } from 'zod' -import { UrlParserException } from '../exception/url-parser.exception' - -export const HttpMethod = z.union([ - z.literal('GET'), - z.literal('POST'), - z.literal('PATCH'), - z.literal('PUT'), - z.literal('DELETE') -]) -export type HttpMethod = z.infer - -export type BuildAnchorageRequestParams = { - url: string - method: HttpMethod - body?: unknown - apiKey: string - signKey: Ed25519PrivateKey - now?: Date -} - -export const parseUrl = (url: string): string => { - const regex = /(\/v\d+(?:\/.*)?)$/ - const match = url.match(regex) - - if (!match) { - throw new UrlParserException({ - message: 'No version pattern found in the URL', - url - }) - } - - return match[1] -} - -export const serializePayload = (time: number, method: HttpMethod, endpoint: string, body: unknown): string => { - return `${time}${method}${endpoint}${body && method !== 'GET' ? JSON.stringify(body) : ''}` -} - -export const buildAnchorageSignedRequest = async ({ - url, - method, - body, - apiKey, - signKey, - now -}: BuildAnchorageRequestParams): Promise => { - const timestamp = now ? now.getTime() : new Date().getTime() - const time = Math.floor(timestamp / 1000) - - const endpoint = parseUrl(url) - const serializedPayload = serializePayload(time, method, endpoint, body) - - const signatureRequest = Buffer.from(serializedPayload, 'utf8').toString('hex') - - const signHexKey = await privateKeyToHex(signKey) - const hexSignature = await sign(signatureRequest, signHexKey.slice(2)) - const signature = Buffer.from(hexSignature).toString('hex') - - const headers = { - 'Api-Access-Key': apiKey, - 'Api-Signature': signature, - 'Api-Timestamp': time, - 'Content-Type': 'application/json' - } - - const data = body && method !== 'GET' ? body : undefined - - const config: AxiosRequestConfig = { - url, - method, - headers, - data - } - - return config -} diff --git a/apps/vault/src/broker/core/service/__test__/integration/anchorage-sync.service.spec.ts b/apps/vault/src/broker/core/service/__test__/integration/anchorage-sync.service.spec.ts index df0fdd8a8..24bec0829 100644 --- a/apps/vault/src/broker/core/service/__test__/integration/anchorage-sync.service.spec.ts +++ b/apps/vault/src/broker/core/service/__test__/integration/anchorage-sync.service.spec.ts @@ -2,7 +2,9 @@ import { EncryptionModuleOptionProvider } from '@narval/encryption-module' import { LoggerModule } from '@narval/nestjs-shared' import { Alg, generateJwk, privateKeyToHex } from '@narval/signature' import { INestApplication } from '@nestjs/common' +import { EventEmitter2 } from '@nestjs/event-emitter' import { Test, TestingModule } from '@nestjs/testing' +import { mock } from 'jest-mock-extended' import { v4 as uuid } from 'uuid' import { ClientService } from '../../../../../client/core/service/client.service' import { MainModule } from '../../../../../main.module' @@ -51,6 +53,10 @@ describe(AnchorageSyncService.name, () => { .useValue({ keyring: getTestRawAesKeyring() }) + // Mock the event emitter because we don't want to send a + // connection.activated event after the creation. + .overrideProvider(EventEmitter2) + .useValue(mock()) .compile() app = module.createNestApplication() diff --git a/apps/vault/src/broker/core/service/anchorage-sync.service.ts b/apps/vault/src/broker/core/service/anchorage-sync.service.ts index ea2de0841..0cc3e0ec8 100644 --- a/apps/vault/src/broker/core/service/anchorage-sync.service.ts +++ b/apps/vault/src/broker/core/service/anchorage-sync.service.ts @@ -4,8 +4,8 @@ import { HttpStatus, Injectable } from '@nestjs/common' import { uniq } from 'lodash' import { v4 as uuid } from 'uuid' import { AnchorageClient } from '../../http/client/anchorage.client' -import { BrokerException } from '../exception/broker.exception' import { ConnectionInvalidException } from '../exception/connection-invalid.exception' +import { SyncException } from '../exception/sync.exception' import { ActiveConnection, ActiveConnectionWithCredentials, Provider } from '../type/connection.type' import { Account, Address, Wallet } from '../type/indexed-resources.type' import { AccountService } from './account.service' @@ -69,7 +69,15 @@ export class AnchorageSyncService { walletId: uuid() })) - await this.walletService.bulkCreate(wallets) + try { + await this.walletService.bulkCreate(wallets) + } catch (error) { + throw new SyncException({ + message: 'Fail to persist wallets', + suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, + origin: error + }) + } return wallets } @@ -120,7 +128,7 @@ export class AnchorageSyncService { const wallet = walletsIndexedByExternalId.get(anchorageWallet.vaultId) if (!wallet) { - throw new BrokerException({ + throw new SyncException({ message: 'Parent wallet for account not found', suggestedHttpStatusCode: HttpStatus.NOT_FOUND, context: { @@ -145,7 +153,15 @@ export class AnchorageSyncService { } }) - await this.accountService.bulkCreate(accounts) + try { + await this.accountService.bulkCreate(accounts) + } catch (error) { + throw new SyncException({ + message: 'Fail to persist accounts', + suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, + origin: error + }) + } return accounts } @@ -224,13 +240,21 @@ export class AnchorageSyncService { } satisfies Address } - throw new BrokerException({ + throw new SyncException({ message: 'Anchorage address parent account not found', suggestedHttpStatusCode: HttpStatus.NOT_FOUND }) }) - await this.addressService.bulkCreate(addresses) + try { + await this.addressService.bulkCreate(addresses) + } catch (error) { + throw new SyncException({ + message: 'Fail to persist addresses', + suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, + origin: error + }) + } return addresses } diff --git a/apps/vault/src/broker/core/service/connection.service.ts b/apps/vault/src/broker/core/service/connection.service.ts index 68cf21d11..a3a8c1cf4 100644 --- a/apps/vault/src/broker/core/service/connection.service.ts +++ b/apps/vault/src/broker/core/service/connection.service.ts @@ -1,4 +1,4 @@ -import { PaginatedResult } from '@narval/nestjs-shared' +import { LoggerService, PaginatedResult } from '@narval/nestjs-shared' import { Alg, Ed25519PrivateKey, @@ -9,6 +9,7 @@ import { privateKeyToJwk } from '@narval/signature' import { Injectable, NotImplementedException } from '@nestjs/common' +import { EventEmitter2 } from '@nestjs/event-emitter' import { SetRequired } from 'type-fest' import { v4 as uuid } from 'uuid' import { EncryptionKeyService } from '../../../transit-encryption/core/service/encryption-key.service' @@ -17,6 +18,7 @@ import { FilterOptions, FindAllPaginatedOptions } from '../../persistence/repository/connection.repository' +import { ConnectionActivatedEvent } from '../../shared/event/connection-activated.event' import { ConnectionInvalidCredentialsException } from '../exception/connection-invalid-credentials.exception' import { ConnectionInvalidPrivateKeyException } from '../exception/connection-invalid-private-key.exception' import { ConnectionInvalidStatusException } from '../exception/connection-invalid-status.exception' @@ -43,10 +45,14 @@ import { export class ConnectionService { constructor( private readonly connectionRepository: ConnectionRepository, - private readonly encryptionKeyService: EncryptionKeyService + private readonly encryptionKeyService: EncryptionKeyService, + private readonly logger: LoggerService, + private readonly eventEmitter: EventEmitter2 ) {} async initiate(clientId: string, input: InitiateConnection): Promise { + this.logger.log('Initiate pending connection', { clientId }) + const now = new Date() const privateKey = await this.generatePrivateKey() const encryptionKey = await this.encryptionKeyService.generate(clientId) @@ -67,6 +73,11 @@ export class ConnectionService { await this.connectionRepository.create(connection) + this.logger.log('Pending connection created', { + clientId, + connection: connection.connectionId + }) + return { clientId: connection.clientId, connectionId: connection.connectionId, @@ -88,6 +99,8 @@ export class ConnectionService { } async create(clientId: string, input: CreateConnection): Promise { + this.logger.log('Create active connection', { clientId }) + // If a connection ID is provided, check if the connection already exists. // If it does, activate the connection. if (input.connectionId) { @@ -100,10 +113,14 @@ export class ConnectionService { } if (input.credentials) { + this.logger.log('Create active account from plain credentials', { clientId }) + return this.createActiveConnection(clientId, input) } if (input.encryptedCredentials) { + this.logger.log('Create active account from encrypted credentials', { clientId }) + const credentials = await this.getInputCredentials(clientId, input) return this.createActiveConnection(clientId, { ...input, credentials }) @@ -145,6 +162,8 @@ export class ConnectionService { await this.connectionRepository.create(connection) + this.eventEmitter.emit(ConnectionActivatedEvent.EVENT_NAME, new ConnectionActivatedEvent(connection)) + return connection } @@ -158,7 +177,11 @@ export class ConnectionService { const pendingConnection = await this.connectionRepository.findById(clientId, input.connectionId, true) if (isPendingConnection(pendingConnection) && pendingConnection.credentials) { - // TODO: Ensure the connection status is pending. + this.logger.log('Activate pending connection', { + clientId, + connectionId: pendingConnection.connectionId + }) + const now = new Date() const credentials = await this.getInputCredentials(clientId, input) @@ -180,9 +203,17 @@ export class ConnectionService { await this.connectionRepository.update(connection) + this.eventEmitter.emit(ConnectionActivatedEvent.EVENT_NAME, new ConnectionActivatedEvent(connection)) + return connection } + this.logger.log("Skip pending connection activation because status it's not pending or missing credentials", { + clientId, + connectionId: pendingConnection.connectionId, + status: pendingConnection.status + }) + throw new ConnectionInvalidStatusException({ from: pendingConnection.status, to: ConnectionStatus.ACTIVE, @@ -336,8 +367,12 @@ export class ConnectionService { return this.connectionRepository.findById(clientId, connectionId, includeCredentials) } - async findAll(clientId: string, options?: FilterOptions): Promise { - return this.connectionRepository.findAll(clientId, options) + async findAll( + clientId: string, + options?: FilterOptions, + includeCredentials?: T + ): Promise { + return this.connectionRepository.findAll(clientId, options, includeCredentials) } async findAllPaginated(clientId: string, options?: FindAllPaginatedOptions): Promise> { @@ -348,6 +383,11 @@ export class ConnectionService { const connection = await this.connectionRepository.findById(clientId, connectionId) if (isRevokedConnection(connection)) { + this.logger.log("Skip connection revoke because it's already revoked", { + clientId, + connectionId: connection.connectionId + }) + throw new ConnectionInvalidStatusException({ from: connection.status, to: ConnectionStatus.REVOKED, @@ -357,6 +397,11 @@ export class ConnectionService { } if (isActiveConnection(connection) || isPendingConnection(connection)) { + this.logger.log('Revoke active or pending connection', { + clientId, + connectionId: connection.connectionId + }) + await this.connectionRepository.update({ ...connection, clientId, diff --git a/apps/vault/src/broker/core/service/proxy.service.ts b/apps/vault/src/broker/core/service/proxy.service.ts index 2b4f6b532..bff19698d 100644 --- a/apps/vault/src/broker/core/service/proxy.service.ts +++ b/apps/vault/src/broker/core/service/proxy.service.ts @@ -1,16 +1,18 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ + import { HttpStatus, Injectable } from '@nestjs/common' import { AnchorageClient } from '../../http/client/anchorage.client' import { ConnectionRepository } from '../../persistence/repository/connection.repository' import { ConnectionInvalidException } from '../exception/connection-invalid.exception' -import { HttpMethod } from '../lib/anchorage-request-builder' -import { ConnectionStatus } from '../type/connection.type' +import { isActiveConnection } from '../type/connection.type' -type RawRequestOptions = { +type ProxyRequestOptions = { connectionId: string - body?: any + data?: any endpoint: string - method: HttpMethod + method: string } + @Injectable() export class ProxyService { constructor( @@ -18,12 +20,13 @@ export class ProxyService { private readonly connectionRepository: ConnectionRepository ) {} - async rawRequest( + async forward( clientId: string, - { connectionId, body, endpoint, method }: RawRequestOptions + { connectionId, data, endpoint, method }: ProxyRequestOptions ): Promise<{ data: any; code: HttpStatus; headers: Record }> { const connection = await this.connectionRepository.findById(clientId, connectionId, true) - if (connection.status !== ConnectionStatus.ACTIVE) { + + if (!isActiveConnection(connection)) { throw new ConnectionInvalidException({ message: 'Connection is not active', context: { connectionId, clientId, status: connection.status } @@ -32,18 +35,20 @@ export class ProxyService { const { url, credentials } = connection const { apiKey, privateKey } = credentials - const fullUrl = `${url}${endpoint}` const response = await this.anchorageClient.forward({ url: fullUrl, method, - body, + data, apiKey, signKey: privateKey }) - const { status: code, headers, data } = response - return { data, code, headers } + return { + data: response.data, + code: response.status, + headers: response.headers + } } } diff --git a/apps/vault/src/broker/core/service/sync.service.ts b/apps/vault/src/broker/core/service/sync.service.ts index f8db74489..a7ca102b3 100644 --- a/apps/vault/src/broker/core/service/sync.service.ts +++ b/apps/vault/src/broker/core/service/sync.service.ts @@ -1,91 +1,58 @@ -import { PaginatedResult, TraceService } from '@narval/nestjs-shared' +import { LoggerService, PaginatedResult, TraceService } from '@narval/nestjs-shared' import { Inject, Injectable } from '@nestjs/common/decorators' import { v4 as uuid } from 'uuid' import { FindAllPaginatedOptions, SyncRepository } from '../../persistence/repository/sync.repository' -import { ActiveConnectionWithCredentials, ConnectionStatus, isActiveConnection } from '../type/connection.type' -import { StartSync, Sync, SyncStatus } from '../type/sync.type' +import { ActiveConnectionWithCredentials } from '../type/connection.type' +import { StartSync, Sync, SyncStarted, SyncStatus } from '../type/sync.type' import { AnchorageSyncService } from './anchorage-sync.service' -import { ConnectionService } from './connection.service' @Injectable() export class SyncService { constructor( private readonly syncRepository: SyncRepository, - private readonly connectionService: ConnectionService, private readonly anchorageSyncService: AnchorageSyncService, + private readonly logger: LoggerService, @Inject(TraceService) private readonly traceService: TraceService ) {} - async start(input: StartSync): Promise<{ - started: boolean - syncs: Sync[] - }> { - const now = new Date() - - if (input.connectionId) { - const syncId = uuid() - const connection = await this.connectionService.findById(input.clientId, input.connectionId, true) - - const sync = await this.syncRepository.create( - this.toProcessingSync({ - ...input, - connectionId: connection.connectionId, - createdAt: now, - syncId - }) - ) + async start(connections: ActiveConnectionWithCredentials[]): Promise { + this.logger.log('Start connections sync', { + count: connections.length, + ids: connections.map((connectionId) => connectionId) + }) - if (isActiveConnection(connection)) { - this.anchorageSyncService - .sync(connection) - .then(async () => { - await this.complete(sync) - }) - .catch(async (error) => { - await this.fail(sync, error) + if (connections.length) { + const now = new Date() + + const syncs = await this.syncRepository.bulkCreate( + connections.map(({ connectionId, clientId }) => + this.toProcessingSync({ + clientId, + connectionId, + createdAt: now, + syncId: uuid() }) + ) + ) - return { started: true, syncs: [sync] } - } + await Promise.allSettled( + connections.map(async (connection) => { + this.anchorageSyncService.sync(connection) + }) + ) + .then(async () => { + await Promise.all(syncs.map((sync) => this.complete(sync))) + }) + .catch(async (error) => { + await Promise.all(syncs.map((sync) => this.fail(sync, error))) + }) - return { started: false, syncs: [] } + return { started: true, syncs } } - const connections = await this.connectionService.findAll(input.clientId, { - filters: { - status: ConnectionStatus.ACTIVE - } - }) + this.logger.log('Skip sync because active connections list is empty') - const syncs = await this.syncRepository.bulkCreate( - connections.map(({ connectionId }) => - this.toProcessingSync({ - ...input, - connectionId, - createdAt: now, - syncId: uuid() - }) - ) - ) - - await Promise.allSettled( - connections.map(async (connection) => { - const connectionWithCredentials = await this.connectionService.findById( - input.clientId, - connection.connectionId, - true - ) - this.anchorageSyncService.sync(connectionWithCredentials as ActiveConnectionWithCredentials) - }) - ) - .then(async () => { - await Promise.all(syncs.map((sync) => this.complete(sync))) - }) - .catch(async (error) => { - await Promise.all(syncs.map((sync) => this.fail(sync, error))) - }) - - return { started: true, syncs } + return { started: false, syncs: [] } } private toProcessingSync(input: StartSync & { connectionId: string; createdAt?: Date; syncId?: string }): Sync { diff --git a/apps/vault/src/broker/core/type/sync.type.ts b/apps/vault/src/broker/core/type/sync.type.ts index 0b7f69a04..d86ff5b60 100644 --- a/apps/vault/src/broker/core/type/sync.type.ts +++ b/apps/vault/src/broker/core/type/sync.type.ts @@ -32,3 +32,9 @@ export const StartSync = z.object({ .optional() }) export type StartSync = z.infer + +export const SyncStarted = z.object({ + started: z.boolean(), + syncs: z.array(Sync) +}) +export type SyncStarted = z.infer diff --git a/apps/vault/src/broker/event/handler/connection-sync.event-handler.ts b/apps/vault/src/broker/event/handler/connection-sync.event-handler.ts new file mode 100644 index 000000000..ecd5d43a7 --- /dev/null +++ b/apps/vault/src/broker/event/handler/connection-sync.event-handler.ts @@ -0,0 +1,23 @@ +import { LoggerService } from '@narval/nestjs-shared' +import { Injectable } from '@nestjs/common' +import { OnEvent } from '@nestjs/event-emitter' +import { SyncService } from '../../core/service/sync.service' +import { ConnectionActivatedEvent } from '../../shared/event/connection-activated.event' + +@Injectable() +export class ConnectionSyncEventHandler { + constructor( + private readonly syncService: SyncService, + private readonly logger: LoggerService + ) {} + + @OnEvent(ConnectionActivatedEvent.EVENT_NAME) + async handleConnectionActivatedEvent(event: ConnectionActivatedEvent) { + this.logger.log('Received connection.activated event', { + clientId: event.connection.clientId, + connectionId: event.connection.connectionId + }) + + await this.syncService.start([event.connection]) + } +} diff --git a/apps/vault/src/broker/http/client/__test__/unit/anchorage.client.spec.ts b/apps/vault/src/broker/http/client/__test__/unit/anchorage.client.spec.ts new file mode 100644 index 000000000..9b7e4e1fb --- /dev/null +++ b/apps/vault/src/broker/http/client/__test__/unit/anchorage.client.spec.ts @@ -0,0 +1,219 @@ +import { LoggerService } from '@narval/nestjs-shared' +import { Alg, privateKeyToJwk } from '@narval/signature' +import { HttpService } from '@nestjs/axios' +import * as nobleEd25519 from '@noble/ed25519' +import { AxiosRequestConfig } from 'axios' +import { mock } from 'jest-mock-extended' +import { UrlParserException } from '../../../../core/exception/url-parser.exception' +import { AnchorageClient } from '../../anchorage.client' + +describe(AnchorageClient.name, () => { + let client: AnchorageClient + + const now = new Date(1234567890) + const nowTimestamp = Math.floor(now.getTime() / 1000) + + beforeEach(() => { + const httpServiceMock = mock() + const loggerServiceMock = mock() + + client = new AnchorageClient(httpServiceMock, loggerServiceMock) + }) + + describe('parseEndpoint', () => { + it('extracts version path from valid URLs', () => { + const testCases = [ + { + input: 'https://api.anchorage.com/v2/accounts', + expected: '/v2/accounts' + }, + { + input: 'https://api.anchorage.com/v1/trading/quotes', + expected: '/v1/trading/quotes' + }, + { + input: 'https://api.anchorage.com/v3/something/nested/path', + expected: '/v3/something/nested/path' + }, + { + input: 'https://api.anchorage.com/v4/something/nested/path?query=param&another=param&yetAnother=param', + expected: '/v4/something/nested/path?query=param&another=param&yetAnother=param' + } + ] + + for (const { input, expected } of testCases) { + expect(client.parseEndpoint(input)).toBe(expected) + } + }) + + it('throws UrlParserException for invalid URLs', () => { + const invalidUrls = [ + 'https://api.anchorage.com/accounts', + 'https://api.anchorage.com/invalidv1/', + 'not-even-an-url' + ] + + for (const url of invalidUrls) { + expect(() => client.parseEndpoint(url)).toThrow(UrlParserException) + } + }) + }) + + describe('buildSignatureMessage', () => { + it('builds GET requests without data', () => { + const request: AxiosRequestConfig = { + method: 'GET', + url: '/v2/accounts' + } + + expect(client.buildSignatureMessage(request, nowTimestamp)).toEqual(`${nowTimestamp}GET/v2/accounts`) + }) + + it('builds post requests with data', () => { + const request: AxiosRequestConfig = { + method: 'POST', + url: '/v2/accounts', + data: { + foo: 'foo', + bar: 'bar' + } + } + + expect(client.buildSignatureMessage(request, nowTimestamp)).toEqual( + `${nowTimestamp}POST/v2/accounts${JSON.stringify(request.data)}` + ) + }) + + it('handles undefined data for non-get requests', () => { + const request: AxiosRequestConfig = { + method: 'POST', + url: '/v2/accounts', + data: undefined + } + + expect(client.buildSignatureMessage(request, nowTimestamp)).toEqual(`${nowTimestamp}POST/v2/accounts`) + }) + + it('handles lower case http methods', () => { + const methods = ['post', 'put', 'patch', 'delete'] + const request: AxiosRequestConfig = { + url: '/v2/test', + data: { + foo: 'foo', + bar: 'bar' + } + } + + for (const method of methods) { + expect(client.buildSignatureMessage({ ...request, method }, nowTimestamp)).toEqual( + `${nowTimestamp}${method.toUpperCase()}/v2/test${JSON.stringify(request.data)}` + ) + } + }) + + it('builds request for all http methods', () => { + const methods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'] + const request: AxiosRequestConfig = { + url: '/v2/test', + data: { + foo: 'foo', + bar: 'bar' + } + } + + for (const method of methods) { + expect(client.buildSignatureMessage({ ...request, method }, nowTimestamp)).toEqual( + `${nowTimestamp}${method}/v2/test${method === 'GET' ? '' : JSON.stringify(request.data)}` + ) + } + }) + }) + + describe('authorize', () => { + const ed25519PrivateKeyHex = '0xe6ad32d225c16074bd4a3b62e28c99dd26136ef341e6368ca05227d1e13822d9' + const signKey = privateKeyToJwk(ed25519PrivateKeyHex, Alg.EDDSA) + + const defaultRequest: AxiosRequestConfig = { + url: 'https://api.anchorage.com/v2/accounts', + method: 'GET', + data: undefined + } + + const apiKey = 'test-api-key' + + it('builds signed get request', async () => { + jest.spyOn(nobleEd25519, 'sign') + + const signedRequest = await client.authorize({ + request: defaultRequest, + signKey, + apiKey, + now + }) + + expect(signedRequest).toEqual({ + url: defaultRequest.url, + method: defaultRequest.method, + headers: { + 'Api-Access-Key': apiKey, + 'Api-Signature': + '6b312c48285544422dc7f4bc44a8f094094453d74fb83f5419c99a2ce1ce79133034b561838b1312d257eb7af5ac8582bfdad319f602f3ff81c484c5a147c50e', + 'Api-Timestamp': nowTimestamp, + 'Content-Type': 'application/json' + }, + data: undefined + }) + + expect(nobleEd25519.sign).toHaveBeenCalledWith( + expect.any(String), + // We need to slice the '0x' prefix from the hex key + ed25519PrivateKeyHex.slice(2) + ) + }) + + it('builds signed post request with data', async () => { + const request = { + ...defaultRequest, + method: 'POST', + data: { test: 'data' } + } + + const signedRequest = await client.authorize({ + request, + signKey, + apiKey, + now + }) + + expect(signedRequest).toEqual({ + url: request.url, + method: request.method, + headers: { + 'Api-Access-Key': apiKey, + 'Api-Signature': + '51f1feffab30a8e8bbad75cb85e99a945db0f71ca0e2dfc9b8f7be0f6ec65b9d5274d1e8eac283be9370a4c6d16bbab84049b58feadfcbcbc499bb816195420d', + 'Api-Timestamp': nowTimestamp, + 'Content-Type': 'application/json' + }, + data: request.data + }) + }) + + it('supports all http methods with appropriate data handling', async () => { + const methods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'] + const data = { test: 'data' } + + for (const method of methods) { + const config = await client.authorize({ + request: { ...defaultRequest, method, data }, + signKey, + apiKey, + now + }) + + expect(config.method).toBe(method) + expect(config.data).toBe(method === 'GET' ? undefined : data) + } + }) + }) +}) diff --git a/apps/vault/src/broker/http/client/anchorage.client.ts b/apps/vault/src/broker/http/client/anchorage.client.ts index 7447b51e7..fa522ee91 100644 --- a/apps/vault/src/broker/http/client/anchorage.client.ts +++ b/apps/vault/src/broker/http/client/anchorage.client.ts @@ -1,12 +1,14 @@ import { LoggerService } from '@narval/nestjs-shared' -import { Ed25519PrivateKey } from '@narval/signature' +import { Ed25519PrivateKey, privateKeyToHex } from '@narval/signature' import { HttpService } from '@nestjs/axios' -import { Injectable } from '@nestjs/common' +import { HttpStatus, Injectable } from '@nestjs/common' +import { sign } from '@noble/ed25519' import axios, { AxiosRequestConfig, AxiosResponse } from 'axios' -import { EMPTY, Observable, catchError, expand, lastValueFrom, map, reduce, tap } from 'rxjs' -import { z } from 'zod' +import { EMPTY, Observable, catchError, expand, from, lastValueFrom, map, reduce, switchMap, tap } from 'rxjs' +import { ZodType, z } from 'zod' +import { BrokerException } from '../../core/exception/broker.exception' import { ProxyRequestException } from '../../core/exception/proxy-request.exception' -import { BuildAnchorageRequestParams, buildAnchorageSignedRequest } from '../../core/lib/anchorage-request-builder' +import { UrlParserException } from '../../core/exception/url-parser.exception' const Amount = z.object({ quantity: z.string(), @@ -105,6 +107,14 @@ interface RequestOptions { limit?: number } +interface ForwardRequestOptions { + url: string + method: string + data?: unknown + apiKey: string + signKey: Ed25519PrivateKey +} + @Injectable() export class AnchorageClient { constructor( @@ -112,27 +122,135 @@ export class AnchorageClient { private readonly logger: LoggerService ) {} - async forward({ url, method, body, apiKey, signKey }: BuildAnchorageRequestParams): Promise { - const request = await buildAnchorageSignedRequest({ - url, - method, - body, + async forward({ url, method, data, apiKey, signKey }: ForwardRequestOptions): Promise { + const signedRequest = await this.authorize({ + request: { + url, + method, + data + }, apiKey, signKey }) try { - const response = await axios(request) + const response = await axios(signedRequest) + return response } catch (error) { throw new ProxyRequestException({ - message: 'Anchorage request failed', + message: 'Anchorage proxy request failed', status: error.response?.status, data: error.response?.data, headers: error.response?.headers, - context: { url, method, body } + context: { + url, + method + } + }) + } + } + + async authorize(opts: { + request: AxiosRequestConfig + apiKey: string + signKey: Ed25519PrivateKey + now?: Date + }): Promise { + const { request, signKey, apiKey } = opts + + this.validateRequest(request) + + const now = opts.now ? opts.now.getTime() : new Date().getTime() + const timestamp = Math.floor(now / 1000) + const message = this.buildSignatureMessage(request, timestamp) + const messageHex = Buffer.from(message, 'utf8').toString('hex') + const signKeyHex = await privateKeyToHex(signKey) + const signature = await sign(messageHex, signKeyHex.slice(2)) + const signatureHex = Buffer.from(signature).toString('hex') + const headers = { + 'Api-Access-Key': apiKey, + 'Api-Signature': signatureHex, + 'Api-Timestamp': timestamp, + 'Content-Type': 'application/json' + } + const data = request.data && request.method !== 'GET' ? request.data : undefined + + return { + ...request, + headers, + data + } + } + + parseEndpoint(url: string): string { + const regex = /(\/v\d+(?:\/.*)?)$/ + const match = url.match(regex) + + if (!match) { + throw new UrlParserException({ + message: 'No version pattern found in the URL', + url }) } + + return match[1] + } + + private validateRequest(request: AxiosRequestConfig): asserts request is AxiosRequestConfig & { + url: string + method: string + } { + if (!request.url) { + throw new BrokerException({ + message: 'Cannot sign a request without an URL', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY + }) + } + + if (!request.method) { + throw new BrokerException({ + message: 'Cannot sign a request without a method', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY + }) + } + } + + buildSignatureMessage(request: AxiosRequestConfig, timestamp: number): string { + this.validateRequest(request) + + const endpoint = this.parseEndpoint(request.url) + const method = request.method.toUpperCase() + + return `${timestamp}${method}${endpoint}${request.data && method !== 'GET' ? JSON.stringify(request.data) : ''}` + } + + private sendSignedRequest(opts: { + schema: ZodType + request: AxiosRequestConfig + signKey: Ed25519PrivateKey + apiKey: string + }): Observable { + return from( + this.authorize({ + request: opts.request, + apiKey: opts.apiKey, + signKey: opts.signKey + }) + ).pipe( + switchMap((signedRequest) => + this.httpService.request(signedRequest).pipe( + tap((response) => { + this.logger.log('Received response', { + url: opts.request.url, + method: opts.request.method, + nextPage: response.data?.page?.next + }) + }), + map((response) => opts.schema.parse(response.data)) + ) + ) + ) } async getVaults(opts: RequestOptions): Promise { @@ -141,24 +259,35 @@ export class AnchorageClient { limit: opts.limit }) - const request = await buildAnchorageSignedRequest({ - url: `${opts.url}/v2/vaults`, - method: 'GET', - apiKey: opts.apiKey, - signKey: opts.signKey - }) + const { apiKey, signKey, url } = opts return lastValueFrom( - this.getVaultsPage(request).pipe( - expand((response) => - response.page.next - ? // TODO: Use the signed request - this.getVaultsPage({ - ...opts, + this.sendSignedRequest({ + schema: GetVaultsResponse, + request: { + url: `${url}/v2/vaults`, + method: 'GET', + params: { + limit: opts.limit + } + }, + apiKey, + signKey + }).pipe( + expand((response) => { + if (response.page.next) { + return this.sendSignedRequest({ + schema: GetVaultsResponse, + request: { url: response.page.next - }) - : EMPTY - ), + }, + apiKey, + signKey + }) + } + + return EMPTY + }), tap((response) => { if (response.page.next) { this.logger.log('Requesting Anchorage vaults next page', { @@ -185,36 +314,37 @@ export class AnchorageClient { ) } - private getVaultsPage(request: AxiosRequestConfig): Observable { - return this.httpService.request(request).pipe( - tap((response) => { - this.logger.log('Received Anchorage vaults page', { - data: response.data - }) - }), - map((response) => GetVaultsResponse.parse(response.data)) - ) - } - async getWallets(opts: RequestOptions): Promise { - const request = await buildAnchorageSignedRequest({ - url: `${opts.url}/v2/wallets`, - method: 'GET', - apiKey: opts.apiKey, - signKey: opts.signKey + this.logger.log('Requesting Anchorage wallets page', { + url: opts.url, + limit: opts.limit }) + const { apiKey, signKey, url } = opts return lastValueFrom( - this.getWalletsPage(request).pipe( - expand((response) => - response.page.next - ? // TODO: use signed request - this.getWalletsPage({ - ...opts, + this.sendSignedRequest({ + schema: GetWalletsResponse, + request: { + url: `${url}/v2/wallets`, + method: 'GET' + }, + apiKey, + signKey + }).pipe( + expand((response) => { + if (response.page.next) { + return this.sendSignedRequest({ + schema: GetWalletsResponse, + request: { url: response.page.next - }) - : EMPTY - ), + }, + apiKey, + signKey + }) + } + + return EMPTY + }), tap((response) => { if (response.page.next) { this.logger.log('Requesting Anchorage wallets next page', { @@ -241,56 +371,59 @@ export class AnchorageClient { ) } - private getWalletsPage(request: AxiosRequestConfig): Observable { - return this.httpService.request(request).pipe( - tap((response) => { - this.logger.log('Received Anchorage wallets page', { - data: response.data - }) - }), - map((response) => GetWalletsResponse.parse(response.data)) - ) - } - async getVaultAddresses(opts: RequestOptions & { vaultId: string; assetType: string }): Promise { - const request = await buildAnchorageSignedRequest({ - url: `${opts.url}/v2/vaults/${opts.vaultId}/addresses`, - method: 'GET', - apiKey: opts.apiKey, - signKey: opts.signKey + this.logger.log('Requesting Anchorage vault addresses page', { + url: opts.url, + vaultId: opts.vaultId, + assetType: opts.assetType }) + const { apiKey, signKey, url, vaultId, assetType } = opts return lastValueFrom( - this.getVaultAddressesPage({ - ...request, - params: { - assetType: opts.assetType - } + this.sendSignedRequest({ + schema: GetVaultAddressesResponse, + request: { + url: `${url}/v2/vaults/${vaultId}/addresses`, + method: 'GET', + params: { + assetType + } + }, + apiKey, + signKey }).pipe( - expand((response) => - response.page.next - ? // TODO: Use the signed request - this.getVaultAddressesPage({ - ...opts, + expand((response) => { + if (response.page.next) { + return this.sendSignedRequest({ + schema: GetVaultAddressesResponse, + request: { url: response.page.next - }) - : EMPTY - ), + }, + apiKey, + signKey + }) + } + + return EMPTY + }), tap((response) => { if (response.page.next) { this.logger.log('Requesting Anchorage vault addresses next page', { url: response.page.next, - limit: opts.limit + vaultId, + assetType }) } else { this.logger.log('Reached Anchorage vault addresses last page') } }), reduce((addresses: Address[], response) => [...addresses, ...response.data], []), - tap((vaults) => { + tap((addresses) => { this.logger.log('Completed fetching all vault addresses', { - vaultsCount: vaults.length, - url: opts.url + addressesCount: addresses.length, + vaultId, + assetType, + url }) }), catchError((error) => { @@ -301,15 +434,4 @@ export class AnchorageClient { ) ) } - - private getVaultAddressesPage(request: AxiosRequestConfig): Observable { - return this.httpService.request(request).pipe( - tap((response) => { - this.logger.log('Received Anchorage vaults addresses page', { - data: response.data - }) - }), - map((response) => GetVaultAddressesResponse.parse(response.data)) - ) - } } diff --git a/apps/vault/src/broker/http/rest/controller/connection.controller.ts b/apps/vault/src/broker/http/rest/controller/connection.controller.ts index 7353f34f6..12768ead0 100644 --- a/apps/vault/src/broker/http/rest/controller/connection.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/connection.controller.ts @@ -1,4 +1,5 @@ import { Paginated, PaginationOptions, PaginationParam } from '@narval/nestjs-shared' +import { publicKeyToHex } from '@narval/signature' import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Patch, Post } from '@nestjs/common' import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../shared/decorator/client-id.decorator' @@ -44,7 +45,22 @@ export class ConnectionController { async initiate(@ClientId() clientId: string, @Body() body: InitiateConnectionDto): Promise { const pendingConnection = await this.connectionService.initiate(clientId, body) - return PendingConnectionDto.create(pendingConnection) + return PendingConnectionDto.create({ + ...pendingConnection, + encryptionPublicKey: { + keyId: pendingConnection.encryptionPublicKey?.kid, + jwk: pendingConnection.encryptionPublicKey + }, + ...(pendingConnection.credentials + ? { + publicKey: { + keyId: pendingConnection.credentials.publicKey.kid, + jwk: pendingConnection.credentials.publicKey, + hex: await publicKeyToHex(pendingConnection.credentials.publicKey) + } + } + : {}) + }) } @Post() @@ -187,7 +203,6 @@ export class ConnectionController { @Param('connectionId') connectionId: string, @PaginationParam() options: PaginationOptions ): Promise { - // TODO: Move the method from the connection service to accounts. const { data, page } = await this.accountService.findAllPaginated(clientId, { ...options, filters: { connectionId } diff --git a/apps/vault/src/broker/http/rest/controller/proxy.controller.ts b/apps/vault/src/broker/http/rest/controller/proxy.controller.ts index a45f8478b..9923ad814 100644 --- a/apps/vault/src/broker/http/rest/controller/proxy.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/proxy.controller.ts @@ -1,18 +1,18 @@ import { All, Body, Controller, HttpStatus, Param, Req, Res } from '@nestjs/common' -import { ApiHeader, ApiOperation, ApiParam, ApiResponse } from '@nestjs/swagger' +import { ApiHeader, ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger' import { Request, Response } from 'express' import { ClientId } from '../../../../shared/decorator/client-id.decorator' import { ConnectionId } from '../../../../shared/decorator/connection-id.decorator' import { PermissionGuard } from '../../../../shared/decorator/permission-guard.decorator' import { VaultPermission } from '../../../../shared/type/domain.type' import { ProxyRequestException } from '../../../core/exception/proxy-request.exception' -import { HttpMethod } from '../../../core/lib/anchorage-request-builder' import { ProxyService } from '../../../core/service/proxy.service' @Controller({ path: 'proxy', version: '1' }) +@ApiTags('Provider Proxy') export class ProxyController { constructor(private readonly proxyService: ProxyService) {} @@ -49,11 +49,11 @@ export class ProxyController { const sanitizedEndpoint = queryString ? `/${endpoint}?${queryString}` : `/${endpoint}` try { - const response = await this.proxyService.rawRequest(clientId, { + const response = await this.proxyService.forward(clientId, { connectionId, endpoint: sanitizedEndpoint, - method: HttpMethod.parse(request.method), - body + method: request.method, + data: body }) res.status(response.code).set(response.headers).send(response.data) diff --git a/apps/vault/src/broker/http/rest/controller/sync.controller.ts b/apps/vault/src/broker/http/rest/controller/sync.controller.ts index 6d0fc3191..8cbab199e 100644 --- a/apps/vault/src/broker/http/rest/controller/sync.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/sync.controller.ts @@ -4,7 +4,9 @@ import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../shared/decorator/client-id.decorator' import { PermissionGuard } from '../../../../shared/decorator/permission-guard.decorator' import { VaultPermission } from '../../../../shared/type/domain.type' +import { ConnectionService } from '../../../core/service/connection.service' import { SyncService } from '../../../core/service/sync.service' +import { ActiveConnectionWithCredentials, ConnectionStatus } from '../../../core/type/connection.type' import { StartSyncDto } from '../dto/request/start-sync.dto' import { PaginatedSyncsDto } from '../dto/response/paginated-syncs.dto' import { SyncStatusDto } from '../dto/response/sync-status.dto' @@ -16,7 +18,10 @@ import { SyncDto } from '../dto/response/sync.dto' }) @ApiTags('Provider Sync') export class SyncController { - constructor(private readonly syncService: SyncService) {} + constructor( + private readonly syncService: SyncService, + private readonly connectionService: ConnectionService + ) {} @Post() @PermissionGuard(VaultPermission.CONNECTION_READ) // Sync is a read operation even though it's a POST. @@ -30,7 +35,23 @@ export class SyncController { type: SyncStatusDto }) async start(@ClientId() clientId: string, @Body() body: StartSyncDto): Promise { - return SyncStatusDto.create(await this.syncService.start({ clientId, ...body })) + if (body.connectionId) { + const connection = await this.connectionService.findById(clientId, body.connectionId, true) + + return SyncStatusDto.create(await this.syncService.start([connection as ActiveConnectionWithCredentials])) + } + + const connections = await this.connectionService.findAll( + clientId, + { + filters: { + status: ConnectionStatus.ACTIVE + } + }, + true + ) + + return SyncStatusDto.create(await this.syncService.start(connections as ActiveConnectionWithCredentials[])) } @Get(':syncId') diff --git a/apps/vault/src/broker/http/rest/dto/response/pending-connection.dto.ts b/apps/vault/src/broker/http/rest/dto/response/pending-connection.dto.ts index fd151ce01..0cd4aa263 100644 --- a/apps/vault/src/broker/http/rest/dto/response/pending-connection.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/pending-connection.dto.ts @@ -1,3 +1,4 @@ +import { hexSchema } from '@narval/policy-engine-shared' import { publicKeySchema } from '@narval/signature' import { createZodDto } from 'nestjs-zod' import { z } from 'zod' @@ -9,11 +10,18 @@ export class PendingConnectionDto extends createZodDto( connectionId: true, provider: true, status: true, - encryptionPublicKey: true, createdAt: true }).extend({ - credentials: z.object({ - publicKey: publicKeySchema.optional() + publicKey: z + .object({ + keyId: z.string().optional(), + jwk: publicKeySchema.optional(), + hex: hexSchema.optional() + }) + .optional(), + encryptionPublicKey: z.object({ + keyId: z.string().optional(), + jwk: publicKeySchema.optional() }) }) ) {} diff --git a/apps/vault/src/broker/persistence/repository/connection.repository.ts b/apps/vault/src/broker/persistence/repository/connection.repository.ts index 60faf64a3..31bf2db87 100644 --- a/apps/vault/src/broker/persistence/repository/connection.repository.ts +++ b/apps/vault/src/broker/persistence/repository/connection.repository.ts @@ -145,16 +145,26 @@ export class ConnectionRepository { throw new NotFoundException({ context: { clientId, connectionId } }) } - async findAll(clientId: string, options?: FilterOptions): Promise { + async findAll( + clientId: string, + options?: FilterOptions, + includeCredentials?: T + ): Promise { const models = await this.prismaService.providerConnection.findMany({ - select: connectionSelectWithoutCredentials, where: { clientId, status: options?.filters?.status - } + }, + ...(includeCredentials + ? {} + : { + select: connectionSelectWithoutCredentials + }) }) - return models.map((model) => ConnectionRepository.parseModel(model, false)) + return models.map((model) => ConnectionRepository.parseModel(model, includeCredentials)) as T extends true + ? ConnectionWithCredentials[] + : Connection[] } async findAllPaginated(clientId: string, options?: FindAllPaginatedOptions): Promise> { diff --git a/apps/vault/src/broker/shared/event/connection-activated.event.ts b/apps/vault/src/broker/shared/event/connection-activated.event.ts new file mode 100644 index 000000000..186427a16 --- /dev/null +++ b/apps/vault/src/broker/shared/event/connection-activated.event.ts @@ -0,0 +1,7 @@ +import { ActiveConnectionWithCredentials } from '../../core/type/connection.type' + +export class ConnectionActivatedEvent { + static EVENT_NAME = 'connection.activated' + + constructor(public readonly connection: ActiveConnectionWithCredentials) {} +} diff --git a/package-lock.json b/package-lock.json index e4684d34e..6117d928a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,6 +27,7 @@ "@nestjs/common": "10.3.10", "@nestjs/config": "3.1.1", "@nestjs/core": "10.4.7", + "@nestjs/event-emitter": "2.1.1", "@nestjs/platform-express": "10.3.9", "@nestjs/swagger": "7.4.0", "@noble/curves": "1.6.0", @@ -139,7 +140,7 @@ "jest-environment-node": "29.7.0", "jest-mock-extended": "3.0.5", "lint-staged": "15.2.0", - "msw": "^2.6.8", + "msw": "2.6.8", "nock": "13.5.4", "nx": "19.4.4", "postcss": "8.4.47", @@ -7018,6 +7019,19 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" }, + "node_modules/@nestjs/event-emitter": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@nestjs/event-emitter/-/event-emitter-2.1.1.tgz", + "integrity": "sha512-6L6fBOZTyfFlL7Ih/JDdqlCzZeCW0RjCX28wnzGyg/ncv5F/EOeT1dfopQr1loBRQ3LTgu8OWM7n4zLN4xigsg==", + "license": "MIT", + "dependencies": { + "eventemitter2": "6.4.9" + }, + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", + "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0" + } + }, "node_modules/@nestjs/mapped-types": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-2.0.5.tgz", diff --git a/package.json b/package.json index db068c093..8aeeb8fbf 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "jest-environment-node": "29.7.0", "jest-mock-extended": "3.0.5", "lint-staged": "15.2.0", - "msw": "^2.6.8", + "msw": "2.6.8", "nock": "13.5.4", "nx": "19.4.4", "postcss": "8.4.47", @@ -87,6 +87,7 @@ "@nestjs/common": "10.3.10", "@nestjs/config": "3.1.1", "@nestjs/core": "10.4.7", + "@nestjs/event-emitter": "2.1.1", "@nestjs/platform-express": "10.3.9", "@nestjs/swagger": "7.4.0", "@noble/curves": "1.6.0", diff --git a/packages/signature/src/lib/__test__/unit/sign.spec.ts b/packages/signature/src/lib/__test__/unit/sign.spec.ts index acecae91a..f4d5c3a7b 100644 --- a/packages/signature/src/lib/__test__/unit/sign.spec.ts +++ b/packages/signature/src/lib/__test__/unit/sign.spec.ts @@ -15,6 +15,7 @@ import { } from '../../sign' import { Alg, Curves, Jwk, KeyTypes, Payload, PrivateKey, SigningAlg } from '../../types' import { + SMALLEST_RSA_MODULUS_LENGTH, base64UrlToBytes, base64UrlToHex, ed25519polyfilled as ed, @@ -107,7 +108,7 @@ describe('sign', () => { }) it('sign RS256 correctly', async () => { - const key = await generateJwk(Alg.RS256) + const key = await generateJwk(Alg.RS256, { modulusLength: SMALLEST_RSA_MODULUS_LENGTH }) const jwt = await signJwt(payload, key) const verifiedJwt = await verifyJwt(jwt, key) expect(verifiedJwt.payload).toEqual(payload) From 946534c29539ea8c6de0aa9a129c78b7ee2e1001 Mon Sep 17 00:00:00 2001 From: Matt Schoch Date: Tue, 17 Dec 2024 15:51:42 +0100 Subject: [PATCH 036/120] RSA jwk<>pem (#35) Co-authored-by: Pierre Troger --- .../broker/__test__/e2e/connection.spec.ts | 1 + .../rest/controller/connection.controller.ts | 9 ++- .../dto/response/pending-connection.dto.ts | 3 +- .../src/lib/__test__/unit/util.spec.ts | 41 ++++++++++++ packages/signature/src/lib/types.ts | 2 + packages/signature/src/lib/utils.ts | 65 ++++++++++++++++++- 6 files changed, 115 insertions(+), 6 deletions(-) diff --git a/apps/vault/src/broker/__test__/e2e/connection.spec.ts b/apps/vault/src/broker/__test__/e2e/connection.spec.ts index 6ddac4b42..987d3f0d3 100644 --- a/apps/vault/src/broker/__test__/e2e/connection.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/connection.spec.ts @@ -176,6 +176,7 @@ describe('Connection', () => { expect(body.publicKey.keyId).toEqual(expect.any(String)) expect(body.encryptionPublicKey.keyId).toEqual(expect.any(String)) + expect(body.encryptionPublicKey.pem).toEqual(expect.any(String)) // ensure we also respond w/ the PEM format. expect(status).toEqual(HttpStatus.CREATED) }) diff --git a/apps/vault/src/broker/http/rest/controller/connection.controller.ts b/apps/vault/src/broker/http/rest/controller/connection.controller.ts index 12768ead0..af7ac16fa 100644 --- a/apps/vault/src/broker/http/rest/controller/connection.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/connection.controller.ts @@ -1,5 +1,5 @@ import { Paginated, PaginationOptions, PaginationParam } from '@narval/nestjs-shared' -import { publicKeyToHex } from '@narval/signature' +import { publicKeyToHex, publicKeyToPem } from '@narval/signature' import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Patch, Post } from '@nestjs/common' import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../shared/decorator/client-id.decorator' @@ -45,11 +45,16 @@ export class ConnectionController { async initiate(@ClientId() clientId: string, @Body() body: InitiateConnectionDto): Promise { const pendingConnection = await this.connectionService.initiate(clientId, body) + const encryptionPem = pendingConnection.encryptionPublicKey + ? await publicKeyToPem(pendingConnection.encryptionPublicKey, pendingConnection.encryptionPublicKey.alg) + : undefined + return PendingConnectionDto.create({ ...pendingConnection, encryptionPublicKey: { keyId: pendingConnection.encryptionPublicKey?.kid, - jwk: pendingConnection.encryptionPublicKey + jwk: pendingConnection.encryptionPublicKey, + pem: encryptionPem ? Buffer.from(encryptionPem).toString('base64') : undefined }, ...(pendingConnection.credentials ? { diff --git a/apps/vault/src/broker/http/rest/dto/response/pending-connection.dto.ts b/apps/vault/src/broker/http/rest/dto/response/pending-connection.dto.ts index 0cd4aa263..9328f88ec 100644 --- a/apps/vault/src/broker/http/rest/dto/response/pending-connection.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/pending-connection.dto.ts @@ -21,7 +21,8 @@ export class PendingConnectionDto extends createZodDto( .optional(), encryptionPublicKey: z.object({ keyId: z.string().optional(), - jwk: publicKeySchema.optional() + jwk: publicKeySchema.optional().describe('JWK format of the public key'), + pem: z.string().optional().describe('Base64url encoded PEM public key') }) }) ) {} diff --git a/packages/signature/src/lib/__test__/unit/util.spec.ts b/packages/signature/src/lib/__test__/unit/util.spec.ts index fc76cafd6..88c4c239a 100644 --- a/packages/signature/src/lib/__test__/unit/util.spec.ts +++ b/packages/signature/src/lib/__test__/unit/util.spec.ts @@ -15,6 +15,7 @@ import { Secp256k1PrivateKey, SigningAlg, p256PublicKeySchema, + rsaPublicKeySchema, secp256k1PublicKeySchema } from '../../types' import { @@ -26,6 +27,8 @@ import { privateKeyToJwk, publicKeyToHex, publicKeyToJwk, + publicKeyToPem, + publicRsaPemToJwk, requestWithoutWildcardFields, rsaPrivateKeyToPublicKey } from '../../utils' @@ -302,6 +305,44 @@ describe('privateKeyToJwk', () => { // }) }) +describe('publicJwkToPem', () => { + const privateJwk = { + kty: 'RSA', + alg: 'RS256', + kid: '0x52920ad0d19d7779106bd9d9d600d26c4b976cdb3cbc49decb7fdc29db00b8e9', + n: 'xNdTjWL9hGa4bz4tLKbmFZ4yjQsQzW35-CMS0kno3403jEqg5y2Cs6sLVyPBX4N2hdK5ERPytpf1PrThHqB-eEO6LtEWpENBgFuNIf8DRHrv0tne7dLNxf7sx1aocGRrkgIk4Ws6Is4Ot3whm3-WihmDGnHoogE-EPwVkkSc2FYPXYlNq4htCZXC8_MUI3LuXry2Gn4tna5HsYSehYhfKDD-nfSajeWxdNUv_3wOeSCr9ICm9Udlo7hpIUHQgnX3Nz6kvfGYuweLGoj_ot-oEUCIdlbQqmrfStAclugbM5NI6tY__6wD0z_4ZBjToupXCBlXbYsde6_ZG9xPmYSykw', + e: 'AQAB', + d: 'QU4rIzpXX8jwob-gHzNUHJH6tX6ZWX6GM0P3p5rrztc8Oag8z9XyigdSYNu0-SpVdTqfOcJDgT7TF7XNBms66k2WBJhMCb1iiuJU5ZWEkQC0dmDgLEkHCgx0pAHlKjy2z580ezEm_YsdqNRfFgbze-fQ7kIiazU8UUhBI-DtpHv7baBgsfqEfQ5nCTiURUPmmpiIU74-ZIJWZjBXTOoJNH0EIsJK9IpZzxpeC9mTMTsWTcHKiR3acze1qf-9I97v461TTZ8e33N6YINyr9I4HZuvxlCJdV_lOM3fLvYM9gPvgkPozhVWL3VKR6xa9JpGGHrCRgH92INuviBB_SmF8Q', + p: '9BNku_-t4Df9Dg7M2yjiNgZgcTNKrDnNqexliIUAt67q0tGmSBubjxeI5unDJZ_giXWUR3q-02v7HT5GYx-ZVgKk2lWnbrrm_F7UZW-ueHzeVvQcjDXTk0z8taXzrDJgnIwZIaZ2XSG3P-VPOrXCaMba8GzSq38Gpzi4g3lTO9s', + q: 'znUtwrqdnVew14_aFjNTRgzOQNN8JhkjzJy3aTSLBScK5NbiuUUZBWs5dQ7Nv7aAoDss1-o9XVQZ1DVV-o9UufJtyrPNcvTnC0cWRrtJrSN5YiuUbECU3Uj3OvGxnhx9tsmhDHnMTo50ObPYUbHcIkNaXkf2FVgL84y1JRWdPak', + dp: 'UNDrFeS-6fMf8zurURXkcQcDf_f_za8GDjGcHOwNJMTiNBP-_vlFNMgSKINWfmrFqj4obtKRxOeIKlKoc8HOv8_4TeL2oY95VC8CHOQx3Otbo2cI3NQlziw7sNnWKTo1CyDIYYAAyS2Uw69l4Ia2bIMLk3g0-VwCE_SQA9h0Wuk', + dq: 'VBe6ieSFKn97UnIPfJdvRcsVf6YknUgEIuV6d2mlbnXWpBs6wgf5BxIDl0BuYbYuchVoUJHiaM9Grf8DhEk5U3wBaF0QQ9CpAxjzY-AJRHJ8kJX7oJQ1jmSX_vRPSn2EXx2FcZVyuFSh1pcAd1YgufwBJQHepBb21z7q0a4aG_E', + qi: 'KhZpFs6xfyRIjbJV8Q9gWxqF37ONayIzBpgio5mdAQlZ-FUmaWZ2_2VWP2xvsP48BmwFXydHqewHBqGnZYCQ1ZHXJgD_-KKEejoqS5AJN1pdI0ZKjs7UCfZ4RJ4DH5p0_35gpuKRzzdvcIhl1CjIC5W8o7nhwmLBJ_QAo9e4t9U' + } + const publicJwk = rsaPublicKeySchema.parse(privateJwk) + it('does pem -> hex round trip for RSA keys', async () => { + const pem = await publicKeyToPem(publicJwk, Alg.RS256) + + const backToJwk = await publicRsaPemToJwk(pem, { kid: publicJwk.kid }) + + expect(backToJwk).toEqual(publicJwk) + }) + it('does pem -> jwk', async () => { + const pem = `-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxNdTjWL9hGa4bz4tLKbm +FZ4yjQsQzW35+CMS0kno3403jEqg5y2Cs6sLVyPBX4N2hdK5ERPytpf1PrThHqB+ +eEO6LtEWpENBgFuNIf8DRHrv0tne7dLNxf7sx1aocGRrkgIk4Ws6Is4Ot3whm3+W +ihmDGnHoogE+EPwVkkSc2FYPXYlNq4htCZXC8/MUI3LuXry2Gn4tna5HsYSehYhf +KDD+nfSajeWxdNUv/3wOeSCr9ICm9Udlo7hpIUHQgnX3Nz6kvfGYuweLGoj/ot+o +EUCIdlbQqmrfStAclugbM5NI6tY//6wD0z/4ZBjToupXCBlXbYsde6/ZG9xPmYSy +kwIDAQAB +-----END PUBLIC KEY-----` + + const newJwk = await publicRsaPemToJwk(pem, { kid: publicJwk.kid }) + expect(newJwk).toEqual(publicJwk) + }) +}) + describe('hashRequestWithoutWildcardFields', () => { const transaction = { chainId: 137, diff --git a/packages/signature/src/lib/types.ts b/packages/signature/src/lib/types.ts index 614aa2d97..38171b0d1 100644 --- a/packages/signature/src/lib/types.ts +++ b/packages/signature/src/lib/types.ts @@ -423,3 +423,5 @@ export type EcdsaSignature = { s: Hex v: bigint } + +export type PemString = `-----BEGIN${string}` diff --git a/packages/signature/src/lib/utils.ts b/packages/signature/src/lib/utils.ts index 8284e3cc3..e42632d01 100644 --- a/packages/signature/src/lib/utils.ts +++ b/packages/signature/src/lib/utils.ts @@ -4,7 +4,7 @@ import * as ed25519 from '@noble/ed25519' import { sha256 as sha256Hash } from '@noble/hashes/sha256' import { sha512 } from '@noble/hashes/sha512' import { subtle } from 'crypto' -import { exportJWK, generateKeyPair } from 'jose' +import { exportJWK, exportSPKI, generateKeyPair, importJWK, importSPKI, KeyLike } from 'jose' import { cloneDeep, omit } from 'lodash' import { toHex } from 'viem' import { publicKeyToAddress } from 'viem/utils' @@ -31,12 +31,13 @@ import { P256PublicKey, PrivateKey, PublicKey, + publicKeySchema, + RsaKey, RsaPrivateKey, RsaPublicKey, Secp256k1PrivateKey, Secp256k1PublicKey, - Use, - publicKeySchema + Use } from './types' import { validateJwk } from './validate' @@ -237,6 +238,10 @@ export const stringToBase64Url = (str: string): string => { return base64ToBase64Url(Buffer.from(str).toString('base64')) } +export const base64UrlToString = (base64Url: string): string => { + return Buffer.from(base64UrlToBase64(base64Url), 'base64').toString('utf-8') +} + export const rsaKeyToKid = (jwk: Jwk) => { // Concatenate the 'n' and 'e' values, splitted by ':' const dataToHash = `${jwk.n}:${jwk.e}` @@ -485,6 +490,60 @@ export const generateJwk = async ( } } +export const publicJwkToPem = async (jwk: Jwk): Promise => { + switch (jwk.kty) { + case KeyTypes.RSA: + return publicRsaJwkToPem(jwk as RsaKey) + default: + throw new Error('Unsupported key type') + } +} + +export const publicHexToPem = async (publicKey: Hex, alg: Alg): Promise => { + switch (alg) { + case Alg.RS256: + return publicRsaJwkToPem((await publicKeyToJwk(publicKey, alg)) as RsaKey) + default: + throw new Error('Unsupported algorithm') + } +} + +export const publicKeyToPem = async (publicKey: Jwk | Hex, alg: Alg): Promise => { + if (typeof publicKey === 'string') { + return publicHexToPem(publicKey, alg) + } + + return publicJwkToPem(publicKey) +} + +export const publicRsaJwkToPem = async (rsaJwk: RsaKey): Promise => { + const jk = (await importJWK(rsaJwk, 'RS256')) as KeyLike + const k = await exportSPKI(jk) + return k +} + +export const publicRsaPemToJwk = async (pem: string, opts?: { kid?: string }): Promise => { + const jk = await importSPKI(pem, 'RS256', { + extractable: true + }) + const key = await exportJWK(jk) + + return rsaPublicKeySchema.parse({ + ...key, + alg: 'RS256', + kid: opts?.kid || rsaKeyToKid({ n: key.n, e: key.e }) + }) +} + +export const publicPemToJwk = (pem: string, alg: Alg, kid?: string): T => { + switch (alg) { + case Alg.RS256: + return publicRsaPemToJwk(pem, { kid }) as T + default: + throw new Error('Unsupported algorithm') + } +} + export const nowSeconds = (): number => Math.floor(Date.now() / 1000) type AlgToPublicKeyType = { From 540edff0de3c94783ae69ea3e71f53e53ecf9b40 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Tue, 17 Dec 2024 16:00:17 +0100 Subject: [PATCH 037/120] Update Vault SDK v0.11.0 (#36) * Refactor proxy controller to remove SEARCH HTTP method This was breaking the OpenAPI generator. * Generate Vault HTTP client and update SDK * Remove test only * Bump SDK version to 0.11.0 --- .../rest/controller/account.controller.ts | 11 +- .../rest/controller/address.controller.ts | 9 +- .../rest/controller/connection.controller.ts | 23 +- .../http/rest/controller/proxy.controller.ts | 199 +- .../http/rest/controller/wallet.controller.ts | 8 +- .../http/rest/dto/response/account.dto.ts | 2 +- .../http/rest/dto/response/address.dto.ts | 2 +- .../http/rest/dto/response/connection.dto.ts | 2 +- .../http/rest/dto/response/wallet.dto.ts | 2 +- package-lock.json | 334 +- .../address-book-management.spec.ts | 0 .../approvals-and-spending-limit.spec.ts | 0 .../defi-interactions.spec.ts | 0 .../tiered-eth-transfer-policy.spec.ts | 0 .../user-journeys.spec.ts | 30 +- packages/armory-sdk/package.json | 2 +- .../src/lib/http/client/vault/api.ts | 5871 ++++++++++++++--- 17 files changed, 5421 insertions(+), 1074 deletions(-) rename packages/armory-e2e-testing/src/__test__/e2e/{scenarii => scenario}/address-book-management.spec.ts (100%) rename packages/armory-e2e-testing/src/__test__/e2e/{scenarii => scenario}/approvals-and-spending-limit.spec.ts (100%) rename packages/armory-e2e-testing/src/__test__/e2e/{scenarii => scenario}/defi-interactions.spec.ts (100%) rename packages/armory-e2e-testing/src/__test__/e2e/{scenarii => scenario}/tiered-eth-transfer-policy.spec.ts (100%) rename packages/armory-e2e-testing/src/__test__/e2e/{scenarii => scenario}/user-journeys.spec.ts (95%) diff --git a/apps/vault/src/broker/http/rest/controller/account.controller.ts b/apps/vault/src/broker/http/rest/controller/account.controller.ts index 257d03646..300cc54ad 100644 --- a/apps/vault/src/broker/http/rest/controller/account.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/account.controller.ts @@ -6,7 +6,7 @@ import { ClientId } from '../../../../shared/decorator/client-id.decorator' import { PermissionGuard } from '../../../../shared/decorator/permission-guard.decorator' import { VaultPermission } from '../../../../shared/type/domain.type' import { AccountService } from '../../../core/service/account.service' -import { AccountDto } from '../dto/response/account.dto' +import { ProviderAccountDto } from '../dto/response/account.dto' import { PaginatedAccountsDto } from '../dto/response/paginated-accounts.dto' import { PaginatedAddressesDto } from '../dto/response/paginated-addresses.dto' @@ -50,15 +50,18 @@ export class AccountController { }) @ApiResponse({ status: HttpStatus.OK, - type: AccountDto + type: ProviderAccountDto }) @ApiResponse({ status: HttpStatus.NOT_FOUND, description: 'Account not found' }) - async getAccountById(@ClientId() clientId: string, @Param('accountId') accountId: string): Promise { + async getAccountById( + @ClientId() clientId: string, + @Param('accountId') accountId: string + ): Promise { const account = await this.accountService.getAccount(clientId, accountId) - return AccountDto.create({ account }) + return ProviderAccountDto.create({ account }) } @Get(':accountId/addresses') diff --git a/apps/vault/src/broker/http/rest/controller/address.controller.ts b/apps/vault/src/broker/http/rest/controller/address.controller.ts index d1fcdebf3..0e1f309b9 100644 --- a/apps/vault/src/broker/http/rest/controller/address.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/address.controller.ts @@ -5,7 +5,7 @@ import { ClientId } from '../../../../shared/decorator/client-id.decorator' import { PermissionGuard } from '../../../../shared/decorator/permission-guard.decorator' import { VaultPermission } from '../../../../shared/type/domain.type' import { AddressService } from '../../../core/service/address.service' -import { AddressDto } from '../dto/response/address.dto' +import { ProviderAddressDto } from '../dto/response/address.dto' import { PaginatedAddressesDto } from '../dto/response/paginated-addresses.dto' @Controller({ @@ -54,9 +54,12 @@ export class AddressController { status: HttpStatus.NOT_FOUND, description: 'Address not found' }) - async getAddressById(@ClientId() clientId: string, @Param('addressId') addressId: string): Promise { + async getAddressById( + @ClientId() clientId: string, + @Param('addressId') addressId: string + ): Promise { const address = await this.addressService.getAddress(clientId, addressId) - return AddressDto.create({ address }) + return ProviderAddressDto.create({ address }) } } diff --git a/apps/vault/src/broker/http/rest/controller/connection.controller.ts b/apps/vault/src/broker/http/rest/controller/connection.controller.ts index af7ac16fa..ba4679a57 100644 --- a/apps/vault/src/broker/http/rest/controller/connection.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/connection.controller.ts @@ -12,7 +12,7 @@ import { CreateConnectionDto } from '../dto/request/create-connection.dto' import { InitiateConnectionDto } from '../dto/request/initiate-connection.dto' import { UpdateConnectionDto } from '../dto/request/update-connection.dto' import { ConnectionListDto } from '../dto/response/connection-list.dto' -import { ConnectionDto } from '../dto/response/connection.dto' +import { ProviderConnectionDto } from '../dto/response/connection.dto' import { PaginatedAccountsDto } from '../dto/response/paginated-accounts.dto' import { PaginatedConnectionsDto } from '../dto/response/paginated-connections.dto' import { PaginatedWalletsDto } from '../dto/response/paginated-wallets.dto' @@ -78,12 +78,12 @@ export class ConnectionController { @ApiResponse({ description: 'Returns a reference to the stored provider connection.', status: HttpStatus.CREATED, - type: ConnectionDto + type: ProviderConnectionDto }) - async create(@ClientId() clientId: string, @Body() body: CreateConnectionDto): Promise { + async create(@ClientId() clientId: string, @Body() body: CreateConnectionDto): Promise { const connection = await this.connectionService.create(clientId, body) - return ConnectionDto.create(connection) + return ProviderConnectionDto.create(connection) } @Delete(':connectionId') @@ -135,13 +135,16 @@ export class ConnectionController { }) @ApiResponse({ description: 'Returns the details of the specified connection.', - type: ConnectionDto, + type: ProviderConnectionDto, status: HttpStatus.OK }) - async getById(@ClientId() clientId: string, @Param('connectionId') connectionId: string): Promise { + async getById( + @ClientId() clientId: string, + @Param('connectionId') connectionId: string + ): Promise { const connection = await this.connectionService.findById(clientId, connectionId) - return ConnectionDto.create(connection) + return ProviderConnectionDto.create(connection) } @Patch(':connectionId') @@ -154,20 +157,20 @@ export class ConnectionController { @ApiResponse({ description: 'Returns the updated details of the provider connection.', status: HttpStatus.OK, - type: ConnectionDto + type: ProviderConnectionDto }) async update( @ClientId() clientId: string, @Param('connectionId') connectionId: string, @Body() body: UpdateConnectionDto - ): Promise { + ): Promise { const connection = await this.connectionService.update({ ...body, clientId, connectionId }) - return ConnectionDto.create(connection) + return ProviderConnectionDto.create(connection) } @Get(':connectionId/wallets') diff --git a/apps/vault/src/broker/http/rest/controller/proxy.controller.ts b/apps/vault/src/broker/http/rest/controller/proxy.controller.ts index 9923ad814..876348ddb 100644 --- a/apps/vault/src/broker/http/rest/controller/proxy.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/proxy.controller.ts @@ -1,4 +1,18 @@ -import { All, Body, Controller, HttpStatus, Param, Req, Res } from '@nestjs/common' +import { + Body, + Controller, + Delete, + Get, + Head, + HttpStatus, + Options, + Param, + Patch, + Post, + Put, + Req, + Res +} from '@nestjs/common' import { ApiHeader, ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger' import { Request, Response } from 'express' import { ClientId } from '../../../../shared/decorator/client-id.decorator' @@ -8,6 +22,31 @@ import { VaultPermission } from '../../../../shared/type/domain.type' import { ProxyRequestException } from '../../../core/exception/proxy-request.exception' import { ProxyService } from '../../../core/service/proxy.service' +const API_PARAM = ':endpoint(*)' + +const API_OPERATION = { + summary: 'Authorizes and forwards the request to the provider', + description: + 'This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider.' +} as const + +const CONNECTION_HEADER = { + name: 'x-connection-id', + required: true, + description: 'The connection ID used to forward request to provider' +} as const + +const ENDPOINT_PARAM = { + name: 'endpoint', + required: true, + description: 'The raw endpoint path in the provider' +} as const + +const INACTIVE_CONNECTION_RESPONSE = { + status: HttpStatus.PROXY_AUTHENTICATION_REQUIRED, + description: 'Requested connection is not active' +} as const + @Controller({ path: 'proxy', version: '1' @@ -16,34 +55,13 @@ import { ProxyService } from '../../../core/service/proxy.service' export class ProxyController { constructor(private readonly proxyService: ProxyService) {} - @All(':endpoint(*)') - @PermissionGuard(VaultPermission.CONNECTION_READ) - @ApiHeader({ - name: 'x-connection-id', - required: true, - description: 'The connection ID used to forward request to provider' - }) - @ApiOperation({ - summary: 'Forward request to provider', - description: - 'This endpoint uses the connection specified in the header to sign and forward the request in the path to the provider.' - }) - @ApiParam({ - name: 'endpoint', - required: true, - description: 'The raw endpoint path in the provider' - }) - @ApiResponse({ - status: HttpStatus.PROXY_AUTHENTICATION_REQUIRED, - description: 'Requested connection is not active' - }) - async proxyRequest( - @ClientId() clientId: string, - @ConnectionId() connectionId: string, - @Param('endpoint') endpoint: string, - @Body() body: unknown, - @Req() request: Request, - @Res() res: Response + private async handleRequest( + clientId: string, + connectionId: string, + endpoint: string, + body: unknown, + request: Request, + res: Response ) { const queryString = new URLSearchParams(request.query as Record).toString() const sanitizedEndpoint = queryString ? `/${endpoint}?${queryString}` : `/${endpoint}` @@ -65,4 +83,127 @@ export class ProxyController { } } } + + // IMPORTANT: The `@All` decorator from NestJS cannot be used here because it + // includes a handler for the SEARCH HTTP method, which causes issues with + // the OpenAPI generator used by the SDK. + + @Get(API_PARAM) + @PermissionGuard(VaultPermission.CONNECTION_READ) + @ApiHeader(CONNECTION_HEADER) + @ApiOperation(API_OPERATION) + @ApiParam(ENDPOINT_PARAM) + @ApiResponse(INACTIVE_CONNECTION_RESPONSE) + async get( + @ClientId() clientId: string, + @ConnectionId() connectionId: string, + @Param('endpoint') endpoint: string, + @Body() body: unknown, + @Req() request: Request, + @Res() res: Response + ) { + return this.handleRequest(clientId, connectionId, endpoint, body, request, res) + } + + @Post(API_PARAM) + @PermissionGuard(VaultPermission.CONNECTION_READ) + @ApiHeader(CONNECTION_HEADER) + @ApiOperation(API_OPERATION) + @ApiParam(ENDPOINT_PARAM) + @ApiResponse(INACTIVE_CONNECTION_RESPONSE) + async post( + @ClientId() clientId: string, + @ConnectionId() connectionId: string, + @Param('endpoint') endpoint: string, + @Body() body: unknown, + @Req() request: Request, + @Res() res: Response + ) { + return this.handleRequest(clientId, connectionId, endpoint, body, request, res) + } + + @Put(API_PARAM) + @PermissionGuard(VaultPermission.CONNECTION_READ) + @ApiHeader(CONNECTION_HEADER) + @ApiOperation(API_OPERATION) + @ApiParam(ENDPOINT_PARAM) + @ApiResponse(INACTIVE_CONNECTION_RESPONSE) + async put( + @ClientId() clientId: string, + @ConnectionId() connectionId: string, + @Param('endpoint') endpoint: string, + @Body() body: unknown, + @Req() request: Request, + @Res() res: Response + ) { + return this.handleRequest(clientId, connectionId, endpoint, body, request, res) + } + + @Patch(API_PARAM) + @PermissionGuard(VaultPermission.CONNECTION_READ) + @ApiHeader(CONNECTION_HEADER) + @ApiOperation(API_OPERATION) + @ApiParam(ENDPOINT_PARAM) + @ApiResponse(INACTIVE_CONNECTION_RESPONSE) + async patch( + @ClientId() clientId: string, + @ConnectionId() connectionId: string, + @Param('endpoint') endpoint: string, + @Body() body: unknown, + @Req() request: Request, + @Res() res: Response + ) { + return this.handleRequest(clientId, connectionId, endpoint, body, request, res) + } + + @Delete(API_PARAM) + @PermissionGuard(VaultPermission.CONNECTION_READ) + @ApiHeader(CONNECTION_HEADER) + @ApiOperation(API_OPERATION) + @ApiParam(ENDPOINT_PARAM) + @ApiResponse(INACTIVE_CONNECTION_RESPONSE) + async delete( + @ClientId() clientId: string, + @ConnectionId() connectionId: string, + @Param('endpoint') endpoint: string, + @Body() body: unknown, + @Req() request: Request, + @Res() res: Response + ) { + return this.handleRequest(clientId, connectionId, endpoint, body, request, res) + } + + @Head(API_PARAM) + @PermissionGuard(VaultPermission.CONNECTION_READ) + @ApiHeader(CONNECTION_HEADER) + @ApiOperation(API_OPERATION) + @ApiParam(ENDPOINT_PARAM) + @ApiResponse(INACTIVE_CONNECTION_RESPONSE) + async head( + @ClientId() clientId: string, + @ConnectionId() connectionId: string, + @Param('endpoint') endpoint: string, + @Body() body: unknown, + @Req() request: Request, + @Res() res: Response + ) { + return this.handleRequest(clientId, connectionId, endpoint, body, request, res) + } + + @Options(API_PARAM) + @PermissionGuard(VaultPermission.CONNECTION_READ) + @ApiHeader(CONNECTION_HEADER) + @ApiOperation(API_OPERATION) + @ApiParam(ENDPOINT_PARAM) + @ApiResponse(INACTIVE_CONNECTION_RESPONSE) + async options( + @ClientId() clientId: string, + @ConnectionId() connectionId: string, + @Param('endpoint') endpoint: string, + @Body() body: unknown, + @Req() request: Request, + @Res() res: Response + ) { + return this.handleRequest(clientId, connectionId, endpoint, body, request, res) + } } diff --git a/apps/vault/src/broker/http/rest/controller/wallet.controller.ts b/apps/vault/src/broker/http/rest/controller/wallet.controller.ts index 4d08f948f..ba09c1b88 100644 --- a/apps/vault/src/broker/http/rest/controller/wallet.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/wallet.controller.ts @@ -8,7 +8,7 @@ import { AccountService } from '../../../core/service/account.service' import { WalletService } from '../../../core/service/wallet.service' import { PaginatedAccountsDto } from '../dto/response/paginated-accounts.dto' import { PaginatedWalletsDto } from '../dto/response/paginated-wallets.dto' -import { WalletDto } from '../dto/response/wallet.dto' +import { ProviderWalletDto } from '../dto/response/wallet.dto' @Controller({ path: 'wallets', @@ -53,15 +53,15 @@ export class WalletController { }) @ApiResponse({ status: HttpStatus.OK, - type: WalletDto + type: ProviderWalletDto }) @ApiResponse({ status: HttpStatus.NOT_FOUND, description: 'Wallet not found' }) - async getWalletById(@ClientId() clientId: string, @Param('walletId') walletId: string): Promise { + async getWalletById(@ClientId() clientId: string, @Param('walletId') walletId: string): Promise { const wallet = await this.walletService.getWallet(clientId, walletId) - return WalletDto.create({ wallet }) + return ProviderWalletDto.create({ wallet }) } @Get(':walletId/accounts') diff --git a/apps/vault/src/broker/http/rest/dto/response/account.dto.ts b/apps/vault/src/broker/http/rest/dto/response/account.dto.ts index a759a00fc..fad350f21 100644 --- a/apps/vault/src/broker/http/rest/dto/response/account.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/account.dto.ts @@ -2,7 +2,7 @@ import { createZodDto } from 'nestjs-zod' import { z } from 'zod' import { Account } from '../../../../core/type/indexed-resources.type' -export class AccountDto extends createZodDto( +export class ProviderAccountDto extends createZodDto( z.object({ account: Account }) diff --git a/apps/vault/src/broker/http/rest/dto/response/address.dto.ts b/apps/vault/src/broker/http/rest/dto/response/address.dto.ts index 570eab03b..866bc2468 100644 --- a/apps/vault/src/broker/http/rest/dto/response/address.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/address.dto.ts @@ -2,7 +2,7 @@ import { createZodDto } from 'nestjs-zod' import { z } from 'zod' import { Address } from '../../../../core/type/indexed-resources.type' -export class AddressDto extends createZodDto( +export class ProviderAddressDto extends createZodDto( z.object({ address: Address }) diff --git a/apps/vault/src/broker/http/rest/dto/response/connection.dto.ts b/apps/vault/src/broker/http/rest/dto/response/connection.dto.ts index cb861b25a..748fa8d48 100644 --- a/apps/vault/src/broker/http/rest/dto/response/connection.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/connection.dto.ts @@ -1,4 +1,4 @@ import { createZodDto } from 'nestjs-zod' import { BaseConnection } from '../../../../core/type/connection.type' -export class ConnectionDto extends createZodDto(BaseConnection) {} +export class ProviderConnectionDto extends createZodDto(BaseConnection) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/wallet.dto.ts b/apps/vault/src/broker/http/rest/dto/response/wallet.dto.ts index 4b165458f..3f5c6f10f 100644 --- a/apps/vault/src/broker/http/rest/dto/response/wallet.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/wallet.dto.ts @@ -2,7 +2,7 @@ import { createZodDto } from 'nestjs-zod' import { z } from 'zod' import { PublicWallet } from '../../../../core/type/indexed-resources.type' -export class WalletDto extends createZodDto( +export class ProviderWalletDto extends createZodDto( z.object({ wallet: PublicWallet }) diff --git a/package-lock.json b/package-lock.json index 6117d928a..bbe5b414b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1332,12 +1332,13 @@ } }, "node_modules/@babel/generator": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz", - "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.3.tgz", + "integrity": "sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ==", + "license": "MIT", "dependencies": { - "@babel/parser": "^7.26.2", - "@babel/types": "^7.26.0", + "@babel/parser": "^7.26.3", + "@babel/types": "^7.26.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -1635,11 +1636,12 @@ } }, "node_modules/@babel/parser": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz", - "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.3.tgz", + "integrity": "sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==", + "license": "MIT", "dependencies": { - "@babel/types": "^7.26.0" + "@babel/types": "^7.26.3" }, "bin": { "parser": "bin/babel-parser.js" @@ -1713,6 +1715,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.", + "license": "MIT", "peer": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.18.6", @@ -1746,6 +1749,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.25.9.tgz", "integrity": "sha512-ykqgwNfSnNOB+C8fV5X4mG3AVmvu+WVxcaU9xHHtBb7PCrPeweMmPjGsn8eMaeJg6SJuoUuZENeeSWaarWqonQ==", + "license": "MIT", "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -1762,6 +1766,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead.", + "license": "MIT", "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.6", @@ -1779,6 +1784,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead.", + "license": "MIT", "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.20.2", @@ -1880,6 +1886,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.25.9.tgz", "integrity": "sha512-9MhJ/SMTsVqsd69GyQg89lYR4o9T+oDGv5F6IsigxxqFVOyR/IflDLYP8WDI1l8fkhNGGktqkvL5qwNCtGEpgQ==", + "license": "MIT", "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -1906,6 +1913,7 @@ "version": "7.26.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.26.0.tgz", "integrity": "sha512-B+O2DnPc0iG+YXFqOxv2WNuNU97ToWjOomUQ78DouOENWUaM5sVrmet9mcomUGQFwpJd//gvUagXBSdzO1fRKg==", + "license": "MIT", "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -2335,6 +2343,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.25.9.tgz", "integrity": "sha512-/VVukELzPDdci7UUsWQaSkhgnjIWXnIyRpM02ldxaVoFK96c41So8JcKT3m0gYjyv7j5FNPGS5vfELrWalkbDA==", + "license": "MIT", "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", @@ -2745,6 +2754,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz", "integrity": "sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==", + "license": "MIT", "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -2760,6 +2770,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz", "integrity": "sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==", + "license": "MIT", "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -3080,6 +3091,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.25.9.tgz", "integrity": "sha512-EASHsAhE+SSlEzJ4bzfusnXSHiU+JfAYzj+jbw2vgQKgq5HrUr8qs+vgtiEL5dOH6sEweI+PNt2D7AqrDSHyqQ==", + "license": "MIT", "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", @@ -3147,6 +3159,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.25.9.tgz", "integrity": "sha512-8D43jXtGsYmEeDvm4MWHYUpWf8iiXgWYx3fW7E7Wb7Oe6FWqJPl5K6TuFW0dOwNZzEE5rjlaSJYH9JjrUKJszA==", + "license": "MIT", "peer": true, "dependencies": { "clone-deep": "^4.0.1", @@ -3166,6 +3179,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "license": "MIT", "peer": true, "dependencies": { "is-plain-object": "^2.0.4", @@ -3180,6 +3194,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "license": "MIT", "peer": true, "dependencies": { "commondir": "^1.0.1", @@ -3194,6 +3209,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "license": "MIT", "peer": true, "dependencies": { "locate-path": "^3.0.0" @@ -3206,6 +3222,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "license": "MIT", "peer": true, "dependencies": { "p-locate": "^3.0.0", @@ -3219,6 +3236,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "license": "MIT", "peer": true, "dependencies": { "pify": "^4.0.1", @@ -3232,6 +3250,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", "peer": true, "dependencies": { "p-try": "^2.0.0" @@ -3247,6 +3266,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "license": "MIT", "peer": true, "dependencies": { "p-limit": "^2.0.0" @@ -3259,6 +3279,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "license": "MIT", "peer": true, "engines": { "node": ">=4" @@ -3268,6 +3289,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "license": "MIT", "peer": true, "engines": { "node": ">=6" @@ -3277,6 +3299,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "license": "MIT", "peer": true, "dependencies": { "find-up": "^3.0.0" @@ -3289,6 +3312,7 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", "peer": true, "bin": { "semver": "bin/semver" @@ -3298,6 +3322,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "license": "MIT", "peer": true, "dependencies": { "kind-of": "^6.0.2" @@ -3366,16 +3391,17 @@ }, "node_modules/@babel/traverse--for-generate-function-map": { "name": "@babel/traverse", - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", - "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "version": "7.26.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.4.tgz", + "integrity": "sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w==", + "license": "MIT", "peer": true, "dependencies": { - "@babel/code-frame": "^7.25.9", - "@babel/generator": "^7.25.9", - "@babel/parser": "^7.25.9", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.3", + "@babel/parser": "^7.26.3", "@babel/template": "^7.25.9", - "@babel/types": "^7.25.9", + "@babel/types": "^7.26.3", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -3384,9 +3410,10 @@ } }, "node_modules/@babel/types": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", - "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz", + "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==", + "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9" @@ -5061,6 +5088,7 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz", "integrity": "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==", + "license": "ISC", "peer": true, "engines": { "node": ">=12" @@ -5222,6 +5250,7 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz", "integrity": "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==", + "license": "MIT", "peer": true, "dependencies": { "@jest/types": "^29.6.3" @@ -17663,30 +17692,33 @@ "integrity": "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==" }, "node_modules/@react-native/assets-registry": { - "version": "0.76.3", - "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.76.3.tgz", - "integrity": "sha512-7Fnc3lzCFFpnoyL1egua6d/qUp0KiIpeSLbfOMln4nI2g2BMzyFHdPjJnpLV2NehmS0omOOkrfRqK5u1F/MXzA==", + "version": "0.76.5", + "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.76.5.tgz", + "integrity": "sha512-MN5dasWo37MirVcKWuysRkRr4BjNc81SXwUtJYstwbn8oEkfnwR9DaqdDTo/hHOnTdhafffLIa2xOOHcjDIGEw==", + "license": "MIT", "peer": true, "engines": { "node": ">=18" } }, "node_modules/@react-native/babel-plugin-codegen": { - "version": "0.76.3", - "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.76.3.tgz", - "integrity": "sha512-mZ7jmIIg4bUnxCqY3yTOkoHvvzsDyrZgfnIKiTGm5QACrsIGa5eT3pMFpMm2OpxGXRDrTMsYdPXE2rCyDX52VQ==", + "version": "0.76.5", + "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.76.5.tgz", + "integrity": "sha512-xe7HSQGop4bnOLMaXt0aU+rIatMNEQbz242SDl8V9vx5oOTI0VbZV9yLy6yBc6poUlYbcboF20YVjoRsxX4yww==", + "license": "MIT", "peer": true, "dependencies": { - "@react-native/codegen": "0.76.3" + "@react-native/codegen": "0.76.5" }, "engines": { "node": ">=18" } }, "node_modules/@react-native/babel-preset": { - "version": "0.76.3", - "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.76.3.tgz", - "integrity": "sha512-zi2nPlQf9q2fmfPyzwWEj6DU96v8ziWtEfG7CTAX2PG/Vjfsr94vn/wWrCdhBVvLRQ6Kvd/MFAuDYpxmQwIiVQ==", + "version": "0.76.5", + "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.76.5.tgz", + "integrity": "sha512-1Nu5Um4EogOdppBLI4pfupkteTjWfmI0hqW8ezWTg7Bezw0FtBj8yS8UYVd3wTnDFT9A5mA2VNoNUqomJnvj2A==", + "license": "MIT", "peer": true, "dependencies": { "@babel/core": "^7.25.2", @@ -17730,7 +17762,7 @@ "@babel/plugin-transform-typescript": "^7.25.2", "@babel/plugin-transform-unicode-regex": "^7.24.7", "@babel/template": "^7.25.0", - "@react-native/babel-plugin-codegen": "0.76.3", + "@react-native/babel-plugin-codegen": "0.76.5", "babel-plugin-syntax-hermes-parser": "^0.25.1", "babel-plugin-transform-flow-enums": "^0.0.2", "react-refresh": "^0.14.0" @@ -17746,6 +17778,7 @@ "version": "0.25.1", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.25.1.tgz", "integrity": "sha512-IVNpGzboFLfXZUAwkLFcI/bnqVbwky0jP3eBno4HKtqvQJAHBLdgxiG6lQ4to0+Q/YCN3PO0od5NZwIKyY4REQ==", + "license": "MIT", "peer": true, "dependencies": { "hermes-parser": "0.25.1" @@ -17755,21 +17788,24 @@ "version": "0.25.1", "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "license": "MIT", "peer": true }, "node_modules/@react-native/babel-preset/node_modules/hermes-parser": { "version": "0.25.1", "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "license": "MIT", "peer": true, "dependencies": { "hermes-estree": "0.25.1" } }, "node_modules/@react-native/codegen": { - "version": "0.76.3", - "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.76.3.tgz", - "integrity": "sha512-oJCH/jbYeGmFJql8/y76gqWCCd74pyug41yzYAjREso1Z7xL88JhDyKMvxEnfhSdMOZYVl479N80xFiXPy3ZYA==", + "version": "0.76.5", + "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.76.5.tgz", + "integrity": "sha512-FoZ9VRQ5MpgtDAnVo1rT9nNRfjnWpE40o1GeJSDlpUMttd36bVXvsDm8W/NhX8BKTWXSX+CPQJsRcvN1UPYGKg==", + "license": "MIT", "peer": true, "dependencies": { "@babel/parser": "^7.25.3", @@ -17792,12 +17828,14 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT", "peer": true }, "node_modules/@react-native/codegen/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -17807,6 +17845,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", "peer": true, "dependencies": { "emoji-regex": "^8.0.0", @@ -17821,6 +17860,7 @@ "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", "peer": true, "dependencies": { "cliui": "^8.0.1", @@ -17836,13 +17876,14 @@ } }, "node_modules/@react-native/community-cli-plugin": { - "version": "0.76.3", - "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.76.3.tgz", - "integrity": "sha512-vgsLixHS24jR0d0QqPykBWFaC+V8x9cM3cs4oYXw3W199jgBNGP9MWcUJLazD2vzrT/lUTVBVg0rBeB+4XR6fg==", + "version": "0.76.5", + "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.76.5.tgz", + "integrity": "sha512-3MKMnlU0cZOWlMhz5UG6WqACJiWUrE3XwBEumzbMmZw3Iw3h+fIsn+7kLLE5EhzqLt0hg5Y4cgYFi4kOaNgq+g==", + "license": "MIT", "peer": true, "dependencies": { - "@react-native/dev-middleware": "0.76.3", - "@react-native/metro-babel-transformer": "0.76.3", + "@react-native/dev-middleware": "0.76.5", + "@react-native/metro-babel-transformer": "0.76.5", "chalk": "^4.0.0", "execa": "^5.1.1", "invariant": "^2.2.4", @@ -17869,6 +17910,7 @@ "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", "peer": true, "bin": { "semver": "bin/semver.js" @@ -17878,22 +17920,24 @@ } }, "node_modules/@react-native/debugger-frontend": { - "version": "0.76.3", - "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.76.3.tgz", - "integrity": "sha512-pMHQ3NpPB28RxXciSvm2yD+uDx3pkhzfuWkc7VFgOduyzPSIr0zotUiOJzsAtrj8++bPbOsAraCeQhCqoOTWQw==", + "version": "0.76.5", + "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.76.5.tgz", + "integrity": "sha512-5gtsLfBaSoa9WP8ToDb/8NnDBLZjv4sybQQj7rDKytKOdsXm3Pr2y4D7x7GQQtP1ZQRqzU0X0OZrhRz9xNnOqA==", + "license": "BSD-3-Clause", "peer": true, "engines": { "node": ">=18" } }, "node_modules/@react-native/dev-middleware": { - "version": "0.76.3", - "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.76.3.tgz", - "integrity": "sha512-b+2IpW40z1/S5Jo5JKrWPmucYU/PzeGyGBZZ/SJvmRnBDaP3txb9yIqNZAII1EWsKNhedh8vyRO5PSuJ9Juqzw==", + "version": "0.76.5", + "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.76.5.tgz", + "integrity": "sha512-f8eimsxpkvMgJia7POKoUu9uqjGF6KgkxX4zqr/a6eoR1qdEAWUd6PonSAqtag3PAqvEaJpB99gLH2ZJI1nDGg==", + "license": "MIT", "peer": true, "dependencies": { "@isaacs/ttlcache": "^1.4.1", - "@react-native/debugger-frontend": "0.76.3", + "@react-native/debugger-frontend": "0.76.5", "chrome-launcher": "^0.15.2", "chromium-edge-launcher": "^0.2.0", "connect": "^3.6.5", @@ -17912,6 +17956,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "peer": true, "dependencies": { "ms": "2.0.0" @@ -17921,12 +17966,14 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT", "peer": true }, "node_modules/@react-native/dev-middleware/node_modules/open": { "version": "7.4.2", "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "license": "MIT", "peer": true, "dependencies": { "is-docker": "^2.0.0", @@ -17943,37 +17990,41 @@ "version": "6.2.3", "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", + "license": "MIT", "peer": true, "dependencies": { "async-limiter": "~1.0.0" } }, "node_modules/@react-native/gradle-plugin": { - "version": "0.76.3", - "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.76.3.tgz", - "integrity": "sha512-t0aYZ8ND7+yc+yIm6Yp52bInneYpki6RSIFZ9/LMUzgMKvEB62ptt/7sfho9QkKHCNxE1DJSWIqLIGi/iHHkyg==", + "version": "0.76.5", + "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.76.5.tgz", + "integrity": "sha512-7KSyD0g0KhbngITduC8OABn0MAlJfwjIdze7nA4Oe1q3R7qmAv+wQzW+UEXvPah8m1WqFjYTkQwz/4mK3XrQGw==", + "license": "MIT", "peer": true, "engines": { "node": ">=18" } }, "node_modules/@react-native/js-polyfills": { - "version": "0.76.3", - "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.76.3.tgz", - "integrity": "sha512-pubJFArMMrdZiytH+W95KngcSQs+LsxOBsVHkwgMnpBfRUxXPMK4fudtBwWvhnwN76Oe+WhxSq7vOS5XgoPhmw==", + "version": "0.76.5", + "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.76.5.tgz", + "integrity": "sha512-ggM8tcKTcaqyKQcXMIvcB0vVfqr9ZRhWVxWIdiFO1mPvJyS6n+a+lLGkgQAyO8pfH0R1qw6K9D0nqbbDo865WQ==", + "license": "MIT", "peer": true, "engines": { "node": ">=18" } }, "node_modules/@react-native/metro-babel-transformer": { - "version": "0.76.3", - "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.76.3.tgz", - "integrity": "sha512-b2zQPXmW7avw/7zewc9nzMULPIAjsTwN03hskhxHUJH5pzUf7pIklB3FrgYPZrRhJgzHiNl3tOPu7vqiKzBYPg==", + "version": "0.76.5", + "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.76.5.tgz", + "integrity": "sha512-Cm9G5Sg5BDty3/MKa3vbCAJtT3YHhlEaPlQALLykju7qBS+pHZV9bE9hocfyyvc5N/osTIGWxG5YOfqTeMu1oQ==", + "license": "MIT", "peer": true, "dependencies": { "@babel/core": "^7.25.2", - "@react-native/babel-preset": "0.76.3", + "@react-native/babel-preset": "0.76.5", "hermes-parser": "0.23.1", "nullthrows": "^1.1.1" }, @@ -17985,15 +18036,17 @@ } }, "node_modules/@react-native/normalize-colors": { - "version": "0.76.3", - "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.76.3.tgz", - "integrity": "sha512-Yrpmrh4IDEupUUM/dqVxhAN8QW1VEUR3Qrk2lzJC1jB2s46hDe0hrMP2vs12YJqlzshteOthjwXQlY0TgIzgbg==", + "version": "0.76.5", + "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.76.5.tgz", + "integrity": "sha512-6QRLEok1r55gLqj+94mEWUENuU5A6wsr2OoXpyq/CgQ7THWowbHtru/kRGRr6o3AQXrVnZheR60JNgFcpNYIug==", + "license": "MIT", "peer": true }, "node_modules/@react-native/virtualized-lists": { - "version": "0.76.3", - "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.76.3.tgz", - "integrity": "sha512-wTGv9pVh3vAOWb29xFm+J9VRe9dUcUcb9FyaMLT/Hxa88W4wqa5ZMe1V9UvrrBiA1G5DKjv8/1ZcDsJhyugVKA==", + "version": "0.76.5", + "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.76.5.tgz", + "integrity": "sha512-M/fW1fTwxrHbcx0OiVOIxzG6rKC0j9cR9Csf80o77y1Xry0yrNPpAlf8D1ev3LvHsiAUiRNFlauoPtodrs2J1A==", + "license": "MIT", "peer": true, "dependencies": { "invariant": "^2.2.4", @@ -21240,6 +21293,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", "peer": true, "dependencies": { "event-target-shim": "^5.0.0" @@ -21424,6 +21478,7 @@ "version": "1.4.10", "resolved": "https://registry.npmjs.org/anser/-/anser-1.4.10.tgz", "integrity": "sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==", + "license": "MIT", "peer": true }, "node_modules/ansi-align": { @@ -21804,6 +21859,7 @@ "version": "0.15.2", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.15.2.tgz", "integrity": "sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg==", + "license": "MIT", "peer": true, "dependencies": { "tslib": "^2.0.1" @@ -21835,6 +21891,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "license": "MIT", "peer": true }, "node_modules/async-mutex": { @@ -21959,6 +22016,7 @@ "version": "7.0.0-bridge.0", "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==", + "license": "MIT", "peer": true, "peerDependencies": { "@babel/core": "^7.0.0-0" @@ -22143,6 +22201,7 @@ "version": "0.23.1", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.23.1.tgz", "integrity": "sha512-uNLD0tk2tLUjGFdmCk+u/3FEw2o+BAwW4g+z2QVlxJrzZYOOPADroEcNtTPt5lNiScctaUmnsTkVEnOwZUOLhA==", + "license": "MIT", "peer": true, "dependencies": { "hermes-parser": "0.23.1" @@ -22152,6 +22211,7 @@ "version": "0.0.2", "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-enums/-/babel-plugin-transform-flow-enums-0.0.2.tgz", "integrity": "sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ==", + "license": "MIT", "peer": true, "dependencies": { "@babel/plugin-syntax-flow": "^7.12.1" @@ -22665,6 +22725,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", "integrity": "sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==", + "license": "MIT", "peer": true, "dependencies": { "callsites": "^2.0.0" @@ -22677,6 +22738,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", "integrity": "sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==", + "license": "MIT", "peer": true, "engines": { "node": ">=4" @@ -22686,6 +22748,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", "integrity": "sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==", + "license": "MIT", "peer": true, "dependencies": { "caller-callsite": "^2.0.0" @@ -22962,6 +23025,7 @@ "version": "0.15.2", "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.2.tgz", "integrity": "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==", + "license": "Apache-2.0", "peer": true, "dependencies": { "@types/node": "*", @@ -22988,6 +23052,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/chromium-edge-launcher/-/chromium-edge-launcher-0.2.0.tgz", "integrity": "sha512-JfJjUnq25y9yg4FABRRVPmBGWPZZi+AQXT4mxupb67766/0UlhG8PAZCz6xzEMXTbW3CsSoE8PcCWA49n35mKg==", + "license": "Apache-2.0", "peer": true, "dependencies": { "@types/node": "*", @@ -23002,6 +23067,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", "peer": true, "bin": { "mkdirp": "bin/cmd.js" @@ -23635,6 +23701,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "license": "MIT", "peer": true }, "node_modules/compare-versions": { @@ -23881,6 +23948,7 @@ "version": "3.7.0", "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "license": "MIT", "peer": true, "dependencies": { "debug": "2.6.9", @@ -23904,6 +23972,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "peer": true, "dependencies": { "ms": "2.0.0" @@ -23913,6 +23982,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "license": "MIT", "peer": true, "dependencies": { "debug": "2.6.9", @@ -23931,12 +24001,14 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT", "peer": true }, "node_modules/connect/node_modules/on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "license": "MIT", "peer": true, "dependencies": { "ee-first": "1.1.1" @@ -23949,6 +24021,7 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "license": "MIT", "peer": true, "engines": { "node": ">= 0.6" @@ -25028,6 +25101,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz", "integrity": "sha512-KNTihKNmQENUZeKu5fzfpzRqR5S2VMp4gl9RFHiWzj9DfvYQPMJ6XHKNaQxaGCXwPk6y9yme3aUoaiAe+KX+vg==", + "license": "MIT", "peer": true }, "node_modules/denque": { @@ -25424,6 +25498,7 @@ "version": "0.3.21", "resolved": "https://registry.npmjs.org/eciesjs/-/eciesjs-0.3.21.tgz", "integrity": "sha512-6FiThm7KlTihph8ROhq/BHEglGCJSwq6c8KVgcCcJiNJFNlbrFtfnTqZobVmWIB764mzhZTOBFyinADSXXvTLg==", + "license": "MIT", "peer": true, "dependencies": { "futoin-hkdf": "^1.5.3", @@ -25644,6 +25719,7 @@ "version": "2.1.4", "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", + "license": "MIT", "peer": true, "dependencies": { "stackframe": "^1.3.4" @@ -27040,6 +27116,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", "peer": true, "engines": { "node": ">=6" @@ -27126,6 +27203,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", + "license": "Apache-2.0", "peer": true }, "node_modules/express": { @@ -27635,12 +27713,14 @@ "version": "0.0.6", "resolved": "https://registry.npmjs.org/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz", "integrity": "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==", + "license": "MIT", "peer": true }, "node_modules/flow-parser": { - "version": "0.255.0", - "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.255.0.tgz", - "integrity": "sha512-7QHV2m2mIMh6yIMaAPOVbyNEW77IARwO69d4DgvfDCjuORiykdMLf7XBjF7Zeov7Cpe1OXJ8sB6/aaCE3xuRBw==", + "version": "0.256.0", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.256.0.tgz", + "integrity": "sha512-HFb/GgB7hq+TYosLJuMLdLp8aGlyAVfrJaTvcM0w2rz2T33PjkVbRU419ncK/69cjowUksewuspkBheq9ZX9Hw==", + "license": "MIT", "peer": true, "engines": { "node": ">=0.4.0" @@ -28069,6 +28149,7 @@ "version": "1.5.3", "resolved": "https://registry.npmjs.org/futoin-hkdf/-/futoin-hkdf-1.5.3.tgz", "integrity": "sha512-SewY5KdMpaoCeh7jachEWFsh1nNlaDjNHZXWqL5IGwtpEYHTgkr2+AMCgNwKWkcc0wpSYrZfR7he4WdmHFtDxQ==", + "license": "Apache-2.0", "peer": true, "engines": { "node": ">=8" @@ -28888,12 +28969,14 @@ "version": "0.23.1", "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.23.1.tgz", "integrity": "sha512-eT5MU3f5aVhTqsfIReZ6n41X5sYn4IdQL0nvz6yO+MMlPxw49aSARHLg/MSehQftyjnrE8X6bYregzSumqc6cg==", + "license": "MIT", "peer": true }, "node_modules/hermes-parser": { "version": "0.23.1", "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.23.1.tgz", "integrity": "sha512-oxl5h2DkFW83hT4DAUJorpah8ou4yvmweUzLJmmr6YV2cezduCdlil1AvU/a/xSsAFo4WUcNA4GoV5Bvq6JffA==", + "license": "MIT", "peer": true, "dependencies": { "hermes-estree": "0.23.1" @@ -30023,6 +30106,7 @@ "version": "0.3.1", "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", "integrity": "sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw==", + "license": "MIT", "peer": true, "engines": { "node": ">=0.10.0" @@ -30819,6 +30903,7 @@ "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", "dev": true, + "license": "MIT", "optional": true, "peer": true, "dependencies": { @@ -30836,6 +30921,7 @@ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", "dev": true, + "license": "MIT", "optional": true, "peer": true, "dependencies": { @@ -31800,18 +31886,21 @@ "version": "250231.0.0", "resolved": "https://registry.npmjs.org/jsc-android/-/jsc-android-250231.0.0.tgz", "integrity": "sha512-rS46PvsjYmdmuz1OAWXY/1kCYG7pnf1TBqeTiOJr1iDz7s5DLxxC9n/ZMknLDxzYzNVfI7R95MH10emSSG1Wuw==", + "license": "BSD-2-Clause", "peer": true }, "node_modules/jsc-safe-url": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/jsc-safe-url/-/jsc-safe-url-0.2.4.tgz", "integrity": "sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q==", + "license": "0BSD", "peer": true }, "node_modules/jscodeshift": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.14.0.tgz", "integrity": "sha512-7eCC1knD7bLUPuSCwXsMZUH51O8jIcoVyKtI6P0XM0IVzlGjckPy3FIwQlorzbN0Sg79oK+RlohN32Mqf/lrYA==", + "license": "MIT", "peer": true, "dependencies": { "@babel/core": "^7.13.16", @@ -31845,6 +31934,7 @@ "version": "2.4.3", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "license": "ISC", "peer": true, "dependencies": { "graceful-fs": "^4.1.11", @@ -31962,6 +32052,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "license": "MIT", "peer": true }, "node_modules/json-parse-even-better-errors": { @@ -32461,6 +32552,7 @@ "version": "1.4.2", "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz", "integrity": "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==", + "license": "Apache-2.0", "peer": true, "dependencies": { "debug": "^2.6.9", @@ -32471,6 +32563,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "peer": true, "dependencies": { "ms": "2.0.0" @@ -32480,6 +32573,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT", "peer": true }, "node_modules/lilconfig": { @@ -32990,6 +33084,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==", + "license": "MIT", "peer": true }, "node_modules/lodash.uniq": { @@ -33394,6 +33489,7 @@ "version": "1.2.5", "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.5.tgz", "integrity": "sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==", + "license": "Apache-2.0", "peer": true }, "node_modules/mdast-util-directive": { @@ -33802,6 +33898,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==", + "license": "MIT", "peer": true }, "node_modules/merge-deep": { @@ -33858,6 +33955,7 @@ "version": "0.81.0", "resolved": "https://registry.npmjs.org/metro/-/metro-0.81.0.tgz", "integrity": "sha512-kzdzmpL0gKhEthZ9aOV7sTqvg6NuTxDV8SIm9pf9sO8VVEbKrQk5DNcwupOUjgPPFAuKUc2NkT0suyT62hm2xg==", + "license": "MIT", "peer": true, "dependencies": { "@babel/code-frame": "^7.24.7", @@ -33914,6 +34012,7 @@ "version": "0.81.0", "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.81.0.tgz", "integrity": "sha512-Dc0QWK4wZIeHnyZ3sevWGTnnSkIDDn/SWyfrn99zbKbDOCoCYy71PAn9uCRrP/hduKLJQOy+tebd63Rr9D8tXg==", + "license": "MIT", "peer": true, "dependencies": { "@babel/core": "^7.25.2", @@ -33929,12 +34028,14 @@ "version": "0.24.0", "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.24.0.tgz", "integrity": "sha512-LyoXLB7IFzeZW0EvAbGZacbxBN7t6KKSDqFJPo3Ydow7wDlrDjXwsdiAHV6XOdvEN9MEuWXsSIFN4tzpyrXIHw==", + "license": "MIT", "peer": true }, "node_modules/metro-babel-transformer/node_modules/hermes-parser": { "version": "0.24.0", "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.24.0.tgz", "integrity": "sha512-IJooSvvu2qNRe7oo9Rb04sUT4omtZqZqf9uq9WM25Tb6v3usmvA93UqfnnoWs5V0uYjEl9Al6MNU10MCGKLwpg==", + "license": "MIT", "peer": true, "dependencies": { "hermes-estree": "0.24.0" @@ -33944,6 +34045,7 @@ "version": "0.81.0", "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.81.0.tgz", "integrity": "sha512-DyuqySicHXkHUDZFVJmh0ygxBSx6pCKUrTcSgb884oiscV/ROt1Vhye+x+OIHcsodyA10gzZtrVtxIFV4l9I4g==", + "license": "MIT", "peer": true, "dependencies": { "exponential-backoff": "^3.1.1", @@ -33958,6 +34060,7 @@ "version": "0.81.0", "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.81.0.tgz", "integrity": "sha512-qX/IwtknP9bQZL78OK9xeSvLM/xlGfrs6SlUGgHvrxtmGTRSsxcyqxR+c+7ch1xr05n62Gin/O44QKg5V70rNQ==", + "license": "MIT", "peer": true, "dependencies": { "flow-enums-runtime": "^0.0.6" @@ -33970,6 +34073,7 @@ "version": "0.81.0", "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.81.0.tgz", "integrity": "sha512-6CinEaBe3WLpRlKlYXXu8r1UblJhbwD6Gtnoib5U8j6Pjp7XxMG9h/DGMeNp9aGLDu1OieUqiXpFo7O0/rR5Kg==", + "license": "MIT", "peer": true, "dependencies": { "connect": "^3.6.5", @@ -33989,6 +34093,7 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "license": "MIT", "peer": true, "dependencies": { "sprintf-js": "~1.0.2" @@ -33998,6 +34103,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "license": "MIT", "peer": true, "dependencies": { "import-fresh": "^2.0.0", @@ -34013,6 +34119,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==", + "license": "MIT", "peer": true, "dependencies": { "caller-path": "^2.0.0", @@ -34026,6 +34133,7 @@ "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "license": "MIT", "peer": true, "dependencies": { "argparse": "^1.0.7", @@ -34039,6 +34147,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "license": "MIT", "peer": true, "dependencies": { "error-ex": "^1.3.1", @@ -34052,6 +34161,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==", + "license": "MIT", "peer": true, "engines": { "node": ">=4" @@ -34061,12 +34171,14 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "license": "BSD-3-Clause", "peer": true }, "node_modules/metro-core": { "version": "0.81.0", "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.81.0.tgz", "integrity": "sha512-CVkM5YCOAFkNMvJai6KzA0RpztzfEKRX62/PFMOJ9J7K0uq/UkOFLxcgpcncMIrfy0PbfEj811b69tjULUQe1Q==", + "license": "MIT", "peer": true, "dependencies": { "flow-enums-runtime": "^0.0.6", @@ -34081,6 +34193,7 @@ "version": "0.81.0", "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.81.0.tgz", "integrity": "sha512-zMDI5uYhQCyxbye/AuFx/pAbsz9K+vKL7h1ShUXdN2fz4VUPiyQYRsRqOoVG1DsiCgzd5B6LW0YW77NFpjDQeg==", + "license": "MIT", "peer": true, "dependencies": { "anymatch": "^3.0.3", @@ -34106,6 +34219,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "peer": true, "dependencies": { "ms": "2.0.0" @@ -34115,12 +34229,14 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT", "peer": true }, "node_modules/metro-minify-terser": { "version": "0.81.0", "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.81.0.tgz", "integrity": "sha512-U2ramh3W822ZR1nfXgIk+emxsf5eZSg10GbQrT0ZizImK8IZ5BmJY+BHRIkQgHzWFpExOVxC7kWbGL1bZALswA==", + "license": "MIT", "peer": true, "dependencies": { "flow-enums-runtime": "^0.0.6", @@ -34134,6 +34250,7 @@ "version": "0.81.0", "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.81.0.tgz", "integrity": "sha512-Uu2Q+buHhm571cEwpPek8egMbdSTqmwT/5U7ZVNpK6Z2ElQBBCxd7HmFAslKXa7wgpTO2FAn6MqGeERbAtVDUA==", + "license": "MIT", "peer": true, "dependencies": { "flow-enums-runtime": "^0.0.6" @@ -34146,6 +34263,7 @@ "version": "0.81.0", "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.81.0.tgz", "integrity": "sha512-6oYB5HOt37RuGz2eV4A6yhcl+PUTwJYLDlY9vhT+aVjbUWI6MdBCf69vc4f5K5Vpt+yOkjy+2LDwLS0ykWFwYw==", + "license": "MIT", "peer": true, "dependencies": { "@babel/runtime": "^7.25.0", @@ -34159,6 +34277,7 @@ "version": "0.81.0", "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.81.0.tgz", "integrity": "sha512-TzsVxhH83dyxg4A4+L1nzNO12I7ps5IHLjKGZH3Hrf549eiZivkdjYiq/S5lOB+p2HiQ+Ykcwtmcja95LIC62g==", + "license": "MIT", "peer": true, "dependencies": { "@babel/traverse": "^7.25.3", @@ -34180,6 +34299,7 @@ "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", "peer": true, "engines": { "node": ">=0.10.0" @@ -34189,6 +34309,7 @@ "version": "0.81.0", "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.81.0.tgz", "integrity": "sha512-C/1rWbNTPYp6yzID8IPuQPpVGzJ2rbWYBATxlvQ9dfK5lVNoxcwz77hjcY8ISLsRRR15hyd/zbjCNKPKeNgE1Q==", + "license": "MIT", "peer": true, "dependencies": { "flow-enums-runtime": "^0.0.6", @@ -34210,6 +34331,7 @@ "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", "peer": true, "engines": { "node": ">=0.10.0" @@ -34219,6 +34341,7 @@ "version": "0.81.0", "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.81.0.tgz", "integrity": "sha512-uErLAPBvttGCrmGSCa0dNHlOTk3uJFVEVWa5WDg6tQ79PRmuYRwzUgLhVzn/9/kyr75eUX3QWXN79Jvu4txt6Q==", + "license": "MIT", "peer": true, "dependencies": { "@babel/core": "^7.25.2", @@ -34236,6 +34359,7 @@ "version": "0.81.0", "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.81.0.tgz", "integrity": "sha512-HrQ0twiruhKy0yA+9nK5bIe3WQXZcC66PXTvRIos61/EASLAP2DzEmW7IxN/MGsfZegN2UzqL2CG38+mOB45vg==", + "license": "MIT", "peer": true, "dependencies": { "@babel/core": "^7.25.2", @@ -34260,12 +34384,14 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "license": "MIT", "peer": true }, "node_modules/metro/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "peer": true, "dependencies": { "ms": "2.0.0" @@ -34275,18 +34401,21 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT", "peer": true }, "node_modules/metro/node_modules/hermes-estree": { "version": "0.24.0", "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.24.0.tgz", "integrity": "sha512-LyoXLB7IFzeZW0EvAbGZacbxBN7t6KKSDqFJPo3Ydow7wDlrDjXwsdiAHV6XOdvEN9MEuWXsSIFN4tzpyrXIHw==", + "license": "MIT", "peer": true }, "node_modules/metro/node_modules/hermes-parser": { "version": "0.24.0", "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.24.0.tgz", "integrity": "sha512-IJooSvvu2qNRe7oo9Rb04sUT4omtZqZqf9uq9WM25Tb6v3usmvA93UqfnnoWs5V0uYjEl9Al6MNU10MCGKLwpg==", + "license": "MIT", "peer": true, "dependencies": { "hermes-estree": "0.24.0" @@ -34296,6 +34425,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -34305,12 +34435,14 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT", "peer": true }, "node_modules/metro/node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", "peer": true, "engines": { "node": ">=0.10.0" @@ -34320,6 +34452,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", "peer": true, "dependencies": { "emoji-regex": "^8.0.0", @@ -34334,6 +34467,7 @@ "version": "7.5.10", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "license": "MIT", "peer": true, "engines": { "node": ">=8.3.0" @@ -34355,6 +34489,7 @@ "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", "peer": true, "dependencies": { "cliui": "^8.0.1", @@ -36234,9 +36369,10 @@ "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==" }, "node_modules/monaco-editor": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.52.0.tgz", - "integrity": "sha512-OeWhNpABLCeTqubfqLMXGsqf6OmPU6pHM85kF3dhy6kq5hnhuVS1p3VrEW/XhWHc71P2tHyS5JFySD8mgs1crw==", + "version": "0.52.2", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.52.2.tgz", + "integrity": "sha512-GEQWEZmfkOGLdd3XK8ryrfWz3AIP8YymVXiPHEdewrUq7mh0qrKrfHLNCXcbB6sTnMLnOZ3ztSiKcciFUkIJwQ==", + "license": "MIT", "peer": true }, "node_modules/motion": { @@ -36700,6 +36836,7 @@ "version": "0.1.17", "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", "integrity": "sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==", + "license": "MIT", "peer": true, "dependencies": { "minimatch": "^3.0.2" @@ -36712,6 +36849,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "license": "MIT", "peer": true, "dependencies": { "balanced-match": "^1.0.0", @@ -36722,6 +36860,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", "peer": true, "dependencies": { "brace-expansion": "^1.1.7" @@ -36934,6 +37073,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==", + "license": "MIT", "peer": true }, "node_modules/nwsapi": { @@ -37091,6 +37231,7 @@ "version": "0.81.0", "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.81.0.tgz", "integrity": "sha512-6Cvrkxt1tqaRdWqTAMcVYEiO5i1xcF9y7t06nFdjFqkfPsEloCf8WwhXdwBpNUkVYSQlSGS7cDgVQR86miBfBQ==", + "license": "MIT", "peer": true, "dependencies": { "flow-enums-runtime": "^0.0.6" @@ -39069,6 +39210,7 @@ "version": "8.3.0", "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", + "license": "MIT", "peer": true, "dependencies": { "asap": "~2.0.6" @@ -39828,6 +39970,7 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-5.3.2.tgz", "integrity": "sha512-crr9HkVrDiJ0A4zot89oS0Cgv0Oa4OG1Em4jit3P3ZxZSKPMYyMjfwMqgcJna9o625g8oN87rBm8SWWrSTBZxg==", + "license": "MIT", "peer": true, "dependencies": { "shell-quote": "^1.6.1", @@ -39838,6 +39981,7 @@ "version": "7.5.10", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "license": "MIT", "peer": true, "engines": { "node": ">=8.3.0" @@ -39938,19 +40082,20 @@ } }, "node_modules/react-native": { - "version": "0.76.3", - "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.76.3.tgz", - "integrity": "sha512-0TUhgmlouRNf6yuDIIAdbQl0g1VsONgCMsLs7Et64hjj5VLMCA7np+4dMrZvGZ3wRNqzgeyT9oWJsUm49AcwSQ==", + "version": "0.76.5", + "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.76.5.tgz", + "integrity": "sha512-op2p2kB+lqMF1D7AdX4+wvaR0OPFbvWYs+VBE7bwsb99Cn9xISrLRLAgFflZedQsa5HvnOGrULhtnmItbIKVVw==", + "license": "MIT", "peer": true, "dependencies": { "@jest/create-cache-key-function": "^29.6.3", - "@react-native/assets-registry": "0.76.3", - "@react-native/codegen": "0.76.3", - "@react-native/community-cli-plugin": "0.76.3", - "@react-native/gradle-plugin": "0.76.3", - "@react-native/js-polyfills": "0.76.3", - "@react-native/normalize-colors": "0.76.3", - "@react-native/virtualized-lists": "0.76.3", + "@react-native/assets-registry": "0.76.5", + "@react-native/codegen": "0.76.5", + "@react-native/community-cli-plugin": "0.76.5", + "@react-native/gradle-plugin": "0.76.5", + "@react-native/js-polyfills": "0.76.5", + "@react-native/normalize-colors": "0.76.5", + "@react-native/virtualized-lists": "0.76.5", "abort-controller": "^3.0.0", "anser": "^1.4.9", "ansi-regex": "^5.0.0", @@ -40023,6 +40168,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "license": "MIT", "peer": true, "engines": { "node": ">=10" @@ -40035,6 +40181,7 @@ "version": "12.1.0", "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "license": "MIT", "peer": true, "engines": { "node": ">=18" @@ -40044,12 +40191,14 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT", "peer": true }, "node_modules/react-native/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -40059,6 +40208,7 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "license": "MIT", "peer": true, "dependencies": { "@jest/schemas": "^29.6.3", @@ -40073,18 +40223,21 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "license": "MIT", "peer": true }, "node_modules/react-native/node_modules/regenerator-runtime": { "version": "0.13.11", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "license": "MIT", "peer": true }, "node_modules/react-native/node_modules/scheduler": { "version": "0.24.0-canary-efb381bbf-20230505", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.24.0-canary-efb381bbf-20230505.tgz", "integrity": "sha512-ABvovCDe/k9IluqSh4/ISoq8tIJnW8euVAWYt5j/bg6dRnqwQwiGO1F/V4AyK96NGF/FB04FhOUDuWj8IKfABA==", + "license": "MIT", "peer": true, "dependencies": { "loose-envify": "^1.1.0" @@ -40094,6 +40247,7 @@ "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", "peer": true, "bin": { "semver": "bin/semver.js" @@ -40106,6 +40260,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", "peer": true, "dependencies": { "emoji-regex": "^8.0.0", @@ -40120,6 +40275,7 @@ "version": "6.2.3", "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", + "license": "MIT", "peer": true, "dependencies": { "async-limiter": "~1.0.0" @@ -40129,6 +40285,7 @@ "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", "peer": true, "dependencies": { "cliui": "^8.0.1", @@ -40147,6 +40304,7 @@ "version": "0.14.2", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "license": "MIT", "peer": true, "engines": { "node": ">=0.10.0" @@ -40327,6 +40485,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz", "integrity": "sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg==", + "license": "BSD", "peer": true }, "node_modules/real-require": { @@ -40341,6 +40500,7 @@ "version": "0.21.5", "resolved": "https://registry.npmjs.org/recast/-/recast-0.21.5.tgz", "integrity": "sha512-hjMmLaUXAm1hIuTqOdeYObMslq/q+Xff6QE3Y2P+uoHAg2nmVlLBps2hzh1UJDdMtDTMXOFewK6ky51JQIeECg==", + "license": "MIT", "peer": true, "dependencies": { "ast-types": "0.15.2", @@ -40356,6 +40516,7 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", "peer": true, "engines": { "node": ">=0.10.0" @@ -41277,6 +41438,7 @@ "version": "2.17.3", "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.17.3.tgz", "integrity": "sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ==", + "license": "MIT", "peer": true }, "node_modules/secp256k1": { @@ -41284,6 +41446,7 @@ "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-5.0.1.tgz", "integrity": "sha512-lDFs9AAIaWP9UCdtWrotXWWF9t8PWgQDcxqgAnpM9rMqxb3Oaq2J0thzPVSxBwdJgyQtkU/sYtFtbM1RSt/iYA==", "hasInstallScript": true, + "license": "MIT", "peer": true, "dependencies": { "elliptic": "^6.5.7", @@ -41298,6 +41461,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", + "license": "MIT", "peer": true }, "node_modules/section-matter": { @@ -41413,6 +41577,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz", "integrity": "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==", + "license": "MIT", "peer": true, "engines": { "node": ">=0.10.0" @@ -42138,12 +42303,14 @@ "version": "1.3.4", "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", + "license": "MIT", "peer": true }, "node_modules/stacktrace-parser": { "version": "0.1.10", "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz", "integrity": "sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==", + "license": "MIT", "peer": true, "dependencies": { "type-fest": "^0.7.1" @@ -42156,6 +42323,7 @@ "version": "0.7.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==", + "license": "(MIT OR CC0-1.0)", "peer": true, "engines": { "node": ">=8" @@ -43071,6 +43239,7 @@ "version": "0.8.4", "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.4.tgz", "integrity": "sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==", + "license": "MIT", "peer": true, "dependencies": { "rimraf": "~2.6.2" @@ -43084,6 +43253,7 @@ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", "peer": true, "dependencies": { "glob": "^7.1.3" @@ -43324,6 +43494,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", + "license": "MIT", "peer": true }, "node_modules/through": { @@ -43336,6 +43507,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "license": "MIT", "peer": true, "dependencies": { "readable-stream": "~2.3.6", @@ -43346,12 +43518,14 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT", "peer": true }, "node_modules/through2/node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", "peer": true, "dependencies": { "core-util-is": "~1.0.0", @@ -43367,12 +43541,14 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT", "peer": true }, "node_modules/through2/node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", "peer": true, "dependencies": { "safe-buffer": "~5.1.0" @@ -44925,6 +45101,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/vlq/-/vlq-1.0.1.tgz", "integrity": "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==", + "license": "MIT", "peer": true }, "node_modules/w3c-xmlserializer": { @@ -45424,6 +45601,7 @@ "version": "3.6.20", "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==", + "license": "MIT", "peer": true }, "node_modules/whatwg-mimetype": { @@ -46026,7 +46204,7 @@ }, "packages/armory-sdk": { "name": "@narval-xyz/armory-sdk", - "version": "0.10.0", + "version": "0.11.0", "license": "MPL-2.0", "dependencies": { "@noble/curves": "1.6.0", diff --git a/packages/armory-e2e-testing/src/__test__/e2e/scenarii/address-book-management.spec.ts b/packages/armory-e2e-testing/src/__test__/e2e/scenario/address-book-management.spec.ts similarity index 100% rename from packages/armory-e2e-testing/src/__test__/e2e/scenarii/address-book-management.spec.ts rename to packages/armory-e2e-testing/src/__test__/e2e/scenario/address-book-management.spec.ts diff --git a/packages/armory-e2e-testing/src/__test__/e2e/scenarii/approvals-and-spending-limit.spec.ts b/packages/armory-e2e-testing/src/__test__/e2e/scenario/approvals-and-spending-limit.spec.ts similarity index 100% rename from packages/armory-e2e-testing/src/__test__/e2e/scenarii/approvals-and-spending-limit.spec.ts rename to packages/armory-e2e-testing/src/__test__/e2e/scenario/approvals-and-spending-limit.spec.ts diff --git a/packages/armory-e2e-testing/src/__test__/e2e/scenarii/defi-interactions.spec.ts b/packages/armory-e2e-testing/src/__test__/e2e/scenario/defi-interactions.spec.ts similarity index 100% rename from packages/armory-e2e-testing/src/__test__/e2e/scenarii/defi-interactions.spec.ts rename to packages/armory-e2e-testing/src/__test__/e2e/scenario/defi-interactions.spec.ts diff --git a/packages/armory-e2e-testing/src/__test__/e2e/scenarii/tiered-eth-transfer-policy.spec.ts b/packages/armory-e2e-testing/src/__test__/e2e/scenario/tiered-eth-transfer-policy.spec.ts similarity index 100% rename from packages/armory-e2e-testing/src/__test__/e2e/scenarii/tiered-eth-transfer-policy.spec.ts rename to packages/armory-e2e-testing/src/__test__/e2e/scenario/tiered-eth-transfer-policy.spec.ts diff --git a/packages/armory-e2e-testing/src/__test__/e2e/scenarii/user-journeys.spec.ts b/packages/armory-e2e-testing/src/__test__/e2e/scenario/user-journeys.spec.ts similarity index 95% rename from packages/armory-e2e-testing/src/__test__/e2e/scenarii/user-journeys.spec.ts rename to packages/armory-e2e-testing/src/__test__/e2e/scenario/user-journeys.spec.ts index d943f5254..8c767ee6b 100644 --- a/packages/armory-e2e-testing/src/__test__/e2e/scenarii/user-journeys.spec.ts +++ b/packages/armory-e2e-testing/src/__test__/e2e/scenario/user-journeys.spec.ts @@ -218,7 +218,35 @@ describe('User Journeys', () => { expect(clientVault).toEqual({ clientId: clientAuth.id, - engineJwk: clientAuth.policyEngine.nodes[0].publicKey, + name: expect.any(String), + backupPublicKey: null, + baseUrl: null, + configurationSource: 'dynamic', + auth: { + disabled: false, + local: { + jwsd: { + maxAge: 300, + requiredComponents: ['htm', 'uri', 'created', 'ath'] + }, + allowedUsersJwksUrl: null, + allowedUsers: null + }, + tokenValidation: { + disabled: false, + url: null, + jwksUrl: null, + pinnedPublicKey: clientAuth.policyEngine.nodes[0].publicKey, + verification: { + audience: null, + issuer: null, + maxTokenAge: null, + requireBoundTokens: true, + allowBearerTokens: false, + allowWildcard: null + } + } + }, createdAt: expect.any(String), updatedAt: expect.any(String) }) diff --git a/packages/armory-sdk/package.json b/packages/armory-sdk/package.json index a985b7c95..220593d1d 100644 --- a/packages/armory-sdk/package.json +++ b/packages/armory-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@narval-xyz/armory-sdk", - "version": "0.10.0", + "version": "0.11.0", "license": "MPL-2.0", "publishConfig": { "access": "public" diff --git a/packages/armory-sdk/src/lib/http/client/vault/api.ts b/packages/armory-sdk/src/lib/http/client/vault/api.ts index 56fa6c980..c49867708 100644 --- a/packages/armory-sdk/src/lib/http/client/vault/api.ts +++ b/packages/armory-sdk/src/lib/http/client/vault/api.ts @@ -91,54 +91,36 @@ export interface ClientDto { * @memberof ClientDto */ 'clientId': string; - /** - * - * @type {CreateClientDtoEngineJwk} - * @memberof ClientDto - */ - 'engineJwk'?: CreateClientDtoEngineJwk; - /** - * - * @type {string} - * @memberof ClientDto - */ - 'audience'?: string; /** * * @type {string} * @memberof ClientDto */ - 'issuer'?: string; - /** - * - * @type {number} - * @memberof ClientDto - */ - 'maxTokenAge'?: number; + 'name': string; /** * - * @type {EncryptionKeyDtoPublicKey} + * @type {ClientDtoConfigurationSource} * @memberof ClientDto */ - 'backupPublicKey'?: EncryptionKeyDtoPublicKey; + 'configurationSource': ClientDtoConfigurationSource; /** * - * @type {boolean} + * @type {ClientDtoBackupPublicKey} * @memberof ClientDto */ - 'allowKeyExport'?: boolean; + 'backupPublicKey': ClientDtoBackupPublicKey | null; /** * - * @type {Array} + * @type {string} * @memberof ClientDto */ - 'allowWildcard'?: Array; + 'baseUrl': string | null; /** * - * @type {string} + * @type {ClientDtoAuth} * @memberof ClientDto */ - 'baseUrl'?: string; + 'auth': ClientDtoAuth; /** * * @type {any} @@ -155,1310 +137,4638 @@ export interface ClientDto { /** * * @export - * @interface CreateClientDto + * @interface ClientDtoAuth */ -export interface CreateClientDto { +export interface ClientDtoAuth { /** * - * @type {string} - * @memberof CreateClientDto + * @type {boolean} + * @memberof ClientDtoAuth */ - 'clientId'?: string; + 'disabled': boolean; /** * - * @type {CreateClientDtoEngineJwk} - * @memberof CreateClientDto + * @type {ClientDtoAuthLocal} + * @memberof ClientDtoAuth */ - 'engineJwk'?: CreateClientDtoEngineJwk; + 'local': ClientDtoAuthLocal | null; /** * - * @type {string} - * @memberof CreateClientDto + * @type {ClientDtoAuthTokenValidation} + * @memberof ClientDtoAuth */ - 'audience'?: string; + 'tokenValidation': ClientDtoAuthTokenValidation; +} +/** + * + * @export + * @interface ClientDtoAuthLocal + */ +export interface ClientDtoAuthLocal { /** * - * @type {string} - * @memberof CreateClientDto + * @type {ClientDtoAuthLocalJwsd} + * @memberof ClientDtoAuthLocal */ - 'issuer'?: string; + 'jwsd': ClientDtoAuthLocalJwsd; /** * - * @type {number} - * @memberof CreateClientDto + * @type {string} + * @memberof ClientDtoAuthLocal */ - 'maxTokenAge'?: number; + 'allowedUsersJwksUrl': string | null; /** * - * @type {EncryptionKeyDtoPublicKey} - * @memberof CreateClientDto + * @type {Array} + * @memberof ClientDtoAuthLocal */ - 'backupPublicKey'?: EncryptionKeyDtoPublicKey; + 'allowedUsers': Array | null; +} +/** + * + * @export + * @interface ClientDtoAuthLocalJwsd + */ +export interface ClientDtoAuthLocalJwsd { /** * - * @type {boolean} - * @memberof CreateClientDto + * @type {number} + * @memberof ClientDtoAuthLocalJwsd */ - 'allowKeyExport'?: boolean; + 'maxAge': number; /** * * @type {Array} - * @memberof CreateClientDto - */ - 'allowWildcard'?: Array; - /** - * - * @type {string} - * @memberof CreateClientDto + * @memberof ClientDtoAuthLocalJwsd */ - 'baseUrl'?: string; + 'requiredComponents': Array; } -/** - * @type CreateClientDtoEngineJwk - * @export - */ -export type CreateClientDtoEngineJwk = CreateClientDtoEngineJwkOneOf | CreateClientDtoEngineJwkOneOf1 | CreateClientDtoEngineJwkOneOf2 | CreateClientDtoEngineJwkOneOf3 | EncryptionKeyDtoPublicKey; - /** * * @export - * @interface CreateClientDtoEngineJwkOneOf + * @interface ClientDtoAuthTokenValidation */ -export interface CreateClientDtoEngineJwkOneOf { +export interface ClientDtoAuthTokenValidation { /** * - * @type {string} - * @memberof CreateClientDtoEngineJwkOneOf + * @type {boolean} + * @memberof ClientDtoAuthTokenValidation */ - 'kty': CreateClientDtoEngineJwkOneOfKtyEnum; + 'disabled': boolean; /** * * @type {string} - * @memberof CreateClientDtoEngineJwkOneOf + * @memberof ClientDtoAuthTokenValidation */ - 'alg': CreateClientDtoEngineJwkOneOfAlgEnum; + 'url': string | null; /** * * @type {string} - * @memberof CreateClientDtoEngineJwkOneOf + * @memberof ClientDtoAuthTokenValidation */ - 'use'?: CreateClientDtoEngineJwkOneOfUseEnum; + 'jwksUrl': string | null; /** * - * @type {string} - * @memberof CreateClientDtoEngineJwkOneOf + * @type {CreateClientDtoAuthTokenValidationPinnedPublicKey} + * @memberof ClientDtoAuthTokenValidation */ - 'kid': string; + 'pinnedPublicKey': CreateClientDtoAuthTokenValidationPinnedPublicKey | null; /** * - * @type {string} - * @memberof CreateClientDtoEngineJwkOneOf + * @type {ClientDtoAuthTokenValidationVerification} + * @memberof ClientDtoAuthTokenValidation */ - 'addr'?: string; + 'verification': ClientDtoAuthTokenValidationVerification; +} +/** + * + * @export + * @interface ClientDtoAuthTokenValidationVerification + */ +export interface ClientDtoAuthTokenValidationVerification { /** * * @type {string} - * @memberof CreateClientDtoEngineJwkOneOf + * @memberof ClientDtoAuthTokenValidationVerification */ - 'crv': CreateClientDtoEngineJwkOneOfCrvEnum; + 'audience': string | null; /** * * @type {string} - * @memberof CreateClientDtoEngineJwkOneOf + * @memberof ClientDtoAuthTokenValidationVerification */ - 'x': string; + 'issuer': string | null; /** * - * @type {string} - * @memberof CreateClientDtoEngineJwkOneOf + * @type {number} + * @memberof ClientDtoAuthTokenValidationVerification */ - 'y': string; + 'maxTokenAge': number | null; + /** + * + * @type {boolean} + * @memberof ClientDtoAuthTokenValidationVerification + */ + 'requireBoundTokens': boolean; + /** + * + * @type {boolean} + * @memberof ClientDtoAuthTokenValidationVerification + */ + 'allowBearerTokens': boolean; + /** + * + * @type {Array} + * @memberof ClientDtoAuthTokenValidationVerification + */ + 'allowWildcard': Array | null; } - -export const CreateClientDtoEngineJwkOneOfKtyEnum = { - Ec: 'EC' -} as const; - -export type CreateClientDtoEngineJwkOneOfKtyEnum = typeof CreateClientDtoEngineJwkOneOfKtyEnum[keyof typeof CreateClientDtoEngineJwkOneOfKtyEnum]; -export const CreateClientDtoEngineJwkOneOfAlgEnum = { - Es256K: 'ES256K' -} as const; - -export type CreateClientDtoEngineJwkOneOfAlgEnum = typeof CreateClientDtoEngineJwkOneOfAlgEnum[keyof typeof CreateClientDtoEngineJwkOneOfAlgEnum]; -export const CreateClientDtoEngineJwkOneOfUseEnum = { - Sig: 'sig', - Enc: 'enc' -} as const; - -export type CreateClientDtoEngineJwkOneOfUseEnum = typeof CreateClientDtoEngineJwkOneOfUseEnum[keyof typeof CreateClientDtoEngineJwkOneOfUseEnum]; -export const CreateClientDtoEngineJwkOneOfCrvEnum = { - Secp256k1: 'secp256k1' -} as const; - -export type CreateClientDtoEngineJwkOneOfCrvEnum = typeof CreateClientDtoEngineJwkOneOfCrvEnum[keyof typeof CreateClientDtoEngineJwkOneOfCrvEnum]; - /** * * @export - * @interface CreateClientDtoEngineJwkOneOf1 + * @interface ClientDtoBackupPublicKey */ -export interface CreateClientDtoEngineJwkOneOf1 { +export interface ClientDtoBackupPublicKey { /** * * @type {string} - * @memberof CreateClientDtoEngineJwkOneOf1 + * @memberof ClientDtoBackupPublicKey */ - 'kty': CreateClientDtoEngineJwkOneOf1KtyEnum; + 'kty': ClientDtoBackupPublicKeyKtyEnum; /** * * @type {string} - * @memberof CreateClientDtoEngineJwkOneOf1 + * @memberof ClientDtoBackupPublicKey */ - 'alg': CreateClientDtoEngineJwkOneOf1AlgEnum; + 'alg': ClientDtoBackupPublicKeyAlgEnum; /** * * @type {string} - * @memberof CreateClientDtoEngineJwkOneOf1 + * @memberof ClientDtoBackupPublicKey */ - 'use'?: CreateClientDtoEngineJwkOneOf1UseEnum; + 'use'?: ClientDtoBackupPublicKeyUseEnum; /** * * @type {string} - * @memberof CreateClientDtoEngineJwkOneOf1 + * @memberof ClientDtoBackupPublicKey */ 'kid': string; /** * * @type {string} - * @memberof CreateClientDtoEngineJwkOneOf1 + * @memberof ClientDtoBackupPublicKey */ 'addr'?: string; /** * * @type {string} - * @memberof CreateClientDtoEngineJwkOneOf1 - */ - 'crv': CreateClientDtoEngineJwkOneOf1CrvEnum; - /** - * - * @type {string} - * @memberof CreateClientDtoEngineJwkOneOf1 + * @memberof ClientDtoBackupPublicKey */ - 'x': string; + 'n': string; /** * * @type {string} - * @memberof CreateClientDtoEngineJwkOneOf1 + * @memberof ClientDtoBackupPublicKey */ - 'y': string; + 'e': string; } -export const CreateClientDtoEngineJwkOneOf1KtyEnum = { - Ec: 'EC' +export const ClientDtoBackupPublicKeyKtyEnum = { + Rsa: 'RSA' } as const; -export type CreateClientDtoEngineJwkOneOf1KtyEnum = typeof CreateClientDtoEngineJwkOneOf1KtyEnum[keyof typeof CreateClientDtoEngineJwkOneOf1KtyEnum]; -export const CreateClientDtoEngineJwkOneOf1AlgEnum = { - Es256: 'ES256' +export type ClientDtoBackupPublicKeyKtyEnum = typeof ClientDtoBackupPublicKeyKtyEnum[keyof typeof ClientDtoBackupPublicKeyKtyEnum]; +export const ClientDtoBackupPublicKeyAlgEnum = { + Rs256: 'RS256' } as const; -export type CreateClientDtoEngineJwkOneOf1AlgEnum = typeof CreateClientDtoEngineJwkOneOf1AlgEnum[keyof typeof CreateClientDtoEngineJwkOneOf1AlgEnum]; -export const CreateClientDtoEngineJwkOneOf1UseEnum = { +export type ClientDtoBackupPublicKeyAlgEnum = typeof ClientDtoBackupPublicKeyAlgEnum[keyof typeof ClientDtoBackupPublicKeyAlgEnum]; +export const ClientDtoBackupPublicKeyUseEnum = { Sig: 'sig', Enc: 'enc' } as const; -export type CreateClientDtoEngineJwkOneOf1UseEnum = typeof CreateClientDtoEngineJwkOneOf1UseEnum[keyof typeof CreateClientDtoEngineJwkOneOf1UseEnum]; -export const CreateClientDtoEngineJwkOneOf1CrvEnum = { - P256: 'P-256' -} as const; +export type ClientDtoBackupPublicKeyUseEnum = typeof ClientDtoBackupPublicKeyUseEnum[keyof typeof ClientDtoBackupPublicKeyUseEnum]; -export type CreateClientDtoEngineJwkOneOf1CrvEnum = typeof CreateClientDtoEngineJwkOneOf1CrvEnum[keyof typeof CreateClientDtoEngineJwkOneOf1CrvEnum]; +/** + * @type ClientDtoConfigurationSource + * @export + */ +export type ClientDtoConfigurationSource = string; /** * * @export - * @interface CreateClientDtoEngineJwkOneOf2 + * @interface ConnectionListDto + */ +export interface ConnectionListDto { + /** + * + * @type {Array} + * @memberof ConnectionListDto + */ + 'connections': Array; +} +/** + * + * @export + * @interface ConnectionListDtoConnectionsInner */ -export interface CreateClientDtoEngineJwkOneOf2 { +export interface ConnectionListDtoConnectionsInner { /** * * @type {string} - * @memberof CreateClientDtoEngineJwkOneOf2 + * @memberof ConnectionListDtoConnectionsInner */ - 'kty': CreateClientDtoEngineJwkOneOf2KtyEnum; + 'clientId': string; /** * * @type {string} - * @memberof CreateClientDtoEngineJwkOneOf2 + * @memberof ConnectionListDtoConnectionsInner + */ + 'connectionId': string; + /** + * + * @type {any} + * @memberof ConnectionListDtoConnectionsInner */ - 'crv': CreateClientDtoEngineJwkOneOf2CrvEnum; + 'createdAt': any; /** * * @type {string} - * @memberof CreateClientDtoEngineJwkOneOf2 + * @memberof ConnectionListDtoConnectionsInner */ - 'alg': CreateClientDtoEngineJwkOneOf2AlgEnum; + 'label'?: string; /** * * @type {string} - * @memberof CreateClientDtoEngineJwkOneOf2 + * @memberof ConnectionListDtoConnectionsInner + */ + 'provider': ConnectionListDtoConnectionsInnerProviderEnum; + /** + * + * @type {any} + * @memberof ConnectionListDtoConnectionsInner */ - 'use'?: CreateClientDtoEngineJwkOneOf2UseEnum; + 'revokedAt'?: any; /** * * @type {string} - * @memberof CreateClientDtoEngineJwkOneOf2 + * @memberof ConnectionListDtoConnectionsInner */ - 'kid': string; + 'status'?: ConnectionListDtoConnectionsInnerStatusEnum; /** * * @type {any} - * @memberof CreateClientDtoEngineJwkOneOf2 + * @memberof ConnectionListDtoConnectionsInner */ - 'addr': any; + 'updatedAt': any; + /** + * + * @type {string} + * @memberof ConnectionListDtoConnectionsInner + */ + 'url'?: string; } -export const CreateClientDtoEngineJwkOneOf2KtyEnum = { - Ec: 'EC' -} as const; - -export type CreateClientDtoEngineJwkOneOf2KtyEnum = typeof CreateClientDtoEngineJwkOneOf2KtyEnum[keyof typeof CreateClientDtoEngineJwkOneOf2KtyEnum]; -export const CreateClientDtoEngineJwkOneOf2CrvEnum = { - Secp256k1: 'secp256k1' -} as const; - -export type CreateClientDtoEngineJwkOneOf2CrvEnum = typeof CreateClientDtoEngineJwkOneOf2CrvEnum[keyof typeof CreateClientDtoEngineJwkOneOf2CrvEnum]; -export const CreateClientDtoEngineJwkOneOf2AlgEnum = { - Es256K: 'ES256K' +export const ConnectionListDtoConnectionsInnerProviderEnum = { + Anchorage: 'anchorage' } as const; -export type CreateClientDtoEngineJwkOneOf2AlgEnum = typeof CreateClientDtoEngineJwkOneOf2AlgEnum[keyof typeof CreateClientDtoEngineJwkOneOf2AlgEnum]; -export const CreateClientDtoEngineJwkOneOf2UseEnum = { - Sig: 'sig', - Enc: 'enc' +export type ConnectionListDtoConnectionsInnerProviderEnum = typeof ConnectionListDtoConnectionsInnerProviderEnum[keyof typeof ConnectionListDtoConnectionsInnerProviderEnum]; +export const ConnectionListDtoConnectionsInnerStatusEnum = { + Pending: 'pending', + Active: 'active', + Revoked: 'revoked' } as const; -export type CreateClientDtoEngineJwkOneOf2UseEnum = typeof CreateClientDtoEngineJwkOneOf2UseEnum[keyof typeof CreateClientDtoEngineJwkOneOf2UseEnum]; +export type ConnectionListDtoConnectionsInnerStatusEnum = typeof ConnectionListDtoConnectionsInnerStatusEnum[keyof typeof ConnectionListDtoConnectionsInnerStatusEnum]; /** * * @export - * @interface CreateClientDtoEngineJwkOneOf3 + * @interface CreateClientDto */ -export interface CreateClientDtoEngineJwkOneOf3 { +export interface CreateClientDto { /** * * @type {string} - * @memberof CreateClientDtoEngineJwkOneOf3 + * @memberof CreateClientDto */ - 'kty': CreateClientDtoEngineJwkOneOf3KtyEnum; + 'clientId'?: string; /** * * @type {string} - * @memberof CreateClientDtoEngineJwkOneOf3 + * @memberof CreateClientDto */ - 'alg': CreateClientDtoEngineJwkOneOf3AlgEnum; + 'name'?: string; /** * * @type {string} - * @memberof CreateClientDtoEngineJwkOneOf3 + * @memberof CreateClientDto */ - 'use'?: CreateClientDtoEngineJwkOneOf3UseEnum; + 'baseUrl'?: string; /** * - * @type {string} - * @memberof CreateClientDtoEngineJwkOneOf3 + * @type {EncryptionKeyDtoPublicKey} + * @memberof CreateClientDto */ - 'kid': string; + 'backupPublicKey'?: EncryptionKeyDtoPublicKey; /** * - * @type {string} - * @memberof CreateClientDtoEngineJwkOneOf3 + * @type {CreateClientDtoAuth} + * @memberof CreateClientDto */ - 'addr'?: string; + 'auth'?: CreateClientDtoAuth; /** * - * @type {string} - * @memberof CreateClientDtoEngineJwkOneOf3 + * @type {CreateClientDtoAuthLocalAllowedUsersInnerPublicKey} + * @memberof CreateClientDto */ - 'crv': CreateClientDtoEngineJwkOneOf3CrvEnum; + 'engineJwk'?: CreateClientDtoAuthLocalAllowedUsersInnerPublicKey; /** * * @type {string} - * @memberof CreateClientDtoEngineJwkOneOf3 + * @memberof CreateClientDto */ - 'x': string; -} - -export const CreateClientDtoEngineJwkOneOf3KtyEnum = { - Okp: 'OKP' -} as const; - -export type CreateClientDtoEngineJwkOneOf3KtyEnum = typeof CreateClientDtoEngineJwkOneOf3KtyEnum[keyof typeof CreateClientDtoEngineJwkOneOf3KtyEnum]; -export const CreateClientDtoEngineJwkOneOf3AlgEnum = { - Eddsa: 'EDDSA' -} as const; - -export type CreateClientDtoEngineJwkOneOf3AlgEnum = typeof CreateClientDtoEngineJwkOneOf3AlgEnum[keyof typeof CreateClientDtoEngineJwkOneOf3AlgEnum]; -export const CreateClientDtoEngineJwkOneOf3UseEnum = { - Sig: 'sig', - Enc: 'enc' -} as const; - -export type CreateClientDtoEngineJwkOneOf3UseEnum = typeof CreateClientDtoEngineJwkOneOf3UseEnum[keyof typeof CreateClientDtoEngineJwkOneOf3UseEnum]; -export const CreateClientDtoEngineJwkOneOf3CrvEnum = { - Ed25519: 'Ed25519' -} as const; - -export type CreateClientDtoEngineJwkOneOf3CrvEnum = typeof CreateClientDtoEngineJwkOneOf3CrvEnum[keyof typeof CreateClientDtoEngineJwkOneOf3CrvEnum]; - -/** - * - * @export - * @interface DeriveAccountDto - */ -export interface DeriveAccountDto { + 'audience'?: string; /** * * @type {string} - * @memberof DeriveAccountDto + * @memberof CreateClientDto */ - 'keyId': string; + 'issuer'?: string; + /** + * + * @type {number} + * @memberof CreateClientDto + */ + 'maxTokenAge'?: number; /** * * @type {Array} - * @memberof DeriveAccountDto + * @memberof CreateClientDto */ - 'derivationPaths'?: Array; + 'allowWildcard'?: Array; /** * - * @type {number} - * @memberof DeriveAccountDto + * @type {boolean} + * @memberof CreateClientDto */ - 'count'?: number; + 'allowKeyExport'?: boolean; } /** * * @export - * @interface DeriveAccountResponseDto + * @interface CreateClientDtoAuth */ -export interface DeriveAccountResponseDto { +export interface CreateClientDtoAuth { /** * - * @type {Array} - * @memberof DeriveAccountResponseDto + * @type {CreateClientDtoAuthLocal} + * @memberof CreateClientDtoAuth */ - 'accounts': Array; + 'local'?: CreateClientDtoAuthLocal | null; + /** + * + * @type {CreateClientDtoAuthTokenValidation} + * @memberof CreateClientDtoAuth + */ + 'tokenValidation'?: CreateClientDtoAuthTokenValidation; } /** * * @export - * @interface EncryptionKeyDto + * @interface CreateClientDtoAuthLocal */ -export interface EncryptionKeyDto { +export interface CreateClientDtoAuthLocal { /** * - * @type {EncryptionKeyDtoPublicKey} - * @memberof EncryptionKeyDto + * @type {CreateClientDtoAuthLocalJwsd} + * @memberof CreateClientDtoAuthLocal */ - 'publicKey': EncryptionKeyDtoPublicKey; + 'jwsd'?: CreateClientDtoAuthLocalJwsd | null; + /** + * Pin specific users to be authorized; if set, ONLY these users are allowed + * @type {Array} + * @memberof CreateClientDtoAuthLocal + */ + 'allowedUsers'?: Array | null; } /** * * @export - * @interface EncryptionKeyDtoPublicKey + * @interface CreateClientDtoAuthLocalAllowedUsersInner */ -export interface EncryptionKeyDtoPublicKey { - /** - * - * @type {string} - * @memberof EncryptionKeyDtoPublicKey - */ - 'kty': EncryptionKeyDtoPublicKeyKtyEnum; +export interface CreateClientDtoAuthLocalAllowedUsersInner { /** * * @type {string} - * @memberof EncryptionKeyDtoPublicKey + * @memberof CreateClientDtoAuthLocalAllowedUsersInner */ - 'alg': EncryptionKeyDtoPublicKeyAlgEnum; + 'userId': string; /** * - * @type {string} - * @memberof EncryptionKeyDtoPublicKey + * @type {CreateClientDtoAuthLocalAllowedUsersInnerPublicKey} + * @memberof CreateClientDtoAuthLocalAllowedUsersInner */ - 'use'?: EncryptionKeyDtoPublicKeyUseEnum; + 'publicKey': CreateClientDtoAuthLocalAllowedUsersInnerPublicKey; +} +/** + * @type CreateClientDtoAuthLocalAllowedUsersInnerPublicKey + * @export + */ +export type CreateClientDtoAuthLocalAllowedUsersInnerPublicKey = CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf | CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1 | CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2 | CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3 | EncryptionKeyDtoPublicKey; + +/** + * + * @export + * @interface CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf + */ +export interface CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf { /** * * @type {string} - * @memberof EncryptionKeyDtoPublicKey + * @memberof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf + */ + 'kty': CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOfKtyEnum; + /** + * + * @type {string} + * @memberof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf + */ + 'alg': CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOfAlgEnum; + /** + * + * @type {string} + * @memberof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf + */ + 'use'?: CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOfUseEnum; + /** + * + * @type {string} + * @memberof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf */ 'kid': string; /** * * @type {string} - * @memberof EncryptionKeyDtoPublicKey + * @memberof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf */ 'addr'?: string; /** * * @type {string} - * @memberof EncryptionKeyDtoPublicKey + * @memberof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf */ - 'n': string; + 'crv': CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOfCrvEnum; /** * * @type {string} - * @memberof EncryptionKeyDtoPublicKey + * @memberof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf */ - 'e': string; + 'x': string; + /** + * + * @type {string} + * @memberof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf + */ + 'y': string; } -export const EncryptionKeyDtoPublicKeyKtyEnum = { - Rsa: 'RSA' +export const CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOfKtyEnum = { + Ec: 'EC' } as const; -export type EncryptionKeyDtoPublicKeyKtyEnum = typeof EncryptionKeyDtoPublicKeyKtyEnum[keyof typeof EncryptionKeyDtoPublicKeyKtyEnum]; -export const EncryptionKeyDtoPublicKeyAlgEnum = { - Rs256: 'RS256' +export type CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOfKtyEnum = typeof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOfKtyEnum[keyof typeof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOfKtyEnum]; +export const CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOfAlgEnum = { + Es256K: 'ES256K' } as const; -export type EncryptionKeyDtoPublicKeyAlgEnum = typeof EncryptionKeyDtoPublicKeyAlgEnum[keyof typeof EncryptionKeyDtoPublicKeyAlgEnum]; -export const EncryptionKeyDtoPublicKeyUseEnum = { +export type CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOfAlgEnum = typeof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOfAlgEnum[keyof typeof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOfAlgEnum]; +export const CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOfUseEnum = { Sig: 'sig', Enc: 'enc' } as const; -export type EncryptionKeyDtoPublicKeyUseEnum = typeof EncryptionKeyDtoPublicKeyUseEnum[keyof typeof EncryptionKeyDtoPublicKeyUseEnum]; +export type CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOfUseEnum = typeof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOfUseEnum[keyof typeof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOfUseEnum]; +export const CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOfCrvEnum = { + Secp256k1: 'secp256k1' +} as const; + +export type CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOfCrvEnum = typeof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOfCrvEnum[keyof typeof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOfCrvEnum]; /** * * @export - * @interface GenerateWalletDto + * @interface CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1 */ -export interface GenerateWalletDto { +export interface CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1 { /** * - * @type {GenerateWalletDtoCurve} - * @memberof GenerateWalletDto + * @type {string} + * @memberof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1 */ - 'curve'?: GenerateWalletDtoCurve; + 'kty': CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1KtyEnum; /** * * @type {string} - * @memberof GenerateWalletDto + * @memberof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1 */ - 'keyId'?: string; -} -/** - * @type GenerateWalletDtoCurve - * @export - */ -export type GenerateWalletDtoCurve = string; - -/** - * - * @export - * @interface ImportPrivateKeyDto - */ -export interface ImportPrivateKeyDto { + 'alg': CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1AlgEnum; /** - * Account Private Key, unencrypted - * @type {any} - * @memberof ImportPrivateKeyDto + * + * @type {string} + * @memberof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1 */ - 'privateKey'?: any; + 'use'?: CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1UseEnum; /** - * Account Private Key encrypted with JWE. Header MUST include \"kid\" + * * @type {string} - * @memberof ImportPrivateKeyDto + * @memberof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1 */ - 'encryptedPrivateKey'?: string; + 'kid': string; /** - * If not provided, it will be derived as \"eip155:eoa:${address}\" + * * @type {string} - * @memberof ImportPrivateKeyDto + * @memberof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1 */ - 'accountId'?: string; -} -/** - * - * @export - * @interface ImportWalletDto - */ -export interface ImportWalletDto { + 'addr'?: string; /** * * @type {string} - * @memberof ImportWalletDto + * @memberof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1 */ - 'keyId'?: string; + 'crv': CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1CrvEnum; /** * - * @type {GenerateWalletDtoCurve} - * @memberof ImportWalletDto + * @type {string} + * @memberof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1 */ - 'curve'?: GenerateWalletDtoCurve; + 'x': string; /** * * @type {string} - * @memberof ImportWalletDto + * @memberof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1 */ - 'encryptedSeed': string; + 'y': string; } + +export const CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1KtyEnum = { + Ec: 'EC' +} as const; + +export type CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1KtyEnum = typeof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1KtyEnum[keyof typeof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1KtyEnum]; +export const CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1AlgEnum = { + Es256: 'ES256' +} as const; + +export type CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1AlgEnum = typeof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1AlgEnum[keyof typeof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1AlgEnum]; +export const CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1UseEnum = { + Sig: 'sig', + Enc: 'enc' +} as const; + +export type CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1UseEnum = typeof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1UseEnum[keyof typeof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1UseEnum]; +export const CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1CrvEnum = { + P256: 'P-256' +} as const; + +export type CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1CrvEnum = typeof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1CrvEnum[keyof typeof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1CrvEnum]; + /** * * @export - * @interface PongDto + * @interface CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2 */ -export interface PongDto { +export interface CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2 { /** * - * @type {boolean} - * @memberof PongDto + * @type {string} + * @memberof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2 */ - 'pong': boolean; -} -/** - * - * @export - * @interface SignRequestDto - */ -export interface SignRequestDto { + 'kty': CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2KtyEnum; /** * - * @type {SignRequestDtoRequest} - * @memberof SignRequestDto + * @type {string} + * @memberof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2 */ - 'request': SignRequestDtoRequest; -} -/** - * @type SignRequestDtoRequest - * @export - */ -export type SignRequestDtoRequest = SignRequestDtoRequestOneOf | SignRequestDtoRequestOneOf1 | SignRequestDtoRequestOneOf2 | SignRequestDtoRequestOneOf3 | SignRequestDtoRequestOneOf4; - -/** - * - * @export - * @interface SignRequestDtoRequestOneOf - */ -export interface SignRequestDtoRequestOneOf { + 'crv': CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2CrvEnum; /** * * @type {string} - * @memberof SignRequestDtoRequestOneOf + * @memberof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2 */ - 'action': SignRequestDtoRequestOneOfActionEnum; + 'alg': CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2AlgEnum; /** * * @type {string} - * @memberof SignRequestDtoRequestOneOf + * @memberof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2 */ - 'nonce': string; + 'use'?: CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2UseEnum; /** * * @type {string} - * @memberof SignRequestDtoRequestOneOf + * @memberof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2 */ - 'resourceId': string; + 'kid': string; /** * - * @type {SignRequestDtoRequestOneOfTransactionRequest} - * @memberof SignRequestDtoRequestOneOf + * @type {any} + * @memberof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2 */ - 'transactionRequest': SignRequestDtoRequestOneOfTransactionRequest; + 'addr': any; } -export const SignRequestDtoRequestOneOfActionEnum = { - SignTransaction: 'signTransaction' +export const CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2KtyEnum = { + Ec: 'EC' } as const; -export type SignRequestDtoRequestOneOfActionEnum = typeof SignRequestDtoRequestOneOfActionEnum[keyof typeof SignRequestDtoRequestOneOfActionEnum]; +export type CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2KtyEnum = typeof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2KtyEnum[keyof typeof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2KtyEnum]; +export const CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2CrvEnum = { + Secp256k1: 'secp256k1' +} as const; + +export type CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2CrvEnum = typeof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2CrvEnum[keyof typeof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2CrvEnum]; +export const CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2AlgEnum = { + Es256K: 'ES256K' +} as const; + +export type CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2AlgEnum = typeof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2AlgEnum[keyof typeof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2AlgEnum]; +export const CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2UseEnum = { + Sig: 'sig', + Enc: 'enc' +} as const; + +export type CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2UseEnum = typeof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2UseEnum[keyof typeof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2UseEnum]; /** * * @export - * @interface SignRequestDtoRequestOneOf1 + * @interface CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3 */ -export interface SignRequestDtoRequestOneOf1 { +export interface CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3 { /** * * @type {string} - * @memberof SignRequestDtoRequestOneOf1 + * @memberof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3 */ - 'action': SignRequestDtoRequestOneOf1ActionEnum; + 'kty': CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3KtyEnum; /** * * @type {string} - * @memberof SignRequestDtoRequestOneOf1 + * @memberof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3 */ - 'nonce': string; + 'alg': CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3AlgEnum; /** * * @type {string} - * @memberof SignRequestDtoRequestOneOf1 + * @memberof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3 */ - 'resourceId': string; + 'use'?: CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3UseEnum; /** * - * @type {SignRequestDtoRequestOneOf1Message} - * @memberof SignRequestDtoRequestOneOf1 + * @type {string} + * @memberof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3 */ - 'message': SignRequestDtoRequestOneOf1Message; + 'kid': string; + /** + * + * @type {string} + * @memberof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3 + */ + 'addr'?: string; + /** + * + * @type {string} + * @memberof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3 + */ + 'crv': CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3CrvEnum; + /** + * + * @type {string} + * @memberof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3 + */ + 'x': string; } -export const SignRequestDtoRequestOneOf1ActionEnum = { - SignMessage: 'signMessage' +export const CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3KtyEnum = { + Okp: 'OKP' } as const; -export type SignRequestDtoRequestOneOf1ActionEnum = typeof SignRequestDtoRequestOneOf1ActionEnum[keyof typeof SignRequestDtoRequestOneOf1ActionEnum]; +export type CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3KtyEnum = typeof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3KtyEnum[keyof typeof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3KtyEnum]; +export const CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3AlgEnum = { + Eddsa: 'EDDSA' +} as const; -/** - * @type SignRequestDtoRequestOneOf1Message - * @export - */ -export type SignRequestDtoRequestOneOf1Message = SignRequestDtoRequestOneOf1MessageOneOf | string; +export type CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3AlgEnum = typeof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3AlgEnum[keyof typeof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3AlgEnum]; +export const CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3UseEnum = { + Sig: 'sig', + Enc: 'enc' +} as const; + +export type CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3UseEnum = typeof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3UseEnum[keyof typeof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3UseEnum]; +export const CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3CrvEnum = { + Ed25519: 'Ed25519' +} as const; + +export type CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3CrvEnum = typeof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3CrvEnum[keyof typeof CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3CrvEnum]; /** * * @export - * @interface SignRequestDtoRequestOneOf1MessageOneOf + * @interface CreateClientDtoAuthLocalJwsd */ -export interface SignRequestDtoRequestOneOf1MessageOneOf { +export interface CreateClientDtoAuthLocalJwsd { /** * - * @type {any} - * @memberof SignRequestDtoRequestOneOf1MessageOneOf + * @type {number} + * @memberof CreateClientDtoAuthLocalJwsd */ - 'raw': any; + 'maxAge'?: number; + /** + * + * @type {Array} + * @memberof CreateClientDtoAuthLocalJwsd + */ + 'requiredComponents'?: Array; } /** * * @export - * @interface SignRequestDtoRequestOneOf2 + * @interface CreateClientDtoAuthTokenValidation */ -export interface SignRequestDtoRequestOneOf2 { +export interface CreateClientDtoAuthTokenValidation { /** * - * @type {string} - * @memberof SignRequestDtoRequestOneOf2 + * @type {boolean} + * @memberof CreateClientDtoAuthTokenValidation */ - 'action': SignRequestDtoRequestOneOf2ActionEnum; + 'disabled'?: boolean; /** * * @type {string} - * @memberof SignRequestDtoRequestOneOf2 + * @memberof CreateClientDtoAuthTokenValidation */ - 'nonce': string; + 'url'?: string | null; /** * - * @type {string} - * @memberof SignRequestDtoRequestOneOf2 + * @type {CreateClientDtoAuthTokenValidationPinnedPublicKey} + * @memberof CreateClientDtoAuthTokenValidation */ - 'resourceId': string; + 'pinnedPublicKey'?: CreateClientDtoAuthTokenValidationPinnedPublicKey | null; /** * - * @type {SignRequestDtoRequestOneOf2TypedData} - * @memberof SignRequestDtoRequestOneOf2 + * @type {CreateClientDtoAuthTokenValidationVerification} + * @memberof CreateClientDtoAuthTokenValidation */ - 'typedData': SignRequestDtoRequestOneOf2TypedData; + 'verification'?: CreateClientDtoAuthTokenValidationVerification; } - -export const SignRequestDtoRequestOneOf2ActionEnum = { - SignTypedData: 'signTypedData' -} as const; - -export type SignRequestDtoRequestOneOf2ActionEnum = typeof SignRequestDtoRequestOneOf2ActionEnum[keyof typeof SignRequestDtoRequestOneOf2ActionEnum]; +/** + * @type CreateClientDtoAuthTokenValidationPinnedPublicKey + * @export + */ +export type CreateClientDtoAuthTokenValidationPinnedPublicKey = CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf | CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1 | CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2 | CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3 | EncryptionKeyDtoPublicKey; /** * * @export - * @interface SignRequestDtoRequestOneOf2TypedData + * @interface CreateClientDtoAuthTokenValidationVerification */ -export interface SignRequestDtoRequestOneOf2TypedData { +export interface CreateClientDtoAuthTokenValidationVerification { /** * - * @type {SignRequestDtoRequestOneOf2TypedDataDomain} - * @memberof SignRequestDtoRequestOneOf2TypedData + * @type {string} + * @memberof CreateClientDtoAuthTokenValidationVerification */ - 'domain': SignRequestDtoRequestOneOf2TypedDataDomain; - /** - * - * @type {{ [key: string]: Array; }} - * @memberof SignRequestDtoRequestOneOf2TypedData - */ - 'types': { [key: string]: Array; }; - /** - * - * @type {string} - * @memberof SignRequestDtoRequestOneOf2TypedData - */ - 'primaryType': string; - /** - * - * @type {{ [key: string]: any; }} - * @memberof SignRequestDtoRequestOneOf2TypedData - */ - 'message': { [key: string]: any; }; -} -/** - * - * @export - * @interface SignRequestDtoRequestOneOf2TypedDataDomain - */ -export interface SignRequestDtoRequestOneOf2TypedDataDomain { + 'audience'?: string | null; /** * * @type {string} - * @memberof SignRequestDtoRequestOneOf2TypedDataDomain + * @memberof CreateClientDtoAuthTokenValidationVerification */ - 'name'?: string; + 'issuer'?: string | null; /** * - * @type {string} - * @memberof SignRequestDtoRequestOneOf2TypedDataDomain + * @type {number} + * @memberof CreateClientDtoAuthTokenValidationVerification */ - 'version'?: string; + 'maxTokenAge'?: number | null; /** * - * @type {number} - * @memberof SignRequestDtoRequestOneOf2TypedDataDomain + * @type {boolean} + * @memberof CreateClientDtoAuthTokenValidationVerification */ - 'chainId'?: number; + 'requireBoundTokens'?: boolean; /** * - * @type {any} - * @memberof SignRequestDtoRequestOneOf2TypedDataDomain + * @type {boolean} + * @memberof CreateClientDtoAuthTokenValidationVerification */ - 'verifyingContract'?: any; + 'allowBearerTokens'?: boolean; /** * - * @type {any} - * @memberof SignRequestDtoRequestOneOf2TypedDataDomain + * @type {Array} + * @memberof CreateClientDtoAuthTokenValidationVerification */ - 'salt'?: any; + 'allowWildcard'?: Array | null; } /** * * @export - * @interface SignRequestDtoRequestOneOf2TypedDataTypesValueInner + * @interface CreateConnectionDto */ -export interface SignRequestDtoRequestOneOf2TypedDataTypesValueInner { +export interface CreateConnectionDto { /** * * @type {string} - * @memberof SignRequestDtoRequestOneOf2TypedDataTypesValueInner + * @memberof CreateConnectionDto */ - 'name': string; + 'connectionId'?: string; /** * + * @type {any} + * @memberof CreateConnectionDto + */ + 'createdAt'?: any; + /** + * RSA encrypted JSON string of the credentials * @type {string} - * @memberof SignRequestDtoRequestOneOf2TypedDataTypesValueInner + * @memberof CreateConnectionDto */ - 'type': string; -} -/** - * - * @export - * @interface SignRequestDtoRequestOneOf3 - */ -export interface SignRequestDtoRequestOneOf3 { + 'encryptedCredentials'?: string; /** * * @type {string} - * @memberof SignRequestDtoRequestOneOf3 + * @memberof CreateConnectionDto */ - 'action': SignRequestDtoRequestOneOf3ActionEnum; + 'label'?: string; /** * * @type {string} - * @memberof SignRequestDtoRequestOneOf3 + * @memberof CreateConnectionDto */ - 'nonce': string; + 'provider': CreateConnectionDtoProviderEnum; /** * * @type {string} - * @memberof SignRequestDtoRequestOneOf3 + * @memberof CreateConnectionDto */ - 'resourceId': string; + 'url': string; /** * - * @type {any} - * @memberof SignRequestDtoRequestOneOf3 + * @type {CreateConnectionDtoCredentials} + * @memberof CreateConnectionDto */ - 'rawMessage': any; + 'credentials'?: CreateConnectionDtoCredentials; } -export const SignRequestDtoRequestOneOf3ActionEnum = { - SignRaw: 'signRaw' +export const CreateConnectionDtoProviderEnum = { + Anchorage: 'anchorage' } as const; -export type SignRequestDtoRequestOneOf3ActionEnum = typeof SignRequestDtoRequestOneOf3ActionEnum[keyof typeof SignRequestDtoRequestOneOf3ActionEnum]; +export type CreateConnectionDtoProviderEnum = typeof CreateConnectionDtoProviderEnum[keyof typeof CreateConnectionDtoProviderEnum]; /** * * @export - * @interface SignRequestDtoRequestOneOf4 + * @interface CreateConnectionDtoCredentials */ -export interface SignRequestDtoRequestOneOf4 { - /** - * - * @type {string} - * @memberof SignRequestDtoRequestOneOf4 - */ - 'action': SignRequestDtoRequestOneOf4ActionEnum; - /** - * - * @type {string} - * @memberof SignRequestDtoRequestOneOf4 - */ - 'nonce': string; +export interface CreateConnectionDtoCredentials { /** * * @type {string} - * @memberof SignRequestDtoRequestOneOf4 + * @memberof CreateConnectionDtoCredentials */ - 'resourceId': string; + 'apiKey': string; /** - * - * @type {SignRequestDtoRequestOneOf4UserOperation} - * @memberof SignRequestDtoRequestOneOf4 + * Ed25519 private key in hex format + * @type {any} + * @memberof CreateConnectionDtoCredentials */ - 'userOperation': SignRequestDtoRequestOneOf4UserOperation; + 'privateKey'?: any; } - -export const SignRequestDtoRequestOneOf4ActionEnum = { - SignUserOperation: 'signUserOperation' -} as const; - -export type SignRequestDtoRequestOneOf4ActionEnum = typeof SignRequestDtoRequestOneOf4ActionEnum[keyof typeof SignRequestDtoRequestOneOf4ActionEnum]; - /** * * @export - * @interface SignRequestDtoRequestOneOf4UserOperation + * @interface DeriveAccountDto */ -export interface SignRequestDtoRequestOneOf4UserOperation { +export interface DeriveAccountDto { /** * - * @type {any} - * @memberof SignRequestDtoRequestOneOf4UserOperation + * @type {string} + * @memberof DeriveAccountDto */ - 'sender': any; + 'keyId': string; /** * - * @type {string} - * @memberof SignRequestDtoRequestOneOf4UserOperation + * @type {Array} + * @memberof DeriveAccountDto */ - 'nonce': string; + 'derivationPaths'?: Array; /** * - * @type {any} - * @memberof SignRequestDtoRequestOneOf4UserOperation + * @type {number} + * @memberof DeriveAccountDto */ - 'initCode': any; + 'count'?: number; +} +/** + * + * @export + * @interface DeriveAccountResponseDto + */ +export interface DeriveAccountResponseDto { /** * - * @type {any} - * @memberof SignRequestDtoRequestOneOf4UserOperation + * @type {Array} + * @memberof DeriveAccountResponseDto */ - 'callData': any; + 'accounts': Array; +} +/** + * + * @export + * @interface EncryptionKeyDto + */ +export interface EncryptionKeyDto { /** * - * @type {string} - * @memberof SignRequestDtoRequestOneOf4UserOperation + * @type {EncryptionKeyDtoPublicKey} + * @memberof EncryptionKeyDto */ - 'callGasLimit': string; + 'publicKey': EncryptionKeyDtoPublicKey; +} +/** + * + * @export + * @interface EncryptionKeyDtoPublicKey + */ +export interface EncryptionKeyDtoPublicKey { /** * * @type {string} - * @memberof SignRequestDtoRequestOneOf4UserOperation + * @memberof EncryptionKeyDtoPublicKey */ - 'verificationGasLimit': string; + 'kty': EncryptionKeyDtoPublicKeyKtyEnum; /** * * @type {string} - * @memberof SignRequestDtoRequestOneOf4UserOperation + * @memberof EncryptionKeyDtoPublicKey */ - 'preVerificationGas': string; + 'alg': EncryptionKeyDtoPublicKeyAlgEnum; /** * * @type {string} - * @memberof SignRequestDtoRequestOneOf4UserOperation + * @memberof EncryptionKeyDtoPublicKey */ - 'maxFeePerGas': string; + 'use'?: EncryptionKeyDtoPublicKeyUseEnum; /** * * @type {string} - * @memberof SignRequestDtoRequestOneOf4UserOperation + * @memberof EncryptionKeyDtoPublicKey */ - 'maxPriorityFeePerGas': string; + 'kid': string; /** * - * @type {any} - * @memberof SignRequestDtoRequestOneOf4UserOperation + * @type {string} + * @memberof EncryptionKeyDtoPublicKey */ - 'paymasterAndData': any; + 'addr'?: string; /** * - * @type {any} - * @memberof SignRequestDtoRequestOneOf4UserOperation + * @type {string} + * @memberof EncryptionKeyDtoPublicKey */ - 'entryPoint': any; + 'n': string; /** * - * @type {any} - * @memberof SignRequestDtoRequestOneOf4UserOperation + * @type {string} + * @memberof EncryptionKeyDtoPublicKey */ - 'signature': any; + 'e': string; +} + +export const EncryptionKeyDtoPublicKeyKtyEnum = { + Rsa: 'RSA' +} as const; + +export type EncryptionKeyDtoPublicKeyKtyEnum = typeof EncryptionKeyDtoPublicKeyKtyEnum[keyof typeof EncryptionKeyDtoPublicKeyKtyEnum]; +export const EncryptionKeyDtoPublicKeyAlgEnum = { + Rs256: 'RS256' +} as const; + +export type EncryptionKeyDtoPublicKeyAlgEnum = typeof EncryptionKeyDtoPublicKeyAlgEnum[keyof typeof EncryptionKeyDtoPublicKeyAlgEnum]; +export const EncryptionKeyDtoPublicKeyUseEnum = { + Sig: 'sig', + Enc: 'enc' +} as const; + +export type EncryptionKeyDtoPublicKeyUseEnum = typeof EncryptionKeyDtoPublicKeyUseEnum[keyof typeof EncryptionKeyDtoPublicKeyUseEnum]; + +/** + * + * @export + * @interface GenerateWalletDto + */ +export interface GenerateWalletDto { /** * - * @type {any} - * @memberof SignRequestDtoRequestOneOf4UserOperation + * @type {GenerateWalletDtoCurve} + * @memberof GenerateWalletDto */ - 'factoryAddress': any; + 'curve'?: GenerateWalletDtoCurve; /** * - * @type {number} - * @memberof SignRequestDtoRequestOneOf4UserOperation + * @type {string} + * @memberof GenerateWalletDto */ - 'chainId': number; + 'keyId'?: string; } /** - * @type SignRequestDtoRequestOneOfTransactionRequest + * @type GenerateWalletDtoCurve * @export */ -export type SignRequestDtoRequestOneOfTransactionRequest = SignRequestDtoRequestOneOfTransactionRequestOneOf | SignRequestDtoRequestOneOfTransactionRequestOneOf1; +export type GenerateWalletDtoCurve = string; /** * * @export - * @interface SignRequestDtoRequestOneOfTransactionRequestOneOf + * @interface ImportPrivateKeyDto */ -export interface SignRequestDtoRequestOneOfTransactionRequestOneOf { - /** - * - * @type {number} - * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf - */ - 'chainId': number; +export interface ImportPrivateKeyDto { /** - * + * Account Private Key, unencrypted * @type {any} - * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf + * @memberof ImportPrivateKeyDto */ - 'from': any; + 'privateKey'?: any; /** - * - * @type {number} - * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf + * Account Private Key encrypted with JWE. Header MUST include \"kid\" + * @type {string} + * @memberof ImportPrivateKeyDto */ - 'nonce'?: number; + 'encryptedPrivateKey'?: string; /** - * - * @type {Array} - * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf + * If not provided, it will be derived as \"eip155:eoa:${address}\" + * @type {string} + * @memberof ImportPrivateKeyDto */ - 'accessList'?: Array; + 'accountId'?: string; +} +/** + * + * @export + * @interface ImportWalletDto + */ +export interface ImportWalletDto { /** * - * @type {any} - * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf + * @type {string} + * @memberof ImportWalletDto */ - 'data'?: any; + 'keyId'?: string; + /** + * + * @type {GenerateWalletDtoCurve} + * @memberof ImportWalletDto + */ + 'curve'?: GenerateWalletDtoCurve; /** * * @type {string} - * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf + * @memberof ImportWalletDto */ - 'gas'?: string; + 'encryptedSeed': string; +} +/** + * + * @export + * @interface InitiateConnectionDto + */ +export interface InitiateConnectionDto { /** * * @type {string} - * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf + * @memberof InitiateConnectionDto */ - 'maxFeePerGas'?: string; + 'connectionId'?: string; /** * * @type {string} - * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf + * @memberof InitiateConnectionDto */ - 'maxPriorityFeePerGas'?: string; + 'provider': InitiateConnectionDtoProviderEnum; +} + +export const InitiateConnectionDtoProviderEnum = { + Anchorage: 'anchorage' +} as const; + +export type InitiateConnectionDtoProviderEnum = typeof InitiateConnectionDtoProviderEnum[keyof typeof InitiateConnectionDtoProviderEnum]; + +/** + * + * @export + * @interface PaginatedAccountsDto + */ +export interface PaginatedAccountsDto { /** * - * @type {any} - * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf + * @type {Array} + * @memberof PaginatedAccountsDto */ - 'to'?: any | null; + 'accounts': Array; /** * - * @type {string} - * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf + * @type {PaginatedWalletsDtoPage} + * @memberof PaginatedAccountsDto */ - 'type'?: SignRequestDtoRequestOneOfTransactionRequestOneOfTypeEnum; + 'page'?: PaginatedWalletsDtoPage; +} +/** + * + * @export + * @interface PaginatedAddressesDto + */ +export interface PaginatedAddressesDto { /** * - * @type {any} - * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf + * @type {Array} + * @memberof PaginatedAddressesDto */ - 'value'?: any; + 'addresses': Array; + /** + * + * @type {PaginatedWalletsDtoPage} + * @memberof PaginatedAddressesDto + */ + 'page'?: PaginatedWalletsDtoPage; } - -export const SignRequestDtoRequestOneOfTransactionRequestOneOfTypeEnum = { - _2: '2' -} as const; - -export type SignRequestDtoRequestOneOfTransactionRequestOneOfTypeEnum = typeof SignRequestDtoRequestOneOfTransactionRequestOneOfTypeEnum[keyof typeof SignRequestDtoRequestOneOfTransactionRequestOneOfTypeEnum]; - /** * * @export - * @interface SignRequestDtoRequestOneOfTransactionRequestOneOf1 + * @interface PaginatedSyncsDto */ -export interface SignRequestDtoRequestOneOfTransactionRequestOneOf1 { +export interface PaginatedSyncsDto { /** * - * @type {number} - * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf1 + * @type {PaginatedWalletsDtoPage} + * @memberof PaginatedSyncsDto */ - 'chainId': number; + 'page'?: PaginatedWalletsDtoPage; /** * - * @type {any} - * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf1 + * @type {Array} + * @memberof PaginatedSyncsDto */ - 'from': any; + 'syncs': Array; +} +/** + * + * @export + * @interface PaginatedWalletsDto + */ +export interface PaginatedWalletsDto { /** * - * @type {number} - * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf1 + * @type {Array} + * @memberof PaginatedWalletsDto */ - 'nonce'?: number; + 'wallets': Array; /** * - * @type {any} - * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf1 + * @type {PaginatedWalletsDtoPage} + * @memberof PaginatedWalletsDto */ - 'data'?: any; + 'page'?: PaginatedWalletsDtoPage; +} +/** + * + * @export + * @interface PaginatedWalletsDtoPage + */ +export interface PaginatedWalletsDtoPage { /** * * @type {string} - * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf1 + * @memberof PaginatedWalletsDtoPage */ - 'gas'?: string; + 'next': string | null; +} +/** + * + * @export + * @interface PaginatedWalletsDtoWalletsInner + */ +export interface PaginatedWalletsDtoWalletsInner { /** * * @type {string} - * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf1 + * @memberof PaginatedWalletsDtoWalletsInner */ - 'gasPrice'?: string; + 'walletId': string; + /** + * + * @type {Array} + * @memberof PaginatedWalletsDtoWalletsInner + */ + 'accounts'?: Array; + /** + * + * @type {Array} + * @memberof PaginatedWalletsDtoWalletsInner + */ + 'connections': Array; /** * * @type {string} - * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf1 + * @memberof PaginatedWalletsDtoWalletsInner */ - 'type'?: SignRequestDtoRequestOneOfTransactionRequestOneOf1TypeEnum; + 'label'?: string | null; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoWalletsInner + */ + 'clientId': string; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoWalletsInner + */ + 'provider': PaginatedWalletsDtoWalletsInnerProviderEnum; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoWalletsInner + */ + 'externalId': string; /** * * @type {any} - * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf1 + * @memberof PaginatedWalletsDtoWalletsInner */ - 'to'?: any | null; + 'createdAt': any; /** * * @type {any} - * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf1 + * @memberof PaginatedWalletsDtoWalletsInner */ - 'value'?: any; + 'updatedAt': any; } -export const SignRequestDtoRequestOneOfTransactionRequestOneOf1TypeEnum = { - _0: '0' +export const PaginatedWalletsDtoWalletsInnerProviderEnum = { + Anchorage: 'anchorage' } as const; -export type SignRequestDtoRequestOneOfTransactionRequestOneOf1TypeEnum = typeof SignRequestDtoRequestOneOfTransactionRequestOneOf1TypeEnum[keyof typeof SignRequestDtoRequestOneOfTransactionRequestOneOf1TypeEnum]; +export type PaginatedWalletsDtoWalletsInnerProviderEnum = typeof PaginatedWalletsDtoWalletsInnerProviderEnum[keyof typeof PaginatedWalletsDtoWalletsInnerProviderEnum]; /** * * @export - * @interface SignRequestDtoRequestOneOfTransactionRequestOneOfAccessListInner + * @interface PaginatedWalletsDtoWalletsInnerAccountsInner */ -export interface SignRequestDtoRequestOneOfTransactionRequestOneOfAccessListInner { +export interface PaginatedWalletsDtoWalletsInnerAccountsInner { /** * - * @type {any} - * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOfAccessListInner + * @type {string} + * @memberof PaginatedWalletsDtoWalletsInnerAccountsInner */ - 'address': any; + 'accountId': string; /** * - * @type {Array} - * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOfAccessListInner + * @type {string} + * @memberof PaginatedWalletsDtoWalletsInnerAccountsInner */ - 'storageKeys': Array; -} -/** - * - * @export - * @interface SignatureDto - */ -export interface SignatureDto { + 'label'?: string | null; /** * - * @type {any} - * @memberof SignatureDto + * @type {Array} + * @memberof PaginatedWalletsDtoWalletsInnerAccountsInner */ - 'signature': any; -} -/** - * - * @export - * @interface WalletDto - */ -export interface WalletDto { + 'addresses'?: Array; /** * - * @type {WalletDtoAccount} - * @memberof WalletDto + * @type {string} + * @memberof PaginatedWalletsDtoWalletsInnerAccountsInner */ - 'account': WalletDtoAccount; + 'clientId': string; /** * * @type {string} - * @memberof WalletDto + * @memberof PaginatedWalletsDtoWalletsInnerAccountsInner */ - 'backup'?: string; + 'provider': PaginatedWalletsDtoWalletsInnerAccountsInnerProviderEnum; /** * * @type {string} - * @memberof WalletDto + * @memberof PaginatedWalletsDtoWalletsInnerAccountsInner */ - 'keyId': string; + 'externalId': string; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoWalletsInnerAccountsInner + */ + 'walletId': string; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoWalletsInnerAccountsInner + */ + 'networkId': string; + /** + * + * @type {any} + * @memberof PaginatedWalletsDtoWalletsInnerAccountsInner + */ + 'createdAt': any; + /** + * + * @type {any} + * @memberof PaginatedWalletsDtoWalletsInnerAccountsInner + */ + 'updatedAt': any; } + +export const PaginatedWalletsDtoWalletsInnerAccountsInnerProviderEnum = { + Anchorage: 'anchorage' +} as const; + +export type PaginatedWalletsDtoWalletsInnerAccountsInnerProviderEnum = typeof PaginatedWalletsDtoWalletsInnerAccountsInnerProviderEnum[keyof typeof PaginatedWalletsDtoWalletsInnerAccountsInnerProviderEnum]; + /** * * @export - * @interface WalletDtoAccount + * @interface PaginatedWalletsDtoWalletsInnerAccountsInnerAddressesInner */ -export interface WalletDtoAccount { +export interface PaginatedWalletsDtoWalletsInnerAccountsInnerAddressesInner { /** * * @type {string} - * @memberof WalletDtoAccount + * @memberof PaginatedWalletsDtoWalletsInnerAccountsInnerAddressesInner */ - 'id': string; + 'addressId': string; /** * - * @type {any} - * @memberof WalletDtoAccount + * @type {string} + * @memberof PaginatedWalletsDtoWalletsInnerAccountsInnerAddressesInner */ - 'publicKey': any; + 'clientId': string; /** * - * @type {any} - * @memberof WalletDtoAccount + * @type {string} + * @memberof PaginatedWalletsDtoWalletsInnerAccountsInnerAddressesInner */ - 'address': any; + 'provider': PaginatedWalletsDtoWalletsInnerAccountsInnerAddressesInnerProviderEnum; /** * - * @type {WalletsDtoWalletsInnerOrigin} - * @memberof WalletDtoAccount + * @type {string} + * @memberof PaginatedWalletsDtoWalletsInnerAccountsInnerAddressesInner */ - 'origin': WalletsDtoWalletsInnerOrigin; + 'externalId': string; /** * * @type {string} - * @memberof WalletDtoAccount + * @memberof PaginatedWalletsDtoWalletsInnerAccountsInnerAddressesInner */ - 'keyId'?: string; + 'accountId': string; /** * * @type {string} - * @memberof WalletDtoAccount + * @memberof PaginatedWalletsDtoWalletsInnerAccountsInnerAddressesInner */ - 'derivationPath'?: string; -} -/** - * - * @export - * @interface WalletsDto - */ -export interface WalletsDto { + 'address': string; /** * - * @type {Array} - * @memberof WalletsDto + * @type {any} + * @memberof PaginatedWalletsDtoWalletsInnerAccountsInnerAddressesInner */ - 'wallets': Array; + 'createdAt': any; + /** + * + * @type {any} + * @memberof PaginatedWalletsDtoWalletsInnerAccountsInnerAddressesInner + */ + 'updatedAt': any; } + +export const PaginatedWalletsDtoWalletsInnerAccountsInnerAddressesInnerProviderEnum = { + Anchorage: 'anchorage' +} as const; + +export type PaginatedWalletsDtoWalletsInnerAccountsInnerAddressesInnerProviderEnum = typeof PaginatedWalletsDtoWalletsInnerAccountsInnerAddressesInnerProviderEnum[keyof typeof PaginatedWalletsDtoWalletsInnerAccountsInnerAddressesInnerProviderEnum]; + /** * * @export - * @interface WalletsDtoWalletsInner + * @interface PaginatedWalletsDtoWalletsInnerConnectionsInner */ -export interface WalletsDtoWalletsInner { +export interface PaginatedWalletsDtoWalletsInnerConnectionsInner { /** * * @type {string} - * @memberof WalletsDtoWalletsInner + * @memberof PaginatedWalletsDtoWalletsInnerConnectionsInner */ - 'keyId': string; + 'connectionId': string; /** * * @type {string} - * @memberof WalletsDtoWalletsInner + * @memberof PaginatedWalletsDtoWalletsInnerConnectionsInner */ - 'curve': string; + 'status'?: PaginatedWalletsDtoWalletsInnerConnectionsInnerStatusEnum; /** * - * @type {WalletsDtoWalletsInnerKeyType} - * @memberof WalletsDtoWalletsInner + * @type {string} + * @memberof PaginatedWalletsDtoWalletsInnerConnectionsInner */ - 'keyType': WalletsDtoWalletsInnerKeyType; + 'label'?: string; /** * - * @type {WalletsDtoWalletsInnerOrigin} - * @memberof WalletsDtoWalletsInner + * @type {string} + * @memberof PaginatedWalletsDtoWalletsInnerConnectionsInner */ - 'origin': WalletsDtoWalletsInnerOrigin; + 'provider': PaginatedWalletsDtoWalletsInnerConnectionsInnerProviderEnum; } + +export const PaginatedWalletsDtoWalletsInnerConnectionsInnerStatusEnum = { + Pending: 'pending', + Active: 'active', + Revoked: 'revoked' +} as const; + +export type PaginatedWalletsDtoWalletsInnerConnectionsInnerStatusEnum = typeof PaginatedWalletsDtoWalletsInnerConnectionsInnerStatusEnum[keyof typeof PaginatedWalletsDtoWalletsInnerConnectionsInnerStatusEnum]; +export const PaginatedWalletsDtoWalletsInnerConnectionsInnerProviderEnum = { + Anchorage: 'anchorage' +} as const; + +export type PaginatedWalletsDtoWalletsInnerConnectionsInnerProviderEnum = typeof PaginatedWalletsDtoWalletsInnerConnectionsInnerProviderEnum[keyof typeof PaginatedWalletsDtoWalletsInnerConnectionsInnerProviderEnum]; + /** - * @type WalletsDtoWalletsInnerKeyType + * + * @export + * @interface PendingConnectionDto + */ +export interface PendingConnectionDto { + /** + * + * @type {string} + * @memberof PendingConnectionDto + */ + 'clientId': string; + /** + * + * @type {string} + * @memberof PendingConnectionDto + */ + 'connectionId': string; + /** + * + * @type {string} + * @memberof PendingConnectionDto + */ + 'provider': PendingConnectionDtoProviderEnum; + /** + * + * @type {string} + * @memberof PendingConnectionDto + */ + 'status': PendingConnectionDtoStatusEnum; + /** + * + * @type {any} + * @memberof PendingConnectionDto + */ + 'createdAt': any; + /** + * + * @type {PendingConnectionDtoPublicKey} + * @memberof PendingConnectionDto + */ + 'publicKey'?: PendingConnectionDtoPublicKey; + /** + * + * @type {PendingConnectionDtoEncryptionPublicKey} + * @memberof PendingConnectionDto + */ + 'encryptionPublicKey': PendingConnectionDtoEncryptionPublicKey; +} + +export const PendingConnectionDtoProviderEnum = { + Anchorage: 'anchorage' +} as const; + +export type PendingConnectionDtoProviderEnum = typeof PendingConnectionDtoProviderEnum[keyof typeof PendingConnectionDtoProviderEnum]; +export const PendingConnectionDtoStatusEnum = { + Pending: 'pending' +} as const; + +export type PendingConnectionDtoStatusEnum = typeof PendingConnectionDtoStatusEnum[keyof typeof PendingConnectionDtoStatusEnum]; + +/** + * + * @export + * @interface PendingConnectionDtoEncryptionPublicKey + */ +export interface PendingConnectionDtoEncryptionPublicKey { + /** + * + * @type {string} + * @memberof PendingConnectionDtoEncryptionPublicKey + */ + 'keyId'?: string; + /** + * + * @type {CreateClientDtoAuthLocalAllowedUsersInnerPublicKey} + * @memberof PendingConnectionDtoEncryptionPublicKey + */ + 'jwk'?: CreateClientDtoAuthLocalAllowedUsersInnerPublicKey; +} +/** + * + * @export + * @interface PendingConnectionDtoPublicKey + */ +export interface PendingConnectionDtoPublicKey { + /** + * + * @type {string} + * @memberof PendingConnectionDtoPublicKey + */ + 'keyId'?: string; + /** + * + * @type {CreateClientDtoAuthLocalAllowedUsersInnerPublicKey} + * @memberof PendingConnectionDtoPublicKey + */ + 'jwk'?: CreateClientDtoAuthLocalAllowedUsersInnerPublicKey; + /** + * + * @type {any} + * @memberof PendingConnectionDtoPublicKey + */ + 'hex'?: any; +} +/** + * + * @export + * @interface PongDto + */ +export interface PongDto { + /** + * + * @type {boolean} + * @memberof PongDto + */ + 'pong': boolean; +} +/** + * + * @export + * @interface ProviderAccountDto + */ +export interface ProviderAccountDto { + /** + * + * @type {PaginatedWalletsDtoWalletsInnerAccountsInner} + * @memberof ProviderAccountDto + */ + 'account': PaginatedWalletsDtoWalletsInnerAccountsInner; +} +/** + * + * @export + * @interface ProviderConnectionDto + */ +export interface ProviderConnectionDto { + /** + * + * @type {string} + * @memberof ProviderConnectionDto + */ + 'clientId': string; + /** + * + * @type {string} + * @memberof ProviderConnectionDto + */ + 'connectionId': string; + /** + * + * @type {any} + * @memberof ProviderConnectionDto + */ + 'createdAt': any; + /** + * + * @type {string} + * @memberof ProviderConnectionDto + */ + 'label'?: string; + /** + * + * @type {string} + * @memberof ProviderConnectionDto + */ + 'provider': ProviderConnectionDtoProviderEnum; + /** + * + * @type {any} + * @memberof ProviderConnectionDto + */ + 'revokedAt'?: any; + /** + * + * @type {string} + * @memberof ProviderConnectionDto + */ + 'status'?: ProviderConnectionDtoStatusEnum; + /** + * + * @type {any} + * @memberof ProviderConnectionDto + */ + 'updatedAt': any; + /** + * + * @type {string} + * @memberof ProviderConnectionDto + */ + 'url'?: string; +} + +export const ProviderConnectionDtoProviderEnum = { + Anchorage: 'anchorage' +} as const; + +export type ProviderConnectionDtoProviderEnum = typeof ProviderConnectionDtoProviderEnum[keyof typeof ProviderConnectionDtoProviderEnum]; +export const ProviderConnectionDtoStatusEnum = { + Pending: 'pending', + Active: 'active', + Revoked: 'revoked' +} as const; + +export type ProviderConnectionDtoStatusEnum = typeof ProviderConnectionDtoStatusEnum[keyof typeof ProviderConnectionDtoStatusEnum]; + +/** + * + * @export + * @interface ProviderWalletDto + */ +export interface ProviderWalletDto { + /** + * + * @type {PaginatedWalletsDtoWalletsInner} + * @memberof ProviderWalletDto + */ + 'wallet': PaginatedWalletsDtoWalletsInner; +} +/** + * + * @export + * @interface SignRequestDto + */ +export interface SignRequestDto { + /** + * + * @type {SignRequestDtoRequest} + * @memberof SignRequestDto + */ + 'request': SignRequestDtoRequest; +} +/** + * @type SignRequestDtoRequest + * @export + */ +export type SignRequestDtoRequest = SignRequestDtoRequestOneOf | SignRequestDtoRequestOneOf1 | SignRequestDtoRequestOneOf2 | SignRequestDtoRequestOneOf3 | SignRequestDtoRequestOneOf4; + +/** + * + * @export + * @interface SignRequestDtoRequestOneOf + */ +export interface SignRequestDtoRequestOneOf { + /** + * + * @type {string} + * @memberof SignRequestDtoRequestOneOf + */ + 'action': SignRequestDtoRequestOneOfActionEnum; + /** + * + * @type {string} + * @memberof SignRequestDtoRequestOneOf + */ + 'nonce': string; + /** + * + * @type {string} + * @memberof SignRequestDtoRequestOneOf + */ + 'resourceId': string; + /** + * + * @type {SignRequestDtoRequestOneOfTransactionRequest} + * @memberof SignRequestDtoRequestOneOf + */ + 'transactionRequest': SignRequestDtoRequestOneOfTransactionRequest; +} + +export const SignRequestDtoRequestOneOfActionEnum = { + SignTransaction: 'signTransaction' +} as const; + +export type SignRequestDtoRequestOneOfActionEnum = typeof SignRequestDtoRequestOneOfActionEnum[keyof typeof SignRequestDtoRequestOneOfActionEnum]; + +/** + * + * @export + * @interface SignRequestDtoRequestOneOf1 + */ +export interface SignRequestDtoRequestOneOf1 { + /** + * + * @type {string} + * @memberof SignRequestDtoRequestOneOf1 + */ + 'action': SignRequestDtoRequestOneOf1ActionEnum; + /** + * + * @type {string} + * @memberof SignRequestDtoRequestOneOf1 + */ + 'nonce': string; + /** + * + * @type {string} + * @memberof SignRequestDtoRequestOneOf1 + */ + 'resourceId': string; + /** + * + * @type {SignRequestDtoRequestOneOf1Message} + * @memberof SignRequestDtoRequestOneOf1 + */ + 'message': SignRequestDtoRequestOneOf1Message; +} + +export const SignRequestDtoRequestOneOf1ActionEnum = { + SignMessage: 'signMessage' +} as const; + +export type SignRequestDtoRequestOneOf1ActionEnum = typeof SignRequestDtoRequestOneOf1ActionEnum[keyof typeof SignRequestDtoRequestOneOf1ActionEnum]; + +/** + * @type SignRequestDtoRequestOneOf1Message + * @export + */ +export type SignRequestDtoRequestOneOf1Message = SignRequestDtoRequestOneOf1MessageOneOf | string; + +/** + * + * @export + * @interface SignRequestDtoRequestOneOf1MessageOneOf + */ +export interface SignRequestDtoRequestOneOf1MessageOneOf { + /** + * + * @type {any} + * @memberof SignRequestDtoRequestOneOf1MessageOneOf + */ + 'raw': any; +} +/** + * + * @export + * @interface SignRequestDtoRequestOneOf2 + */ +export interface SignRequestDtoRequestOneOf2 { + /** + * + * @type {string} + * @memberof SignRequestDtoRequestOneOf2 + */ + 'action': SignRequestDtoRequestOneOf2ActionEnum; + /** + * + * @type {string} + * @memberof SignRequestDtoRequestOneOf2 + */ + 'nonce': string; + /** + * + * @type {string} + * @memberof SignRequestDtoRequestOneOf2 + */ + 'resourceId': string; + /** + * + * @type {SignRequestDtoRequestOneOf2TypedData} + * @memberof SignRequestDtoRequestOneOf2 + */ + 'typedData': SignRequestDtoRequestOneOf2TypedData; +} + +export const SignRequestDtoRequestOneOf2ActionEnum = { + SignTypedData: 'signTypedData' +} as const; + +export type SignRequestDtoRequestOneOf2ActionEnum = typeof SignRequestDtoRequestOneOf2ActionEnum[keyof typeof SignRequestDtoRequestOneOf2ActionEnum]; + +/** + * + * @export + * @interface SignRequestDtoRequestOneOf2TypedData + */ +export interface SignRequestDtoRequestOneOf2TypedData { + /** + * + * @type {SignRequestDtoRequestOneOf2TypedDataDomain} + * @memberof SignRequestDtoRequestOneOf2TypedData + */ + 'domain': SignRequestDtoRequestOneOf2TypedDataDomain; + /** + * + * @type {{ [key: string]: Array; }} + * @memberof SignRequestDtoRequestOneOf2TypedData + */ + 'types': { [key: string]: Array; }; + /** + * + * @type {string} + * @memberof SignRequestDtoRequestOneOf2TypedData + */ + 'primaryType': string; + /** + * + * @type {{ [key: string]: any; }} + * @memberof SignRequestDtoRequestOneOf2TypedData + */ + 'message': { [key: string]: any; }; +} +/** + * + * @export + * @interface SignRequestDtoRequestOneOf2TypedDataDomain + */ +export interface SignRequestDtoRequestOneOf2TypedDataDomain { + /** + * + * @type {string} + * @memberof SignRequestDtoRequestOneOf2TypedDataDomain + */ + 'name'?: string; + /** + * + * @type {string} + * @memberof SignRequestDtoRequestOneOf2TypedDataDomain + */ + 'version'?: string; + /** + * + * @type {number} + * @memberof SignRequestDtoRequestOneOf2TypedDataDomain + */ + 'chainId'?: number; + /** + * + * @type {any} + * @memberof SignRequestDtoRequestOneOf2TypedDataDomain + */ + 'verifyingContract'?: any; + /** + * + * @type {any} + * @memberof SignRequestDtoRequestOneOf2TypedDataDomain + */ + 'salt'?: any; +} +/** + * + * @export + * @interface SignRequestDtoRequestOneOf2TypedDataTypesValueInner + */ +export interface SignRequestDtoRequestOneOf2TypedDataTypesValueInner { + /** + * + * @type {string} + * @memberof SignRequestDtoRequestOneOf2TypedDataTypesValueInner + */ + 'name': string; + /** + * + * @type {string} + * @memberof SignRequestDtoRequestOneOf2TypedDataTypesValueInner + */ + 'type': string; +} +/** + * + * @export + * @interface SignRequestDtoRequestOneOf3 + */ +export interface SignRequestDtoRequestOneOf3 { + /** + * + * @type {string} + * @memberof SignRequestDtoRequestOneOf3 + */ + 'action': SignRequestDtoRequestOneOf3ActionEnum; + /** + * + * @type {string} + * @memberof SignRequestDtoRequestOneOf3 + */ + 'nonce': string; + /** + * + * @type {string} + * @memberof SignRequestDtoRequestOneOf3 + */ + 'resourceId': string; + /** + * + * @type {any} + * @memberof SignRequestDtoRequestOneOf3 + */ + 'rawMessage': any; +} + +export const SignRequestDtoRequestOneOf3ActionEnum = { + SignRaw: 'signRaw' +} as const; + +export type SignRequestDtoRequestOneOf3ActionEnum = typeof SignRequestDtoRequestOneOf3ActionEnum[keyof typeof SignRequestDtoRequestOneOf3ActionEnum]; + +/** + * + * @export + * @interface SignRequestDtoRequestOneOf4 + */ +export interface SignRequestDtoRequestOneOf4 { + /** + * + * @type {string} + * @memberof SignRequestDtoRequestOneOf4 + */ + 'action': SignRequestDtoRequestOneOf4ActionEnum; + /** + * + * @type {string} + * @memberof SignRequestDtoRequestOneOf4 + */ + 'nonce': string; + /** + * + * @type {string} + * @memberof SignRequestDtoRequestOneOf4 + */ + 'resourceId': string; + /** + * + * @type {SignRequestDtoRequestOneOf4UserOperation} + * @memberof SignRequestDtoRequestOneOf4 + */ + 'userOperation': SignRequestDtoRequestOneOf4UserOperation; +} + +export const SignRequestDtoRequestOneOf4ActionEnum = { + SignUserOperation: 'signUserOperation' +} as const; + +export type SignRequestDtoRequestOneOf4ActionEnum = typeof SignRequestDtoRequestOneOf4ActionEnum[keyof typeof SignRequestDtoRequestOneOf4ActionEnum]; + +/** + * + * @export + * @interface SignRequestDtoRequestOneOf4UserOperation + */ +export interface SignRequestDtoRequestOneOf4UserOperation { + /** + * + * @type {any} + * @memberof SignRequestDtoRequestOneOf4UserOperation + */ + 'sender': any; + /** + * + * @type {string} + * @memberof SignRequestDtoRequestOneOf4UserOperation + */ + 'nonce': string; + /** + * + * @type {any} + * @memberof SignRequestDtoRequestOneOf4UserOperation + */ + 'initCode': any; + /** + * + * @type {any} + * @memberof SignRequestDtoRequestOneOf4UserOperation + */ + 'callData': any; + /** + * + * @type {string} + * @memberof SignRequestDtoRequestOneOf4UserOperation + */ + 'callGasLimit': string; + /** + * + * @type {string} + * @memberof SignRequestDtoRequestOneOf4UserOperation + */ + 'verificationGasLimit': string; + /** + * + * @type {string} + * @memberof SignRequestDtoRequestOneOf4UserOperation + */ + 'preVerificationGas': string; + /** + * + * @type {string} + * @memberof SignRequestDtoRequestOneOf4UserOperation + */ + 'maxFeePerGas': string; + /** + * + * @type {string} + * @memberof SignRequestDtoRequestOneOf4UserOperation + */ + 'maxPriorityFeePerGas': string; + /** + * + * @type {any} + * @memberof SignRequestDtoRequestOneOf4UserOperation + */ + 'paymasterAndData': any; + /** + * + * @type {any} + * @memberof SignRequestDtoRequestOneOf4UserOperation + */ + 'entryPoint': any; + /** + * + * @type {any} + * @memberof SignRequestDtoRequestOneOf4UserOperation + */ + 'signature': any; + /** + * + * @type {any} + * @memberof SignRequestDtoRequestOneOf4UserOperation + */ + 'factoryAddress': any; + /** + * + * @type {number} + * @memberof SignRequestDtoRequestOneOf4UserOperation + */ + 'chainId': number; +} +/** + * @type SignRequestDtoRequestOneOfTransactionRequest + * @export + */ +export type SignRequestDtoRequestOneOfTransactionRequest = SignRequestDtoRequestOneOfTransactionRequestOneOf | SignRequestDtoRequestOneOfTransactionRequestOneOf1; + +/** + * + * @export + * @interface SignRequestDtoRequestOneOfTransactionRequestOneOf + */ +export interface SignRequestDtoRequestOneOfTransactionRequestOneOf { + /** + * + * @type {number} + * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf + */ + 'chainId': number; + /** + * + * @type {any} + * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf + */ + 'from': any; + /** + * + * @type {number} + * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf + */ + 'nonce'?: number; + /** + * + * @type {Array} + * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf + */ + 'accessList'?: Array; + /** + * + * @type {any} + * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf + */ + 'data'?: any; + /** + * + * @type {string} + * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf + */ + 'gas'?: string; + /** + * + * @type {string} + * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf + */ + 'maxFeePerGas'?: string; + /** + * + * @type {string} + * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf + */ + 'maxPriorityFeePerGas'?: string; + /** + * + * @type {any} + * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf + */ + 'to'?: any | null; + /** + * + * @type {string} + * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf + */ + 'type'?: SignRequestDtoRequestOneOfTransactionRequestOneOfTypeEnum; + /** + * + * @type {any} + * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf + */ + 'value'?: any; +} + +export const SignRequestDtoRequestOneOfTransactionRequestOneOfTypeEnum = { + _2: '2' +} as const; + +export type SignRequestDtoRequestOneOfTransactionRequestOneOfTypeEnum = typeof SignRequestDtoRequestOneOfTransactionRequestOneOfTypeEnum[keyof typeof SignRequestDtoRequestOneOfTransactionRequestOneOfTypeEnum]; + +/** + * + * @export + * @interface SignRequestDtoRequestOneOfTransactionRequestOneOf1 + */ +export interface SignRequestDtoRequestOneOfTransactionRequestOneOf1 { + /** + * + * @type {number} + * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf1 + */ + 'chainId': number; + /** + * + * @type {any} + * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf1 + */ + 'from': any; + /** + * + * @type {number} + * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf1 + */ + 'nonce'?: number; + /** + * + * @type {any} + * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf1 + */ + 'data'?: any; + /** + * + * @type {string} + * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf1 + */ + 'gas'?: string; + /** + * + * @type {string} + * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf1 + */ + 'gasPrice'?: string; + /** + * + * @type {string} + * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf1 + */ + 'type'?: SignRequestDtoRequestOneOfTransactionRequestOneOf1TypeEnum; + /** + * + * @type {any} + * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf1 + */ + 'to'?: any | null; + /** + * + * @type {any} + * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOf1 + */ + 'value'?: any; +} + +export const SignRequestDtoRequestOneOfTransactionRequestOneOf1TypeEnum = { + _0: '0' +} as const; + +export type SignRequestDtoRequestOneOfTransactionRequestOneOf1TypeEnum = typeof SignRequestDtoRequestOneOfTransactionRequestOneOf1TypeEnum[keyof typeof SignRequestDtoRequestOneOfTransactionRequestOneOf1TypeEnum]; + +/** + * + * @export + * @interface SignRequestDtoRequestOneOfTransactionRequestOneOfAccessListInner + */ +export interface SignRequestDtoRequestOneOfTransactionRequestOneOfAccessListInner { + /** + * + * @type {any} + * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOfAccessListInner + */ + 'address': any; + /** + * + * @type {Array} + * @memberof SignRequestDtoRequestOneOfTransactionRequestOneOfAccessListInner + */ + 'storageKeys': Array; +} +/** + * + * @export + * @interface SignatureDto + */ +export interface SignatureDto { + /** + * + * @type {any} + * @memberof SignatureDto + */ + 'signature': any; +} +/** + * + * @export + * @interface StartSyncDto + */ +export interface StartSyncDto { + /** + * The connection to sync. If undefined, start the sync on all active connections + * @type {string} + * @memberof StartSyncDto + */ + 'connectionId'?: string; +} +/** + * + * @export + * @interface SyncDto + */ +export interface SyncDto { + /** + * + * @type {string} + * @memberof SyncDto + */ + 'clientId': string; + /** + * + * @type {any} + * @memberof SyncDto + */ + 'completedAt'?: any; + /** + * + * @type {string} + * @memberof SyncDto + */ + 'connectionId': string; + /** + * + * @type {any} + * @memberof SyncDto + */ + 'createdAt': any; + /** + * + * @type {SyncStatusDtoSyncsInnerError} + * @memberof SyncDto + */ + 'error'?: SyncStatusDtoSyncsInnerError; + /** + * + * @type {string} + * @memberof SyncDto + */ + 'status'?: SyncDtoStatusEnum; + /** + * + * @type {string} + * @memberof SyncDto + */ + 'syncId': string; +} + +export const SyncDtoStatusEnum = { + Processing: 'processing', + Success: 'success', + Failed: 'failed' +} as const; + +export type SyncDtoStatusEnum = typeof SyncDtoStatusEnum[keyof typeof SyncDtoStatusEnum]; + +/** + * + * @export + * @interface SyncStatusDto + */ +export interface SyncStatusDto { + /** + * + * @type {boolean} + * @memberof SyncStatusDto + */ + 'started': boolean; + /** + * + * @type {Array} + * @memberof SyncStatusDto + */ + 'syncs': Array; +} +/** + * + * @export + * @interface SyncStatusDtoSyncsInner + */ +export interface SyncStatusDtoSyncsInner { + /** + * + * @type {string} + * @memberof SyncStatusDtoSyncsInner + */ + 'clientId': string; + /** + * + * @type {any} + * @memberof SyncStatusDtoSyncsInner + */ + 'completedAt'?: any; + /** + * + * @type {string} + * @memberof SyncStatusDtoSyncsInner + */ + 'connectionId': string; + /** + * + * @type {any} + * @memberof SyncStatusDtoSyncsInner + */ + 'createdAt': any; + /** + * + * @type {SyncStatusDtoSyncsInnerError} + * @memberof SyncStatusDtoSyncsInner + */ + 'error'?: SyncStatusDtoSyncsInnerError; + /** + * + * @type {string} + * @memberof SyncStatusDtoSyncsInner + */ + 'status'?: SyncStatusDtoSyncsInnerStatusEnum; + /** + * + * @type {string} + * @memberof SyncStatusDtoSyncsInner + */ + 'syncId': string; +} + +export const SyncStatusDtoSyncsInnerStatusEnum = { + Processing: 'processing', + Success: 'success', + Failed: 'failed' +} as const; + +export type SyncStatusDtoSyncsInnerStatusEnum = typeof SyncStatusDtoSyncsInnerStatusEnum[keyof typeof SyncStatusDtoSyncsInnerStatusEnum]; + +/** + * + * @export + * @interface SyncStatusDtoSyncsInnerError + */ +export interface SyncStatusDtoSyncsInnerError { + /** + * + * @type {string} + * @memberof SyncStatusDtoSyncsInnerError + */ + 'name'?: string; + /** + * + * @type {string} + * @memberof SyncStatusDtoSyncsInnerError + */ + 'message'?: string; + /** + * + * @type {string} + * @memberof SyncStatusDtoSyncsInnerError + */ + 'traceId'?: string; +} +/** + * + * @export + * @interface UpdateConnectionDto + */ +export interface UpdateConnectionDto { + /** + * + * @type {string} + * @memberof UpdateConnectionDto + */ + 'label'?: string; + /** + * RSA encrypted JSON string of the credentials + * @type {string} + * @memberof UpdateConnectionDto + */ + 'encryptedCredentials'?: string; + /** + * + * @type {CreateConnectionDtoCredentials} + * @memberof UpdateConnectionDto + */ + 'credentials'?: CreateConnectionDtoCredentials; +} +/** + * + * @export + * @interface WalletDto + */ +export interface WalletDto { + /** + * + * @type {WalletDtoAccount} + * @memberof WalletDto + */ + 'account': WalletDtoAccount; + /** + * + * @type {string} + * @memberof WalletDto + */ + 'backup'?: string; + /** + * + * @type {string} + * @memberof WalletDto + */ + 'keyId': string; +} +/** + * + * @export + * @interface WalletDtoAccount + */ +export interface WalletDtoAccount { + /** + * + * @type {string} + * @memberof WalletDtoAccount + */ + 'id': string; + /** + * + * @type {any} + * @memberof WalletDtoAccount + */ + 'publicKey': any; + /** + * + * @type {any} + * @memberof WalletDtoAccount + */ + 'address': any; + /** + * + * @type {WalletsDtoWalletsInnerOrigin} + * @memberof WalletDtoAccount + */ + 'origin': WalletsDtoWalletsInnerOrigin; + /** + * + * @type {string} + * @memberof WalletDtoAccount + */ + 'keyId'?: string; + /** + * + * @type {string} + * @memberof WalletDtoAccount + */ + 'derivationPath'?: string; +} +/** + * + * @export + * @interface WalletsDto + */ +export interface WalletsDto { + /** + * + * @type {Array} + * @memberof WalletsDto + */ + 'wallets': Array; +} +/** + * + * @export + * @interface WalletsDtoWalletsInner + */ +export interface WalletsDtoWalletsInner { + /** + * + * @type {string} + * @memberof WalletsDtoWalletsInner + */ + 'keyId': string; + /** + * + * @type {string} + * @memberof WalletsDtoWalletsInner + */ + 'curve': string; + /** + * + * @type {WalletsDtoWalletsInnerKeyType} + * @memberof WalletsDtoWalletsInner + */ + 'keyType': WalletsDtoWalletsInnerKeyType; + /** + * + * @type {WalletsDtoWalletsInnerOrigin} + * @memberof WalletsDtoWalletsInner + */ + 'origin': WalletsDtoWalletsInnerOrigin; +} +/** + * @type WalletsDtoWalletsInnerKeyType * @export */ export type WalletsDtoWalletsInnerKeyType = string; -/** - * @type WalletsDtoWalletsInnerOrigin - * @export - */ -export type WalletsDtoWalletsInnerOrigin = string; +/** + * @type WalletsDtoWalletsInnerOrigin + * @export + */ +export type WalletsDtoWalletsInnerOrigin = string; + + +/** + * AccountApi - axios parameter creator + * @export + */ +export const AccountApiAxiosParamCreator = function (configuration?: Configuration) { + return { + /** + * + * @summary Add a new account to a wallet + * @param {string} xClientId + * @param {string} authorization + * @param {DeriveAccountDto} deriveAccountDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + derive: async (xClientId: string, authorization: string, deriveAccountDto: DeriveAccountDto, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('derive', 'xClientId', xClientId) + // verify required parameter 'authorization' is not null or undefined + assertParamExists('derive', 'authorization', authorization) + // verify required parameter 'deriveAccountDto' is not null or undefined + assertParamExists('derive', 'deriveAccountDto', deriveAccountDto) + const localVarPath = `/v1/accounts`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(deriveAccountDto, localVarRequestOptions, configuration) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @summary Imports an account + * @param {string} xClientId + * @param {string} authorization + * @param {ImportPrivateKeyDto} importPrivateKeyDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + importPrivateKey: async (xClientId: string, authorization: string, importPrivateKeyDto: ImportPrivateKeyDto, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('importPrivateKey', 'xClientId', xClientId) + // verify required parameter 'authorization' is not null or undefined + assertParamExists('importPrivateKey', 'authorization', authorization) + // verify required parameter 'importPrivateKeyDto' is not null or undefined + assertParamExists('importPrivateKey', 'importPrivateKeyDto', importPrivateKeyDto) + const localVarPath = `/v1/accounts/import`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(importPrivateKeyDto, localVarRequestOptions, configuration) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @summary Lists the client accounts + * @param {string} xClientId + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + list: async (xClientId: string, authorization: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('list', 'xClientId', xClientId) + // verify required parameter 'authorization' is not null or undefined + assertParamExists('list', 'authorization', authorization) + const localVarPath = `/v1/accounts`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + } +}; + +/** + * AccountApi - functional programming interface + * @export + */ +export const AccountApiFp = function(configuration?: Configuration) { + const localVarAxiosParamCreator = AccountApiAxiosParamCreator(configuration) + return { + /** + * + * @summary Add a new account to a wallet + * @param {string} xClientId + * @param {string} authorization + * @param {DeriveAccountDto} deriveAccountDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async derive(xClientId: string, authorization: string, deriveAccountDto: DeriveAccountDto, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.derive(xClientId, authorization, deriveAccountDto, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['AccountApi.derive']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + /** + * + * @summary Imports an account + * @param {string} xClientId + * @param {string} authorization + * @param {ImportPrivateKeyDto} importPrivateKeyDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async importPrivateKey(xClientId: string, authorization: string, importPrivateKeyDto: ImportPrivateKeyDto, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.importPrivateKey(xClientId, authorization, importPrivateKeyDto, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['AccountApi.importPrivateKey']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + /** + * + * @summary Lists the client accounts + * @param {string} xClientId + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async list(xClientId: string, authorization: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.list(xClientId, authorization, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['AccountApi.list']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + } +}; + +/** + * AccountApi - factory interface + * @export + */ +export const AccountApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { + const localVarFp = AccountApiFp(configuration) + return { + /** + * + * @summary Add a new account to a wallet + * @param {string} xClientId + * @param {string} authorization + * @param {DeriveAccountDto} deriveAccountDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + derive(xClientId: string, authorization: string, deriveAccountDto: DeriveAccountDto, options?: any): AxiosPromise { + return localVarFp.derive(xClientId, authorization, deriveAccountDto, options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary Imports an account + * @param {string} xClientId + * @param {string} authorization + * @param {ImportPrivateKeyDto} importPrivateKeyDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + importPrivateKey(xClientId: string, authorization: string, importPrivateKeyDto: ImportPrivateKeyDto, options?: any): AxiosPromise { + return localVarFp.importPrivateKey(xClientId, authorization, importPrivateKeyDto, options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary Lists the client accounts + * @param {string} xClientId + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + list(xClientId: string, authorization: string, options?: any): AxiosPromise { + return localVarFp.list(xClientId, authorization, options).then((request) => request(axios, basePath)); + }, + }; +}; + +/** + * AccountApi - object-oriented interface + * @export + * @class AccountApi + * @extends {BaseAPI} + */ +export class AccountApi extends BaseAPI { + /** + * + * @summary Add a new account to a wallet + * @param {string} xClientId + * @param {string} authorization + * @param {DeriveAccountDto} deriveAccountDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof AccountApi + */ + public derive(xClientId: string, authorization: string, deriveAccountDto: DeriveAccountDto, options?: RawAxiosRequestConfig) { + return AccountApiFp(this.configuration).derive(xClientId, authorization, deriveAccountDto, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * + * @summary Imports an account + * @param {string} xClientId + * @param {string} authorization + * @param {ImportPrivateKeyDto} importPrivateKeyDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof AccountApi + */ + public importPrivateKey(xClientId: string, authorization: string, importPrivateKeyDto: ImportPrivateKeyDto, options?: RawAxiosRequestConfig) { + return AccountApiFp(this.configuration).importPrivateKey(xClientId, authorization, importPrivateKeyDto, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * + * @summary Lists the client accounts + * @param {string} xClientId + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof AccountApi + */ + public list(xClientId: string, authorization: string, options?: RawAxiosRequestConfig) { + return AccountApiFp(this.configuration).list(xClientId, authorization, options).then((request) => request(this.axios, this.basePath)); + } +} + + + +/** + * ApplicationApi - axios parameter creator + * @export + */ +export const ApplicationApiAxiosParamCreator = function (configuration?: Configuration) { + return { + /** + * + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + ping: async (options: RawAxiosRequestConfig = {}): Promise => { + const localVarPath = `/ping`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + } +}; + +/** + * ApplicationApi - functional programming interface + * @export + */ +export const ApplicationApiFp = function(configuration?: Configuration) { + const localVarAxiosParamCreator = ApplicationApiAxiosParamCreator(configuration) + return { + /** + * + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async ping(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.ping(options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ApplicationApi.ping']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + } +}; + +/** + * ApplicationApi - factory interface + * @export + */ +export const ApplicationApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { + const localVarFp = ApplicationApiFp(configuration) + return { + /** + * + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + ping(options?: any): AxiosPromise { + return localVarFp.ping(options).then((request) => request(axios, basePath)); + }, + }; +}; + +/** + * ApplicationApi - object-oriented interface + * @export + * @class ApplicationApi + * @extends {BaseAPI} + */ +export class ApplicationApi extends BaseAPI { + /** + * + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ApplicationApi + */ + public ping(options?: RawAxiosRequestConfig) { + return ApplicationApiFp(this.configuration).ping(options).then((request) => request(this.axios, this.basePath)); + } +} + + + +/** + * ClientApi - axios parameter creator + * @export + */ +export const ClientApiAxiosParamCreator = function (configuration?: Configuration) { + return { + /** + * + * @summary Creates a new client + * @param {string} xApiKey + * @param {CreateClientDto} createClientDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + create: async (xApiKey: string, createClientDto: CreateClientDto, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xApiKey' is not null or undefined + assertParamExists('create', 'xApiKey', xApiKey) + // verify required parameter 'createClientDto' is not null or undefined + assertParamExists('create', 'createClientDto', createClientDto) + const localVarPath = `/v1/clients`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication ADMIN_API_KEY required + await setApiKeyToObject(localVarHeaderParameter, "ADMIN_API_KEY", configuration) + + if (xApiKey != null) { + localVarHeaderParameter['x-api-key'] = String(xApiKey); + } + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(createClientDto, localVarRequestOptions, configuration) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + } +}; + +/** + * ClientApi - functional programming interface + * @export + */ +export const ClientApiFp = function(configuration?: Configuration) { + const localVarAxiosParamCreator = ClientApiAxiosParamCreator(configuration) + return { + /** + * + * @summary Creates a new client + * @param {string} xApiKey + * @param {CreateClientDto} createClientDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async create(xApiKey: string, createClientDto: CreateClientDto, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.create(xApiKey, createClientDto, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ClientApi.create']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + } +}; + +/** + * ClientApi - factory interface + * @export + */ +export const ClientApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { + const localVarFp = ClientApiFp(configuration) + return { + /** + * + * @summary Creates a new client + * @param {string} xApiKey + * @param {CreateClientDto} createClientDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + create(xApiKey: string, createClientDto: CreateClientDto, options?: any): AxiosPromise { + return localVarFp.create(xApiKey, createClientDto, options).then((request) => request(axios, basePath)); + }, + }; +}; + +/** + * ClientApi - object-oriented interface + * @export + * @class ClientApi + * @extends {BaseAPI} + */ +export class ClientApi extends BaseAPI { + /** + * + * @summary Creates a new client + * @param {string} xApiKey + * @param {CreateClientDto} createClientDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ClientApi + */ + public create(xApiKey: string, createClientDto: CreateClientDto, options?: RawAxiosRequestConfig) { + return ClientApiFp(this.configuration).create(xApiKey, createClientDto, options).then((request) => request(this.axios, this.basePath)); + } +} + + + +/** + * EncryptionKeyApi - axios parameter creator + * @export + */ +export const EncryptionKeyApiAxiosParamCreator = function (configuration?: Configuration) { + return { + /** + * + * @summary Generates an encryption key pair used to secure end-to-end communication containing sensitive information + * @param {string} xClientId + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + generate: async (xClientId: string, authorization: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('generate', 'xClientId', xClientId) + // verify required parameter 'authorization' is not null or undefined + assertParamExists('generate', 'authorization', authorization) + const localVarPath = `/v1/encryption-keys`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + } +}; + +/** + * EncryptionKeyApi - functional programming interface + * @export + */ +export const EncryptionKeyApiFp = function(configuration?: Configuration) { + const localVarAxiosParamCreator = EncryptionKeyApiAxiosParamCreator(configuration) + return { + /** + * + * @summary Generates an encryption key pair used to secure end-to-end communication containing sensitive information + * @param {string} xClientId + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async generate(xClientId: string, authorization: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.generate(xClientId, authorization, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['EncryptionKeyApi.generate']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + } +}; + +/** + * EncryptionKeyApi - factory interface + * @export + */ +export const EncryptionKeyApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { + const localVarFp = EncryptionKeyApiFp(configuration) + return { + /** + * + * @summary Generates an encryption key pair used to secure end-to-end communication containing sensitive information + * @param {string} xClientId + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + generate(xClientId: string, authorization: string, options?: any): AxiosPromise { + return localVarFp.generate(xClientId, authorization, options).then((request) => request(axios, basePath)); + }, + }; +}; + +/** + * EncryptionKeyApi - object-oriented interface + * @export + * @class EncryptionKeyApi + * @extends {BaseAPI} + */ +export class EncryptionKeyApi extends BaseAPI { + /** + * + * @summary Generates an encryption key pair used to secure end-to-end communication containing sensitive information + * @param {string} xClientId + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof EncryptionKeyApi + */ + public generate(xClientId: string, authorization: string, options?: RawAxiosRequestConfig) { + return EncryptionKeyApiFp(this.configuration).generate(xClientId, authorization, options).then((request) => request(this.axios, this.basePath)); + } +} + + + +/** + * ProviderAccountApi - axios parameter creator + * @export + */ +export const ProviderAccountApiAxiosParamCreator = function (configuration?: Configuration) { + return { + /** + * + * @summary List addresses for a specific account + * @param {string} accountId The ID of the account to retrieve addresses for + * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getAccountAddresses: async (accountId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'accountId' is not null or undefined + assertParamExists('getAccountAddresses', 'accountId', accountId) + // verify required parameter 'authorization' is not null or undefined + assertParamExists('getAccountAddresses', 'authorization', authorization) + const localVarPath = `/v1/provider/accounts/{accountId}/addresses` + .replace(`{${"accountId"}}`, encodeURIComponent(String(accountId))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + if (cursor !== undefined) { + localVarQueryParameter['cursor'] = cursor; + } + + if (limit !== undefined) { + localVarQueryParameter['limit'] = limit; + } + + if (orderBy !== undefined) { + localVarQueryParameter['orderBy'] = orderBy; + } + + if (desc !== undefined) { + localVarQueryParameter['desc'] = desc; + } + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @summary Get a specific account by ID + * @param {string} accountId The ID of the account to retrieve + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getAccountById: async (accountId: string, authorization: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'accountId' is not null or undefined + assertParamExists('getAccountById', 'accountId', accountId) + // verify required parameter 'authorization' is not null or undefined + assertParamExists('getAccountById', 'authorization', authorization) + const localVarPath = `/v1/provider/accounts/{accountId}` + .replace(`{${"accountId"}}`, encodeURIComponent(String(accountId))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @summary List the client accounts + * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + listByClientId: async (authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'authorization' is not null or undefined + assertParamExists('listByClientId', 'authorization', authorization) + const localVarPath = `/v1/provider/accounts`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + if (cursor !== undefined) { + localVarQueryParameter['cursor'] = cursor; + } + + if (limit !== undefined) { + localVarQueryParameter['limit'] = limit; + } + + if (orderBy !== undefined) { + localVarQueryParameter['orderBy'] = orderBy; + } + + if (desc !== undefined) { + localVarQueryParameter['desc'] = desc; + } + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + } +}; + +/** + * ProviderAccountApi - functional programming interface + * @export + */ +export const ProviderAccountApiFp = function(configuration?: Configuration) { + const localVarAxiosParamCreator = ProviderAccountApiAxiosParamCreator(configuration) + return { + /** + * + * @summary List addresses for a specific account + * @param {string} accountId The ID of the account to retrieve addresses for + * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getAccountAddresses(accountId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getAccountAddresses(accountId, authorization, cursor, limit, orderBy, desc, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderAccountApi.getAccountAddresses']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + /** + * + * @summary Get a specific account by ID + * @param {string} accountId The ID of the account to retrieve + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getAccountById(accountId: string, authorization: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getAccountById(accountId, authorization, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderAccountApi.getAccountById']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + /** + * + * @summary List the client accounts + * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async listByClientId(authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.listByClientId(authorization, cursor, limit, orderBy, desc, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderAccountApi.listByClientId']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + } +}; + +/** + * ProviderAccountApi - factory interface + * @export + */ +export const ProviderAccountApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { + const localVarFp = ProviderAccountApiFp(configuration) + return { + /** + * + * @summary List addresses for a specific account + * @param {string} accountId The ID of the account to retrieve addresses for + * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getAccountAddresses(accountId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: any): AxiosPromise { + return localVarFp.getAccountAddresses(accountId, authorization, cursor, limit, orderBy, desc, options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary Get a specific account by ID + * @param {string} accountId The ID of the account to retrieve + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getAccountById(accountId: string, authorization: string, options?: any): AxiosPromise { + return localVarFp.getAccountById(accountId, authorization, options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary List the client accounts + * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + listByClientId(authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: any): AxiosPromise { + return localVarFp.listByClientId(authorization, cursor, limit, orderBy, desc, options).then((request) => request(axios, basePath)); + }, + }; +}; + +/** + * ProviderAccountApi - object-oriented interface + * @export + * @class ProviderAccountApi + * @extends {BaseAPI} + */ +export class ProviderAccountApi extends BaseAPI { + /** + * + * @summary List addresses for a specific account + * @param {string} accountId The ID of the account to retrieve addresses for + * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderAccountApi + */ + public getAccountAddresses(accountId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig) { + return ProviderAccountApiFp(this.configuration).getAccountAddresses(accountId, authorization, cursor, limit, orderBy, desc, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * + * @summary Get a specific account by ID + * @param {string} accountId The ID of the account to retrieve + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderAccountApi + */ + public getAccountById(accountId: string, authorization: string, options?: RawAxiosRequestConfig) { + return ProviderAccountApiFp(this.configuration).getAccountById(accountId, authorization, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * + * @summary List the client accounts + * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderAccountApi + */ + public listByClientId(authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig) { + return ProviderAccountApiFp(this.configuration).listByClientId(authorization, cursor, limit, orderBy, desc, options).then((request) => request(this.axios, this.basePath)); + } +} + + + +/** + * ProviderAddressApi - axios parameter creator + * @export + */ +export const ProviderAddressApiAxiosParamCreator = function (configuration?: Configuration) { + return { + /** + * + * @summary Get a specific address by ID + * @param {string} addressId The ID of the address to retrieve + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getAddressById: async (addressId: string, authorization: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'addressId' is not null or undefined + assertParamExists('getAddressById', 'addressId', addressId) + // verify required parameter 'authorization' is not null or undefined + assertParamExists('getAddressById', 'authorization', authorization) + const localVarPath = `/v1/provider/addresses/{addressId}` + .replace(`{${"addressId"}}`, encodeURIComponent(String(addressId))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @summary List the client addresss + * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + list: async (authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'authorization' is not null or undefined + assertParamExists('list', 'authorization', authorization) + const localVarPath = `/v1/provider/addresses`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + if (cursor !== undefined) { + localVarQueryParameter['cursor'] = cursor; + } + + if (limit !== undefined) { + localVarQueryParameter['limit'] = limit; + } + + if (orderBy !== undefined) { + localVarQueryParameter['orderBy'] = orderBy; + } + + if (desc !== undefined) { + localVarQueryParameter['desc'] = desc; + } + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + } +}; + +/** + * ProviderAddressApi - functional programming interface + * @export + */ +export const ProviderAddressApiFp = function(configuration?: Configuration) { + const localVarAxiosParamCreator = ProviderAddressApiAxiosParamCreator(configuration) + return { + /** + * + * @summary Get a specific address by ID + * @param {string} addressId The ID of the address to retrieve + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getAddressById(addressId: string, authorization: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getAddressById(addressId, authorization, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderAddressApi.getAddressById']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + /** + * + * @summary List the client addresss + * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async list(authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.list(authorization, cursor, limit, orderBy, desc, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderAddressApi.list']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + } +}; + +/** + * ProviderAddressApi - factory interface + * @export + */ +export const ProviderAddressApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { + const localVarFp = ProviderAddressApiFp(configuration) + return { + /** + * + * @summary Get a specific address by ID + * @param {string} addressId The ID of the address to retrieve + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getAddressById(addressId: string, authorization: string, options?: any): AxiosPromise { + return localVarFp.getAddressById(addressId, authorization, options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary List the client addresss + * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + list(authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: any): AxiosPromise { + return localVarFp.list(authorization, cursor, limit, orderBy, desc, options).then((request) => request(axios, basePath)); + }, + }; +}; + +/** + * ProviderAddressApi - object-oriented interface + * @export + * @class ProviderAddressApi + * @extends {BaseAPI} + */ +export class ProviderAddressApi extends BaseAPI { + /** + * + * @summary Get a specific address by ID + * @param {string} addressId The ID of the address to retrieve + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderAddressApi + */ + public getAddressById(addressId: string, authorization: string, options?: RawAxiosRequestConfig) { + return ProviderAddressApiFp(this.configuration).getAddressById(addressId, authorization, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * + * @summary List the client addresss + * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderAddressApi + */ + public list(authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig) { + return ProviderAddressApiFp(this.configuration).list(authorization, cursor, limit, orderBy, desc, options).then((request) => request(this.axios, this.basePath)); + } +} + + + +/** + * ProviderConnectionApi - axios parameter creator + * @export + */ +export const ProviderConnectionApiAxiosParamCreator = function (configuration?: Configuration) { + return { + /** + * This endpoint securely stores the details of a provider connection, ensuring that all sensitive information is encrypted. + * @summary Store a provider connection securely + * @param {string} authorization + * @param {CreateConnectionDto} createConnectionDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + create: async (authorization: string, createConnectionDto: CreateConnectionDto, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'authorization' is not null or undefined + assertParamExists('create', 'authorization', authorization) + // verify required parameter 'createConnectionDto' is not null or undefined + assertParamExists('create', 'createConnectionDto', createConnectionDto) + const localVarPath = `/v1/provider/connections`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(createConnectionDto, localVarRequestOptions, configuration) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * This endpoint retrieves a list of accounts associated with a specific connection. + * @summary List accounts for a specific connection + * @param {string} connectionId + * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getAccounts: async (connectionId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'connectionId' is not null or undefined + assertParamExists('getAccounts', 'connectionId', connectionId) + // verify required parameter 'authorization' is not null or undefined + assertParamExists('getAccounts', 'authorization', authorization) + const localVarPath = `/v1/provider/connections/{connectionId}/accounts` + .replace(`{${"connectionId"}}`, encodeURIComponent(String(connectionId))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + if (cursor !== undefined) { + localVarQueryParameter['cursor'] = cursor; + } + + if (limit !== undefined) { + localVarQueryParameter['limit'] = limit; + } + + if (orderBy !== undefined) { + localVarQueryParameter['orderBy'] = orderBy; + } + + if (desc !== undefined) { + localVarQueryParameter['desc'] = desc; + } + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * This endpoint retrieves the details of a specific connection associated with the client, identified by the ID. + * @summary Retrieve a specific connection by ID + * @param {string} connectionId + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getById: async (connectionId: string, authorization: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'connectionId' is not null or undefined + assertParamExists('getById', 'connectionId', connectionId) + // verify required parameter 'authorization' is not null or undefined + assertParamExists('getById', 'authorization', authorization) + const localVarPath = `/v1/provider/connections/{connectionId}` + .replace(`{${"connectionId"}}`, encodeURIComponent(String(connectionId))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * This endpoint retrieves a list of wallets associated with a specific connection. + * @summary List wallets for a specific connection + * @param {string} connectionId + * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getWallets: async (connectionId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'connectionId' is not null or undefined + assertParamExists('getWallets', 'connectionId', connectionId) + // verify required parameter 'authorization' is not null or undefined + assertParamExists('getWallets', 'authorization', authorization) + const localVarPath = `/v1/provider/connections/{connectionId}/wallets` + .replace(`{${"connectionId"}}`, encodeURIComponent(String(connectionId))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + if (cursor !== undefined) { + localVarQueryParameter['cursor'] = cursor; + } + + if (limit !== undefined) { + localVarQueryParameter['limit'] = limit; + } + + if (orderBy !== undefined) { + localVarQueryParameter['orderBy'] = orderBy; + } + + if (desc !== undefined) { + localVarQueryParameter['desc'] = desc; + } + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * This endpoint initiates a new connection by generating a public key and an encryption key for secure communication. + * @summary Initiate a new provider connection + * @param {string} authorization + * @param {InitiateConnectionDto} initiateConnectionDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + initiate: async (authorization: string, initiateConnectionDto: InitiateConnectionDto, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'authorization' is not null or undefined + assertParamExists('initiate', 'authorization', authorization) + // verify required parameter 'initiateConnectionDto' is not null or undefined + assertParamExists('initiate', 'initiateConnectionDto', initiateConnectionDto) + const localVarPath = `/v1/provider/connections/initiate`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(initiateConnectionDto, localVarRequestOptions, configuration) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * This endpoint retrieves a list of all connections associated with the client. + * @summary List all connections + * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + list: async (authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'authorization' is not null or undefined + assertParamExists('list', 'authorization', authorization) + const localVarPath = `/v1/provider/connections`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + if (cursor !== undefined) { + localVarQueryParameter['cursor'] = cursor; + } + + if (limit !== undefined) { + localVarQueryParameter['limit'] = limit; + } + + if (orderBy !== undefined) { + localVarQueryParameter['orderBy'] = orderBy; + } + + if (desc !== undefined) { + localVarQueryParameter['desc'] = desc; + } + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * This endpoint revokes an existing connection, effectively terminating any ongoing communication and invalidating the connection credentials. + * @summary Revoke an existing connection + * @param {string} connectionId + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + revoke: async (connectionId: string, authorization: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'connectionId' is not null or undefined + assertParamExists('revoke', 'connectionId', connectionId) + // verify required parameter 'authorization' is not null or undefined + assertParamExists('revoke', 'authorization', authorization) + const localVarPath = `/v1/provider/connections/{connectionId}` + .replace(`{${"connectionId"}}`, encodeURIComponent(String(connectionId))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'DELETE', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * This endpoint updates the details of a specific connection associated with the client, identified by the connection ID. + * @summary Update a specific connection by ID + * @param {string} connectionId + * @param {string} authorization + * @param {UpdateConnectionDto} updateConnectionDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + update: async (connectionId: string, authorization: string, updateConnectionDto: UpdateConnectionDto, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'connectionId' is not null or undefined + assertParamExists('update', 'connectionId', connectionId) + // verify required parameter 'authorization' is not null or undefined + assertParamExists('update', 'authorization', authorization) + // verify required parameter 'updateConnectionDto' is not null or undefined + assertParamExists('update', 'updateConnectionDto', updateConnectionDto) + const localVarPath = `/v1/provider/connections/{connectionId}` + .replace(`{${"connectionId"}}`, encodeURIComponent(String(connectionId))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'PATCH', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(updateConnectionDto, localVarRequestOptions, configuration) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + } +}; + +/** + * ProviderConnectionApi - functional programming interface + * @export + */ +export const ProviderConnectionApiFp = function(configuration?: Configuration) { + const localVarAxiosParamCreator = ProviderConnectionApiAxiosParamCreator(configuration) + return { + /** + * This endpoint securely stores the details of a provider connection, ensuring that all sensitive information is encrypted. + * @summary Store a provider connection securely + * @param {string} authorization + * @param {CreateConnectionDto} createConnectionDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async create(authorization: string, createConnectionDto: CreateConnectionDto, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.create(authorization, createConnectionDto, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderConnectionApi.create']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + /** + * This endpoint retrieves a list of accounts associated with a specific connection. + * @summary List accounts for a specific connection + * @param {string} connectionId + * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getAccounts(connectionId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getAccounts(connectionId, authorization, cursor, limit, orderBy, desc, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderConnectionApi.getAccounts']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + /** + * This endpoint retrieves the details of a specific connection associated with the client, identified by the ID. + * @summary Retrieve a specific connection by ID + * @param {string} connectionId + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getById(connectionId: string, authorization: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getById(connectionId, authorization, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderConnectionApi.getById']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + /** + * This endpoint retrieves a list of wallets associated with a specific connection. + * @summary List wallets for a specific connection + * @param {string} connectionId + * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getWallets(connectionId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getWallets(connectionId, authorization, cursor, limit, orderBy, desc, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderConnectionApi.getWallets']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + /** + * This endpoint initiates a new connection by generating a public key and an encryption key for secure communication. + * @summary Initiate a new provider connection + * @param {string} authorization + * @param {InitiateConnectionDto} initiateConnectionDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async initiate(authorization: string, initiateConnectionDto: InitiateConnectionDto, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.initiate(authorization, initiateConnectionDto, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderConnectionApi.initiate']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + /** + * This endpoint retrieves a list of all connections associated with the client. + * @summary List all connections + * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async list(authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.list(authorization, cursor, limit, orderBy, desc, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderConnectionApi.list']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + /** + * This endpoint revokes an existing connection, effectively terminating any ongoing communication and invalidating the connection credentials. + * @summary Revoke an existing connection + * @param {string} connectionId + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async revoke(connectionId: string, authorization: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.revoke(connectionId, authorization, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderConnectionApi.revoke']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + /** + * This endpoint updates the details of a specific connection associated with the client, identified by the connection ID. + * @summary Update a specific connection by ID + * @param {string} connectionId + * @param {string} authorization + * @param {UpdateConnectionDto} updateConnectionDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async update(connectionId: string, authorization: string, updateConnectionDto: UpdateConnectionDto, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.update(connectionId, authorization, updateConnectionDto, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderConnectionApi.update']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + } +}; + +/** + * ProviderConnectionApi - factory interface + * @export + */ +export const ProviderConnectionApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { + const localVarFp = ProviderConnectionApiFp(configuration) + return { + /** + * This endpoint securely stores the details of a provider connection, ensuring that all sensitive information is encrypted. + * @summary Store a provider connection securely + * @param {string} authorization + * @param {CreateConnectionDto} createConnectionDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + create(authorization: string, createConnectionDto: CreateConnectionDto, options?: any): AxiosPromise { + return localVarFp.create(authorization, createConnectionDto, options).then((request) => request(axios, basePath)); + }, + /** + * This endpoint retrieves a list of accounts associated with a specific connection. + * @summary List accounts for a specific connection + * @param {string} connectionId + * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getAccounts(connectionId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: any): AxiosPromise { + return localVarFp.getAccounts(connectionId, authorization, cursor, limit, orderBy, desc, options).then((request) => request(axios, basePath)); + }, + /** + * This endpoint retrieves the details of a specific connection associated with the client, identified by the ID. + * @summary Retrieve a specific connection by ID + * @param {string} connectionId + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getById(connectionId: string, authorization: string, options?: any): AxiosPromise { + return localVarFp.getById(connectionId, authorization, options).then((request) => request(axios, basePath)); + }, + /** + * This endpoint retrieves a list of wallets associated with a specific connection. + * @summary List wallets for a specific connection + * @param {string} connectionId + * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getWallets(connectionId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: any): AxiosPromise { + return localVarFp.getWallets(connectionId, authorization, cursor, limit, orderBy, desc, options).then((request) => request(axios, basePath)); + }, + /** + * This endpoint initiates a new connection by generating a public key and an encryption key for secure communication. + * @summary Initiate a new provider connection + * @param {string} authorization + * @param {InitiateConnectionDto} initiateConnectionDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + initiate(authorization: string, initiateConnectionDto: InitiateConnectionDto, options?: any): AxiosPromise { + return localVarFp.initiate(authorization, initiateConnectionDto, options).then((request) => request(axios, basePath)); + }, + /** + * This endpoint retrieves a list of all connections associated with the client. + * @summary List all connections + * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + list(authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: any): AxiosPromise { + return localVarFp.list(authorization, cursor, limit, orderBy, desc, options).then((request) => request(axios, basePath)); + }, + /** + * This endpoint revokes an existing connection, effectively terminating any ongoing communication and invalidating the connection credentials. + * @summary Revoke an existing connection + * @param {string} connectionId + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + revoke(connectionId: string, authorization: string, options?: any): AxiosPromise { + return localVarFp.revoke(connectionId, authorization, options).then((request) => request(axios, basePath)); + }, + /** + * This endpoint updates the details of a specific connection associated with the client, identified by the connection ID. + * @summary Update a specific connection by ID + * @param {string} connectionId + * @param {string} authorization + * @param {UpdateConnectionDto} updateConnectionDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + update(connectionId: string, authorization: string, updateConnectionDto: UpdateConnectionDto, options?: any): AxiosPromise { + return localVarFp.update(connectionId, authorization, updateConnectionDto, options).then((request) => request(axios, basePath)); + }, + }; +}; + +/** + * ProviderConnectionApi - object-oriented interface + * @export + * @class ProviderConnectionApi + * @extends {BaseAPI} + */ +export class ProviderConnectionApi extends BaseAPI { + /** + * This endpoint securely stores the details of a provider connection, ensuring that all sensitive information is encrypted. + * @summary Store a provider connection securely + * @param {string} authorization + * @param {CreateConnectionDto} createConnectionDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderConnectionApi + */ + public create(authorization: string, createConnectionDto: CreateConnectionDto, options?: RawAxiosRequestConfig) { + return ProviderConnectionApiFp(this.configuration).create(authorization, createConnectionDto, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * This endpoint retrieves a list of accounts associated with a specific connection. + * @summary List accounts for a specific connection + * @param {string} connectionId + * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderConnectionApi + */ + public getAccounts(connectionId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig) { + return ProviderConnectionApiFp(this.configuration).getAccounts(connectionId, authorization, cursor, limit, orderBy, desc, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * This endpoint retrieves the details of a specific connection associated with the client, identified by the ID. + * @summary Retrieve a specific connection by ID + * @param {string} connectionId + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderConnectionApi + */ + public getById(connectionId: string, authorization: string, options?: RawAxiosRequestConfig) { + return ProviderConnectionApiFp(this.configuration).getById(connectionId, authorization, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * This endpoint retrieves a list of wallets associated with a specific connection. + * @summary List wallets for a specific connection + * @param {string} connectionId + * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderConnectionApi + */ + public getWallets(connectionId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig) { + return ProviderConnectionApiFp(this.configuration).getWallets(connectionId, authorization, cursor, limit, orderBy, desc, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * This endpoint initiates a new connection by generating a public key and an encryption key for secure communication. + * @summary Initiate a new provider connection + * @param {string} authorization + * @param {InitiateConnectionDto} initiateConnectionDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderConnectionApi + */ + public initiate(authorization: string, initiateConnectionDto: InitiateConnectionDto, options?: RawAxiosRequestConfig) { + return ProviderConnectionApiFp(this.configuration).initiate(authorization, initiateConnectionDto, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * This endpoint retrieves a list of all connections associated with the client. + * @summary List all connections + * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderConnectionApi + */ + public list(authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig) { + return ProviderConnectionApiFp(this.configuration).list(authorization, cursor, limit, orderBy, desc, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * This endpoint revokes an existing connection, effectively terminating any ongoing communication and invalidating the connection credentials. + * @summary Revoke an existing connection + * @param {string} connectionId + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderConnectionApi + */ + public revoke(connectionId: string, authorization: string, options?: RawAxiosRequestConfig) { + return ProviderConnectionApiFp(this.configuration).revoke(connectionId, authorization, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * This endpoint updates the details of a specific connection associated with the client, identified by the connection ID. + * @summary Update a specific connection by ID + * @param {string} connectionId + * @param {string} authorization + * @param {UpdateConnectionDto} updateConnectionDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderConnectionApi + */ + public update(connectionId: string, authorization: string, updateConnectionDto: UpdateConnectionDto, options?: RawAxiosRequestConfig) { + return ProviderConnectionApiFp(this.configuration).update(connectionId, authorization, updateConnectionDto, options).then((request) => request(this.axios, this.basePath)); + } +} + /** - * AccountApi - axios parameter creator + * ProviderProxyApi - axios parameter creator * @export */ -export const AccountApiAxiosParamCreator = function (configuration?: Configuration) { +export const ProviderProxyApiAxiosParamCreator = function (configuration?: Configuration) { return { /** - * - * @summary Add a new account to a wallet - * @param {string} xClientId + * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. + * @summary Authorizes and forwards the request to the provider + * @param {string} endpoint The raw endpoint path in the provider + * @param {string} xConnectionId The connection ID used to forward request to provider * @param {string} authorization - * @param {DeriveAccountDto} deriveAccountDto * @param {*} [options] Override http request option. * @throws {RequiredError} */ - derive: async (xClientId: string, authorization: string, deriveAccountDto: DeriveAccountDto, options: RawAxiosRequestConfig = {}): Promise => { - // verify required parameter 'xClientId' is not null or undefined - assertParamExists('derive', 'xClientId', xClientId) + _delete: async (endpoint: string, xConnectionId: string, authorization: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'endpoint' is not null or undefined + assertParamExists('_delete', 'endpoint', endpoint) + // verify required parameter 'xConnectionId' is not null or undefined + assertParamExists('_delete', 'xConnectionId', xConnectionId) // verify required parameter 'authorization' is not null or undefined - assertParamExists('derive', 'authorization', authorization) - // verify required parameter 'deriveAccountDto' is not null or undefined - assertParamExists('derive', 'deriveAccountDto', deriveAccountDto) - const localVarPath = `/v1/accounts`; + assertParamExists('_delete', 'authorization', authorization) + const localVarPath = `/v1/provider/proxy/{endpoint}` + .replace(`{${"endpoint"}}`, encodeURIComponent(String(endpoint))); // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); let baseOptions; @@ -1466,14 +4776,14 @@ export const AccountApiAxiosParamCreator = function (configuration?: Configurati baseOptions = configuration.baseOptions; } - const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarRequestOptions = { method: 'DELETE', ...baseOptions, ...options}; const localVarHeaderParameter = {} as any; const localVarQueryParameter = {} as any; // authentication GNAP required - if (xClientId != null) { - localVarHeaderParameter['x-client-id'] = String(xClientId); + if (xConnectionId != null) { + localVarHeaderParameter['x-connection-id'] = String(xConnectionId); } if (authorization != null) { @@ -1482,12 +4792,59 @@ export const AccountApiAxiosParamCreator = function (configuration?: Configurati - localVarHeaderParameter['Content-Type'] = 'application/json'; + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. + * @summary Authorizes and forwards the request to the provider + * @param {string} endpoint The raw endpoint path in the provider + * @param {string} xConnectionId The connection ID used to forward request to provider + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + _options: async (endpoint: string, xConnectionId: string, authorization: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'endpoint' is not null or undefined + assertParamExists('_options', 'endpoint', endpoint) + // verify required parameter 'xConnectionId' is not null or undefined + assertParamExists('_options', 'xConnectionId', xConnectionId) + // verify required parameter 'authorization' is not null or undefined + assertParamExists('_options', 'authorization', authorization) + const localVarPath = `/v1/provider/proxy/{endpoint}` + .replace(`{${"endpoint"}}`, encodeURIComponent(String(endpoint))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'OPTIONS', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + if (xConnectionId != null) { + localVarHeaderParameter['x-connection-id'] = String(xConnectionId); + } + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + + + setSearchParams(localVarUrlObj, localVarQueryParameter); let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - localVarRequestOptions.data = serializeDataIfNeeded(deriveAccountDto, localVarRequestOptions, configuration) return { url: toPathString(localVarUrlObj), @@ -1495,22 +4852,23 @@ export const AccountApiAxiosParamCreator = function (configuration?: Configurati }; }, /** - * - * @summary Imports an account - * @param {string} xClientId + * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. + * @summary Authorizes and forwards the request to the provider + * @param {string} endpoint The raw endpoint path in the provider + * @param {string} xConnectionId The connection ID used to forward request to provider * @param {string} authorization - * @param {ImportPrivateKeyDto} importPrivateKeyDto * @param {*} [options] Override http request option. * @throws {RequiredError} */ - importPrivateKey: async (xClientId: string, authorization: string, importPrivateKeyDto: ImportPrivateKeyDto, options: RawAxiosRequestConfig = {}): Promise => { - // verify required parameter 'xClientId' is not null or undefined - assertParamExists('importPrivateKey', 'xClientId', xClientId) + get: async (endpoint: string, xConnectionId: string, authorization: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'endpoint' is not null or undefined + assertParamExists('get', 'endpoint', endpoint) + // verify required parameter 'xConnectionId' is not null or undefined + assertParamExists('get', 'xConnectionId', xConnectionId) // verify required parameter 'authorization' is not null or undefined - assertParamExists('importPrivateKey', 'authorization', authorization) - // verify required parameter 'importPrivateKeyDto' is not null or undefined - assertParamExists('importPrivateKey', 'importPrivateKeyDto', importPrivateKeyDto) - const localVarPath = `/v1/accounts/import`; + assertParamExists('get', 'authorization', authorization) + const localVarPath = `/v1/provider/proxy/{endpoint}` + .replace(`{${"endpoint"}}`, encodeURIComponent(String(endpoint))); // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); let baseOptions; @@ -1518,14 +4876,14 @@ export const AccountApiAxiosParamCreator = function (configuration?: Configurati baseOptions = configuration.baseOptions; } - const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; const localVarHeaderParameter = {} as any; const localVarQueryParameter = {} as any; // authentication GNAP required - if (xClientId != null) { - localVarHeaderParameter['x-client-id'] = String(xClientId); + if (xConnectionId != null) { + localVarHeaderParameter['x-connection-id'] = String(xConnectionId); } if (authorization != null) { @@ -1534,12 +4892,59 @@ export const AccountApiAxiosParamCreator = function (configuration?: Configurati - localVarHeaderParameter['Content-Type'] = 'application/json'; + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. + * @summary Authorizes and forwards the request to the provider + * @param {string} endpoint The raw endpoint path in the provider + * @param {string} xConnectionId The connection ID used to forward request to provider + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + head: async (endpoint: string, xConnectionId: string, authorization: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'endpoint' is not null or undefined + assertParamExists('head', 'endpoint', endpoint) + // verify required parameter 'xConnectionId' is not null or undefined + assertParamExists('head', 'xConnectionId', xConnectionId) + // verify required parameter 'authorization' is not null or undefined + assertParamExists('head', 'authorization', authorization) + const localVarPath = `/v1/provider/proxy/{endpoint}` + .replace(`{${"endpoint"}}`, encodeURIComponent(String(endpoint))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'HEAD', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + if (xConnectionId != null) { + localVarHeaderParameter['x-connection-id'] = String(xConnectionId); + } + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + + setSearchParams(localVarUrlObj, localVarQueryParameter); let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - localVarRequestOptions.data = serializeDataIfNeeded(importPrivateKeyDto, localVarRequestOptions, configuration) return { url: toPathString(localVarUrlObj), @@ -1547,19 +4952,23 @@ export const AccountApiAxiosParamCreator = function (configuration?: Configurati }; }, /** - * - * @summary Lists the client accounts - * @param {string} xClientId + * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. + * @summary Authorizes and forwards the request to the provider + * @param {string} endpoint The raw endpoint path in the provider + * @param {string} xConnectionId The connection ID used to forward request to provider * @param {string} authorization * @param {*} [options] Override http request option. * @throws {RequiredError} */ - list: async (xClientId: string, authorization: string, options: RawAxiosRequestConfig = {}): Promise => { - // verify required parameter 'xClientId' is not null or undefined - assertParamExists('list', 'xClientId', xClientId) + patch: async (endpoint: string, xConnectionId: string, authorization: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'endpoint' is not null or undefined + assertParamExists('patch', 'endpoint', endpoint) + // verify required parameter 'xConnectionId' is not null or undefined + assertParamExists('patch', 'xConnectionId', xConnectionId) // verify required parameter 'authorization' is not null or undefined - assertParamExists('list', 'authorization', authorization) - const localVarPath = `/v1/accounts`; + assertParamExists('patch', 'authorization', authorization) + const localVarPath = `/v1/provider/proxy/{endpoint}` + .replace(`{${"endpoint"}}`, encodeURIComponent(String(endpoint))); // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); let baseOptions; @@ -1567,14 +4976,114 @@ export const AccountApiAxiosParamCreator = function (configuration?: Configurati baseOptions = configuration.baseOptions; } - const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarRequestOptions = { method: 'PATCH', ...baseOptions, ...options}; const localVarHeaderParameter = {} as any; const localVarQueryParameter = {} as any; // authentication GNAP required - if (xClientId != null) { - localVarHeaderParameter['x-client-id'] = String(xClientId); + if (xConnectionId != null) { + localVarHeaderParameter['x-connection-id'] = String(xConnectionId); + } + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. + * @summary Authorizes and forwards the request to the provider + * @param {string} endpoint The raw endpoint path in the provider + * @param {string} xConnectionId The connection ID used to forward request to provider + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + post: async (endpoint: string, xConnectionId: string, authorization: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'endpoint' is not null or undefined + assertParamExists('post', 'endpoint', endpoint) + // verify required parameter 'xConnectionId' is not null or undefined + assertParamExists('post', 'xConnectionId', xConnectionId) + // verify required parameter 'authorization' is not null or undefined + assertParamExists('post', 'authorization', authorization) + const localVarPath = `/v1/provider/proxy/{endpoint}` + .replace(`{${"endpoint"}}`, encodeURIComponent(String(endpoint))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + if (xConnectionId != null) { + localVarHeaderParameter['x-connection-id'] = String(xConnectionId); + } + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. + * @summary Authorizes and forwards the request to the provider + * @param {string} endpoint The raw endpoint path in the provider + * @param {string} xConnectionId The connection ID used to forward request to provider + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + put: async (endpoint: string, xConnectionId: string, authorization: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'endpoint' is not null or undefined + assertParamExists('put', 'endpoint', endpoint) + // verify required parameter 'xConnectionId' is not null or undefined + assertParamExists('put', 'xConnectionId', xConnectionId) + // verify required parameter 'authorization' is not null or undefined + assertParamExists('put', 'authorization', authorization) + const localVarPath = `/v1/provider/proxy/{endpoint}` + .replace(`{${"endpoint"}}`, encodeURIComponent(String(endpoint))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'PUT', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + if (xConnectionId != null) { + localVarHeaderParameter['x-connection-id'] = String(xConnectionId); } if (authorization != null) { @@ -1592,172 +5101,350 @@ export const AccountApiAxiosParamCreator = function (configuration?: Configurati options: localVarRequestOptions, }; }, - } -}; - -/** - * AccountApi - functional programming interface - * @export - */ -export const AccountApiFp = function(configuration?: Configuration) { - const localVarAxiosParamCreator = AccountApiAxiosParamCreator(configuration) - return { + } +}; + +/** + * ProviderProxyApi - functional programming interface + * @export + */ +export const ProviderProxyApiFp = function(configuration?: Configuration) { + const localVarAxiosParamCreator = ProviderProxyApiAxiosParamCreator(configuration) + return { + /** + * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. + * @summary Authorizes and forwards the request to the provider + * @param {string} endpoint The raw endpoint path in the provider + * @param {string} xConnectionId The connection ID used to forward request to provider + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async _delete(endpoint: string, xConnectionId: string, authorization: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator._delete(endpoint, xConnectionId, authorization, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderProxyApi._delete']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + /** + * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. + * @summary Authorizes and forwards the request to the provider + * @param {string} endpoint The raw endpoint path in the provider + * @param {string} xConnectionId The connection ID used to forward request to provider + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async _options(endpoint: string, xConnectionId: string, authorization: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator._options(endpoint, xConnectionId, authorization, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderProxyApi._options']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + /** + * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. + * @summary Authorizes and forwards the request to the provider + * @param {string} endpoint The raw endpoint path in the provider + * @param {string} xConnectionId The connection ID used to forward request to provider + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async get(endpoint: string, xConnectionId: string, authorization: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.get(endpoint, xConnectionId, authorization, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderProxyApi.get']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, /** - * - * @summary Add a new account to a wallet - * @param {string} xClientId + * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. + * @summary Authorizes and forwards the request to the provider + * @param {string} endpoint The raw endpoint path in the provider + * @param {string} xConnectionId The connection ID used to forward request to provider * @param {string} authorization - * @param {DeriveAccountDto} deriveAccountDto * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async derive(xClientId: string, authorization: string, deriveAccountDto: DeriveAccountDto, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.derive(xClientId, authorization, deriveAccountDto, options); + async head(endpoint: string, xConnectionId: string, authorization: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.head(endpoint, xConnectionId, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = operationServerMap['AccountApi.derive']?.[localVarOperationServerIndex]?.url; + const localVarOperationServerBasePath = operationServerMap['ProviderProxyApi.head']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** - * - * @summary Imports an account - * @param {string} xClientId + * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. + * @summary Authorizes and forwards the request to the provider + * @param {string} endpoint The raw endpoint path in the provider + * @param {string} xConnectionId The connection ID used to forward request to provider * @param {string} authorization - * @param {ImportPrivateKeyDto} importPrivateKeyDto * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async importPrivateKey(xClientId: string, authorization: string, importPrivateKeyDto: ImportPrivateKeyDto, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.importPrivateKey(xClientId, authorization, importPrivateKeyDto, options); + async patch(endpoint: string, xConnectionId: string, authorization: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.patch(endpoint, xConnectionId, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = operationServerMap['AccountApi.importPrivateKey']?.[localVarOperationServerIndex]?.url; + const localVarOperationServerBasePath = operationServerMap['ProviderProxyApi.patch']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** - * - * @summary Lists the client accounts - * @param {string} xClientId + * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. + * @summary Authorizes and forwards the request to the provider + * @param {string} endpoint The raw endpoint path in the provider + * @param {string} xConnectionId The connection ID used to forward request to provider * @param {string} authorization * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async list(xClientId: string, authorization: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.list(xClientId, authorization, options); + async post(endpoint: string, xConnectionId: string, authorization: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.post(endpoint, xConnectionId, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = operationServerMap['AccountApi.list']?.[localVarOperationServerIndex]?.url; + const localVarOperationServerBasePath = operationServerMap['ProviderProxyApi.post']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + /** + * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. + * @summary Authorizes and forwards the request to the provider + * @param {string} endpoint The raw endpoint path in the provider + * @param {string} xConnectionId The connection ID used to forward request to provider + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async put(endpoint: string, xConnectionId: string, authorization: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.put(endpoint, xConnectionId, authorization, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderProxyApi.put']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, } }; /** - * AccountApi - factory interface + * ProviderProxyApi - factory interface * @export */ -export const AccountApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { - const localVarFp = AccountApiFp(configuration) +export const ProviderProxyApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { + const localVarFp = ProviderProxyApiFp(configuration) return { /** - * - * @summary Add a new account to a wallet - * @param {string} xClientId + * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. + * @summary Authorizes and forwards the request to the provider + * @param {string} endpoint The raw endpoint path in the provider + * @param {string} xConnectionId The connection ID used to forward request to provider * @param {string} authorization - * @param {DeriveAccountDto} deriveAccountDto * @param {*} [options] Override http request option. * @throws {RequiredError} */ - derive(xClientId: string, authorization: string, deriveAccountDto: DeriveAccountDto, options?: any): AxiosPromise { - return localVarFp.derive(xClientId, authorization, deriveAccountDto, options).then((request) => request(axios, basePath)); + _delete(endpoint: string, xConnectionId: string, authorization: string, options?: any): AxiosPromise { + return localVarFp._delete(endpoint, xConnectionId, authorization, options).then((request) => request(axios, basePath)); }, /** - * - * @summary Imports an account - * @param {string} xClientId + * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. + * @summary Authorizes and forwards the request to the provider + * @param {string} endpoint The raw endpoint path in the provider + * @param {string} xConnectionId The connection ID used to forward request to provider * @param {string} authorization - * @param {ImportPrivateKeyDto} importPrivateKeyDto * @param {*} [options] Override http request option. * @throws {RequiredError} */ - importPrivateKey(xClientId: string, authorization: string, importPrivateKeyDto: ImportPrivateKeyDto, options?: any): AxiosPromise { - return localVarFp.importPrivateKey(xClientId, authorization, importPrivateKeyDto, options).then((request) => request(axios, basePath)); + _options(endpoint: string, xConnectionId: string, authorization: string, options?: any): AxiosPromise { + return localVarFp._options(endpoint, xConnectionId, authorization, options).then((request) => request(axios, basePath)); }, /** - * - * @summary Lists the client accounts - * @param {string} xClientId + * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. + * @summary Authorizes and forwards the request to the provider + * @param {string} endpoint The raw endpoint path in the provider + * @param {string} xConnectionId The connection ID used to forward request to provider * @param {string} authorization * @param {*} [options] Override http request option. * @throws {RequiredError} */ - list(xClientId: string, authorization: string, options?: any): AxiosPromise { - return localVarFp.list(xClientId, authorization, options).then((request) => request(axios, basePath)); + get(endpoint: string, xConnectionId: string, authorization: string, options?: any): AxiosPromise { + return localVarFp.get(endpoint, xConnectionId, authorization, options).then((request) => request(axios, basePath)); + }, + /** + * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. + * @summary Authorizes and forwards the request to the provider + * @param {string} endpoint The raw endpoint path in the provider + * @param {string} xConnectionId The connection ID used to forward request to provider + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + head(endpoint: string, xConnectionId: string, authorization: string, options?: any): AxiosPromise { + return localVarFp.head(endpoint, xConnectionId, authorization, options).then((request) => request(axios, basePath)); + }, + /** + * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. + * @summary Authorizes and forwards the request to the provider + * @param {string} endpoint The raw endpoint path in the provider + * @param {string} xConnectionId The connection ID used to forward request to provider + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + patch(endpoint: string, xConnectionId: string, authorization: string, options?: any): AxiosPromise { + return localVarFp.patch(endpoint, xConnectionId, authorization, options).then((request) => request(axios, basePath)); + }, + /** + * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. + * @summary Authorizes and forwards the request to the provider + * @param {string} endpoint The raw endpoint path in the provider + * @param {string} xConnectionId The connection ID used to forward request to provider + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + post(endpoint: string, xConnectionId: string, authorization: string, options?: any): AxiosPromise { + return localVarFp.post(endpoint, xConnectionId, authorization, options).then((request) => request(axios, basePath)); + }, + /** + * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. + * @summary Authorizes and forwards the request to the provider + * @param {string} endpoint The raw endpoint path in the provider + * @param {string} xConnectionId The connection ID used to forward request to provider + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + put(endpoint: string, xConnectionId: string, authorization: string, options?: any): AxiosPromise { + return localVarFp.put(endpoint, xConnectionId, authorization, options).then((request) => request(axios, basePath)); }, }; }; /** - * AccountApi - object-oriented interface + * ProviderProxyApi - object-oriented interface * @export - * @class AccountApi + * @class ProviderProxyApi * @extends {BaseAPI} */ -export class AccountApi extends BaseAPI { +export class ProviderProxyApi extends BaseAPI { /** - * - * @summary Add a new account to a wallet - * @param {string} xClientId + * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. + * @summary Authorizes and forwards the request to the provider + * @param {string} endpoint The raw endpoint path in the provider + * @param {string} xConnectionId The connection ID used to forward request to provider * @param {string} authorization - * @param {DeriveAccountDto} deriveAccountDto * @param {*} [options] Override http request option. * @throws {RequiredError} - * @memberof AccountApi + * @memberof ProviderProxyApi */ - public derive(xClientId: string, authorization: string, deriveAccountDto: DeriveAccountDto, options?: RawAxiosRequestConfig) { - return AccountApiFp(this.configuration).derive(xClientId, authorization, deriveAccountDto, options).then((request) => request(this.axios, this.basePath)); + public _delete(endpoint: string, xConnectionId: string, authorization: string, options?: RawAxiosRequestConfig) { + return ProviderProxyApiFp(this.configuration)._delete(endpoint, xConnectionId, authorization, options).then((request) => request(this.axios, this.basePath)); } /** - * - * @summary Imports an account - * @param {string} xClientId + * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. + * @summary Authorizes and forwards the request to the provider + * @param {string} endpoint The raw endpoint path in the provider + * @param {string} xConnectionId The connection ID used to forward request to provider * @param {string} authorization - * @param {ImportPrivateKeyDto} importPrivateKeyDto * @param {*} [options] Override http request option. * @throws {RequiredError} - * @memberof AccountApi + * @memberof ProviderProxyApi */ - public importPrivateKey(xClientId: string, authorization: string, importPrivateKeyDto: ImportPrivateKeyDto, options?: RawAxiosRequestConfig) { - return AccountApiFp(this.configuration).importPrivateKey(xClientId, authorization, importPrivateKeyDto, options).then((request) => request(this.axios, this.basePath)); + public _options(endpoint: string, xConnectionId: string, authorization: string, options?: RawAxiosRequestConfig) { + return ProviderProxyApiFp(this.configuration)._options(endpoint, xConnectionId, authorization, options).then((request) => request(this.axios, this.basePath)); } /** - * - * @summary Lists the client accounts - * @param {string} xClientId + * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. + * @summary Authorizes and forwards the request to the provider + * @param {string} endpoint The raw endpoint path in the provider + * @param {string} xConnectionId The connection ID used to forward request to provider * @param {string} authorization * @param {*} [options] Override http request option. * @throws {RequiredError} - * @memberof AccountApi + * @memberof ProviderProxyApi */ - public list(xClientId: string, authorization: string, options?: RawAxiosRequestConfig) { - return AccountApiFp(this.configuration).list(xClientId, authorization, options).then((request) => request(this.axios, this.basePath)); + public get(endpoint: string, xConnectionId: string, authorization: string, options?: RawAxiosRequestConfig) { + return ProviderProxyApiFp(this.configuration).get(endpoint, xConnectionId, authorization, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. + * @summary Authorizes and forwards the request to the provider + * @param {string} endpoint The raw endpoint path in the provider + * @param {string} xConnectionId The connection ID used to forward request to provider + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderProxyApi + */ + public head(endpoint: string, xConnectionId: string, authorization: string, options?: RawAxiosRequestConfig) { + return ProviderProxyApiFp(this.configuration).head(endpoint, xConnectionId, authorization, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. + * @summary Authorizes and forwards the request to the provider + * @param {string} endpoint The raw endpoint path in the provider + * @param {string} xConnectionId The connection ID used to forward request to provider + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderProxyApi + */ + public patch(endpoint: string, xConnectionId: string, authorization: string, options?: RawAxiosRequestConfig) { + return ProviderProxyApiFp(this.configuration).patch(endpoint, xConnectionId, authorization, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. + * @summary Authorizes and forwards the request to the provider + * @param {string} endpoint The raw endpoint path in the provider + * @param {string} xConnectionId The connection ID used to forward request to provider + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderProxyApi + */ + public post(endpoint: string, xConnectionId: string, authorization: string, options?: RawAxiosRequestConfig) { + return ProviderProxyApiFp(this.configuration).post(endpoint, xConnectionId, authorization, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. + * @summary Authorizes and forwards the request to the provider + * @param {string} endpoint The raw endpoint path in the provider + * @param {string} xConnectionId The connection ID used to forward request to provider + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderProxyApi + */ + public put(endpoint: string, xConnectionId: string, authorization: string, options?: RawAxiosRequestConfig) { + return ProviderProxyApiFp(this.configuration).put(endpoint, xConnectionId, authorization, options).then((request) => request(this.axios, this.basePath)); } } /** - * ApplicationApi - axios parameter creator + * ProviderSyncApi - axios parameter creator * @export */ -export const ApplicationApiAxiosParamCreator = function (configuration?: Configuration) { +export const ProviderSyncApiAxiosParamCreator = function (configuration?: Configuration) { return { /** - * + * This endpoint retrieves a list of synchronization processes associated with the client. Optionally, it can filter the processes by a specific connection ID. + * @summary Retrieve a list of synchronization processes + * @param {string} connectionId + * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order * @param {*} [options] Override http request option. * @throws {RequiredError} */ - ping: async (options: RawAxiosRequestConfig = {}): Promise => { - const localVarPath = `/ping`; + findAll: async (connectionId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'connectionId' is not null or undefined + assertParamExists('findAll', 'connectionId', connectionId) + // verify required parameter 'authorization' is not null or undefined + assertParamExists('findAll', 'authorization', authorization) + const localVarPath = `/v1/provider/syncs`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); let baseOptions; @@ -1769,6 +5456,32 @@ export const ApplicationApiAxiosParamCreator = function (configuration?: Configu const localVarHeaderParameter = {} as any; const localVarQueryParameter = {} as any; + // authentication GNAP required + + if (connectionId !== undefined) { + localVarQueryParameter['connectionId'] = connectionId; + } + + if (cursor !== undefined) { + localVarQueryParameter['cursor'] = cursor; + } + + if (limit !== undefined) { + localVarQueryParameter['limit'] = limit; + } + + if (orderBy !== undefined) { + localVarQueryParameter['orderBy'] = orderBy; + } + + if (desc !== undefined) { + localVarQueryParameter['desc'] = desc; + } + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + setSearchParams(localVarUrlObj, localVarQueryParameter); @@ -1780,88 +5493,63 @@ export const ApplicationApiAxiosParamCreator = function (configuration?: Configu options: localVarRequestOptions, }; }, - } -}; - -/** - * ApplicationApi - functional programming interface - * @export - */ -export const ApplicationApiFp = function(configuration?: Configuration) { - const localVarAxiosParamCreator = ApplicationApiAxiosParamCreator(configuration) - return { /** - * + * This endpoint retrieves the details of a specific synchronization process associated with the client, identified by the sync ID. + * @summary Retrieve a specific synchronization process by ID + * @param {string} syncId + * @param {string} authorization * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async ping(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.ping(options); - const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = operationServerMap['ApplicationApi.ping']?.[localVarOperationServerIndex]?.url; - return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); - }, - } -}; + findById: async (syncId: string, authorization: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'syncId' is not null or undefined + assertParamExists('findById', 'syncId', syncId) + // verify required parameter 'authorization' is not null or undefined + assertParamExists('findById', 'authorization', authorization) + const localVarPath = `/v1/provider/syncs/{syncId}` + .replace(`{${"syncId"}}`, encodeURIComponent(String(syncId))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } -/** - * ApplicationApi - factory interface - * @export - */ -export const ApplicationApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { - const localVarFp = ApplicationApiFp(configuration) - return { - /** - * - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - ping(options?: any): AxiosPromise { - return localVarFp.ping(options).then((request) => request(axios, basePath)); - }, - }; -}; + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; -/** - * ApplicationApi - object-oriented interface - * @export - * @class ApplicationApi - * @extends {BaseAPI} - */ -export class ApplicationApi extends BaseAPI { - /** - * - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof ApplicationApi - */ - public ping(options?: RawAxiosRequestConfig) { - return ApplicationApiFp(this.configuration).ping(options).then((request) => request(this.axios, this.basePath)); - } -} + // authentication GNAP required + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } -/** - * ClientApi - axios parameter creator - * @export - */ -export const ClientApiAxiosParamCreator = function (configuration?: Configuration) { - return { + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, /** - * - * @summary Creates a new client - * @param {string} xApiKey - * @param {CreateClientDto} createClientDto + * This endpoint starts synchronization process for the client. + * @summary Start a synchronization process + * @param {string} authorization + * @param {StartSyncDto} startSyncDto * @param {*} [options] Override http request option. * @throws {RequiredError} - */ - create: async (xApiKey: string, createClientDto: CreateClientDto, options: RawAxiosRequestConfig = {}): Promise => { - // verify required parameter 'xApiKey' is not null or undefined - assertParamExists('create', 'xApiKey', xApiKey) - // verify required parameter 'createClientDto' is not null or undefined - assertParamExists('create', 'createClientDto', createClientDto) - const localVarPath = `/v1/clients`; + */ + start: async (authorization: string, startSyncDto: StartSyncDto, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'authorization' is not null or undefined + assertParamExists('start', 'authorization', authorization) + // verify required parameter 'startSyncDto' is not null or undefined + assertParamExists('start', 'startSyncDto', startSyncDto) + const localVarPath = `/v1/provider/syncs`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); let baseOptions; @@ -1873,11 +5561,10 @@ export const ClientApiAxiosParamCreator = function (configuration?: Configuratio const localVarHeaderParameter = {} as any; const localVarQueryParameter = {} as any; - // authentication ADMIN_API_KEY required - await setApiKeyToObject(localVarHeaderParameter, "ADMIN_API_KEY", configuration) + // authentication GNAP required - if (xApiKey != null) { - localVarHeaderParameter['x-api-key'] = String(xApiKey); + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); } @@ -1887,7 +5574,7 @@ export const ClientApiAxiosParamCreator = function (configuration?: Configuratio setSearchParams(localVarUrlObj, localVarQueryParameter); let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - localVarRequestOptions.data = serializeDataIfNeeded(createClientDto, localVarRequestOptions, configuration) + localVarRequestOptions.data = serializeDataIfNeeded(startSyncDto, localVarRequestOptions, configuration) return { url: toPathString(localVarUrlObj), @@ -1898,93 +5585,186 @@ export const ClientApiAxiosParamCreator = function (configuration?: Configuratio }; /** - * ClientApi - functional programming interface + * ProviderSyncApi - functional programming interface * @export */ -export const ClientApiFp = function(configuration?: Configuration) { - const localVarAxiosParamCreator = ClientApiAxiosParamCreator(configuration) +export const ProviderSyncApiFp = function(configuration?: Configuration) { + const localVarAxiosParamCreator = ProviderSyncApiAxiosParamCreator(configuration) return { /** - * - * @summary Creates a new client - * @param {string} xApiKey - * @param {CreateClientDto} createClientDto + * This endpoint retrieves a list of synchronization processes associated with the client. Optionally, it can filter the processes by a specific connection ID. + * @summary Retrieve a list of synchronization processes + * @param {string} connectionId + * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async create(xApiKey: string, createClientDto: CreateClientDto, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.create(xApiKey, createClientDto, options); + async findAll(connectionId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.findAll(connectionId, authorization, cursor, limit, orderBy, desc, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = operationServerMap['ClientApi.create']?.[localVarOperationServerIndex]?.url; + const localVarOperationServerBasePath = operationServerMap['ProviderSyncApi.findAll']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + /** + * This endpoint retrieves the details of a specific synchronization process associated with the client, identified by the sync ID. + * @summary Retrieve a specific synchronization process by ID + * @param {string} syncId + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async findById(syncId: string, authorization: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.findById(syncId, authorization, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderSyncApi.findById']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + /** + * This endpoint starts synchronization process for the client. + * @summary Start a synchronization process + * @param {string} authorization + * @param {StartSyncDto} startSyncDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async start(authorization: string, startSyncDto: StartSyncDto, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.start(authorization, startSyncDto, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderSyncApi.start']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, } }; /** - * ClientApi - factory interface + * ProviderSyncApi - factory interface * @export */ -export const ClientApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { - const localVarFp = ClientApiFp(configuration) +export const ProviderSyncApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { + const localVarFp = ProviderSyncApiFp(configuration) return { /** - * - * @summary Creates a new client - * @param {string} xApiKey - * @param {CreateClientDto} createClientDto + * This endpoint retrieves a list of synchronization processes associated with the client. Optionally, it can filter the processes by a specific connection ID. + * @summary Retrieve a list of synchronization processes + * @param {string} connectionId + * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order * @param {*} [options] Override http request option. * @throws {RequiredError} */ - create(xApiKey: string, createClientDto: CreateClientDto, options?: any): AxiosPromise { - return localVarFp.create(xApiKey, createClientDto, options).then((request) => request(axios, basePath)); + findAll(connectionId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: any): AxiosPromise { + return localVarFp.findAll(connectionId, authorization, cursor, limit, orderBy, desc, options).then((request) => request(axios, basePath)); + }, + /** + * This endpoint retrieves the details of a specific synchronization process associated with the client, identified by the sync ID. + * @summary Retrieve a specific synchronization process by ID + * @param {string} syncId + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + findById(syncId: string, authorization: string, options?: any): AxiosPromise { + return localVarFp.findById(syncId, authorization, options).then((request) => request(axios, basePath)); + }, + /** + * This endpoint starts synchronization process for the client. + * @summary Start a synchronization process + * @param {string} authorization + * @param {StartSyncDto} startSyncDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + start(authorization: string, startSyncDto: StartSyncDto, options?: any): AxiosPromise { + return localVarFp.start(authorization, startSyncDto, options).then((request) => request(axios, basePath)); }, }; }; /** - * ClientApi - object-oriented interface + * ProviderSyncApi - object-oriented interface * @export - * @class ClientApi + * @class ProviderSyncApi * @extends {BaseAPI} */ -export class ClientApi extends BaseAPI { +export class ProviderSyncApi extends BaseAPI { /** - * - * @summary Creates a new client - * @param {string} xApiKey - * @param {CreateClientDto} createClientDto + * This endpoint retrieves a list of synchronization processes associated with the client. Optionally, it can filter the processes by a specific connection ID. + * @summary Retrieve a list of synchronization processes + * @param {string} connectionId + * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order * @param {*} [options] Override http request option. * @throws {RequiredError} - * @memberof ClientApi + * @memberof ProviderSyncApi */ - public create(xApiKey: string, createClientDto: CreateClientDto, options?: RawAxiosRequestConfig) { - return ClientApiFp(this.configuration).create(xApiKey, createClientDto, options).then((request) => request(this.axios, this.basePath)); + public findAll(connectionId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig) { + return ProviderSyncApiFp(this.configuration).findAll(connectionId, authorization, cursor, limit, orderBy, desc, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * This endpoint retrieves the details of a specific synchronization process associated with the client, identified by the sync ID. + * @summary Retrieve a specific synchronization process by ID + * @param {string} syncId + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderSyncApi + */ + public findById(syncId: string, authorization: string, options?: RawAxiosRequestConfig) { + return ProviderSyncApiFp(this.configuration).findById(syncId, authorization, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * This endpoint starts synchronization process for the client. + * @summary Start a synchronization process + * @param {string} authorization + * @param {StartSyncDto} startSyncDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderSyncApi + */ + public start(authorization: string, startSyncDto: StartSyncDto, options?: RawAxiosRequestConfig) { + return ProviderSyncApiFp(this.configuration).start(authorization, startSyncDto, options).then((request) => request(this.axios, this.basePath)); } } /** - * EncryptionKeyApi - axios parameter creator + * ProviderWalletApi - axios parameter creator * @export */ -export const EncryptionKeyApiAxiosParamCreator = function (configuration?: Configuration) { +export const ProviderWalletApiAxiosParamCreator = function (configuration?: Configuration) { return { /** * - * @summary Generates an encryption key pair used to secure end-to-end communication containing sensitive information - * @param {string} xClientId + * @summary List accounts for a specific wallet + * @param {string} walletId The ID of the wallet to retrieve accounts for * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order * @param {*} [options] Override http request option. * @throws {RequiredError} */ - generate: async (xClientId: string, authorization: string, options: RawAxiosRequestConfig = {}): Promise => { - // verify required parameter 'xClientId' is not null or undefined - assertParamExists('generate', 'xClientId', xClientId) + getWalletAccounts: async (walletId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'walletId' is not null or undefined + assertParamExists('getWalletAccounts', 'walletId', walletId) // verify required parameter 'authorization' is not null or undefined - assertParamExists('generate', 'authorization', authorization) - const localVarPath = `/v1/encryption-keys`; + assertParamExists('getWalletAccounts', 'authorization', authorization) + const localVarPath = `/v1/provider/wallets/{walletId}/accounts` + .replace(`{${"walletId"}}`, encodeURIComponent(String(walletId))); // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); let baseOptions; @@ -1992,14 +5772,128 @@ export const EncryptionKeyApiAxiosParamCreator = function (configuration?: Confi baseOptions = configuration.baseOptions; } - const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; const localVarHeaderParameter = {} as any; const localVarQueryParameter = {} as any; // authentication GNAP required - if (xClientId != null) { - localVarHeaderParameter['x-client-id'] = String(xClientId); + if (cursor !== undefined) { + localVarQueryParameter['cursor'] = cursor; + } + + if (limit !== undefined) { + localVarQueryParameter['limit'] = limit; + } + + if (orderBy !== undefined) { + localVarQueryParameter['orderBy'] = orderBy; + } + + if (desc !== undefined) { + localVarQueryParameter['desc'] = desc; + } + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @summary Get a specific wallet by ID + * @param {string} walletId The ID of the wallet to retrieve + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getWalletById: async (walletId: string, authorization: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'walletId' is not null or undefined + assertParamExists('getWalletById', 'walletId', walletId) + // verify required parameter 'authorization' is not null or undefined + assertParamExists('getWalletById', 'authorization', authorization) + const localVarPath = `/v1/provider/wallets/{walletId}` + .replace(`{${"walletId"}}`, encodeURIComponent(String(walletId))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @summary List the client wallets + * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + listByClientId: async (authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'authorization' is not null or undefined + assertParamExists('listByClientId', 'authorization', authorization) + const localVarPath = `/v1/provider/wallets`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + if (cursor !== undefined) { + localVarQueryParameter['cursor'] = cursor; + } + + if (limit !== undefined) { + localVarQueryParameter['limit'] = limit; + } + + if (orderBy !== undefined) { + localVarQueryParameter['orderBy'] = orderBy; + } + + if (desc !== undefined) { + localVarQueryParameter['desc'] = desc; } if (authorization != null) { @@ -2021,68 +5915,165 @@ export const EncryptionKeyApiAxiosParamCreator = function (configuration?: Confi }; /** - * EncryptionKeyApi - functional programming interface + * ProviderWalletApi - functional programming interface * @export */ -export const EncryptionKeyApiFp = function(configuration?: Configuration) { - const localVarAxiosParamCreator = EncryptionKeyApiAxiosParamCreator(configuration) +export const ProviderWalletApiFp = function(configuration?: Configuration) { + const localVarAxiosParamCreator = ProviderWalletApiAxiosParamCreator(configuration) return { /** * - * @summary Generates an encryption key pair used to secure end-to-end communication containing sensitive information - * @param {string} xClientId + * @summary List accounts for a specific wallet + * @param {string} walletId The ID of the wallet to retrieve accounts for * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async generate(xClientId: string, authorization: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.generate(xClientId, authorization, options); + async getWalletAccounts(walletId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getWalletAccounts(walletId, authorization, cursor, limit, orderBy, desc, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = operationServerMap['EncryptionKeyApi.generate']?.[localVarOperationServerIndex]?.url; + const localVarOperationServerBasePath = operationServerMap['ProviderWalletApi.getWalletAccounts']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + /** + * + * @summary Get a specific wallet by ID + * @param {string} walletId The ID of the wallet to retrieve + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getWalletById(walletId: string, authorization: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getWalletById(walletId, authorization, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderWalletApi.getWalletById']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + /** + * + * @summary List the client wallets + * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async listByClientId(authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.listByClientId(authorization, cursor, limit, orderBy, desc, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderWalletApi.listByClientId']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, } }; /** - * EncryptionKeyApi - factory interface + * ProviderWalletApi - factory interface * @export */ -export const EncryptionKeyApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { - const localVarFp = EncryptionKeyApiFp(configuration) +export const ProviderWalletApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { + const localVarFp = ProviderWalletApiFp(configuration) return { /** * - * @summary Generates an encryption key pair used to secure end-to-end communication containing sensitive information - * @param {string} xClientId + * @summary List accounts for a specific wallet + * @param {string} walletId The ID of the wallet to retrieve accounts for * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order * @param {*} [options] Override http request option. * @throws {RequiredError} */ - generate(xClientId: string, authorization: string, options?: any): AxiosPromise { - return localVarFp.generate(xClientId, authorization, options).then((request) => request(axios, basePath)); + getWalletAccounts(walletId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: any): AxiosPromise { + return localVarFp.getWalletAccounts(walletId, authorization, cursor, limit, orderBy, desc, options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary Get a specific wallet by ID + * @param {string} walletId The ID of the wallet to retrieve + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getWalletById(walletId: string, authorization: string, options?: any): AxiosPromise { + return localVarFp.getWalletById(walletId, authorization, options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary List the client wallets + * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + listByClientId(authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: any): AxiosPromise { + return localVarFp.listByClientId(authorization, cursor, limit, orderBy, desc, options).then((request) => request(axios, basePath)); }, }; }; /** - * EncryptionKeyApi - object-oriented interface + * ProviderWalletApi - object-oriented interface * @export - * @class EncryptionKeyApi + * @class ProviderWalletApi * @extends {BaseAPI} */ -export class EncryptionKeyApi extends BaseAPI { +export class ProviderWalletApi extends BaseAPI { /** * - * @summary Generates an encryption key pair used to secure end-to-end communication containing sensitive information - * @param {string} xClientId + * @summary List accounts for a specific wallet + * @param {string} walletId The ID of the wallet to retrieve accounts for * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order * @param {*} [options] Override http request option. * @throws {RequiredError} - * @memberof EncryptionKeyApi + * @memberof ProviderWalletApi */ - public generate(xClientId: string, authorization: string, options?: RawAxiosRequestConfig) { - return EncryptionKeyApiFp(this.configuration).generate(xClientId, authorization, options).then((request) => request(this.axios, this.basePath)); + public getWalletAccounts(walletId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig) { + return ProviderWalletApiFp(this.configuration).getWalletAccounts(walletId, authorization, cursor, limit, orderBy, desc, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * + * @summary Get a specific wallet by ID + * @param {string} walletId The ID of the wallet to retrieve + * @param {string} authorization + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderWalletApi + */ + public getWalletById(walletId: string, authorization: string, options?: RawAxiosRequestConfig) { + return ProviderWalletApiFp(this.configuration).getWalletById(walletId, authorization, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * + * @summary List the client wallets + * @param {string} authorization + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderWalletApi + */ + public listByClientId(authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig) { + return ProviderWalletApiFp(this.configuration).listByClientId(authorization, cursor, limit, orderBy, desc, options).then((request) => request(this.axios, this.basePath)); } } From d4b3fa62f9223a22f707bf826dec1e1a616b34b5 Mon Sep 17 00:00:00 2001 From: Matt Schoch Date: Tue, 17 Dec 2024 16:48:48 +0100 Subject: [PATCH 038/120] fix pem description --- .../src/broker/http/rest/dto/response/pending-connection.dto.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/vault/src/broker/http/rest/dto/response/pending-connection.dto.ts b/apps/vault/src/broker/http/rest/dto/response/pending-connection.dto.ts index 9328f88ec..4fda145ff 100644 --- a/apps/vault/src/broker/http/rest/dto/response/pending-connection.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/pending-connection.dto.ts @@ -22,7 +22,7 @@ export class PendingConnectionDto extends createZodDto( encryptionPublicKey: z.object({ keyId: z.string().optional(), jwk: publicKeySchema.optional().describe('JWK format of the public key'), - pem: z.string().optional().describe('Base64url encoded PEM public key') + pem: z.string().optional().describe('Base64 encoded PEM public key') }) }) ) {} From 4178f453bb6899063dcf80cc4ace70aa638c0e1f Mon Sep 17 00:00:00 2001 From: Ptroger <44851272+Ptroger@users.noreply.github.com> Date: Tue, 17 Dec 2024 16:53:33 +0100 Subject: [PATCH 039/120] Simplified pagination (#33) * wip, simplifying types * pagination simplified * added e2e tests on wallet controller * expect undefined orderBy by default in tests * correctly pass options in connection repo * don't expect a specific ordering when no created at provided * pagination always defaults * renamed findAllPaginated to findAll * removed logs * reverse expected order * removed prisma import in shared utils * format fix --- .../src/broker/__test__/e2e/account.spec.ts | 12 +- .../src/broker/__test__/e2e/address.spec.ts | 12 +- .../broker/__test__/e2e/connection.spec.ts | 8 +- .../src/broker/__test__/e2e/sync.spec.ts | 4 +- .../src/broker/__test__/e2e/wallet.spec.ts | 275 ++++++++++++-- .../src/broker/__test__/util/mock-data.ts | 143 +++++-- .../anchorage-sync.service.spec.ts | 9 +- .../broker/core/service/account.service.ts | 12 +- .../broker/core/service/address.service.ts | 4 +- .../core/service/anchorage-sync.service.ts | 10 +- .../broker/core/service/connection.service.ts | 14 +- .../src/broker/core/service/sync.service.ts | 6 +- .../src/broker/core/service/wallet.service.ts | 12 +- .../rest/controller/connection.controller.ts | 6 +- .../http/rest/controller/sync.controller.ts | 4 +- .../http/rest/controller/wallet.controller.ts | 2 +- .../repository/account.repository.ts | 66 +--- .../repository/address.repository.ts | 33 +- .../repository/connection.repository.ts | 44 +-- .../persistence/repository/sync.repository.ts | 18 +- .../repository/wallet.repository.ts | 81 +--- .../service/test-prisma.service.ts | 7 +- .../src/lib/__test__/unit/pagination.spec.ts | 356 ++++++++++++------ packages/nestjs-shared/src/lib/constant.ts | 18 + .../decorator/pagination-param.decorator.ts | 7 +- .../src/lib/type/pagination.type.ts | 67 ++-- .../src/lib/util/pagination.util.ts | 132 ++++--- 27 files changed, 882 insertions(+), 480 deletions(-) diff --git a/apps/vault/src/broker/__test__/e2e/account.spec.ts b/apps/vault/src/broker/__test__/e2e/account.spec.ts index 3eeedabc7..7bfa0eff7 100644 --- a/apps/vault/src/broker/__test__/e2e/account.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/account.spec.ts @@ -81,7 +81,7 @@ describe('Account', () => { expect(response.status).toEqual(HttpStatus.OK) expect(response.body).toEqual({ - accounts: TEST_ACCOUNTS.map(getExpectedAccount), + accounts: TEST_ACCOUNTS.map(getExpectedAccount).reverse(), page: { next: null } @@ -164,15 +164,15 @@ describe('Account', () => { expect(secondResponse.body.accounts[0].accountId).not.toBe(firstResponse.body.accounts[0].accountId) }) - it('handles descending orderBy createdAt parameter correctly', async () => { + it('handles ascending createdAt parameter correctly', async () => { const response = await request(app.getHttpServer()) - .get(`/provider/accounts?orderBy=createdAt&desc=true`) + .get(`/provider/accounts?sortOrder=asc`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( 'detached-jws', await getJwsd({ userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/accounts?orderBy=createdAt&desc=true', + requestUrl: '/provider/accounts?sortOrder=asc', payload: {}, htm: 'GET' }) @@ -181,8 +181,8 @@ describe('Account', () => { const returnedAccounts = response.body.accounts expect(returnedAccounts).toHaveLength(TEST_ACCOUNTS.length) - expect(new Date(returnedAccounts[0].createdAt).getTime()).toBeGreaterThanOrEqual( - new Date(returnedAccounts[1].createdAt).getTime() + expect(new Date(returnedAccounts[1].createdAt).getTime()).toBeGreaterThanOrEqual( + new Date(returnedAccounts[0].createdAt).getTime() ) }) }) diff --git a/apps/vault/src/broker/__test__/e2e/address.spec.ts b/apps/vault/src/broker/__test__/e2e/address.spec.ts index 4209c9bd3..e75a60034 100644 --- a/apps/vault/src/broker/__test__/e2e/address.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/address.spec.ts @@ -74,7 +74,7 @@ describe('Address', () => { expect(response.status).toEqual(HttpStatus.OK) expect(response.body).toEqual({ - addresses: TEST_ADDRESSES.map(getExpectedAddress), + addresses: TEST_ADDRESSES.map(getExpectedAddress).reverse(), page: { next: null } @@ -140,15 +140,15 @@ describe('Address', () => { expect(secondResponse.body.addresses[0].addressId).not.toBe(firstResponse.body.addresses[0].addressId) }) - it('handles descending orderBy createdAt parameter correctly', async () => { + it('handles ascending createdAt parameter correctly', async () => { const response = await request(app.getHttpServer()) - .get('/provider/addresses?orderBy=createdAt&desc=true') + .get('/provider/addresses?sortOrder=asc') .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( 'detached-jws', await getJwsd({ userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/addresses?orderBy=createdAt&desc=true', + requestUrl: '/provider/addresses?sortOrder=asc', payload: {}, htm: 'GET' }) @@ -157,8 +157,8 @@ describe('Address', () => { const returnedAddresses = response.body.addresses expect(returnedAddresses).toHaveLength(TEST_ADDRESSES.length) - expect(new Date(returnedAddresses[0].createdAt).getTime()).toBeGreaterThanOrEqual( - new Date(returnedAddresses[1].createdAt).getTime() + expect(new Date(returnedAddresses[1].createdAt).getTime()).toBeGreaterThanOrEqual( + new Date(returnedAddresses[0].createdAt).getTime() ) }) }) diff --git a/apps/vault/src/broker/__test__/e2e/connection.spec.ts b/apps/vault/src/broker/__test__/e2e/connection.spec.ts index 987d3f0d3..78c277647 100644 --- a/apps/vault/src/broker/__test__/e2e/connection.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/connection.spec.ts @@ -623,11 +623,7 @@ describe('Connection', () => { .send() const { body: pageTwo } = await request(app.getHttpServer()) - .get('/provider/connections') - .query({ - limit: 1, - cursor: pageOne.page.next - }) + .get(`/provider/connections?limit=1&cursor=${pageOne.page.next}`) .set(REQUEST_HEADER_CLIENT_ID, clientId) .set( 'detached-jws', @@ -839,7 +835,7 @@ describe('Connection', () => { expect(status).toEqual(HttpStatus.OK) expect(body).toMatchObject({ - accounts: accountsForConnection.map(getExpectedAccount), + accounts: accountsForConnection.map(getExpectedAccount).reverse(), page: {} }) }) diff --git a/apps/vault/src/broker/__test__/e2e/sync.spec.ts b/apps/vault/src/broker/__test__/e2e/sync.spec.ts index e707dbf03..65bc4b4c9 100644 --- a/apps/vault/src/broker/__test__/e2e/sync.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/sync.spec.ts @@ -156,7 +156,7 @@ describe('Sync', () => { ) .send() - const syncs = await syncService.findAllPaginated(clientId) + const syncs = await syncService.findAll(clientId) const [sync] = syncs.data expect(body).toMatchObject({ @@ -192,7 +192,7 @@ describe('Sync', () => { ) .send({ connectionId: activeConnection.connectionId }) - const syncs = await syncService.findAllPaginated(clientId) + const syncs = await syncService.findAll(clientId) const [sync] = syncs.data expect(body).toEqual({ diff --git a/apps/vault/src/broker/__test__/e2e/wallet.spec.ts b/apps/vault/src/broker/__test__/e2e/wallet.spec.ts index 6297282ae..06a41a9ba 100644 --- a/apps/vault/src/broker/__test__/e2e/wallet.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/wallet.spec.ts @@ -10,8 +10,18 @@ import { KeyValueRepository } from '../../../shared/module/key-value/core/reposi import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' +import { Wallet } from '../../core/type/indexed-resources.type' import { getExpectedAccount, getExpectedWallet } from '../util/map-db-to-returned' -import { TEST_ACCOUNTS, TEST_CLIENT_ID, TEST_WALLETS, getJwsd, testClient, testUserPrivateJwk } from '../util/mock-data' +import { + TEST_ACCOUNTS, + TEST_CLIENT_ID, + TEST_DIFFERENT_CLIENT_ID, + TEST_WALLETS, + getJwsd, + testClient, + testDifferentClient, + testUserPrivateJwk +} from '../util/mock-data' describe('Wallet', () => { let app: INestApplication @@ -51,6 +61,7 @@ describe('Wallet', () => { await testPrismaService.truncateAll() await provisionService.provision() + await clientService.save(testDifferentClient) await clientService.save(testClient) await testPrismaService.seedBrokerTestData() @@ -74,7 +85,9 @@ describe('Wallet', () => { expect(res.status).toBe(HttpStatus.OK) expect(res.body).toEqual({ - wallets: TEST_WALLETS.map(getExpectedWallet), + wallets: TEST_WALLETS.filter((w) => w.clientId === TEST_CLIENT_ID) + .map(getExpectedWallet) + .reverse(), page: { next: null } @@ -130,103 +143,291 @@ describe('Wallet', () => { describe('GET /wallets with pagination', () => { it('returns limited number of wallets when limit parameter is provided', async () => { - // We have 2 wallets in TEST_WALLETS - const limit = 1 + const limit = 2 const res = await request(app.getHttpServer()) - .get('/provider/wallets?limit=1') + .get(`/provider/wallets?limit=${limit}`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( 'detached-jws', await getJwsd({ userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/wallets?limit=1', + requestUrl: `/provider/wallets?limit=${limit}`, payload: {}, htm: 'GET' }) ) - expect(res.body.wallets).toHaveLength(limit) - expect(res.body.page).toHaveProperty('next') expect(res.status).toBe(HttpStatus.OK) + expect(res.body.wallets).toHaveLength(limit) + expect(res.body.page.next).toBeDefined() + // First two wallets should be returned in createdAt descending order + expect(res.body.wallets.map((w: Wallet) => w.walletId)).toEqual(['wallet-5', 'wallet-4']) }) - it('returns next page of results using cursor', async () => { - const firstResponse = await request(app.getHttpServer()) - .get(`/provider/wallets?limit=1`) + it('returns all wallets when limit exceeds total count', async () => { + const limit = 10 + const res = await request(app.getHttpServer()) + .get(`/provider/wallets?limit=${limit}`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( 'detached-jws', await getJwsd({ userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/wallets?limit=1', + requestUrl: `/provider/wallets?limit=${limit}`, payload: {}, htm: 'GET' }) ) - expect(firstResponse.status).toBe(HttpStatus.OK) - const cursor = firstResponse.body.page?.next - expect(cursor).toBeDefined() + expect(res.status).toBe(HttpStatus.OK) + expect(res.body.wallets).toHaveLength(5) // Total wallets for TEST_CLIENT_ID + expect(res.body.page.next).toBeNull() // No next page + }) - const secondResponse = await request(app.getHttpServer()) - .get(`/provider/wallets?cursor=${cursor}`) + it('navigates through all pages using cursor', async () => { + const limit = 2 + const allWallets = [] + let cursor = null + + do { + const url: string = cursor + ? `/provider/wallets?limit=${limit}&cursor=${cursor}` + : `/provider/wallets?limit=${limit}` + + const res = await request(app.getHttpServer()) + .get(url) + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: url, + payload: {}, + htm: 'GET' + }) + ) + + expect(res.status).toBe(HttpStatus.OK) + allWallets.push(...res.body.wallets) + cursor = res.body.page.next + } while (cursor) + + expect(allWallets).toHaveLength(5) // Total wallets for TEST_CLIENT_ID + // Check if wallets are unique + const uniqueWalletIds = new Set(allWallets.map((w) => w.walletId)) + expect(uniqueWalletIds.size).toBe(5) + }) + it('handles descending order by createdAt parameter correctly', async () => { + const res = await request(app.getHttpServer()) + .get('/provider/wallets?sortOrder=desc') .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( 'detached-jws', await getJwsd({ userPrivateJwk: testUserPrivateJwk, - requestUrl: `/provider/wallets?cursor=${cursor}`, + requestUrl: '/provider/wallets?sortOrder=desc', payload: {}, htm: 'GET' }) ) - expect(secondResponse.status).toBe(HttpStatus.OK) - expect(secondResponse.body.wallets).toHaveLength(1) - // The second wallet should not be the same as the first - expect(secondResponse.body.wallets[0].walletId).not.toBe(firstResponse.body.wallets[0].walletId) + expect(res.status).toBe(HttpStatus.OK) + const wallets = res.body.wallets + // Should return wallets in reverse order + expect(wallets.map((w: Wallet) => w.walletId)).toEqual([ + 'wallet-5', + 'wallet-4', + 'wallet-3', + 'wallet-2', + 'wallet-1' + ]) }) - it('handles descending orderBy createdAt parameter correctly', async () => { + + it('handles ascending order by createdAt parameter correctly', async () => { const res = await request(app.getHttpServer()) - .get('/provider/wallets?orderBy=createdAt&desc=true') + .get('/provider/wallets?sortOrder=asc') .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( 'detached-jws', await getJwsd({ userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/wallets?orderBy=createdAt&desc=true', + requestUrl: '/provider/wallets?sortOrder=asc', + payload: {}, + htm: 'GET' + }) + ) + + expect(res.status).toBe(HttpStatus.OK) + const wallets = res.body.wallets + // Should return wallets in normal order + expect(wallets.map((w: Wallet) => w.walletId)).toEqual([ + 'wallet-1', + 'wallet-2', + 'wallet-3', + 'wallet-4', + 'wallet-5' + ]) + }) + + it('handles asc order when createdAt is same for multiple wallets', async () => { + const res = await request(app.getHttpServer()) + .get('/provider/wallets?sortOrder=asc') + .set(REQUEST_HEADER_CLIENT_ID, TEST_DIFFERENT_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/wallets?sortOrder=asc', + payload: {}, + htm: 'GET' + }) + ) + + expect(res.status).toBe(HttpStatus.OK) + const wallets = res.body.wallets + + const walletIds = wallets.map((w: Wallet) => w.walletId) + + // Should return wallets in normal order + expect(walletIds).toEqual(['wallet-6', 'wallet-7', 'wallet-8']) + }) + + it('handles desc order when createdAt is same for multiple wallets', async () => { + const res = await request(app.getHttpServer()) + .get('/provider/wallets?sortOrder=desc') + .set(REQUEST_HEADER_CLIENT_ID, TEST_DIFFERENT_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/wallets?sortOrder=desc', payload: {}, htm: 'GET' }) ) - // Check descending order by createdAt - const returnedWallets = res.body.wallets - expect(returnedWallets).toHaveLength(TEST_WALLETS.length) expect(res.status).toBe(HttpStatus.OK) + const wallets = res.body.wallets + const walletIds = wallets.map((w: Wallet) => w.walletId) - // When ordering by DESC, first item should have GREATER timestamp than second - expect(new Date(returnedWallets[0].createdAt).getTime()).toBeGreaterThan( - new Date(returnedWallets[1].createdAt).getTime() - ) + // Should return wallets in normal order + expect(walletIds).toEqual(['wallet-8', 'wallet-7', 'wallet-6']) }) - it('throws invalidField orderBy is not a valid field', async () => { + describe('GET /wallets pagination with different directions and sort orders', () => { + let cursor: string + + beforeEach(async () => { + // Get initial cursor from latest wallet + const initialRes = await request(app.getHttpServer()) + .get('/provider/wallets?limit=1&sortOrder=desc') + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/wallets?limit=1&sortOrder=desc', + payload: {}, + htm: 'GET' + }) + ) + + expect(initialRes.status).toBe(HttpStatus.OK) + cursor = initialRes.body.page.next + }) + + it('returns no results when paginating prev in desc order from newest record', async () => { + const res = await request(app.getHttpServer()) + .get(`/provider/wallets?cursor=${cursor}&direction=prev&limit=2&sortOrder=desc`) + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: `/provider/wallets?cursor=${cursor}&direction=prev&limit=2&sortOrder=desc`, + payload: {}, + htm: 'GET' + }) + ) + + expect(res.status).toBe(HttpStatus.OK) + expect(res.body.wallets).toHaveLength(0) + expect(res.body.wallets).toEqual([]) + }) + + it('returns next older records when paginating next in desc order', async () => { + const res = await request(app.getHttpServer()) + .get(`/provider/wallets?cursor=${cursor}&direction=next&limit=2&sortOrder=desc`) + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: `/provider/wallets?cursor=${cursor}&direction=next&limit=2&sortOrder=desc`, + payload: {}, + htm: 'GET' + }) + ) + + expect(res.status).toBe(HttpStatus.OK) + expect(res.body.wallets).toHaveLength(2) + expect(res.body.wallets.map((w: Wallet) => w.walletId)).toEqual(['wallet-4', 'wallet-3']) + }) + + it('returns next newer records when paginating prev in asc order', async () => { + const res = await request(app.getHttpServer()) + .get(`/provider/wallets?cursor=${cursor}&direction=prev&limit=2&sortOrder=asc`) + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: `/provider/wallets?cursor=${cursor}&direction=prev&limit=2&sortOrder=asc`, + payload: {}, + htm: 'GET' + }) + ) + + expect(res.status).toBe(HttpStatus.OK) + expect(res.body.wallets).toHaveLength(2) + expect(res.body.wallets.map((w: Wallet) => w.walletId)).toEqual(['wallet-3', 'wallet-4']) + }) + }) + + it('returns empty array when cursor points to first wallet and direction is prev', async () => { + // First get the earliest wallet + const initialRes = await request(app.getHttpServer()) + .get('/provider/wallets?limit=1&sortOrder=asc') + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/wallets?limit=1&sortOrder=asc', + payload: {}, + htm: 'GET' + }) + ) + + const cursor = initialRes.body.page.next + const res = await request(app.getHttpServer()) - .get('/provider/wallets?orderBy=invalid-field') + .get(`/provider/wallets?cursor=${cursor}&sortOrder=asc&direction=prev`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( 'detached-jws', await getJwsd({ userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/wallets?orderBy=invalid-field', + requestUrl: `/provider/wallets?cursor=${cursor}&sortOrder=asc&direction=prev`, payload: {}, htm: 'GET' }) ) - expect(res.status).toBe(HttpStatus.UNPROCESSABLE_ENTITY) + expect(res.status).toBe(HttpStatus.OK) + expect(res.body.wallets).toHaveLength(0) + expect(res.body.page.next).toBeNull() }) }) @@ -308,7 +509,7 @@ describe('Wallet', () => { expect(res.status).toBe(HttpStatus.OK) expect(res.body).toEqual({ - accounts: accounts.map(getExpectedAccount), + accounts: accounts.map(getExpectedAccount).reverse(), page: { next: null } diff --git a/apps/vault/src/broker/__test__/util/mock-data.ts b/apps/vault/src/broker/__test__/util/mock-data.ts index 40b5f44dc..e672f79e8 100644 --- a/apps/vault/src/broker/__test__/util/mock-data.ts +++ b/apps/vault/src/broker/__test__/util/mock-data.ts @@ -24,9 +24,11 @@ const privateKey = { const { d: _d, ...publicKey } = privateKey export const TEST_CLIENT_ID = 'test-client-id' +export const TEST_DIFFERENT_CLIENT_ID = 'different-client-id' const PRIVATE_KEY = '0x7cfef3303797cbc7515d9ce22ffe849c701b0f2812f999b0847229c47951fca5' +const now = new Date() export const testUserPrivateJwk = secp256k1PrivateKeyToJwk(PRIVATE_KEY) export const testUserPublicJWK = secp256k1PrivateKeyToPublicJwk(PRIVATE_KEY) export const testClient: Client = { @@ -65,8 +67,48 @@ export const testClient: Client = { configurationSource: 'dynamic', backupPublicKey: null, baseUrl: null, - createdAt: new Date(), - updatedAt: new Date() + createdAt: now, + updatedAt: now +} + +export const testDifferentClient: Client = { + clientId: TEST_DIFFERENT_CLIENT_ID, + auth: { + disabled: false, + local: { + jwsd: { + maxAge: 600, + requiredComponents: ['htm', 'uri', 'created', 'ath'] + }, + allowedUsersJwksUrl: null, + allowedUsers: [ + { + userId: 'user-1', + publicKey: testUserPublicJWK + } + ] + }, + tokenValidation: { + disabled: true, + url: null, + jwksUrl: null, + verification: { + audience: null, + issuer: 'https://armory.narval.xyz', + maxTokenAge: 300, + requireBoundTokens: false, // DO NOT REQUIRE BOUND TOKENS; we're testing both payload.cnf bound tokens and unbound here. + allowBearerTokens: false, + allowWildcard: [] + }, + pinnedPublicKey: null + } + }, + name: 'test-client', + configurationSource: 'dynamic', + backupPublicKey: null, + baseUrl: null, + createdAt: now, + updatedAt: now } export const TEST_CONNECTIONS = [ @@ -82,8 +124,8 @@ export const TEST_CONNECTIONS = [ publicKey }, status: 'active', - createdAt: new Date(), - updatedAt: new Date(), + createdAt: now, + updatedAt: now, revokedAt: null }, { @@ -98,8 +140,8 @@ export const TEST_CONNECTIONS = [ publicKey }, status: 'active', - createdAt: new Date(), - updatedAt: new Date(), + createdAt: now, + updatedAt: now, revokedAt: null } ] @@ -109,13 +151,43 @@ export const TEST_WALLET_CONNECTIONS = [ clientId: TEST_CLIENT_ID, connectionId: 'connection-1', walletId: 'wallet-1', - createdAt: new Date() + createdAt: now }, { clientId: TEST_CLIENT_ID, connectionId: 'connection-2', walletId: 'wallet-2', - createdAt: new Date() + createdAt: now + } +] + +export const TEST_WALLETS_WITH_SAME_TIMESTAMP = [ + { + id: 'wallet-6', + clientId: TEST_DIFFERENT_CLIENT_ID, + provider: 'anchorage', + label: 'Test Wallet 1', + externalId: 'ext-wallet-1', + createdAt: now, + updatedAt: now + }, + { + id: 'wallet-7', + clientId: TEST_DIFFERENT_CLIENT_ID, + provider: 'anchorage', + label: 'Test Wallet 2', + externalId: 'ext-wallet-2', + createdAt: now, + updatedAt: now + }, + { + id: 'wallet-8', + clientId: TEST_DIFFERENT_CLIENT_ID, + provider: 'anchorage', + label: 'Test Wallet 3', + externalId: 'ext-wallet-3', + createdAt: now, + updatedAt: now } ] @@ -126,8 +198,8 @@ export const TEST_WALLETS = [ provider: 'anchorage', label: 'Test Wallet 1', externalId: 'ext-wallet-1', - createdAt: new Date('2024-01-01T00:00:00.000Z'), - updatedAt: new Date('2024-01-01T00:00:00.000Z') + createdAt: now, + updatedAt: now }, { id: 'wallet-2', @@ -135,8 +207,35 @@ export const TEST_WALLETS = [ provider: 'anchorage', label: 'Test Wallet 2', externalId: 'ext-wallet-2', - createdAt: new Date('2024-01-01T00:00:01.000Z'), // One second later - updatedAt: new Date('2024-01-01T00:00:01.000Z') + createdAt: new Date(now.getTime() + 1000), + updatedAt: new Date(now.getTime() + 1000) + }, + { + id: 'wallet-3', + clientId: TEST_CLIENT_ID, + provider: 'anchorage', + label: 'Test Wallet 3', + externalId: 'ext-wallet-3', + createdAt: new Date(now.getTime() + 2000), + updatedAt: new Date(now.getTime() + 2000) + }, + { + id: 'wallet-4', + clientId: TEST_CLIENT_ID, + provider: 'anchorage', + label: 'Test Wallet 4', + externalId: 'ext-wallet-4', + createdAt: new Date(now.getTime() + 3000), + updatedAt: new Date(now.getTime() + 3000) + }, + { + id: 'wallet-5', + clientId: TEST_CLIENT_ID, + provider: 'anchorage', + label: 'Test Wallet 5', + externalId: 'ext-wallet-5', + createdAt: new Date(now.getTime() + 4000), + updatedAt: new Date(now.getTime() + 4000) } ] @@ -149,8 +248,8 @@ export const TEST_ACCOUNTS = [ externalId: 'ext-account-1', walletId: 'wallet-1', // Linking to wallet-1 networkId: '1', - createdAt: new Date(), - updatedAt: new Date() + createdAt: now, + updatedAt: now }, { id: 'account-2', @@ -160,8 +259,8 @@ export const TEST_ACCOUNTS = [ externalId: 'ext-account-2', walletId: 'wallet-1', // Linking to wallet-1 networkId: '60', - createdAt: new Date(), - updatedAt: new Date() + createdAt: now, + updatedAt: now } ] @@ -173,8 +272,8 @@ export const TEST_ADDRESSES = [ externalId: 'ext-address-1', accountId: 'account-1', // Linking to account-1 address: '0x1234567890123456789012345678901234567890', // Example ETH address - createdAt: new Date(), - updatedAt: new Date() + createdAt: now, + updatedAt: now }, { id: 'address-2', @@ -183,8 +282,8 @@ export const TEST_ADDRESSES = [ externalId: 'ext-address-2', accountId: 'account-1', // Another address for account-1 address: '0x0987654321098765432109876543210987654321', // Example ETH address - createdAt: new Date(), - updatedAt: new Date() + createdAt: now, + updatedAt: now }, { id: 'address-3', @@ -193,8 +292,8 @@ export const TEST_ADDRESSES = [ externalId: 'ext-address-3', accountId: 'account-2', // Linking to account-2 address: 'bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh', // Example BTC address - createdAt: new Date(), - updatedAt: new Date() + createdAt: now, + updatedAt: now } ] diff --git a/apps/vault/src/broker/core/service/__test__/integration/anchorage-sync.service.spec.ts b/apps/vault/src/broker/core/service/__test__/integration/anchorage-sync.service.spec.ts index 24bec0829..c879b1f22 100644 --- a/apps/vault/src/broker/core/service/__test__/integration/anchorage-sync.service.spec.ts +++ b/apps/vault/src/broker/core/service/__test__/integration/anchorage-sync.service.spec.ts @@ -102,9 +102,8 @@ describe(AnchorageSyncService.name, () => { it('fetches anchorage vaults and persist them as wallets', async () => { const syncedWallets = await anchorageSyncService.syncWallets(connection) - const wallets = await walletService.findAll(connection.clientId) - - expect(syncedWallets).toEqual(wallets) + const { data: wallets } = await walletService.findAll(connection.clientId) + expect(syncedWallets).toEqual(expect.arrayContaining(wallets)) }) it('does not duplicate wallets', async () => { @@ -126,7 +125,7 @@ describe(AnchorageSyncService.name, () => { const syncedAccounts = await anchorageSyncService.syncAccounts(connection) - const accounts = await accountService.findAll(connection.clientId) + const { data: accounts } = await accountService.findAll(connection.clientId) expect(syncedAccounts.sort(sortByExternalId)).toEqual(accounts.sort(sortByExternalId)) }) @@ -153,7 +152,7 @@ describe(AnchorageSyncService.name, () => { it('fetches anchorage addresses and persist them as addresses', async () => { const syncedAddresses = await anchorageSyncService.syncAddresses(connection) - const addresses = await addressService.findAll(connection.clientId) + const { data: addresses } = await addressService.findAll(connection.clientId) expect(syncedAddresses).toEqual( addresses.map((address) => ({ diff --git a/apps/vault/src/broker/core/service/account.service.ts b/apps/vault/src/broker/core/service/account.service.ts index c0e267497..babc99c0d 100644 --- a/apps/vault/src/broker/core/service/account.service.ts +++ b/apps/vault/src/broker/core/service/account.service.ts @@ -1,10 +1,6 @@ import { PaginatedResult, PaginationOptions } from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' -import { - AccountRepository, - FindAllOptions, - FindAllPaginatedOptions -} from '../../persistence/repository/account.repository' +import { AccountRepository, FindAllOptions } from '../../persistence/repository/account.repository' import { Account, Address } from '../type/indexed-resources.type' @Injectable() @@ -27,15 +23,15 @@ export class AccountService { return this.accountRepository.findAddressesByAccountId(clientId, AccountId, options) } - async findAllPaginated(clientId: string, options?: FindAllPaginatedOptions): Promise> { - return this.accountRepository.findAllPaginated(clientId, options) + async findAllPaginated(clientId: string, options?: FindAllOptions): Promise> { + return this.accountRepository.findAll(clientId, options) } async bulkCreate(accounts: Account[]): Promise { return this.accountRepository.bulkCreate(accounts) } - async findAll(clientId: string, options?: FindAllOptions): Promise { + async findAll(clientId: string, options?: FindAllOptions): Promise> { return this.accountRepository.findAll(clientId, options) } } diff --git a/apps/vault/src/broker/core/service/address.service.ts b/apps/vault/src/broker/core/service/address.service.ts index 83ea49343..4a182c2ba 100644 --- a/apps/vault/src/broker/core/service/address.service.ts +++ b/apps/vault/src/broker/core/service/address.service.ts @@ -1,6 +1,6 @@ import { PaginatedResult, PaginationOptions } from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' -import { AddressRepository, FindAllFilters } from '../../persistence/repository/address.repository' +import { AddressRepository, FindAllOptions } from '../../persistence/repository/address.repository' import { Address } from '../type/indexed-resources.type' @Injectable() @@ -19,7 +19,7 @@ export class AddressService { return this.addressRepository.bulkCreate(addresses) } - async findAll(clientId: string, opts?: FindAllFilters): Promise { + async findAll(clientId: string, opts?: FindAllOptions): Promise> { return this.addressRepository.findAll(clientId, opts) } } diff --git a/apps/vault/src/broker/core/service/anchorage-sync.service.ts b/apps/vault/src/broker/core/service/anchorage-sync.service.ts index 0cc3e0ec8..3add04bee 100644 --- a/apps/vault/src/broker/core/service/anchorage-sync.service.ts +++ b/apps/vault/src/broker/core/service/anchorage-sync.service.ts @@ -43,7 +43,7 @@ export class AnchorageSyncService { signKey: connection.credentials.privateKey }) - const existingWallets = await this.walletService.findAll(connection.clientId, { + const { data: existingWallets } = await this.walletService.findAll(connection.clientId, { filters: { externalIds: anchorageVaults.map((vault) => vault.vaultId) } @@ -101,13 +101,13 @@ export class AnchorageSyncService { const walletExternalIds = uniq(anchorageWallets.map(({ vaultId }) => vaultId)) - const existingWallets = await this.walletService.findAll(connection.clientId, { + const { data: existingWallets } = await this.walletService.findAll(connection.clientId, { filters: { externalIds: walletExternalIds } }) - const existingAccounts = await this.accountService.findAll(connection.clientId, { + const { data: existingAccounts } = await this.accountService.findAll(connection.clientId, { filters: { externalIds: uniq(anchorageWallets.map((wallet) => wallet.walletId)) } @@ -200,7 +200,7 @@ export class AnchorageSyncService { ).flat() // Query existing accounts to associate them with their children addresses. - const existingAccounts = await this.accountService.findAll(connection.clientId, { + const { data: existingAccounts } = await this.accountService.findAll(connection.clientId, { filters: { externalIds: anchorageAddresses.map((anchorageAddress) => anchorageAddress.walletId) } @@ -208,7 +208,7 @@ export class AnchorageSyncService { const existingAccountsByExternalId = new Map(existingAccounts.map((account) => [account.externalId, account])) - const existingAddresses = await this.addressService.findAll(connection.clientId, { + const { data: existingAddresses } = await this.addressService.findAll(connection.clientId, { filters: { externalIds: anchorageAddresses.map((anchorageAddress) => anchorageAddress.addressId) } diff --git a/apps/vault/src/broker/core/service/connection.service.ts b/apps/vault/src/broker/core/service/connection.service.ts index a3a8c1cf4..860644b00 100644 --- a/apps/vault/src/broker/core/service/connection.service.ts +++ b/apps/vault/src/broker/core/service/connection.service.ts @@ -13,11 +13,7 @@ import { EventEmitter2 } from '@nestjs/event-emitter' import { SetRequired } from 'type-fest' import { v4 as uuid } from 'uuid' import { EncryptionKeyService } from '../../../transit-encryption/core/service/encryption-key.service' -import { - ConnectionRepository, - FilterOptions, - FindAllPaginatedOptions -} from '../../persistence/repository/connection.repository' +import { ConnectionRepository, FindAllOptions } from '../../persistence/repository/connection.repository' import { ConnectionActivatedEvent } from '../../shared/event/connection-activated.event' import { ConnectionInvalidCredentialsException } from '../exception/connection-invalid-credentials.exception' import { ConnectionInvalidPrivateKeyException } from '../exception/connection-invalid-private-key.exception' @@ -369,16 +365,12 @@ export class ConnectionService { async findAll( clientId: string, - options?: FilterOptions, + options?: FindAllOptions, includeCredentials?: T - ): Promise { + ): Promise : PaginatedResult> { return this.connectionRepository.findAll(clientId, options, includeCredentials) } - async findAllPaginated(clientId: string, options?: FindAllPaginatedOptions): Promise> { - return this.connectionRepository.findAllPaginated(clientId, options) - } - async revoke(clientId: string, connectionId: string): Promise { const connection = await this.connectionRepository.findById(clientId, connectionId) diff --git a/apps/vault/src/broker/core/service/sync.service.ts b/apps/vault/src/broker/core/service/sync.service.ts index a7ca102b3..716ac7a17 100644 --- a/apps/vault/src/broker/core/service/sync.service.ts +++ b/apps/vault/src/broker/core/service/sync.service.ts @@ -1,7 +1,7 @@ import { LoggerService, PaginatedResult, TraceService } from '@narval/nestjs-shared' import { Inject, Injectable } from '@nestjs/common/decorators' import { v4 as uuid } from 'uuid' -import { FindAllPaginatedOptions, SyncRepository } from '../../persistence/repository/sync.repository' +import { FindAllOptions, SyncRepository } from '../../persistence/repository/sync.repository' import { ActiveConnectionWithCredentials } from '../type/connection.type' import { StartSync, Sync, SyncStarted, SyncStatus } from '../type/sync.type' import { AnchorageSyncService } from './anchorage-sync.service' @@ -66,8 +66,8 @@ export class SyncService { } } - async findAllPaginated(clientId: string, options?: FindAllPaginatedOptions): Promise> { - return this.syncRepository.findAllPaginated(clientId, options) + async findAll(clientId: string, options?: FindAllOptions): Promise> { + return this.syncRepository.findAll(clientId, options) } async findById(clientId: string, syncId: string): Promise { diff --git a/apps/vault/src/broker/core/service/wallet.service.ts b/apps/vault/src/broker/core/service/wallet.service.ts index 88ff5f05a..a8846412c 100644 --- a/apps/vault/src/broker/core/service/wallet.service.ts +++ b/apps/vault/src/broker/core/service/wallet.service.ts @@ -1,10 +1,6 @@ import { PaginatedResult, PaginationOptions } from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' -import { - FindAllOptions, - FindAllPaginatedOptions, - WalletRepository -} from '../../persistence/repository/wallet.repository' +import { FindAllOptions, WalletRepository } from '../../persistence/repository/wallet.repository' import { Wallet } from '../type/indexed-resources.type' @Injectable() @@ -23,11 +19,7 @@ export class WalletService { return this.walletRepository.bulkCreate(wallets) } - async findAllPaginated(clientId: string, options?: FindAllPaginatedOptions): Promise> { - return this.walletRepository.findAllPaginated(clientId, options) - } - - async findAll(clientId: string, options?: FindAllOptions): Promise { + async findAll(clientId: string, options?: FindAllOptions): Promise> { return this.walletRepository.findAll(clientId, options) } } diff --git a/apps/vault/src/broker/http/rest/controller/connection.controller.ts b/apps/vault/src/broker/http/rest/controller/connection.controller.ts index ba4679a57..ee3b5d0af 100644 --- a/apps/vault/src/broker/http/rest/controller/connection.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/connection.controller.ts @@ -121,7 +121,7 @@ export class ConnectionController { @ClientId() clientId: string, @PaginationParam() options: PaginationOptions ): Promise { - const { data, page } = await this.connectionService.findAllPaginated(clientId, options) + const { data, page } = await this.connectionService.findAll(clientId, { pagination: options }) return PaginatedConnectionsDto.create({ connections: data, page }) } @@ -188,7 +188,7 @@ export class ConnectionController { @Param('connectionId') connectionId: string, @PaginationParam() options: PaginationOptions ): Promise { - const { data, page } = await this.walletService.findAllPaginated(clientId, { + const { data, page } = await this.walletService.findAll(clientId, { ...options, filters: { connectionId } }) @@ -211,7 +211,7 @@ export class ConnectionController { @Param('connectionId') connectionId: string, @PaginationParam() options: PaginationOptions ): Promise { - const { data, page } = await this.accountService.findAllPaginated(clientId, { + const { data, page } = await this.accountService.findAll(clientId, { ...options, filters: { connectionId } }) diff --git a/apps/vault/src/broker/http/rest/controller/sync.controller.ts b/apps/vault/src/broker/http/rest/controller/sync.controller.ts index 8cbab199e..289dc1e1b 100644 --- a/apps/vault/src/broker/http/rest/controller/sync.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/sync.controller.ts @@ -41,7 +41,7 @@ export class SyncController { return SyncStatusDto.create(await this.syncService.start([connection as ActiveConnectionWithCredentials])) } - const connections = await this.connectionService.findAll( + const { data: connections } = await this.connectionService.findAll( clientId, { filters: { @@ -88,7 +88,7 @@ export class SyncController { @PaginationParam() options: PaginationOptions, @Query('connectionId') connectionId?: string ): Promise { - const { data, page } = await this.syncService.findAllPaginated(clientId, { + const { data, page } = await this.syncService.findAll(clientId, { ...options, filters: { connectionId } }) diff --git a/apps/vault/src/broker/http/rest/controller/wallet.controller.ts b/apps/vault/src/broker/http/rest/controller/wallet.controller.ts index ba09c1b88..405b778f2 100644 --- a/apps/vault/src/broker/http/rest/controller/wallet.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/wallet.controller.ts @@ -86,7 +86,7 @@ export class WalletController { @Param('walletId') walletId: string, @PaginationParam() options: PaginationOptions ): Promise { - const { data, page } = await this.accountService.findAllPaginated(clientId, { + const { data, page } = await this.accountService.findAll(clientId, { ...options, filters: { walletId } }) diff --git a/apps/vault/src/broker/persistence/repository/account.repository.ts b/apps/vault/src/broker/persistence/repository/account.repository.ts index 386b65c29..8000cf7d5 100644 --- a/apps/vault/src/broker/persistence/repository/account.repository.ts +++ b/apps/vault/src/broker/persistence/repository/account.repository.ts @@ -1,4 +1,4 @@ -import { PaginatedResult, PaginationOptions, getPaginatedResult, getPaginationQuery } from '@narval/nestjs-shared' +import { PaginatedResult, PaginationOptions, applyPagination, getPaginatedResult } from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' import { ProviderAccount, ProviderAddress } from '@prisma/client/vault' import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' @@ -18,18 +18,12 @@ type FindAllFilters = { } } -export type FindAllPaginatedOptions = PaginationOptions & FindAllFilters - -export type FindAllOptions = FindAllFilters +export type FindAllOptions = FindAllFilters & { pagination?: PaginationOptions } @Injectable() export class AccountRepository { constructor(private prismaService: PrismaService) {} - static getCursorOrderColumns(): Array { - return ['createdAt'] - } - static parseModel(model: ProviderAccountAndRelations): Account { const { id, ...rest } = model @@ -54,17 +48,18 @@ export class AccountRepository { } } - async findByClientId(clientId: string, options?: PaginationOptions): Promise> { - const pagination = getPaginationQuery({ options, cursorOrderColumns: AccountRepository.getCursorOrderColumns() }) + async findByClientId(clientId: string, opts?: PaginationOptions): Promise> { + const pagination = applyPagination(opts) - const result = await this.prismaService.providerAccount.findMany({ + const items = await this.prismaService.providerAccount.findMany({ where: { clientId }, include: { addresses: true }, ...pagination }) - const { data, page } = getPaginatedResult({ items: result, options: pagination }) + + const { data, page } = getPaginatedResult({ items, pagination }) return { data: data.map(AccountRepository.parseModel), page @@ -91,10 +86,8 @@ export class AccountRepository { async findAddressesByAccountId( clientId: string, accountId: string, - options: PaginationOptions + pagination: PaginationOptions ): Promise> { - const pagination = getPaginationQuery({ options, cursorOrderColumns: AccountRepository.getCursorOrderColumns() }) - const account = await this.prismaService.providerAccount.findUnique({ where: { clientId, id: accountId }, include: { @@ -108,40 +101,13 @@ export class AccountRepository { context: { accountId } }) } - const { data, page } = getPaginatedResult({ items: account.addresses, options: pagination }) + const { data, page } = getPaginatedResult({ items: account.addresses, pagination }) return { data: data.map(AddressRepository.parseModel), page } } - async findAllPaginated(clientId: string, options?: FindAllPaginatedOptions): Promise> { - const pagination = getPaginationQuery({ options, cursorOrderColumns: AccountRepository.getCursorOrderColumns() }) - const result = await this.prismaService.providerAccount.findMany({ - where: { - clientId, - walletId: options?.filters?.walletId, - wallet: { - connections: { - some: { - connectionId: options?.filters?.connectionId - } - } - } - }, - include: { - addresses: true - }, - ...pagination - }) - const { data, page } = getPaginatedResult({ items: result, options: pagination }) - - return { - data: data.map(AccountRepository.parseModel), - page - } - } - async bulkCreate(accounts: Account[]): Promise { await this.prismaService.providerAccount.createMany({ data: accounts.map(AccountRepository.parseEntity) @@ -150,7 +116,9 @@ export class AccountRepository { return accounts } - async findAll(clientId: string, options?: FindAllOptions): Promise { + async findAll(clientId: string, options?: FindAllOptions): Promise> { + const pagination = applyPagination(options?.pagination) + const models = await this.prismaService.providerAccount.findMany({ where: { clientId, @@ -172,9 +140,15 @@ export class AccountRepository { }, include: { addresses: true - } + }, + ...pagination }) - return models.map(AccountRepository.parseModel) + const { data, page } = getPaginatedResult({ items: models, pagination }) + + return { + data: data.map(AccountRepository.parseModel), + page + } } } diff --git a/apps/vault/src/broker/persistence/repository/address.repository.ts b/apps/vault/src/broker/persistence/repository/address.repository.ts index 8429959aa..71889a35d 100644 --- a/apps/vault/src/broker/persistence/repository/address.repository.ts +++ b/apps/vault/src/broker/persistence/repository/address.repository.ts @@ -1,4 +1,4 @@ -import { PaginatedResult, PaginationOptions, getPaginatedResult, getPaginationQuery } from '@narval/nestjs-shared' +import { PaginatedResult, PaginationOptions, applyPagination, getPaginatedResult } from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' import { ProviderAddress } from '@prisma/client/vault' import { z } from 'zod' @@ -7,20 +7,21 @@ import { NotFoundException } from '../../core/exception/not-found.exception' import { Provider } from '../../core/type/connection.type' import { Address } from '../../core/type/indexed-resources.type' -export type FindAllFilters = { +type FindAllFilters = { filters?: { + connectionId?: string + accountIds?: string[] + walletIds?: string[] externalIds?: string[] } } +export type FindAllOptions = FindAllFilters & { pagination?: PaginationOptions } + @Injectable() export class AddressRepository { constructor(private prismaService: PrismaService) {} - static getCursorOrderColumns(): Array { - return ['createdAt'] - } - static parseModel(model: ProviderAddress): Address { const { id, ...rest } = model @@ -44,15 +45,15 @@ export class AddressRepository { } } - async findByClientId(clientId: string, options?: PaginationOptions): Promise> { - const pagination = getPaginationQuery({ options, cursorOrderColumns: AddressRepository.getCursorOrderColumns() }) + async findByClientId(clientId: string, opts?: PaginationOptions): Promise> { + const pagination = applyPagination(opts) const result = await this.prismaService.providerAddress.findMany({ where: { clientId }, ...pagination }) - const { data, page } = getPaginatedResult({ items: result, options: pagination }) + const { data, page } = getPaginatedResult({ items: result, pagination }) return { data: data.map(AddressRepository.parseModel), page @@ -73,7 +74,9 @@ export class AddressRepository { return AddressRepository.parseModel(address) } - async findAll(clientId: string, opts?: FindAllFilters): Promise { + async findAll(clientId: string, opts?: FindAllOptions): Promise> { + const pagination = applyPagination(opts?.pagination) + const models = await this.prismaService.providerAddress.findMany({ where: { clientId, @@ -84,10 +87,16 @@ export class AddressRepository { } } : {}) - } + }, + ...pagination }) - return models.map(AddressRepository.parseModel) + const { data, page } = getPaginatedResult({ items: models, pagination }) + + return { + data: data.map(AddressRepository.parseModel), + page + } } async bulkCreate(addresses: Address[]): Promise { diff --git a/apps/vault/src/broker/persistence/repository/connection.repository.ts b/apps/vault/src/broker/persistence/repository/connection.repository.ts index 31bf2db87..d01192035 100644 --- a/apps/vault/src/broker/persistence/repository/connection.repository.ts +++ b/apps/vault/src/broker/persistence/repository/connection.repository.ts @@ -1,4 +1,4 @@ -import { PaginatedResult, PaginationOptions, getPaginatedResult, getPaginationQuery } from '@narval/nestjs-shared' +import { PaginatedResult, PaginationOptions, applyPagination, getPaginatedResult } from '@narval/nestjs-shared' import { HttpStatus, Injectable } from '@nestjs/common' import { ProviderConnection } from '@prisma/client/vault' import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' @@ -26,7 +26,7 @@ export type FilterOptions = { } } -export type FindAllPaginatedOptions = PaginationOptions & FilterOptions +export type FindAllOptions = FilterOptions & { pagination?: PaginationOptions } export const connectionSelectWithoutCredentials = { id: true, @@ -46,9 +46,6 @@ export const connectionSelectWithoutCredentials = { export class ConnectionRepository { constructor(private prismaService: PrismaService) {} - static getCursorOrderColumns(): Array { - return ['createdAt'] - } static parseModel( model?: Partial | null, includeCredentials?: T @@ -147,9 +144,10 @@ export class ConnectionRepository { async findAll( clientId: string, - options?: FilterOptions, + options?: FindAllOptions, includeCredentials?: T - ): Promise { + ): Promise : PaginatedResult> { + const pagination = applyPagination(options?.pagination) const models = await this.prismaService.providerConnection.findMany({ where: { clientId, @@ -159,35 +157,21 @@ export class ConnectionRepository { ? {} : { select: connectionSelectWithoutCredentials - }) - }) - - return models.map((model) => ConnectionRepository.parseModel(model, includeCredentials)) as T extends true - ? ConnectionWithCredentials[] - : Connection[] - } - - async findAllPaginated(clientId: string, options?: FindAllPaginatedOptions): Promise> { - const pagination = getPaginationQuery({ - options: PaginationOptions.parse(options), - cursorOrderColumns: ConnectionRepository.getCursorOrderColumns() - }) - - const models = await this.prismaService.providerConnection.findMany({ - select: connectionSelectWithoutCredentials, - where: { - clientId, - status: options?.filters?.status - }, + }), ...pagination }) + const { data, page } = getPaginatedResult({ items: models, pagination }) - const { data, page } = getPaginatedResult({ items: models, options: pagination }) + const parsedData = data.map((model) => ConnectionRepository.parseModel(model, includeCredentials)) - return { - data: data.map((model) => ConnectionRepository.parseModel(model, false)), + const result = { + data: parsedData, page } + + return result as unknown as T extends true + ? PaginatedResult + : PaginatedResult } async exists(clientId: string, id: string): Promise { diff --git a/apps/vault/src/broker/persistence/repository/sync.repository.ts b/apps/vault/src/broker/persistence/repository/sync.repository.ts index 8f07bb165..a4bbb4d87 100644 --- a/apps/vault/src/broker/persistence/repository/sync.repository.ts +++ b/apps/vault/src/broker/persistence/repository/sync.repository.ts @@ -1,4 +1,4 @@ -import { PaginatedResult, PaginationOptions, getPaginatedResult, getPaginationQuery } from '@narval/nestjs-shared' +import { PaginatedResult, PaginationOptions, applyPagination, getPaginatedResult } from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common/decorators' import { ProviderSync } from '@prisma/client/vault' import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' @@ -6,11 +6,12 @@ import { ModelInvalidException } from '../../core/exception/model-invalid.except import { NotFoundException } from '../../core/exception/not-found.exception' import { Sync, SyncStatus } from '../../core/type/sync.type' -export type FindAllPaginatedOptions = PaginationOptions & { +export type FindAllOptions = PaginationOptions & { filters?: { connectionId?: string status?: SyncStatus } + pagination?: PaginationOptions } export type UpdateSync = { @@ -68,10 +69,6 @@ export class SyncRepository { } } - static getCursorOrderColumns(): Array { - return ['createdAt'] - } - async create(sync: Sync): Promise { await this.prismaService.providerSync.create({ data: SyncRepository.parseEntity(sync) @@ -119,11 +116,8 @@ export class SyncRepository { throw new NotFoundException({ context: { clientId, syncId } }) } - async findAllPaginated(clientId: string, options?: FindAllPaginatedOptions): Promise> { - const pagination = getPaginationQuery({ - options, - cursorOrderColumns: SyncRepository.getCursorOrderColumns() - }) + async findAll(clientId: string, options?: FindAllOptions): Promise> { + const pagination = applyPagination(options?.pagination) const models = await this.prismaService.providerSync.findMany({ where: { @@ -134,7 +128,7 @@ export class SyncRepository { ...pagination }) - const { data, page } = getPaginatedResult({ items: models, options: pagination }) + const { data, page } = getPaginatedResult({ items: models, pagination }) return { data: data.map(SyncRepository.parseModel), diff --git a/apps/vault/src/broker/persistence/repository/wallet.repository.ts b/apps/vault/src/broker/persistence/repository/wallet.repository.ts index 9eca94498..145699fb9 100644 --- a/apps/vault/src/broker/persistence/repository/wallet.repository.ts +++ b/apps/vault/src/broker/persistence/repository/wallet.repository.ts @@ -1,4 +1,4 @@ -import { PaginatedResult, PaginationOptions, getPaginatedResult, getPaginationQuery } from '@narval/nestjs-shared' +import { PaginatedResult, PaginationOptions, applyPagination, getPaginatedResult } from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' import { ProviderAccount, @@ -30,7 +30,7 @@ type FindAllFilters = { } } -export type FindAllOptions = FindAllFilters +export type FindAllOptions = FindAllFilters & { pagination?: PaginationOptions } export type FindAllPaginatedOptions = PaginationOptions & FindAllFilters @@ -38,10 +38,6 @@ export type FindAllPaginatedOptions = PaginationOptions & FindAllFilters export class WalletRepository { constructor(private prismaService: PrismaService) {} - static getCursorOrderColumns(): Array { - return ['createdAt'] - } - static parseModel(wallet: ProviderWalletsAndRelations): Wallet { const { connections, accounts, id, ...walletData } = wallet @@ -53,12 +49,14 @@ export class WalletRepository { return AccountRepository.parseModel(account) }) - return Wallet.parse({ + const parsedWallet = Wallet.parse({ ...walletData, walletId: id, accounts: mappedAccounts, connections: validConnections }) + + return parsedWallet } static parseEntity(entity: Wallet): ProviderWallet { @@ -74,7 +72,8 @@ export class WalletRepository { } async findByClientId(clientId: string, options?: PaginationOptions): Promise> { - const pagination = getPaginationQuery({ options, cursorOrderColumns: WalletRepository.getCursorOrderColumns() }) + const pagination = applyPagination(options) + const result = await this.prismaService.providerWallet.findMany({ where: { clientId }, include: { @@ -93,7 +92,8 @@ export class WalletRepository { }, ...pagination }) - const { data, page } = getPaginatedResult({ items: result, options: pagination }) + + const { data, page } = getPaginatedResult({ items: result, pagination }) return { data: data.map(WalletRepository.parseModel), @@ -129,15 +129,15 @@ export class WalletRepository { return WalletRepository.parseModel(wallet) } - async findAllPaginated(clientId: string, options?: FindAllPaginatedOptions): Promise> { - const pagination = getPaginationQuery({ options, cursorOrderColumns: WalletRepository.getCursorOrderColumns() }) + async findAll(clientId: string, options?: FindAllOptions): Promise> { + const pagination = applyPagination(options?.pagination) const result = await this.prismaService.providerWallet.findMany({ where: { clientId, ...(options?.filters?.walletIds ? { id: { - in: options.filters.walletIds + in: options?.filters.walletIds } } : {}), @@ -145,7 +145,7 @@ export class WalletRepository { ? { connections: { some: { - connectionId: options.filters.connectionId + connectionId: options?.filters.connectionId } } } @@ -167,7 +167,7 @@ export class WalletRepository { }, ...pagination }) - const { data, page } = getPaginatedResult({ items: result, options: pagination }) + const { data, page } = getPaginatedResult({ items: result, pagination }) return { data: data.map(WalletRepository.parseModel), @@ -175,60 +175,11 @@ export class WalletRepository { } } - async findAll(clientId: string, options?: FindAllOptions): Promise { - const models = await this.prismaService.providerWallet.findMany({ - where: { - clientId, - ...(options?.filters?.connectionId - ? { - connections: { - some: { - connectionId: options.filters.connectionId - } - } - } - : {}), - ...(options?.filters?.walletIds - ? { - id: { - in: options.filters.walletIds - } - } - : {}), - ...(options?.filters?.externalIds - ? { - externalId: { - in: options.filters.externalIds - } - } - : {}) - }, - include: { - accounts: { - include: { - addresses: true - } - }, - connections: { - include: { - connection: { - select: connectionSelectWithoutCredentials - } - } - } - } - }) - - return models.map(WalletRepository.parseModel) - } - async findAccountsByWalletId( clientId: string, walletId: string, - options: PaginationOptions + pagination: PaginationOptions ): Promise> { - const pagination = getPaginationQuery({ options, cursorOrderColumns: AccountRepository.getCursorOrderColumns() }) - const wallet = await this.prismaService.providerWallet.findUnique({ where: { clientId, id: walletId }, include: { @@ -253,7 +204,7 @@ export class WalletRepository { context: { walletId } }) } - const { data, page } = getPaginatedResult({ items: wallet.accounts, options: pagination }) + const { data, page } = getPaginatedResult({ items: wallet.accounts, pagination }) return { data: data.map(AccountRepository.parseModel), diff --git a/apps/vault/src/shared/module/persistence/service/test-prisma.service.ts b/apps/vault/src/shared/module/persistence/service/test-prisma.service.ts index 514f2ddf4..ab644d4ec 100644 --- a/apps/vault/src/shared/module/persistence/service/test-prisma.service.ts +++ b/apps/vault/src/shared/module/persistence/service/test-prisma.service.ts @@ -5,7 +5,8 @@ import { TEST_ADDRESSES, TEST_CONNECTIONS, TEST_WALLET_CONNECTIONS, - TEST_WALLETS + TEST_WALLETS, + TEST_WALLETS_WITH_SAME_TIMESTAMP } from '../../../../broker/__test__/util/mock-data' import { PrismaService } from './prisma.service' @@ -51,6 +52,10 @@ export class TestPrismaService { data: TEST_WALLETS }) + await client.providerWallet.createMany({ + data: TEST_WALLETS_WITH_SAME_TIMESTAMP + }) + await client.providerWalletConnection.createMany({ data: TEST_WALLET_CONNECTIONS }) diff --git a/packages/nestjs-shared/src/lib/__test__/unit/pagination.spec.ts b/packages/nestjs-shared/src/lib/__test__/unit/pagination.spec.ts index b2ad17c51..2c3f3610a 100644 --- a/packages/nestjs-shared/src/lib/__test__/unit/pagination.spec.ts +++ b/packages/nestjs-shared/src/lib/__test__/unit/pagination.spec.ts @@ -1,109 +1,253 @@ -import { describe, expect, it } from '@jest/globals' -import { PaginationOptions } from '../../type/pagination.type' -import { getPaginatedResult, getPaginationQuery } from '../../util/pagination.util' - -describe('Pagination Utilities', () => { - // Sample data for testing - const testData = [ - { id: '1', createdAt: new Date('2024-01-01'), name: 'Item 1' }, - { id: '2', createdAt: new Date('2024-01-02'), name: 'Item 2' }, - { id: '3', createdAt: new Date('2024-01-03'), name: 'Item 3' }, - { id: '4', createdAt: new Date('2024-01-04'), name: 'Item 4' }, - { id: '5', createdAt: new Date('2024-01-05'), name: 'Item 5' } - ] +import { DEFAULT_QUERY_PAGINATION_LIMIT } from '../../constant'; +import { PageCursorEncoder, PaginationQuery } from '../../type/pagination.type'; +import { getPaginatedResult, getPaginationQuery } from '../../util/pagination.util'; - describe('getPaginatedResult', () => { - it('returns correct number of items with take parameter', () => { - const result = getPaginatedResult({ - items: testData.slice(0, 3), - options: getPaginationQuery({ - options: PaginationOptions.parse({ limit: 2 }), - cursorOrderColumns: ['createdAt'] - }) - }) - expect(result.data).toHaveLength(2) - expect(result.data[0]).toEqual(testData[0]) - expect(result.data[1]).toEqual(testData[1]) - expect(result.page?.next).toBeDefined() - }) - - it('returns null next cursor on last page', () => { - const result = getPaginatedResult({ - items: testData, - options: getPaginationQuery({ - options: PaginationOptions.parse({ limit: 10 }), - cursorOrderColumns: ['createdAt'] - }) - }) - expect(result.data).toHaveLength(5) - expect(result.page?.next).toEqual(null) - }) - - it('works with cursor-based pagination', () => { - // First page - const firstPage = getPaginatedResult({ - items: testData.slice(0, 3), - options: getPaginationQuery({ - options: PaginationOptions.parse({ limit: 2 }), - cursorOrderColumns: ['createdAt'] - }) - }) - expect(firstPage.data).toHaveLength(2) - expect(firstPage.page?.next).toBeDefined() - - // Second page using cursor - const secondPage = getPaginatedResult({ - items: testData.slice(2), - options: getPaginationQuery({ - options: PaginationOptions.parse({ limit: 2, cursor: firstPage.page?.next }), - cursorOrderColumns: ['createdAt'] - }) - }) - - expect(secondPage.data).toHaveLength(2) - expect(secondPage.data[0]).toEqual(testData[2]) - }) - }) +describe('Pagination System', () => { + const generateMockData = (count: number) => + Array.from({ length: count }, (_, i) => ({ + id: `id${String(i + 1).padStart(3, '0')}`, + createdAt: new Date(2024, 0, i + 1), + name: `Item ${i + 1}` + })); + + const mockData = generateMockData(50); describe('getPaginationQuery', () => { - it('handles empty options', () => { - const query = getPaginationQuery({ cursorOrderColumns: [] }) - expect(query.take).toBeUndefined() - expect(query.skip).toBeUndefined() - expect(query.cursor).toBeUndefined() - }) - - it('defaults lets you orderBy createdAt', () => { - const query = getPaginationQuery({ - options: PaginationOptions.parse({ limit: 10, orderBy: 'createdAt' }), - cursorOrderColumns: ['createdAt'] - }) - expect(query.orderBy).toEqual({ createdAt: 'asc' }) - }) - - it('lets you provide custom orderByFields', () => { - const query = getPaginationQuery({ - options: PaginationOptions.parse({ limit: 10, orderBy: 'name' }), - cursorOrderColumns: ['name'] - }) - expect(query.orderBy).toEqual({ name: 'asc' }) - }) - - it('throws error for invalid orderByFields', () => { - expect(() => - getPaginationQuery({ - options: PaginationOptions.parse({ limit: 10, orderBy: 'name' }), - cursorOrderColumns: ['createdAt'] - }) - ).toThrow() - }) - - it('adds extra record for cursor calculation', () => { - const query = getPaginationQuery({ - options: PaginationOptions.parse({ limit: 10 }), - cursorOrderColumns: ['createdAt'] - }) - expect(query.take).toBe(11) - }) - }) -}) + describe('Forward Pagination', () => { + it('returns default query parameters', () => { + const query = getPaginationQuery({}); + expect(query).toEqual({ + orderBy: undefined, + take: DEFAULT_QUERY_PAGINATION_LIMIT, + skip: undefined, + cursor: undefined + }); + }); + + it('applies custom limit', () => { + const options = PaginationQuery.parse({ + limit: 10, + direction: 'next' + }); + + const query = getPaginationQuery({ options }); + expect(query).toEqual({ + take: 10, + orderBy: undefined, + cursor: undefined, + skip: undefined + }); + }); + + it('handles ascending sort order', () => { + const options = PaginationQuery.parse({ + sortOrder: 'asc', + direction: 'next' + }); + + const query = getPaginationQuery({ options }); + expect(query).toEqual({ + take: 25, + orderBy: undefined, + sortOrder: 'asc', + cursor: undefined, + skip: undefined + }); + }); + }); + + describe('Backward Pagination', () => { + it('handles prev direction with cursor', () => { + const cursor = PageCursorEncoder.parse({ + id: 'id010', + createdAt: new Date('2024-01-10') + }); + + const options = PaginationQuery.parse({ + cursor, + direction: 'prev' + }); + + const query = getPaginationQuery({ options }); + expect(query).toEqual({ + take: -25, + cursor: { + id: 'id010', + createdAt: new Date('2024-01-10') + }, + skip: 1, + orderBy: undefined, + }); + }); + }); + }); + + describe('getPaginatedResult', () => { + describe('Edge Cases', () => { + it('returns empty result for no items', () => { + const result = getPaginatedResult({ items: [] }); + expect(result).toEqual({ + data: [], + page: { next: null } + }); + }); + + it('returns cursor to item when take === 1', () => { + const result = getPaginatedResult({ + items: [mockData[0]], + pagination: { take: 1 } + }); + expect(result).toEqual({ + data: [{ ...mockData[0] }], + page: { next: PageCursorEncoder.parse({ + id: mockData[0].id, + createdAt: mockData[0].createdAt + })} + }); + }); + + it('handles items with same timestamp', () => { + const sameTimeItems = [ + { id: 'id001', createdAt: new Date('2024-01-01T00:00:00Z'), name: 'A' }, + { id: 'id002', createdAt: new Date('2024-01-01T00:00:00Z'), name: 'B' }, + { id: 'id003', createdAt: new Date('2024-01-01T00:00:00Z'), name: 'C' } + ]; + + const result = getPaginatedResult({ + items: sameTimeItems, + pagination: { take: 3 } + }); + + expect(result.data).toHaveLength(2); + expect(result.page?.next).not.toBeNull(); + }); + }); + + describe('Forward Pagination', () => { + it('generates cursor when more items exist', () => { + const items = mockData.slice(0, 11); + const result = getPaginatedResult({ + items, + pagination: { take: 11 } + }); + + expect(result.data).toHaveLength(10); + expect(result.page?.next).not.toBeNull(); + + const decodedCursor = Buffer.from(result.page!.next!, 'base64').toString(); + const [timestamp] = decodedCursor.split('|'); + expect(new Date(timestamp)).toEqual(items[9].createdAt); + }); + }); + + describe('Backward Pagination', () => { + it('paginates through dataset backwards', () => { + const cursor = PageCursorEncoder.parse({ + id: 'id025', + createdAt: new Date('2024-01-25') + }); + + const options = PaginationQuery.parse({ + cursor, + direction: 'prev', + limit: 10 + }); + + const query = getPaginationQuery({ options }); + const items = mockData.slice(10, 20).reverse(); // Important: reverse items for prev direction + + const result = getPaginatedResult({ + items, + pagination: query + }); + + expect(result.data).toHaveLength(9); + expect(result.page?.next).not.toBeNull(); + }); + + it('handles first page in prev direction', () => { + const cursor = PageCursorEncoder.parse({ + id: 'id010', + createdAt: new Date('2024-01-10') + }); + + const options = PaginationQuery.parse({ + cursor, + direction: 'prev' + }); + + const query = getPaginationQuery({ options }); + const items = mockData.slice(0, 9).reverse(); // Important: reverse for prev direction + + const result = getPaginatedResult({ + items, + pagination: { ...query, take: Math.abs(query.take!) } + }); + + expect(result.data).toHaveLength(9); + expect(result.page?.next).toBeNull(); + }); + }); + + describe('Bidirectional Navigation', () => { + it('allows switching between next and prev direction', () => { + // Forward pagination + let options = PaginationQuery.parse({ + limit: 10, + direction: 'next' + }); + + let query = getPaginationQuery({ options }); + let items = mockData.slice(0, 10); + let result = getPaginatedResult({ items, pagination: query }); + + expect(result.data).toHaveLength(9); + expect(result.page?.next).not.toBeNull(); + + // Backward pagination from last item + const cursor = result.page!.next!; + options = PaginationQuery.parse({ + cursor, + limit: 5, + direction: 'prev' + }); + + query = getPaginationQuery({ options }); + items = mockData.slice(0, 5).reverse(); + result = getPaginatedResult({ + items, + pagination: { ...query, take: Math.abs(query.take!) } + }); + + expect(result.data).toHaveLength(4); + expect(result.page?.next).not.toBeNull(); + }); + }); + + it('generates correct cursor for both directions', () => { + const items = generateMockData(4); + + // Forward pagination + const forwardResult = getPaginatedResult({ + items, + pagination: { take: 4 } + }); + + const forwardCursor = Buffer.from(forwardResult.page!.next!, 'base64').toString(); + const [forwardTimestamp, forwardId] = forwardCursor.split('|'); + expect(forwardId).toBe('id003'); + expect(new Date(forwardTimestamp)).toEqual(items[2].createdAt); + + // Backward pagination + const backwardResult = getPaginatedResult({ + items: [...items].reverse(), + pagination: { take: -4 } + }); + + const backwardCursor = Buffer.from(backwardResult.page!.next!, 'base64').toString(); + const [backwardTimestamp, backwardId] = backwardCursor.split('|'); + expect(backwardId).toBe('id002'); + expect(new Date(backwardTimestamp)).toEqual(items[1].createdAt); + }); + }); +}); \ No newline at end of file diff --git a/packages/nestjs-shared/src/lib/constant.ts b/packages/nestjs-shared/src/lib/constant.ts index 8c96a04e0..72b296862 100644 --- a/packages/nestjs-shared/src/lib/constant.ts +++ b/packages/nestjs-shared/src/lib/constant.ts @@ -10,3 +10,21 @@ export const REQUEST_HEADER_CLIENT_SECRET = 'x-client-secret' // export const OTEL_ATTR_CLIENT_ID = 'domain.client.id' + + +// +// Pagination +// + +export const MIN_QUERY_PAGINATION_LIMIT = 1 +export const DEFAULT_QUERY_PAGINATION_LIMIT = 25 +export const MAX_QUERY_PAGINATION_LIMIT = 100 +export const DEFAULT_SERVICE_PAGINATION_LIMIT = 100 +export const DEFAULT_ORDER_BY = [ + { + createdAt: 'desc' as const, + }, + { + id: 'desc' as const, + }, +] as {[key: string]: 'asc' | 'desc'}[] diff --git a/packages/nestjs-shared/src/lib/decorator/pagination-param.decorator.ts b/packages/nestjs-shared/src/lib/decorator/pagination-param.decorator.ts index 9f0623aef..389b5ae61 100644 --- a/packages/nestjs-shared/src/lib/decorator/pagination-param.decorator.ts +++ b/packages/nestjs-shared/src/lib/decorator/pagination-param.decorator.ts @@ -1,7 +1,10 @@ import { createParamDecorator, ExecutionContext } from '@nestjs/common' -import { PaginationOptions } from '../type/pagination.type' +import { PaginationOptions, PaginationQuery } from '../type' +import { getPaginationQuery } from '../util' export const PaginationParam = createParamDecorator((_data: unknown, context: ExecutionContext): PaginationOptions => { const req = context.switchToHttp().getRequest() - return PaginationOptions.parse(req.query) + + const options = PaginationQuery.parse(req.query) + return getPaginationQuery({ options }) }) diff --git a/packages/nestjs-shared/src/lib/type/pagination.type.ts b/packages/nestjs-shared/src/lib/type/pagination.type.ts index 2700ef384..1332ffec3 100644 --- a/packages/nestjs-shared/src/lib/type/pagination.type.ts +++ b/packages/nestjs-shared/src/lib/type/pagination.type.ts @@ -5,45 +5,60 @@ export const Page = z next: z.string().nullable() }) .optional() - export type Page = z.infer +export const PageCursorEncoder = z.object({ + id: z.string(), + createdAt: z.date() +}).transform((data) => { + const cursorData = `${data.createdAt.toISOString()}|${data.id}` + return Buffer.from(cursorData).toString('base64') +}) +export type PageCursorEncoder = z.infer + +export const PageCursorDecoder = z.string() + .transform((cursor) => Buffer.from(cursor, 'base64').toString()) + .pipe( + z.string().regex(/^[^|]+\|[^|]+$/, 'Cursor must contain exactly one "|"') + .transform(str => { + const [timestamp, id] = str.split('|') + return { timestamp, id } + }) + .pipe( + z.object({ + timestamp: z.string().datetime(), + id: z.string().min(1) + }).transform(({ timestamp, id }) => ({ + id, + createdAt: new Date(timestamp) + })) + ) + ) +export type PageCursor = z.infer + export const createPaginatedSchema = (itemSchema: T) => z.object({ data: z.array(itemSchema), - page: Page + page: Page.optional() }) export type PaginatedResult = z.infer>>> -export const PaginationOptions = z +export const PaginationQuery = z .object({ cursor: z.string().optional(), - limit: z.coerce.number().min(1).max(100).default(25).optional(), - orderBy: z.string().optional(), - desc: z - .string() - .optional() - .transform((val) => val === 'true') - // TODO: @ptroger remamed 'desc' into 'sortOrder' that defaults to 'asc' and is optional + limit: z.coerce.number().min(1).max(100).optional().default(25), + sortOrder: z + .enum(['asc', 'desc']) + .optional(), + direction: z.enum(['prev', 'next']).optional().default('next') }) - .transform((data) => ({ - cursor: data.cursor, - limit: data.limit, - orderBy: data.orderBy - ? { - [data.orderBy]: data.desc ? ('desc' as const) : ('asc' as const) - } - : undefined - })) - -export type PaginationOptions = z.infer +export type PaginationQuery = z.infer -export type PrismaPagination = { +export type PaginationOptions = { take?: number - cursor?: { - id: string - } + cursor?: PageCursor skip?: number - orderBy?: Record + sortOrder?: 'asc' | 'desc' + orderBy?: {[key: string]: 'asc' | 'desc'}[] } diff --git a/packages/nestjs-shared/src/lib/util/pagination.util.ts b/packages/nestjs-shared/src/lib/util/pagination.util.ts index 36f432a6b..9464006e0 100644 --- a/packages/nestjs-shared/src/lib/util/pagination.util.ts +++ b/packages/nestjs-shared/src/lib/util/pagination.util.ts @@ -1,71 +1,101 @@ -import { z } from 'zod' -import { PaginatedResult, PaginationOptions, PrismaPagination } from '../type/pagination.type' +import { DEFAULT_ORDER_BY, DEFAULT_QUERY_PAGINATION_LIMIT, DEFAULT_SERVICE_PAGINATION_LIMIT } from '../constant'; +import { PageCursorDecoder, PageCursorEncoder, PaginatedResult, PaginationQuery, PaginationOptions } from '../type/pagination.type' export function getPaginatedResult({ - items, - options + items, + pagination }: { - items: T[] - options?: PrismaPagination + items: T[] + pagination?: PaginationOptions }): PaginatedResult { - if (!items || items.length === 0) { - return { - data: [], - page: { next: null } - } - } + // If there are no items, return an empty array + // If theres only one item, return an empty array: + // - getPaginatedResult expect take to be incremented by one. Take = 1 || -1 means a request for 0 item. + const take = pagination?.take ? Math.abs(pagination.take) : undefined; - // limit was increased by one to determine if there's more data - // if limit === items.length, then there's at least one more item - // if limit > items.length, then there's no more data - // if limit === 0, pagination is disabled - const hasNextPage = options?.take && options?.take > 1 && items.length === options.take + if (!items || items.length === 0 || take && take < 1) { + return { + data: [], + page: { next: null } + } + } - // If there's more data, remove the last item from the list (which is the first item of the next page) - const data = hasNextPage ? items.slice(0, items.length - 1) : items + const hasNextPage = items.length === take - return { - data, - page: { - // cursor is the id of the last item that is actually returned - // we can safely access the last item because we know for sure there's at least one more item - next: hasNextPage ? items[items.length - 2]?.id : null - } - } + // If there's more data and more than one item, remove the last item from the list, it is the first item of the next page + const data = hasNextPage && items.length > 1 + ? pagination?.take && pagination.take < 0 + ? items.slice(1) // For prev direction: take last N items + : items.slice(0, -1) // For next direction: take first N items + : items + + let next = null; + + // we can safely access processedItems[processedItems.length - 2] because we know for sure: + // - take > 1 + // - processedItems.length > 1 + if (hasNextPage) { + // here protecting against an edge case where take = 1 + // in this case, we return the last item as the next cursor because we didn't took one more item + const lastItem = take === 1 ? items[items.length - 1] : items[items.length - 2]; + next = PageCursorEncoder.parse({ id: lastItem.id, createdAt: lastItem.createdAt }); + } + + return { + data, + page: { + next + } + } } export function getPaginationQuery({ options, - cursorOrderColumns }: { - options?: PaginationOptions - cursorOrderColumns: string[] -}): PrismaPagination { - // If no valid fields are provided, default to createdAt - // If someone tries createdAt on a model that doesn't have it, we will throw a 500 + options?: PaginationQuery +}): PaginationOptions { - const validOrderBySchema = z.string().refine( - (value) => cursorOrderColumns.includes(value), - (value) => ({ message: `Invalid orderBy field: ${value}. Valid fields are: ${cursorOrderColumns.join(', ')}` }) - ) + const cursor = options?.cursor ? PageCursorDecoder.parse(options.cursor) : undefined + const multiplier = options?.direction === 'prev' ? -1 : 1 - const key = options?.orderBy && Object.keys(options.orderBy)[0] + let take = DEFAULT_QUERY_PAGINATION_LIMIT; - if (key) { - validOrderBySchema.parse(key) + if (options?.limit && options?.limit > 0) { + take = (options.limit) * multiplier } return { - // if limit is enabled (meaning pagination), limit is increased by one to determine if there's more data - // if limit == 0, pagination is disabled - take: typeof options?.limit === 'number' && options.limit > 0 ? options.limit + 1 : undefined, - ...(options?.cursor && { - cursor: { - id: options.cursor - }, - // Skip the cursor record if it was provided - skip: options.cursor ? 1 : undefined - }), - orderBy: options?.orderBy + take, + cursor, + sortOrder: options?.sortOrder, + skip: options?.cursor ? 1 : undefined, + orderBy: undefined } } + +export const applyPagination = (pagination?: PaginationOptions): { + skip?: number + cursor?: { id: string; createdAt: Date } + take: number + orderBy: { [key: string]: 'asc' | 'desc' }[] +} => { + const multiplier = pagination?.take && pagination?.take < 0 ? -1 : 1 + const skip = pagination?.cursor ? 1 : undefined + const take = (Math.abs(pagination?.take || DEFAULT_SERVICE_PAGINATION_LIMIT) + 1) * multiplier + + let orderBy = DEFAULT_ORDER_BY + + + + if (pagination?.orderBy) { + orderBy = pagination.orderBy + } else if (pagination?.sortOrder) { + orderBy = [ + { createdAt: pagination.sortOrder }, + { id: pagination.sortOrder } + ] + } + + const ret = { take, orderBy, skip, cursor: pagination?.cursor } + return ret +} \ No newline at end of file From bc7a109224f5190adb4e6e6ea016fdf5bb0f3d19 Mon Sep 17 00:00:00 2001 From: Matt Schoch Date: Tue, 17 Dec 2024 17:04:05 +0100 Subject: [PATCH 040/120] Updating prettier config to use single quotes for yaml --- .prettierrc | 1 - config/vault-config.local.yml | 56 ++-- config/vault-config.template.yml | 54 ++-- .../src/lib/__test__/unit/pagination.spec.ts | 298 +++++++++--------- packages/nestjs-shared/src/lib/constant.ts | 9 +- .../src/lib/type/pagination.type.ts | 70 ++-- .../src/lib/util/pagination.util.ts | 145 +++++---- 7 files changed, 318 insertions(+), 315 deletions(-) diff --git a/.prettierrc b/.prettierrc index 2f3b81abc..73f58d72c 100644 --- a/.prettierrc +++ b/.prettierrc @@ -11,7 +11,6 @@ { "files": ["*.yml", "*.yaml"], "options": { - "singleQuote": false, "quoteProps": "preserve" } } diff --git a/config/vault-config.local.yml b/config/vault-config.local.yml index c64bd0204..d485ad91b 100644 --- a/config/vault-config.local.yml +++ b/config/vault-config.local.yml @@ -5,7 +5,7 @@ ##### # Config File Version -version: "1" +version: '1' # Core service configuration env: development # Enum: development, test, production @@ -44,22 +44,22 @@ keyring: # If type=raw, you can set the master key to be used here. # It must be an AES-256 key encoded as a hex string, encrypted by the KEK derived from the masterPassword. Ensure you wrap the string in quotes otherwise it will be interpreted as a number. # If not set, it will be generated during first-boot. - encryptionMasterKey: "0x020578c93e6e65c27de1dddd752a83c6f50a235d90243e15be346c360d2c9d9f64ba17009800030003617070001861726d6f72792e656e6372797074696f6e2d6d6f64756c6500156177732d63727970746f2d7075626c69632d6b6579004441364a5577556f6f6f63476e752b6e6a465477414d56576a516f304b72447a34615a325761515861375236354330464d6567352f69556e4a31386f6a7169533877413d3d0007707572706f7365000f646174612d656e6372797074696f6e000100146e617276616c2e61726d6f72792e656e67696e65002561726d6f72792e656e67696e652e6b656b000000800000000c8ea6c76bba04c350fdd918b50030f5de1f7910661ae891dd5ce7d3b2692c0ae51916e08bfe4125842f259ed5bf6a2c9d5e3ec06411fcbc840805623da471020000100077f11eac1ff728005f6870ffe8864c1618aacbc5cc35879a0a59cfdafac822e4c852bb9e4c70ce8c18f8f02067a5641dffffffff00000001000000000000000000000001000000202ed04425860a9f6645bcac8616979af1ff484edf661a2501c85e20126c1530750784fc11ca5f2e660b11930c500c3d870068306602310098765ed9afdba77cccc53d493a99b8553873511e904175dcda86007eccccf0b660273e451fc2b900f3e7a60133d08c14023100f196c9312409263a59ee9ca227698e819887ef53798bf74b523cf9d8ecf909ae32c8d4c055907b3051a810a45a0f6ff7" + encryptionMasterKey: '0x020578c93e6e65c27de1dddd752a83c6f50a235d90243e15be346c360d2c9d9f64ba17009800030003617070001861726d6f72792e656e6372797074696f6e2d6d6f64756c6500156177732d63727970746f2d7075626c69632d6b6579004441364a5577556f6f6f63476e752b6e6a465477414d56576a516f304b72447a34615a325761515861375236354330464d6567352f69556e4a31386f6a7169533877413d3d0007707572706f7365000f646174612d656e6372797074696f6e000100146e617276616c2e61726d6f72792e656e67696e65002561726d6f72792e656e67696e652e6b656b000000800000000c8ea6c76bba04c350fdd918b50030f5de1f7910661ae891dd5ce7d3b2692c0ae51916e08bfe4125842f259ed5bf6a2c9d5e3ec06411fcbc840805623da471020000100077f11eac1ff728005f6870ffe8864c1618aacbc5cc35879a0a59cfdafac822e4c852bb9e4c70ce8c18f8f02067a5641dffffffff00000001000000000000000000000001000000202ed04425860a9f6645bcac8616979af1ff484edf661a2501c85e20126c1530750784fc11ca5f2e660b11930c500c3d870068306602310098765ed9afdba77cccc53d493a99b8553873511e904175dcda86007eccccf0b660273e451fc2b900f3e7a60133d08c14023100f196c9312409263a59ee9ca227698e819887ef53798bf74b523cf9d8ecf909ae32c8d4c055907b3051a810a45a0f6ff7' # If type=awskms: # The ARN of the AWS KMS key used as the Master Key. encryptionMasterAwsKmsArn: null # HMAC secret for integrity verification of data in the database. Ensure you wrap the string in quotes otherwise it will be interpreted as a number. - hmacSecret: "4ce6d3404a13c971202693b669668e49e2d6d7e190428d0edd99d1cec1536efb" + hmacSecret: '4ce6d3404a13c971202693b669668e49e2d6d7e190428d0edd99d1cec1536efb' # Declarative clients (tenants) clients: # Each key is the client ID dev-client-1: - name: "Example Client" + name: 'Example Client' # Override default baseUrl for this client, used for verifying jwsd/httpsig - baseUrl: "http://localhost:3011" # [optional] + baseUrl: 'http://localhost:3011' # [optional] auth: # Disable all auth; only useful in dev @@ -77,10 +77,10 @@ clients: jwsd: maxAge: 300 requiredComponents: - - "htm" # HTTP method - - "uri" # Target URI - - "created" # Created timestamp - - "ath" # Authorization (accessToken) + - 'htm' # HTTP method + - 'uri' # Target URI + - 'created' # Created timestamp + - 'ath' # Authorization (accessToken) ## # [optional]: Restrict to specific user credentials @@ -93,35 +93,35 @@ clients: allowedUsers: - userId: armory publicKey: - kid: "ZvO6VhPB2Ebe6qmk2RH5ly6qOb2O" # armory staging dev-client-1 - kty: "EC" - crv: "secp256k1" - alg: "ES256K" - x: "PismhbGayPpeTjyxi021v6Z3gwaVak1A7l8PQC337XM" - y: "I2pO8D3v9CFgcZo0ej9jhFHwI3QSVFlaw3l4Gx8QbGI" + kid: 'ZvO6VhPB2Ebe6qmk2RH5ly6qOb2O' # armory staging dev-client-1 + kty: 'EC' + crv: 'secp256k1' + alg: 'ES256K' + x: 'PismhbGayPpeTjyxi021v6Z3gwaVak1A7l8PQC337XM' + y: 'I2pO8D3v9CFgcZo0ej9jhFHwI3QSVFlaw3l4Gx8QbGI' # Authorization options, typically this will be used to pin the policy engine's public signing key. tokenValidation: # (optional) if you want to disable authorization for this client. DO NOT USE IN PRODUCTION. disabled: false # The GNAP Authorization Server that issues tokens - url: "http://armory" + url: 'http://armory' # [optional] JWKS endpoint for the auth server; used for jwt verification. Or you can pin the key. # jwksUrl: https://policy-engine/.well-known/jwks.json # [optional] Pinned public key; used for jwt verification. publicKey: - kid: "ZvO6VhPB2Ebe6qmk2RH5ly6qOb2O" # armory staging dev-client-1 - kty: "EC" - crv: "secp256k1" - alg: "ES256K" - x: "PismhbGayPpeTjyxi021v6Z3gwaVak1A7l8PQC337XM" - y: "I2pO8D3v9CFgcZo0ej9jhFHwI3QSVFlaw3l4Gx8QbGI" + kid: 'ZvO6VhPB2Ebe6qmk2RH5ly6qOb2O' # armory staging dev-client-1 + kty: 'EC' + crv: 'secp256k1' + alg: 'ES256K' + x: 'PismhbGayPpeTjyxi021v6Z3gwaVak1A7l8PQC337XM' + y: 'I2pO8D3v9CFgcZo0ej9jhFHwI3QSVFlaw3l4Gx8QbGI' verification: # JWT verification options audience: null # [optional] Expected audience in JWTs - issuer: "dev-client-1.armory.narval.xyz" # [optional] Expected issuer in JWTs + issuer: 'dev-client-1.armory.narval.xyz' # [optional] Expected issuer in JWTs maxTokenAge: 600 # [optional] Maximum age of JWTs in seconds # Whether tokens must be bound to signing keys requireBoundTokens: true @@ -129,11 +129,11 @@ clients: allowBearerTokens: false # [optional] Paths that can be omitted from request hashing allowWildcard: - - "transactionRequest.maxPriorityFeePerGas" - - "transactionRequest.maxFeePerGas" - - "transactionRequest.gas" - - "transactionRequest.gasPrice" - - "transactionRequest.nonce" + - 'transactionRequest.maxPriorityFeePerGas' + - 'transactionRequest.maxFeePerGas' + - 'transactionRequest.gas' + - 'transactionRequest.gasPrice' + - 'transactionRequest.nonce' # Auth config for requests from this service outgoing: null diff --git a/config/vault-config.template.yml b/config/vault-config.template.yml index 0244f871c..802583de3 100644 --- a/config/vault-config.template.yml +++ b/config/vault-config.template.yml @@ -5,7 +5,7 @@ ##### # Config File Version -version: "1" +version: '1' # Core service configuration env: development # Enum: development, test, production @@ -59,15 +59,15 @@ keyring: # HMAC secret for integrity verification of data in the database. Ensure you wrap the string in quotes otherwise it will be interpreted as a number. # If not set, will be generated during first boot. - hmacSecret: "4ce6d3404a13c971202693b669668e49e2d6d7e190428d0edd99d1cec1536efb" + hmacSecret: '4ce6d3404a13c971202693b669668e49e2d6d7e190428d0edd99d1cec1536efb' # Declarative clients (tenants) clients: # Each key is the client ID dev-client-1: - name: "Example Client" + name: 'Example Client' # Override default baseUrl for this client, used for verifying jwsd/httpsig - baseUrl: "http://localhost:3011" # [optional] + baseUrl: 'http://localhost:3011' # [optional] auth: # Disable all auth; only useful in dev @@ -85,10 +85,10 @@ clients: jwsd: maxAge: 300 requiredComponents: - - "htm" # HTTP method - - "uri" # Target URI - - "created" # Created timestamp - - "ath" # Authorization (accessToken) + - 'htm' # HTTP method + - 'uri' # Target URI + - 'created' # Created timestamp + - 'ath' # Authorization (accessToken) # [optional]: Restrict to specific user credentials # - If set, ONLY these keys will be accepted. @@ -100,37 +100,37 @@ clients: allowedUsers: - userId: admin-user-id-1 publicKey: - kid: "user-credential-id" - kty: "EC" - crv: "secp256k1" - alg: "ES256K" - x: "..." - y: "..." + kid: 'user-credential-id' + kty: 'EC' + crv: 'secp256k1' + alg: 'ES256K' + x: '...' + y: '...' # Authorization options, typically this will be used to pin the policy engine's public signing key. tokenValidation: # (optional) if you want to disable authorization for this client. DO NOT USE IN PRODUCTION. disabled: false # The GNAP Authorization Server that issues tokens - url: "http://armory" + url: 'http://armory' # [optional] JWKS endpoint for the auth server; used for jwt verification. Or you can pin the key below. # jwksUrl: https://policy-engine/.well-known/jwks.json # [optional] Pinned public key; used for jwt verification. Must have this OR jwksUrl. publicKey: - kid: "policy-engine-client-key-id" - kty: "EC" - crv: "secp256k1" - alg: "ES256K" - x: "..." - y: "..." + kid: 'policy-engine-client-key-id' + kty: 'EC' + crv: 'secp256k1' + alg: 'ES256K' + x: '...' + y: '...' verification: # JWT verification options # [optional] Expected audience in JWTs audience: null # [optional] Expected issuer in JWTs - issuer: "dev-client-1.armory.narval.xyz" + issuer: 'dev-client-1.armory.narval.xyz' # [optional] Maximum age of JWTs in seconds maxTokenAge: 600 # Whether tokens must be bound to signing keys @@ -139,11 +139,11 @@ clients: allowBearerTokens: false # [optional] Paths that can be omitted from request hashing, e.g. for authorizing txns with variable gas allowWildcard: - - "transactionRequest.maxPriorityFeePerGas" - - "transactionRequest.maxFeePerGas" - - "transactionRequest.gas" - - "transactionRequest.gasPrice" - - "transactionRequest.nonce" + - 'transactionRequest.maxPriorityFeePerGas' + - 'transactionRequest.maxFeePerGas' + - 'transactionRequest.gas' + - 'transactionRequest.gasPrice' + - 'transactionRequest.nonce' # Auth config for requests from this service outgoing: null diff --git a/packages/nestjs-shared/src/lib/__test__/unit/pagination.spec.ts b/packages/nestjs-shared/src/lib/__test__/unit/pagination.spec.ts index 2c3f3610a..ffdd9170d 100644 --- a/packages/nestjs-shared/src/lib/__test__/unit/pagination.spec.ts +++ b/packages/nestjs-shared/src/lib/__test__/unit/pagination.spec.ts @@ -1,74 +1,74 @@ -import { DEFAULT_QUERY_PAGINATION_LIMIT } from '../../constant'; -import { PageCursorEncoder, PaginationQuery } from '../../type/pagination.type'; -import { getPaginatedResult, getPaginationQuery } from '../../util/pagination.util'; +import { DEFAULT_QUERY_PAGINATION_LIMIT } from '../../constant' +import { PageCursorEncoder, PaginationQuery } from '../../type/pagination.type' +import { getPaginatedResult, getPaginationQuery } from '../../util/pagination.util' describe('Pagination System', () => { - const generateMockData = (count: number) => + const generateMockData = (count: number) => Array.from({ length: count }, (_, i) => ({ id: `id${String(i + 1).padStart(3, '0')}`, createdAt: new Date(2024, 0, i + 1), name: `Item ${i + 1}` - })); + })) - const mockData = generateMockData(50); + const mockData = generateMockData(50) describe('getPaginationQuery', () => { describe('Forward Pagination', () => { it('returns default query parameters', () => { - const query = getPaginationQuery({}); + const query = getPaginationQuery({}) expect(query).toEqual({ - orderBy: undefined, - take: DEFAULT_QUERY_PAGINATION_LIMIT, - skip: undefined, - cursor: undefined - }); - }); + orderBy: undefined, + take: DEFAULT_QUERY_PAGINATION_LIMIT, + skip: undefined, + cursor: undefined + }) + }) it('applies custom limit', () => { const options = PaginationQuery.parse({ limit: 10, direction: 'next' - }); - - const query = getPaginationQuery({ options }); + }) + + const query = getPaginationQuery({ options }) expect(query).toEqual({ take: 10, orderBy: undefined, cursor: undefined, skip: undefined - }); - }); + }) + }) it('handles ascending sort order', () => { const options = PaginationQuery.parse({ sortOrder: 'asc', direction: 'next' - }); - - const query = getPaginationQuery({ options }); + }) + + const query = getPaginationQuery({ options }) expect(query).toEqual({ take: 25, orderBy: undefined, sortOrder: 'asc', cursor: undefined, skip: undefined - }); - }); - }); + }) + }) + }) describe('Backward Pagination', () => { it('handles prev direction with cursor', () => { const cursor = PageCursorEncoder.parse({ id: 'id010', createdAt: new Date('2024-01-10') - }); - + }) + const options = PaginationQuery.parse({ cursor, direction: 'prev' - }); - - const query = getPaginationQuery({ options }); + }) + + const query = getPaginationQuery({ options }) expect(query).toEqual({ take: -25, cursor: { @@ -76,118 +76,120 @@ describe('Pagination System', () => { createdAt: new Date('2024-01-10') }, skip: 1, - orderBy: undefined, - }); - }); - }); - }); + orderBy: undefined + }) + }) + }) + }) describe('getPaginatedResult', () => { describe('Edge Cases', () => { it('returns empty result for no items', () => { - const result = getPaginatedResult({ items: [] }); + const result = getPaginatedResult({ items: [] }) expect(result).toEqual({ data: [], page: { next: null } - }); - }); + }) + }) it('returns cursor to item when take === 1', () => { - const result = getPaginatedResult({ - items: [mockData[0]], - pagination: { take: 1 } - }); + const result = getPaginatedResult({ + items: [mockData[0]], + pagination: { take: 1 } + }) expect(result).toEqual({ data: [{ ...mockData[0] }], - page: { next: PageCursorEncoder.parse({ - id: mockData[0].id, - createdAt: mockData[0].createdAt - })} - }); - }); + page: { + next: PageCursorEncoder.parse({ + id: mockData[0].id, + createdAt: mockData[0].createdAt + }) + } + }) + }) it('handles items with same timestamp', () => { const sameTimeItems = [ { id: 'id001', createdAt: new Date('2024-01-01T00:00:00Z'), name: 'A' }, { id: 'id002', createdAt: new Date('2024-01-01T00:00:00Z'), name: 'B' }, { id: 'id003', createdAt: new Date('2024-01-01T00:00:00Z'), name: 'C' } - ]; - - const result = getPaginatedResult({ - items: sameTimeItems, - pagination: { take: 3 } - }); - - expect(result.data).toHaveLength(2); - expect(result.page?.next).not.toBeNull(); - }); - }); + ] + + const result = getPaginatedResult({ + items: sameTimeItems, + pagination: { take: 3 } + }) + + expect(result.data).toHaveLength(2) + expect(result.page?.next).not.toBeNull() + }) + }) describe('Forward Pagination', () => { it('generates cursor when more items exist', () => { - const items = mockData.slice(0, 11); - const result = getPaginatedResult({ - items, - pagination: { take: 11 } - }); - - expect(result.data).toHaveLength(10); - expect(result.page?.next).not.toBeNull(); - - const decodedCursor = Buffer.from(result.page!.next!, 'base64').toString(); - const [timestamp] = decodedCursor.split('|'); - expect(new Date(timestamp)).toEqual(items[9].createdAt); - }); - }); + const items = mockData.slice(0, 11) + const result = getPaginatedResult({ + items, + pagination: { take: 11 } + }) + + expect(result.data).toHaveLength(10) + expect(result.page?.next).not.toBeNull() + + const decodedCursor = Buffer.from(result.page!.next!, 'base64').toString() + const [timestamp] = decodedCursor.split('|') + expect(new Date(timestamp)).toEqual(items[9].createdAt) + }) + }) describe('Backward Pagination', () => { it('paginates through dataset backwards', () => { const cursor = PageCursorEncoder.parse({ id: 'id025', createdAt: new Date('2024-01-25') - }); - + }) + const options = PaginationQuery.parse({ cursor, direction: 'prev', limit: 10 - }); - - const query = getPaginationQuery({ options }); - const items = mockData.slice(10, 20).reverse(); // Important: reverse items for prev direction - - const result = getPaginatedResult({ - items, + }) + + const query = getPaginationQuery({ options }) + const items = mockData.slice(10, 20).reverse() // Important: reverse items for prev direction + + const result = getPaginatedResult({ + items, pagination: query - }); - - expect(result.data).toHaveLength(9); - expect(result.page?.next).not.toBeNull(); - }); + }) + + expect(result.data).toHaveLength(9) + expect(result.page?.next).not.toBeNull() + }) it('handles first page in prev direction', () => { const cursor = PageCursorEncoder.parse({ id: 'id010', createdAt: new Date('2024-01-10') - }); - + }) + const options = PaginationQuery.parse({ cursor, direction: 'prev' - }); - - const query = getPaginationQuery({ options }); - const items = mockData.slice(0, 9).reverse(); // Important: reverse for prev direction - - const result = getPaginatedResult({ - items, + }) + + const query = getPaginationQuery({ options }) + const items = mockData.slice(0, 9).reverse() // Important: reverse for prev direction + + const result = getPaginatedResult({ + items, pagination: { ...query, take: Math.abs(query.take!) } - }); - - expect(result.data).toHaveLength(9); - expect(result.page?.next).toBeNull(); - }); - }); + }) + + expect(result.data).toHaveLength(9) + expect(result.page?.next).toBeNull() + }) + }) describe('Bidirectional Navigation', () => { it('allows switching between next and prev direction', () => { @@ -195,59 +197,59 @@ describe('Pagination System', () => { let options = PaginationQuery.parse({ limit: 10, direction: 'next' - }); - - let query = getPaginationQuery({ options }); - let items = mockData.slice(0, 10); - let result = getPaginatedResult({ items, pagination: query }); - - expect(result.data).toHaveLength(9); - expect(result.page?.next).not.toBeNull(); - + }) + + let query = getPaginationQuery({ options }) + let items = mockData.slice(0, 10) + let result = getPaginatedResult({ items, pagination: query }) + + expect(result.data).toHaveLength(9) + expect(result.page?.next).not.toBeNull() + // Backward pagination from last item - const cursor = result.page!.next!; + const cursor = result.page!.next! options = PaginationQuery.parse({ cursor, limit: 5, direction: 'prev' - }); - - query = getPaginationQuery({ options }); - items = mockData.slice(0, 5).reverse(); + }) + + query = getPaginationQuery({ options }) + items = mockData.slice(0, 5).reverse() result = getPaginatedResult({ - items, + items, pagination: { ...query, take: Math.abs(query.take!) } - }); - - expect(result.data).toHaveLength(4); - expect(result.page?.next).not.toBeNull(); - }); - }); + }) + + expect(result.data).toHaveLength(4) + expect(result.page?.next).not.toBeNull() + }) + }) it('generates correct cursor for both directions', () => { - const items = generateMockData(4); - - // Forward pagination - const forwardResult = getPaginatedResult({ - items, - pagination: { take: 4 } - }); - - const forwardCursor = Buffer.from(forwardResult.page!.next!, 'base64').toString(); - const [forwardTimestamp, forwardId] = forwardCursor.split('|'); - expect(forwardId).toBe('id003'); - expect(new Date(forwardTimestamp)).toEqual(items[2].createdAt); - - // Backward pagination - const backwardResult = getPaginatedResult({ - items: [...items].reverse(), - pagination: { take: -4 } - }); - - const backwardCursor = Buffer.from(backwardResult.page!.next!, 'base64').toString(); - const [backwardTimestamp, backwardId] = backwardCursor.split('|'); - expect(backwardId).toBe('id002'); - expect(new Date(backwardTimestamp)).toEqual(items[1].createdAt); - }); - }); -}); \ No newline at end of file + const items = generateMockData(4) + + // Forward pagination + const forwardResult = getPaginatedResult({ + items, + pagination: { take: 4 } + }) + + const forwardCursor = Buffer.from(forwardResult.page!.next!, 'base64').toString() + const [forwardTimestamp, forwardId] = forwardCursor.split('|') + expect(forwardId).toBe('id003') + expect(new Date(forwardTimestamp)).toEqual(items[2].createdAt) + + // Backward pagination + const backwardResult = getPaginatedResult({ + items: [...items].reverse(), + pagination: { take: -4 } + }) + + const backwardCursor = Buffer.from(backwardResult.page!.next!, 'base64').toString() + const [backwardTimestamp, backwardId] = backwardCursor.split('|') + expect(backwardId).toBe('id002') + expect(new Date(backwardTimestamp)).toEqual(items[1].createdAt) + }) + }) +}) diff --git a/packages/nestjs-shared/src/lib/constant.ts b/packages/nestjs-shared/src/lib/constant.ts index 72b296862..1f5b47c6c 100644 --- a/packages/nestjs-shared/src/lib/constant.ts +++ b/packages/nestjs-shared/src/lib/constant.ts @@ -11,7 +11,6 @@ export const REQUEST_HEADER_CLIENT_SECRET = 'x-client-secret' export const OTEL_ATTR_CLIENT_ID = 'domain.client.id' - // // Pagination // @@ -22,9 +21,9 @@ export const MAX_QUERY_PAGINATION_LIMIT = 100 export const DEFAULT_SERVICE_PAGINATION_LIMIT = 100 export const DEFAULT_ORDER_BY = [ { - createdAt: 'desc' as const, + createdAt: 'desc' as const }, { - id: 'desc' as const, - }, -] as {[key: string]: 'asc' | 'desc'}[] + id: 'desc' as const + } +] as { [key: string]: 'asc' | 'desc' }[] diff --git a/packages/nestjs-shared/src/lib/type/pagination.type.ts b/packages/nestjs-shared/src/lib/type/pagination.type.ts index 1332ffec3..8b738d9ee 100644 --- a/packages/nestjs-shared/src/lib/type/pagination.type.ts +++ b/packages/nestjs-shared/src/lib/type/pagination.type.ts @@ -7,32 +7,39 @@ export const Page = z .optional() export type Page = z.infer -export const PageCursorEncoder = z.object({ - id: z.string(), - createdAt: z.date() -}).transform((data) => { - const cursorData = `${data.createdAt.toISOString()}|${data.id}` - return Buffer.from(cursorData).toString('base64') -}) -export type PageCursorEncoder = z.infer +export const PageCursorEncoder = z + .object({ + id: z.string(), + createdAt: z.date() + }) + .transform((data) => { + const cursorData = `${data.createdAt.toISOString()}|${data.id}` + return Buffer.from(cursorData).toString('base64') + }) +export type PageCursorEncoder = z.infer -export const PageCursorDecoder = z.string() +export const PageCursorDecoder = z + .string() .transform((cursor) => Buffer.from(cursor, 'base64').toString()) .pipe( - z.string().regex(/^[^|]+\|[^|]+$/, 'Cursor must contain exactly one "|"') - .transform(str => { - const [timestamp, id] = str.split('|') - return { timestamp, id } - }) - .pipe( - z.object({ - timestamp: z.string().datetime(), - id: z.string().min(1) - }).transform(({ timestamp, id }) => ({ - id, - createdAt: new Date(timestamp) - })) - ) + z + .string() + .regex(/^[^|]+\|[^|]+$/, 'Cursor must contain exactly one "|"') + .transform((str) => { + const [timestamp, id] = str.split('|') + return { timestamp, id } + }) + .pipe( + z + .object({ + timestamp: z.string().datetime(), + id: z.string().min(1) + }) + .transform(({ timestamp, id }) => ({ + id, + createdAt: new Date(timestamp) + })) + ) ) export type PageCursor = z.infer @@ -44,15 +51,12 @@ export const createPaginatedSchema = (itemSchema: T) => export type PaginatedResult = z.infer>>> -export const PaginationQuery = z - .object({ - cursor: z.string().optional(), - limit: z.coerce.number().min(1).max(100).optional().default(25), - sortOrder: z - .enum(['asc', 'desc']) - .optional(), - direction: z.enum(['prev', 'next']).optional().default('next') - }) +export const PaginationQuery = z.object({ + cursor: z.string().optional(), + limit: z.coerce.number().min(1).max(100).optional().default(25), + sortOrder: z.enum(['asc', 'desc']).optional(), + direction: z.enum(['prev', 'next']).optional().default('next') +}) export type PaginationQuery = z.infer export type PaginationOptions = { @@ -60,5 +64,5 @@ export type PaginationOptions = { cursor?: PageCursor skip?: number sortOrder?: 'asc' | 'desc' - orderBy?: {[key: string]: 'asc' | 'desc'}[] + orderBy?: { [key: string]: 'asc' | 'desc' }[] } diff --git a/packages/nestjs-shared/src/lib/util/pagination.util.ts b/packages/nestjs-shared/src/lib/util/pagination.util.ts index 9464006e0..4bf0eac65 100644 --- a/packages/nestjs-shared/src/lib/util/pagination.util.ts +++ b/packages/nestjs-shared/src/lib/util/pagination.util.ts @@ -1,67 +1,69 @@ -import { DEFAULT_ORDER_BY, DEFAULT_QUERY_PAGINATION_LIMIT, DEFAULT_SERVICE_PAGINATION_LIMIT } from '../constant'; -import { PageCursorDecoder, PageCursorEncoder, PaginatedResult, PaginationQuery, PaginationOptions } from '../type/pagination.type' +import { DEFAULT_ORDER_BY, DEFAULT_QUERY_PAGINATION_LIMIT, DEFAULT_SERVICE_PAGINATION_LIMIT } from '../constant' +import { + PageCursorDecoder, + PageCursorEncoder, + PaginatedResult, + PaginationOptions, + PaginationQuery +} from '../type/pagination.type' export function getPaginatedResult({ - items, - pagination + items, + pagination }: { - items: T[] - pagination?: PaginationOptions + items: T[] + pagination?: PaginationOptions }): PaginatedResult { - // If there are no items, return an empty array - // If theres only one item, return an empty array: - // - getPaginatedResult expect take to be incremented by one. Take = 1 || -1 means a request for 0 item. - const take = pagination?.take ? Math.abs(pagination.take) : undefined; - - if (!items || items.length === 0 || take && take < 1) { - return { - data: [], - page: { next: null } - } - } - - const hasNextPage = items.length === take - - // If there's more data and more than one item, remove the last item from the list, it is the first item of the next page - const data = hasNextPage && items.length > 1 - ? pagination?.take && pagination.take < 0 - ? items.slice(1) // For prev direction: take last N items - : items.slice(0, -1) // For next direction: take first N items - : items - - let next = null; + // If there are no items, return an empty array + // If theres only one item, return an empty array: + // - getPaginatedResult expect take to be incremented by one. Take = 1 || -1 means a request for 0 item. + const take = pagination?.take ? Math.abs(pagination.take) : undefined + + if (!items || items.length === 0 || (take && take < 1)) { + return { + data: [], + page: { next: null } + } + } - // we can safely access processedItems[processedItems.length - 2] because we know for sure: - // - take > 1 - // - processedItems.length > 1 - if (hasNextPage) { - // here protecting against an edge case where take = 1 - // in this case, we return the last item as the next cursor because we didn't took one more item - const lastItem = take === 1 ? items[items.length - 1] : items[items.length - 2]; - next = PageCursorEncoder.parse({ id: lastItem.id, createdAt: lastItem.createdAt }); - } + const hasNextPage = items.length === take + + // If there's more data and more than one item, remove the last item from the list, it is the first item of the next page + const data = + hasNextPage && items.length > 1 + ? pagination?.take && pagination.take < 0 + ? items.slice(1) // For prev direction: take last N items + : items.slice(0, -1) // For next direction: take first N items + : items + + let next = null + + // we can safely access processedItems[processedItems.length - 2] because we know for sure: + // - take > 1 + // - processedItems.length > 1 + if (hasNextPage) { + // here protecting against an edge case where take = 1 + // in this case, we return the last item as the next cursor because we didn't took one more item + const lastItem = take === 1 ? items[items.length - 1] : items[items.length - 2] + next = PageCursorEncoder.parse({ id: lastItem.id, createdAt: lastItem.createdAt }) + } - return { - data, - page: { - next - } - } + return { + data, + page: { + next + } + } } -export function getPaginationQuery({ - options, -}: { - options?: PaginationQuery -}): PaginationOptions { - +export function getPaginationQuery({ options }: { options?: PaginationQuery }): PaginationOptions { const cursor = options?.cursor ? PageCursorDecoder.parse(options.cursor) : undefined const multiplier = options?.direction === 'prev' ? -1 : 1 - let take = DEFAULT_QUERY_PAGINATION_LIMIT; + let take = DEFAULT_QUERY_PAGINATION_LIMIT if (options?.limit && options?.limit > 0) { - take = (options.limit) * multiplier + take = options.limit * multiplier } return { @@ -73,29 +75,26 @@ export function getPaginationQuery({ } } -export const applyPagination = (pagination?: PaginationOptions): { - skip?: number - cursor?: { id: string; createdAt: Date } - take: number - orderBy: { [key: string]: 'asc' | 'desc' }[] +export const applyPagination = ( + pagination?: PaginationOptions +): { + skip?: number + cursor?: { id: string; createdAt: Date } + take: number + orderBy: { [key: string]: 'asc' | 'desc' }[] } => { - const multiplier = pagination?.take && pagination?.take < 0 ? -1 : 1 - const skip = pagination?.cursor ? 1 : undefined - const take = (Math.abs(pagination?.take || DEFAULT_SERVICE_PAGINATION_LIMIT) + 1) * multiplier - - let orderBy = DEFAULT_ORDER_BY + const multiplier = pagination?.take && pagination?.take < 0 ? -1 : 1 + const skip = pagination?.cursor ? 1 : undefined + const take = (Math.abs(pagination?.take || DEFAULT_SERVICE_PAGINATION_LIMIT) + 1) * multiplier + let orderBy = DEFAULT_ORDER_BY + if (pagination?.orderBy) { + orderBy = pagination.orderBy + } else if (pagination?.sortOrder) { + orderBy = [{ createdAt: pagination.sortOrder }, { id: pagination.sortOrder }] + } - if (pagination?.orderBy) { - orderBy = pagination.orderBy - } else if (pagination?.sortOrder) { - orderBy = [ - { createdAt: pagination.sortOrder }, - { id: pagination.sortOrder } - ] - } - - const ret = { take, orderBy, skip, cursor: pagination?.cursor } - return ret -} \ No newline at end of file + const ret = { take, orderBy, skip, cursor: pagination?.cursor } + return ret +} From e3f703c5ddd236956956c642a4f4f4127145c05c Mon Sep 17 00:00:00 2001 From: Matt Schoch Date: Wed, 18 Dec 2024 10:12:29 +0100 Subject: [PATCH 041/120] Adding eddsa signing for jwsd headers too --- apps/vault/src/broker/__test__/util/mock-data.ts | 16 +++++++++------- .../src/shared/guard/authorization.guard.ts | 1 + packages/signature/src/lib/schemas.ts | 2 +- packages/signature/src/lib/sign.ts | 4 ++++ 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/apps/vault/src/broker/__test__/util/mock-data.ts b/apps/vault/src/broker/__test__/util/mock-data.ts index e672f79e8..beed2b76b 100644 --- a/apps/vault/src/broker/__test__/util/mock-data.ts +++ b/apps/vault/src/broker/__test__/util/mock-data.ts @@ -1,13 +1,11 @@ import { - buildSignerEip191, + buildSignerForAlg, hash, hexToBase64Url, JwsdHeader, PrivateKey, - privateKeyToHex, secp256k1PrivateKeyToJwk, secp256k1PrivateKeyToPublicJwk, - SigningAlg, signJwsd } from '@narval/signature' import { Client } from '../../../shared/type/domain.type' @@ -26,11 +24,15 @@ const { d: _d, ...publicKey } = privateKey export const TEST_CLIENT_ID = 'test-client-id' export const TEST_DIFFERENT_CLIENT_ID = 'different-client-id' -const PRIVATE_KEY = '0x7cfef3303797cbc7515d9ce22ffe849c701b0f2812f999b0847229c47951fca5' - const now = new Date() +const PRIVATE_KEY = '0x7cfef3303797cbc7515d9ce22ffe849c701b0f2812f999b0847229c47951fca5' export const testUserPrivateJwk = secp256k1PrivateKeyToJwk(PRIVATE_KEY) export const testUserPublicJWK = secp256k1PrivateKeyToPublicJwk(PRIVATE_KEY) +/* Here's a variant of using an eddsa key to sign it too; just to prove it works with other alg*/ +// const PRIVATE_KEY = '0x0101010101010101010101010101010101010101010101010101010101010101' +// export const testUserPrivateJwk = ed25519PrivateKeyToJwk(PRIVATE_KEY) +// export const testUserPublicJWK = ed25519PrivateKeyToPublicJwk(PRIVATE_KEY) + export const testClient: Client = { clientId: TEST_CLIENT_ID, auth: { @@ -314,9 +316,9 @@ export const getJwsd = async ({ }) => { const now = Math.floor(Date.now() / 1000) - const jwsdSigner = buildSignerEip191(await privateKeyToHex(userPrivateJwk)) + const jwsdSigner = await buildSignerForAlg(userPrivateJwk) const jwsdHeader: JwsdHeader = { - alg: SigningAlg.EIP191, + alg: userPrivateJwk.alg, kid: userPrivateJwk.kid, typ: 'gnap-binding-jwsd', htm: htm || 'POST', diff --git a/apps/vault/src/shared/guard/authorization.guard.ts b/apps/vault/src/shared/guard/authorization.guard.ts index 9e1aa8d96..1af0080d9 100644 --- a/apps/vault/src/shared/guard/authorization.guard.ts +++ b/apps/vault/src/shared/guard/authorization.guard.ts @@ -75,6 +75,7 @@ export class AuthorizationGuard implements CanActivate { break } catch (err) { // Continue trying other keys + this.logger.warn('Invalid request signature, but could have another allowedUser key', { error: err }) continue } } diff --git a/packages/signature/src/lib/schemas.ts b/packages/signature/src/lib/schemas.ts index 7ee896cd7..07e399983 100644 --- a/packages/signature/src/lib/schemas.ts +++ b/packages/signature/src/lib/schemas.ts @@ -166,7 +166,7 @@ export const Header = z.intersection( ) export const JwsdHeader = z.object({ - alg: z.union([z.literal('ES256K'), z.literal('ES256'), z.literal('RS256'), z.literal('EIP191')]), + alg: z.union([z.literal('ES256K'), z.literal('ES256'), z.literal('RS256'), z.literal('EIP191'), z.literal('EDDSA')]), kid: z.string().min(1).describe('The key ID to identify the signing key.'), typ: z .literal('gnap-binding-jwsd') diff --git a/packages/signature/src/lib/sign.ts b/packages/signature/src/lib/sign.ts index 8e14c3740..cfaa0026b 100644 --- a/packages/signature/src/lib/sign.ts +++ b/packages/signature/src/lib/sign.ts @@ -287,6 +287,10 @@ export const buildSignerForAlg = async (jwk: Jwk) => { } case SigningAlg.RS256: return buildSignerRs256(privateKey) + case SigningAlg.ED25519: { + const privateKeyHex = await privateKeyToHex(privateKey) + return buildSignerEdDSA(privateKeyHex) + } default: throw new JwtError({ message: 'Unsupported signing algorithm', From f94106360fdd9faf936aef6dc304ce9a4729dd06 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Wed, 18 Dec 2024 11:04:29 +0100 Subject: [PATCH 042/120] Fix crash on sync (#39) --- apps/vault/src/broker/core/service/sync.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/vault/src/broker/core/service/sync.service.ts b/apps/vault/src/broker/core/service/sync.service.ts index 716ac7a17..17f9b96f9 100644 --- a/apps/vault/src/broker/core/service/sync.service.ts +++ b/apps/vault/src/broker/core/service/sync.service.ts @@ -35,9 +35,9 @@ export class SyncService { ) ) - await Promise.allSettled( + Promise.all( connections.map(async (connection) => { - this.anchorageSyncService.sync(connection) + return this.anchorageSyncService.sync(connection) }) ) .then(async () => { From b87929019443c41365a1a900472ebb35963d38bc Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Wed, 18 Dec 2024 11:16:45 +0100 Subject: [PATCH 043/120] Fix anchorage sigend request (#41) --- .../http/client/anchorage-request-builder.ts | 80 +++++++++++++++++++ .../broker/http/client/anchorage.client.ts | 13 ++- 2 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 apps/vault/src/broker/http/client/anchorage-request-builder.ts diff --git a/apps/vault/src/broker/http/client/anchorage-request-builder.ts b/apps/vault/src/broker/http/client/anchorage-request-builder.ts new file mode 100644 index 000000000..2958ed88c --- /dev/null +++ b/apps/vault/src/broker/http/client/anchorage-request-builder.ts @@ -0,0 +1,80 @@ +import { Ed25519PrivateKey, privateKeyToHex } from '@narval/signature' +import { sign } from '@noble/ed25519' +import { AxiosRequestConfig } from 'axios' +import { z } from 'zod' +import { UrlParserException } from '../../core/exception/url-parser.exception' + +export const HttpMethod = z.union([ + z.literal('GET'), + z.literal('POST'), + z.literal('PATCH'), + z.literal('PUT'), + z.literal('DELETE') +]) +export type HttpMethod = z.infer + +export type BuildAnchorageRequestParams = { + url: string + method: HttpMethod + body?: unknown + apiKey: string + signKey: Ed25519PrivateKey + now?: Date +} + +export const parseUrl = (url: string): string => { + const regex = /(\/v\d+(?:\/.*)?)$/ + const match = url.match(regex) + + if (!match) { + throw new UrlParserException({ + message: 'No version pattern found in the URL', + url + }) + } + + return match[1] +} + +export const serializePayload = (time: number, method: HttpMethod, endpoint: string, body: unknown): string => { + return `${time}${method}${endpoint}${body && method !== 'GET' ? JSON.stringify(body) : ''}` +} + +export const buildAnchorageSignedRequest = async ({ + url, + method, + body, + apiKey, + signKey, + now +}: BuildAnchorageRequestParams): Promise => { + const timestamp = now ? now.getTime() : new Date().getTime() + const time = Math.floor(timestamp / 1000) + + const endpoint = parseUrl(url) + const serializedPayload = serializePayload(time, method, endpoint, body) + + const signatureRequest = Buffer.from(serializedPayload, 'utf8').toString('hex') + + const signHexKey = await privateKeyToHex(signKey) + const hexSignature = await sign(signatureRequest, signHexKey.slice(2)) + const signature = Buffer.from(hexSignature).toString('hex') + + const headers = { + 'Api-Access-Key': apiKey, + 'Api-Signature': signature, + 'Api-Timestamp': time, + 'Content-Type': 'application/json' + } + + const data = body && method !== 'GET' ? body : undefined + + const config: AxiosRequestConfig = { + url, + method, + headers, + data + } + + return config +} diff --git a/apps/vault/src/broker/http/client/anchorage.client.ts b/apps/vault/src/broker/http/client/anchorage.client.ts index fa522ee91..9740403ab 100644 --- a/apps/vault/src/broker/http/client/anchorage.client.ts +++ b/apps/vault/src/broker/http/client/anchorage.client.ts @@ -9,6 +9,7 @@ import { ZodType, z } from 'zod' import { BrokerException } from '../../core/exception/broker.exception' import { ProxyRequestException } from '../../core/exception/proxy-request.exception' import { UrlParserException } from '../../core/exception/url-parser.exception' +import { HttpMethod, buildAnchorageSignedRequest } from './anchorage-request-builder' const Amount = z.object({ quantity: z.string(), @@ -174,6 +175,7 @@ export class AnchorageClient { 'Api-Timestamp': timestamp, 'Content-Type': 'application/json' } + const data = request.data && request.method !== 'GET' ? request.data : undefined return { @@ -232,8 +234,15 @@ export class AnchorageClient { apiKey: string }): Observable { return from( - this.authorize({ - request: opts.request, + // this.authorize({ + // request: opts.request, + // apiKey: opts.apiKey, + // signKey: opts.signKey + // }) + buildAnchorageSignedRequest({ + url: opts.request.url as string, + method: opts.request.method as HttpMethod, + body: opts.request.data, apiKey: opts.apiKey, signKey: opts.signKey }) From a3e7ba219e0fd33fd59e61bbd06c0b6f36aba846 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Wed, 18 Dec 2024 13:36:22 +0100 Subject: [PATCH 044/120] Wrap provider API responses into "data" (#42) * Refactor provider API to wrap responses into data * Fix wrong conflict resolution --- .../src/broker/__test__/e2e/account.spec.ts | 74 ++++---- .../src/broker/__test__/e2e/address.spec.ts | 57 +++--- .../broker/__test__/e2e/connection.spec.ts | 56 +++--- .../src/broker/__test__/e2e/sync.spec.ts | 16 +- .../src/broker/__test__/e2e/wallet.spec.ts | 167 ++++++++++-------- .../core/lib/anchorage-request-builder.ts | 51 ++++++ .../broker/http/client/anchorage.client.ts | 11 ++ .../rest/controller/account.controller.ts | 31 +--- .../rest/controller/address.controller.ts | 18 +- .../rest/controller/connection.controller.ts | 63 ++++--- .../http/rest/controller/sync.controller.ts | 35 ++-- .../http/rest/controller/wallet.controller.ts | 35 ++-- .../http/rest/dto/response/connection.dto.ts | 4 - .../dto/response/paginated-accounts.dto.ts | 2 +- .../dto/response/paginated-addresses.dto.ts | 2 +- .../dto/response/paginated-connections.dto.ts | 2 +- .../rest/dto/response/paginated-syncs.dto.ts | 4 +- .../dto/response/paginated-wallets.dto.ts | 2 +- ...account.dto.ts => provider-account.dto.ts} | 2 +- ...address.dto.ts => provider-address.dto.ts} | 2 +- ...list.dto.ts => provider-connection.dto.ts} | 6 +- .../provider-pending-connection.dto.ts | 30 ++++ .../{wallet.dto.ts => provider-wallet.dto.ts} | 2 +- .../http/rest/dto/response/sync-list.dto.ts | 9 - .../rest/dto/response/sync-started.dto.ts | 9 + .../http/rest/dto/response/sync-status.dto.ts | 7 +- .../broker/http/rest/dto/response/sync.dto.ts | 7 +- .../module/persistence/schema/schema.prisma | 4 + 28 files changed, 407 insertions(+), 301 deletions(-) create mode 100644 apps/vault/src/broker/core/lib/anchorage-request-builder.ts delete mode 100644 apps/vault/src/broker/http/rest/dto/response/connection.dto.ts rename apps/vault/src/broker/http/rest/dto/response/{account.dto.ts => provider-account.dto.ts} (91%) rename apps/vault/src/broker/http/rest/dto/response/{address.dto.ts => provider-address.dto.ts} (91%) rename apps/vault/src/broker/http/rest/dto/response/{connection-list.dto.ts => provider-connection.dto.ts} (56%) create mode 100644 apps/vault/src/broker/http/rest/dto/response/provider-pending-connection.dto.ts rename apps/vault/src/broker/http/rest/dto/response/{wallet.dto.ts => provider-wallet.dto.ts} (89%) delete mode 100644 apps/vault/src/broker/http/rest/dto/response/sync-list.dto.ts create mode 100644 apps/vault/src/broker/http/rest/dto/response/sync-started.dto.ts diff --git a/apps/vault/src/broker/__test__/e2e/account.spec.ts b/apps/vault/src/broker/__test__/e2e/account.spec.ts index 7bfa0eff7..7df2d90d2 100644 --- a/apps/vault/src/broker/__test__/e2e/account.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/account.spec.ts @@ -66,7 +66,7 @@ describe('Account', () => { describe('GET /accounts', () => { it('returns the list of accounts with addresses for the client', async () => { - const response = await request(app.getHttpServer()) + const { status, body } = await request(app.getHttpServer()) .get('/provider/accounts') .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( @@ -78,18 +78,19 @@ describe('Account', () => { htm: 'GET' }) ) - expect(response.status).toEqual(HttpStatus.OK) - expect(response.body).toEqual({ - accounts: TEST_ACCOUNTS.map(getExpectedAccount).reverse(), + expect(body).toEqual({ + data: TEST_ACCOUNTS.map(getExpectedAccount).reverse(), page: { next: null } }) + + expect(status).toEqual(HttpStatus.OK) }) - it('returns empty list for unknown client', async () => { - const response = await request(app.getHttpServer()) + it('returns 404 for unknown client', async () => { + const { status } = await request(app.getHttpServer()) .get('/provider/accounts') .set(REQUEST_HEADER_CLIENT_ID, 'unknown-client') .set( @@ -101,14 +102,15 @@ describe('Account', () => { htm: 'GET' }) ) - expect(response.status).toEqual(HttpStatus.NOT_FOUND) + + expect(status).toEqual(HttpStatus.NOT_FOUND) }) }) describe('GET /accounts with pagination', () => { it('returns limited number of accounts when limit parameter is provided', async () => { const limit = 1 - const response = await request(app.getHttpServer()) + const { status, body } = await request(app.getHttpServer()) .get(`/provider/accounts?limit=${limit}`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( @@ -120,10 +122,11 @@ describe('Account', () => { htm: 'GET' }) ) - expect(response.status).toEqual(HttpStatus.OK) - expect(response.body.accounts).toHaveLength(limit) - expect(response.body.page).toHaveProperty('next') + expect(body.data).toHaveLength(limit) + expect(body.page).toHaveProperty('next') + + expect(status).toEqual(HttpStatus.OK) }) it('returns next page of results using cursor', async () => { @@ -140,6 +143,7 @@ describe('Account', () => { htm: 'GET' }) ) + expect(firstResponse.status).toEqual(HttpStatus.OK) const cursor = firstResponse.body.page?.next @@ -158,10 +162,11 @@ describe('Account', () => { htm: 'GET' }) ) - expect(secondResponse.status).toEqual(HttpStatus.OK) - expect(secondResponse.body.accounts).toHaveLength(1) - expect(secondResponse.body.accounts[0].accountId).not.toBe(firstResponse.body.accounts[0].accountId) + expect(secondResponse.body.data).toHaveLength(1) + expect(secondResponse.body.data[0].accountId).not.toBe(firstResponse.body.data[0].accountId) + + expect(secondResponse.status).toEqual(HttpStatus.OK) }) it('handles ascending createdAt parameter correctly', async () => { @@ -179,7 +184,7 @@ describe('Account', () => { ) expect(response.status).toEqual(HttpStatus.OK) - const returnedAccounts = response.body.accounts + const returnedAccounts = response.body.data expect(returnedAccounts).toHaveLength(TEST_ACCOUNTS.length) expect(new Date(returnedAccounts[1].createdAt).getTime()).toBeGreaterThanOrEqual( new Date(returnedAccounts[0].createdAt).getTime() @@ -190,7 +195,7 @@ describe('Account', () => { describe('GET /accounts/:accountId', () => { it('returns the account details with addresses', async () => { const account = TEST_ACCOUNTS[0] - const response = await request(app.getHttpServer()) + const { status, body } = await request(app.getHttpServer()) .get(`/provider/accounts/${account.id}`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( @@ -202,14 +207,16 @@ describe('Account', () => { htm: 'GET' }) ) - expect(response.status).toEqual(HttpStatus.OK) - expect(response.body).toEqual({ - account: getExpectedAccount(account) + + expect(body).toEqual({ + data: getExpectedAccount(account) }) + + expect(status).toEqual(HttpStatus.OK) }) it('returns 404 with proper error message for non-existent account', async () => { - const response = await request(app.getHttpServer()) + const { status } = await request(app.getHttpServer()) .get(`/provider/accounts/non-existent`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( @@ -221,11 +228,12 @@ describe('Account', () => { htm: 'GET' }) ) - expect(response.status).toEqual(HttpStatus.NOT_FOUND) + + expect(status).toEqual(HttpStatus.NOT_FOUND) }) it('returns 404 when accessing account from unknown client', async () => { - const response = await request(app.getHttpServer()) + const { status } = await request(app.getHttpServer()) .get(`/provider/accounts/${TEST_ACCOUNTS[0].id}`) .set(REQUEST_HEADER_CLIENT_ID, 'unknown-client') .set( @@ -237,7 +245,8 @@ describe('Account', () => { htm: 'GET' }) ) - expect(response.status).toEqual(HttpStatus.NOT_FOUND) + + expect(status).toEqual(HttpStatus.NOT_FOUND) }) }) @@ -246,7 +255,7 @@ describe('Account', () => { const account = TEST_ACCOUNTS[0] const addresses = TEST_ADDRESSES.filter((addr) => addr.accountId === account.id) - const response = await request(app.getHttpServer()) + const { status, body } = await request(app.getHttpServer()) .get(`/provider/accounts/${account.id}/addresses`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( @@ -258,14 +267,15 @@ describe('Account', () => { htm: 'GET' }) ) - expect(response.status).toEqual(HttpStatus.OK) - expect(response.body).toEqual({ - addresses: addresses.map(getExpectedAddress), + expect(body).toEqual({ + data: addresses.map(getExpectedAddress), page: { next: null } }) + + expect(status).toEqual(HttpStatus.OK) }) it('returns empty addresses array for account with no addresses', async () => { @@ -279,7 +289,7 @@ describe('Account', () => { data: accountWithoutAddresses }) - const response = await request(app.getHttpServer()) + const { status, body } = await request(app.getHttpServer()) .get(`/provider/accounts/${accountWithoutAddresses.id}/addresses`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( @@ -291,13 +301,15 @@ describe('Account', () => { htm: 'GET' }) ) - expect(response.status).toEqual(HttpStatus.OK) - expect(response.body).toEqual({ - addresses: [], + + expect(body).toEqual({ + data: [], page: { next: null } }) + + expect(status).toEqual(HttpStatus.OK) }) }) }) diff --git a/apps/vault/src/broker/__test__/e2e/address.spec.ts b/apps/vault/src/broker/__test__/e2e/address.spec.ts index e75a60034..0080d315c 100644 --- a/apps/vault/src/broker/__test__/e2e/address.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/address.spec.ts @@ -59,7 +59,7 @@ describe('Address', () => { describe('GET /addresses', () => { it('returns the list of addresses for the client', async () => { - const response = await request(app.getHttpServer()) + const { status, body } = await request(app.getHttpServer()) .get(`/provider/addresses`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( @@ -71,21 +71,22 @@ describe('Address', () => { htm: 'GET' }) ) - expect(response.status).toEqual(HttpStatus.OK) - expect(response.body).toEqual({ - addresses: TEST_ADDRESSES.map(getExpectedAddress).reverse(), + expect(body).toEqual({ + data: TEST_ADDRESSES.map(getExpectedAddress).reverse(), page: { next: null } }) + + expect(status).toEqual(HttpStatus.OK) }) }) describe('GET /addresses with pagination', () => { it('returns limited number of addresses when limit parameter is provided', async () => { const limit = 1 - const response = await request(app.getHttpServer()) + const { body } = await request(app.getHttpServer()) .get(`/provider/addresses?limit=${limit}`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( @@ -98,8 +99,8 @@ describe('Address', () => { }) ) - expect(response.body.addresses).toHaveLength(limit) - expect(response.body.page).toHaveProperty('next') + expect(body.data).toHaveLength(limit) + expect(body.page).toHaveProperty('next') }) it('returns next page of results using cursor', async () => { @@ -119,6 +120,7 @@ describe('Address', () => { .expect(HttpStatus.OK) const cursor = firstResponse.body.page?.next + expect(cursor).toBeDefined() // Second request using the cursor @@ -136,37 +138,39 @@ describe('Address', () => { ) .expect(HttpStatus.OK) - expect(secondResponse.body.addresses).toHaveLength(1) - expect(secondResponse.body.addresses[0].addressId).not.toBe(firstResponse.body.addresses[0].addressId) + expect(secondResponse.body.data).toHaveLength(1) + expect(secondResponse.body.data[0].addressId).not.toBe(firstResponse.body.data[0].addressId) }) - it('handles ascending createdAt parameter correctly', async () => { - const response = await request(app.getHttpServer()) - .get('/provider/addresses?sortOrder=asc') + it('handles descending orderBy createdAt parameter correctly', async () => { + const { status, body } = await request(app.getHttpServer()) + .get('/provider/addresses?orderBy=createdAt&desc=true') .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( 'detached-jws', await getJwsd({ userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/addresses?sortOrder=asc', + requestUrl: '/provider/addresses?orderBy=createdAt&desc=true', payload: {}, htm: 'GET' }) ) - .expect(HttpStatus.OK) - const returnedAddresses = response.body.addresses - expect(returnedAddresses).toHaveLength(TEST_ADDRESSES.length) - expect(new Date(returnedAddresses[1].createdAt).getTime()).toBeGreaterThanOrEqual( - new Date(returnedAddresses[0].createdAt).getTime() + const addresses = body.data + + expect(addresses).toHaveLength(TEST_ADDRESSES.length) + expect(new Date(addresses[1].createdAt).getTime()).toBeGreaterThanOrEqual( + new Date(addresses[0].createdAt).getTime() ) + + expect(status).toEqual(HttpStatus.OK) }) }) describe('GET /addresses/:addressId', () => { it('returns the address details', async () => { const address = TEST_ADDRESSES[0] - const response = await request(app.getHttpServer()) + const { status, body } = await request(app.getHttpServer()) .get(`/provider/addresses/${address.id}`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( @@ -179,14 +183,15 @@ describe('Address', () => { }) ) - expect(response.body).toEqual({ - address: getExpectedAddress(address) + expect(body).toEqual({ + data: getExpectedAddress(address) }) - expect(response.status).toBe(HttpStatus.OK) + + expect(status).toBe(HttpStatus.OK) }) it('returns 404 with proper error message for non-existent address', async () => { - const response = await request(app.getHttpServer()) + const { status } = await request(app.getHttpServer()) .get('/provider/addresses/non-existent') .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( @@ -199,11 +204,11 @@ describe('Address', () => { }) ) - expect(response.status).toBe(HttpStatus.NOT_FOUND) + expect(status).toBe(HttpStatus.NOT_FOUND) }) it('returns 404 when accessing address from different client', async () => { - const response = await request(app.getHttpServer()) + const { status } = await request(app.getHttpServer()) .get(`/provider/addresses/${TEST_ADDRESSES[0].id}`) .set(REQUEST_HEADER_CLIENT_ID, 'different-client') .set( @@ -216,7 +221,7 @@ describe('Address', () => { }) ) - expect(response.status).toBe(HttpStatus.NOT_FOUND) + expect(status).toBe(HttpStatus.NOT_FOUND) }) }) }) diff --git a/apps/vault/src/broker/__test__/e2e/connection.spec.ts b/apps/vault/src/broker/__test__/e2e/connection.spec.ts index 78c277647..30ce71dfd 100644 --- a/apps/vault/src/broker/__test__/e2e/connection.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/connection.spec.ts @@ -156,7 +156,9 @@ describe('Connection', () => { ) .send(connection) - expect(body).toMatchObject({ + const { data } = body + + expect(data).toMatchObject({ clientId, connectionId: connection.connectionId, provider: connection.provider, @@ -164,19 +166,19 @@ describe('Connection', () => { }) // Ensure it doesn't leak the private key. - expect(body.credentials).toEqual(undefined) - expect(body.privateKey).toEqual(undefined) + expect(data.credentials).toEqual(undefined) + expect(data.privateKey).toEqual(undefined) // Ensure it doesn't leak a private key as JWK by including the `d` // property. - toMatchZodSchema(body.publicKey.jwk, ed25519PublicKeySchema) - toMatchZodSchema(body.encryptionPublicKey.jwk, rsaPublicKeySchema) + toMatchZodSchema(data.publicKey.jwk, ed25519PublicKeySchema) + toMatchZodSchema(data.encryptionPublicKey.jwk, rsaPublicKeySchema) - toMatchZodSchema(body.publicKey.hex, hexSchema) + toMatchZodSchema(data.publicKey.hex, hexSchema) - expect(body.publicKey.keyId).toEqual(expect.any(String)) - expect(body.encryptionPublicKey.keyId).toEqual(expect.any(String)) - expect(body.encryptionPublicKey.pem).toEqual(expect.any(String)) // ensure we also respond w/ the PEM format. + expect(data.publicKey.keyId).toEqual(expect.any(String)) + expect(data.encryptionPublicKey.keyId).toEqual(expect.any(String)) + expect(data.encryptionPublicKey.pem).toEqual(expect.any(String)) // ensure we also respond w/ the PEM format. expect(status).toEqual(HttpStatus.CREATED) }) @@ -249,7 +251,7 @@ describe('Connection', () => { const createdConnection = await connectionService.findById(clientId, connection.connectionId, true) - expect(body).toEqual({ + expect(body.data).toEqual({ clientId, connectionId, url, @@ -375,7 +377,7 @@ describe('Connection', () => { url }) - expect(body).toEqual({ + expect(body.data).toEqual({ clientId, connectionId, label, @@ -403,7 +405,7 @@ describe('Connection', () => { if (isActiveConnection(createdConnection)) { expect(createdConnection.credentials).toMatchObject({ apiKey: credentials.apiKey, - publicKey: pendingConnection.publicKey.jwk + publicKey: pendingConnection.data.publicKey.jwk }) } else { fail('expected an active connection') @@ -433,7 +435,7 @@ describe('Connection', () => { const encryptedCredentials = await rsaEncrypt( JSON.stringify(credentials), - pendingConnection.encryptionPublicKey.jwk + pendingConnection.data.encryptionPublicKey.jwk ) const { status, body } = await request(app.getHttpServer()) @@ -461,7 +463,7 @@ describe('Connection', () => { encryptedCredentials }) - expect(body).toEqual({ + expect(body.data).toEqual({ clientId, connectionId, label, @@ -489,7 +491,7 @@ describe('Connection', () => { if (isActiveConnection(createdConnection)) { expect(createdConnection.credentials).toMatchObject({ apiKey: credentials.apiKey, - publicKey: pendingConnection.publicKey.jwk + publicKey: pendingConnection.data.publicKey.jwk }) } else { fail('expected an active connection') @@ -570,9 +572,9 @@ describe('Connection', () => { ) .send() - expect(body.connections.length).toEqual(3) + expect(body.data.length).toEqual(3) - expect(body.connections[0]).toMatchObject({ + expect(body.data[0]).toMatchObject({ clientId, url, connectionId: expect.any(String), @@ -581,7 +583,7 @@ describe('Connection', () => { provider: Provider.ANCHORAGE, updatedAt: expect.any(String) }) - expect(body.connections[0]).not.toHaveProperty('credentials') + expect(body.data[0]).not.toHaveProperty('credentials') expect(status).toEqual(HttpStatus.OK) }) @@ -602,7 +604,7 @@ describe('Connection', () => { ) .send() - expect(body.connections.length).toEqual(1) + expect(body.data.length).toEqual(1) expect(body.page).toHaveProperty('next') }) @@ -636,7 +638,7 @@ describe('Connection', () => { ) .send() - expect(pageTwo.connections.length).toEqual(1) + expect(pageTwo.data.length).toEqual(1) expect(pageTwo.page).toHaveProperty('next') }) @@ -677,7 +679,7 @@ describe('Connection', () => { ) .send() - expect(body).toMatchObject({ + expect(body.data).toMatchObject({ connectionId: expect.any(String), clientId, createdAt: expect.any(String), @@ -732,8 +734,8 @@ describe('Connection', () => { encryptedCredentials }) - expect(body).toMatchObject({ label: 'new label' }) - expect(body).not.toHaveProperty('credentials') + expect(body.data).toMatchObject({ label: 'new label' }) + expect(body.data).not.toHaveProperty('credentials') expect(status).toEqual(HttpStatus.OK) @@ -765,7 +767,7 @@ describe('Connection', () => { expect(status).toEqual(HttpStatus.OK) expect(body).toMatchObject({ - wallets: [getExpectedWallet(TEST_WALLETS[0])], + data: [getExpectedWallet(TEST_WALLETS[0])], page: {} }) }) @@ -800,7 +802,7 @@ describe('Connection', () => { expect(status).toEqual(HttpStatus.OK) expect(body).toMatchObject({ - wallets: [], + data: [], page: {} }) }) @@ -835,7 +837,7 @@ describe('Connection', () => { expect(status).toEqual(HttpStatus.OK) expect(body).toMatchObject({ - accounts: accountsForConnection.map(getExpectedAccount).reverse(), + data: accountsForConnection.map(getExpectedAccount).reverse(), page: {} }) }) @@ -871,7 +873,7 @@ describe('Connection', () => { expect(status).toEqual(HttpStatus.OK) expect(body).toMatchObject({ - accounts: [], + data: [], page: {} }) }) diff --git a/apps/vault/src/broker/__test__/e2e/sync.spec.ts b/apps/vault/src/broker/__test__/e2e/sync.spec.ts index 65bc4b4c9..55ed0a905 100644 --- a/apps/vault/src/broker/__test__/e2e/sync.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/sync.spec.ts @@ -159,7 +159,7 @@ describe('Sync', () => { const syncs = await syncService.findAll(clientId) const [sync] = syncs.data - expect(body).toMatchObject({ + expect(body.data).toMatchObject({ started: true, syncs: [ { @@ -195,7 +195,7 @@ describe('Sync', () => { const syncs = await syncService.findAll(clientId) const [sync] = syncs.data - expect(body).toEqual({ + expect(body.data).toEqual({ started: true, syncs: [ { @@ -233,7 +233,7 @@ describe('Sync', () => { ) .send() - expect(body).toMatchObject({ + expect(body.data).toMatchObject({ clientId: sync.clientId, connectionId: sync.connectionId, createdAt: sync.createdAt.toISOString(), @@ -267,7 +267,7 @@ describe('Sync', () => { .send() expect(body).toMatchObject({ - syncs: [ + data: [ { clientId: sync.clientId, connectionId: sync.connectionId, @@ -282,7 +282,7 @@ describe('Sync', () => { expect(status).toEqual(HttpStatus.OK) - expect(body.syncs.length).toEqual(1) + expect(body.data.length).toEqual(1) }) it('responds with the specific sync filter by connection', async () => { @@ -305,7 +305,7 @@ describe('Sync', () => { .send() expect(body).toMatchObject({ - syncs: [ + data: [ { clientId: sync.clientId, connectionId: sync.connectionId, @@ -318,7 +318,7 @@ describe('Sync', () => { expect(status).toEqual(HttpStatus.OK) - expect(body.syncs.length).toEqual(1) + expect(body.data.length).toEqual(1) }) it('responds with limited number of syncs when limit is given', async () => { @@ -339,7 +339,7 @@ describe('Sync', () => { ) .send() - expect(body.syncs.length).toEqual(1) + expect(body.data.length).toEqual(1) expect(body.page).toHaveProperty('next') }) }) diff --git a/apps/vault/src/broker/__test__/e2e/wallet.spec.ts b/apps/vault/src/broker/__test__/e2e/wallet.spec.ts index 06a41a9ba..361369860 100644 --- a/apps/vault/src/broker/__test__/e2e/wallet.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/wallet.spec.ts @@ -48,6 +48,7 @@ describe('Wallet', () => { testPrismaService = module.get(TestPrismaService) provisionService = module.get(ProvisionService) clientService = module.get(ClientService) + await testPrismaService.truncateAll() }) @@ -70,7 +71,7 @@ describe('Wallet', () => { describe('GET /wallets', () => { it('returns the list of wallets with accounts for the client', async () => { - const res = await request(app.getHttpServer()) + const { status, body } = await request(app.getHttpServer()) .get('/provider/wallets') .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( @@ -83,19 +84,20 @@ describe('Wallet', () => { }) ) - expect(res.status).toBe(HttpStatus.OK) - expect(res.body).toEqual({ - wallets: TEST_WALLETS.filter((w) => w.clientId === TEST_CLIENT_ID) + expect(body).toEqual({ + data: TEST_WALLETS.filter((w) => w.clientId === TEST_CLIENT_ID) .map(getExpectedWallet) .reverse(), page: { next: null } }) + + expect(status).toBe(HttpStatus.OK) }) - it("doesn't return private connection information", async () => { - const res = await request(app.getHttpServer()) + it('does not return private connection information', async () => { + const { status, body } = await request(app.getHttpServer()) .get('/provider/wallets') .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( @@ -108,18 +110,18 @@ describe('Wallet', () => { }) ) - expect(res.status).toBe(HttpStatus.OK) - - for (const wallet of res.body.wallets) { + for (const wallet of body.data) { for (const connection of wallet.connections) { expect(connection).not.toHaveProperty('credentials') expect(connection).not.toHaveProperty('revokedAt') } } + + expect(status).toBe(HttpStatus.OK) }) it('returns 404 auth error for unknown client', async () => { - const res = await request(app.getHttpServer()) + const { status, body } = await request(app.getHttpServer()) .get('/provider/wallets') .set(REQUEST_HEADER_CLIENT_ID, 'unknown-client') .set( @@ -132,19 +134,20 @@ describe('Wallet', () => { }) ) - expect(res.status).toBe(HttpStatus.NOT_FOUND) - expect(res.body).toEqual({ + expect(body).toEqual({ message: 'Client not found', statusCode: HttpStatus.NOT_FOUND, stack: expect.any(String) }) + + expect(status).toBe(HttpStatus.NOT_FOUND) }) }) describe('GET /wallets with pagination', () => { it('returns limited number of wallets when limit parameter is provided', async () => { const limit = 2 - const res = await request(app.getHttpServer()) + const { status, body } = await request(app.getHttpServer()) .get(`/provider/wallets?limit=${limit}`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( @@ -157,16 +160,17 @@ describe('Wallet', () => { }) ) - expect(res.status).toBe(HttpStatus.OK) - expect(res.body.wallets).toHaveLength(limit) - expect(res.body.page.next).toBeDefined() + expect(body.data).toHaveLength(limit) + expect(body.page.next).toBeDefined() // First two wallets should be returned in createdAt descending order - expect(res.body.wallets.map((w: Wallet) => w.walletId)).toEqual(['wallet-5', 'wallet-4']) + expect(body.data.map((w: Wallet) => w.walletId)).toEqual(['wallet-5', 'wallet-4']) + + expect(status).toBe(HttpStatus.OK) }) it('returns all wallets when limit exceeds total count', async () => { const limit = 10 - const res = await request(app.getHttpServer()) + const { status, body } = await request(app.getHttpServer()) .get(`/provider/wallets?limit=${limit}`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( @@ -179,9 +183,10 @@ describe('Wallet', () => { }) ) - expect(res.status).toBe(HttpStatus.OK) - expect(res.body.wallets).toHaveLength(5) // Total wallets for TEST_CLIENT_ID - expect(res.body.page.next).toBeNull() // No next page + expect(body.data).toHaveLength(5) // Total wallets for TEST_CLIENT_ID + expect(body.page.next).toBeNull() // No next page + + expect(status).toBe(HttpStatus.OK) }) it('navigates through all pages using cursor', async () => { @@ -194,7 +199,7 @@ describe('Wallet', () => { ? `/provider/wallets?limit=${limit}&cursor=${cursor}` : `/provider/wallets?limit=${limit}` - const res = await request(app.getHttpServer()) + const { status, body } = await request(app.getHttpServer()) .get(url) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( @@ -207,9 +212,9 @@ describe('Wallet', () => { }) ) - expect(res.status).toBe(HttpStatus.OK) - allWallets.push(...res.body.wallets) - cursor = res.body.page.next + expect(status).toBe(HttpStatus.OK) + allWallets.push(...body.data) + cursor = body.page.next } while (cursor) expect(allWallets).toHaveLength(5) // Total wallets for TEST_CLIENT_ID @@ -219,7 +224,7 @@ describe('Wallet', () => { }) it('handles descending order by createdAt parameter correctly', async () => { - const res = await request(app.getHttpServer()) + const { status, body } = await request(app.getHttpServer()) .get('/provider/wallets?sortOrder=desc') .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( @@ -232,20 +237,19 @@ describe('Wallet', () => { }) ) - expect(res.status).toBe(HttpStatus.OK) - const wallets = res.body.wallets - // Should return wallets in reverse order - expect(wallets.map((w: Wallet) => w.walletId)).toEqual([ + expect(body.data.map((w: Wallet) => w.walletId)).toEqual([ 'wallet-5', 'wallet-4', 'wallet-3', 'wallet-2', 'wallet-1' ]) + + expect(status).toBe(HttpStatus.OK) }) it('handles ascending order by createdAt parameter correctly', async () => { - const res = await request(app.getHttpServer()) + const { status, body } = await request(app.getHttpServer()) .get('/provider/wallets?sortOrder=asc') .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( @@ -258,8 +262,7 @@ describe('Wallet', () => { }) ) - expect(res.status).toBe(HttpStatus.OK) - const wallets = res.body.wallets + const wallets = body.data // Should return wallets in normal order expect(wallets.map((w: Wallet) => w.walletId)).toEqual([ 'wallet-1', @@ -268,10 +271,12 @@ describe('Wallet', () => { 'wallet-4', 'wallet-5' ]) + + expect(status).toBe(HttpStatus.OK) }) it('handles asc order when createdAt is same for multiple wallets', async () => { - const res = await request(app.getHttpServer()) + const { status, body } = await request(app.getHttpServer()) .get('/provider/wallets?sortOrder=asc') .set(REQUEST_HEADER_CLIENT_ID, TEST_DIFFERENT_CLIENT_ID) .set( @@ -284,17 +289,18 @@ describe('Wallet', () => { }) ) - expect(res.status).toBe(HttpStatus.OK) - const wallets = res.body.wallets + const wallets = body.data const walletIds = wallets.map((w: Wallet) => w.walletId) // Should return wallets in normal order expect(walletIds).toEqual(['wallet-6', 'wallet-7', 'wallet-8']) + + expect(status).toBe(HttpStatus.OK) }) it('handles desc order when createdAt is same for multiple wallets', async () => { - const res = await request(app.getHttpServer()) + const { status, body } = await request(app.getHttpServer()) .get('/provider/wallets?sortOrder=desc') .set(REQUEST_HEADER_CLIENT_ID, TEST_DIFFERENT_CLIENT_ID) .set( @@ -307,12 +313,13 @@ describe('Wallet', () => { }) ) - expect(res.status).toBe(HttpStatus.OK) - const wallets = res.body.wallets + const wallets = body.data const walletIds = wallets.map((w: Wallet) => w.walletId) // Should return wallets in normal order expect(walletIds).toEqual(['wallet-8', 'wallet-7', 'wallet-6']) + + expect(status).toBe(HttpStatus.OK) }) describe('GET /wallets pagination with different directions and sort orders', () => { @@ -320,7 +327,7 @@ describe('Wallet', () => { beforeEach(async () => { // Get initial cursor from latest wallet - const initialRes = await request(app.getHttpServer()) + const { status, body } = await request(app.getHttpServer()) .get('/provider/wallets?limit=1&sortOrder=desc') .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( @@ -333,12 +340,13 @@ describe('Wallet', () => { }) ) - expect(initialRes.status).toBe(HttpStatus.OK) - cursor = initialRes.body.page.next + expect(status).toBe(HttpStatus.OK) + + cursor = body.page.next }) it('returns no results when paginating prev in desc order from newest record', async () => { - const res = await request(app.getHttpServer()) + const { status, body } = await request(app.getHttpServer()) .get(`/provider/wallets?cursor=${cursor}&direction=prev&limit=2&sortOrder=desc`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( @@ -351,13 +359,13 @@ describe('Wallet', () => { }) ) - expect(res.status).toBe(HttpStatus.OK) - expect(res.body.wallets).toHaveLength(0) - expect(res.body.wallets).toEqual([]) + expect(body.data).toEqual([]) + + expect(status).toBe(HttpStatus.OK) }) it('returns next older records when paginating next in desc order', async () => { - const res = await request(app.getHttpServer()) + const { status, body } = await request(app.getHttpServer()) .get(`/provider/wallets?cursor=${cursor}&direction=next&limit=2&sortOrder=desc`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( @@ -370,13 +378,14 @@ describe('Wallet', () => { }) ) - expect(res.status).toBe(HttpStatus.OK) - expect(res.body.wallets).toHaveLength(2) - expect(res.body.wallets.map((w: Wallet) => w.walletId)).toEqual(['wallet-4', 'wallet-3']) + expect(body.data).toHaveLength(2) + expect(body.data.map((w: Wallet) => w.walletId)).toEqual(['wallet-4', 'wallet-3']) + + expect(status).toBe(HttpStatus.OK) }) it('returns next newer records when paginating prev in asc order', async () => { - const res = await request(app.getHttpServer()) + const { status, body } = await request(app.getHttpServer()) .get(`/provider/wallets?cursor=${cursor}&direction=prev&limit=2&sortOrder=asc`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( @@ -389,15 +398,16 @@ describe('Wallet', () => { }) ) - expect(res.status).toBe(HttpStatus.OK) - expect(res.body.wallets).toHaveLength(2) - expect(res.body.wallets.map((w: Wallet) => w.walletId)).toEqual(['wallet-3', 'wallet-4']) + expect(body.data).toHaveLength(2) + expect(body.data.map((w: Wallet) => w.walletId)).toEqual(['wallet-3', 'wallet-4']) + + expect(status).toBe(HttpStatus.OK) }) }) it('returns empty array when cursor points to first wallet and direction is prev', async () => { // First get the earliest wallet - const initialRes = await request(app.getHttpServer()) + const firstRequest = await request(app.getHttpServer()) .get('/provider/wallets?limit=1&sortOrder=asc') .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( @@ -410,9 +420,9 @@ describe('Wallet', () => { }) ) - const cursor = initialRes.body.page.next + const cursor = firstRequest.body.page.next - const res = await request(app.getHttpServer()) + const { status, body } = await request(app.getHttpServer()) .get(`/provider/wallets?cursor=${cursor}&sortOrder=asc&direction=prev`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( @@ -425,16 +435,17 @@ describe('Wallet', () => { }) ) - expect(res.status).toBe(HttpStatus.OK) - expect(res.body.wallets).toHaveLength(0) - expect(res.body.page.next).toBeNull() + expect(body.data).toHaveLength(0) + expect(body.page.next).toBeNull() + + expect(status).toBe(HttpStatus.OK) }) }) describe('GET /wallets/:walletId', () => { it('returns the wallet details with accounts and addresses', async () => { const wallet = TEST_WALLETS[0] - const res = await request(app.getHttpServer()) + const { status, body } = await request(app.getHttpServer()) .get(`/provider/wallets/${wallet.id}`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( @@ -447,15 +458,15 @@ describe('Wallet', () => { }) ) - expect(res.status).toBe(HttpStatus.OK) - - expect(res.body).toEqual({ - wallet: getExpectedWallet(wallet) + expect(body).toEqual({ + data: getExpectedWallet(wallet) }) + + expect(status).toBe(HttpStatus.OK) }) it('returns 404 with proper error message for non-existent wallet', async () => { - const res = await request(app.getHttpServer()) + const { status } = await request(app.getHttpServer()) .get(`/provider/wallets/non-existent`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( @@ -468,12 +479,12 @@ describe('Wallet', () => { }) ) - expect(res.status).toBe(HttpStatus.NOT_FOUND) + expect(status).toBe(HttpStatus.NOT_FOUND) }) it('returns 404 when accessing wallet from wrong client', async () => { const wallet = TEST_WALLETS[0] - const res = await request(app.getHttpServer()) + const { status } = await request(app.getHttpServer()) .get(`/provider/wallets/${wallet.id}`) .set(REQUEST_HEADER_CLIENT_ID, 'wrong-client') .set( @@ -486,7 +497,7 @@ describe('Wallet', () => { }) ) - expect(res.status).toBe(HttpStatus.NOT_FOUND) + expect(status).toBe(HttpStatus.NOT_FOUND) }) }) @@ -494,7 +505,7 @@ describe('Wallet', () => { it('returns the list of accounts for the wallet', async () => { const wallet = TEST_WALLETS[0] const accounts = TEST_ACCOUNTS.filter((acc) => acc.walletId === wallet.id) - const res = await request(app.getHttpServer()) + const { status, body } = await request(app.getHttpServer()) .get(`/provider/wallets/${wallet.id}/accounts`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( @@ -507,17 +518,18 @@ describe('Wallet', () => { }) ) - expect(res.status).toBe(HttpStatus.OK) - expect(res.body).toEqual({ - accounts: accounts.map(getExpectedAccount).reverse(), + expect(body).toEqual({ + data: accounts.map(getExpectedAccount).reverse(), page: { next: null } }) + + expect(status).toBe(HttpStatus.OK) }) it('returns empty accounts array for wallet with no accounts', async () => { - const res = await request(app.getHttpServer()) + const { status, body } = await request(app.getHttpServer()) .get(`/provider/wallets/${TEST_WALLETS[1].id}/accounts`) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) .set( @@ -530,13 +542,14 @@ describe('Wallet', () => { }) ) - expect(res.status).toBe(HttpStatus.OK) - expect(res.body).toEqual({ - accounts: [], + expect(body).toEqual({ + data: [], page: { next: null } }) + + expect(status).toBe(HttpStatus.OK) }) }) }) diff --git a/apps/vault/src/broker/core/lib/anchorage-request-builder.ts b/apps/vault/src/broker/core/lib/anchorage-request-builder.ts new file mode 100644 index 000000000..c272b2c8b --- /dev/null +++ b/apps/vault/src/broker/core/lib/anchorage-request-builder.ts @@ -0,0 +1,51 @@ +import { sign } from '@noble/ed25519' +import { AxiosRequestConfig } from 'axios' + +type HttpMethod = 'GET' | 'POST' + +export type BuildAnchorageRequestParams = { + url: string + method: HttpMethod + body?: Record + endpoint: string + apiKey: string + signKey: string +} + +export const extractVersion = (url: string): string => '/v2' +export const buildAnchorageSignedRequest = async ({ + url, + method, + endpoint, + body, + apiKey, + signKey +}: BuildAnchorageRequestParams): Promise => { + const time = Math.floor(new Date().getTime() / 1000) + const version = extractVersion(url) + const serializedPayload = body + ? `${time}${method}${version}${endpoint}${JSON.stringify(body)}` + : `${time}${method}${version}${endpoint}` + + const signatureRequest = Buffer.from(serializedPayload, 'utf8').toString('hex') + const hexSignature = await sign(signatureRequest, signKey.slice(2)) + + const signature = Buffer.from(hexSignature).toString('hex') + + const finalUrl = `${url}/v2${endpoint}` + const headers = { + 'Api-Access-Key': apiKey, + 'Api-Signature': signature, + 'Api-Timestamp': time, + 'Content-Type': 'application/json' + } + + const config: AxiosRequestConfig = { + url: finalUrl, + method, + headers, + data: body + } + + return config +} diff --git a/apps/vault/src/broker/http/client/anchorage.client.ts b/apps/vault/src/broker/http/client/anchorage.client.ts index 9740403ab..f9ba690fa 100644 --- a/apps/vault/src/broker/http/client/anchorage.client.ts +++ b/apps/vault/src/broker/http/client/anchorage.client.ts @@ -323,6 +323,17 @@ export class AnchorageClient { ) } + private getVaultsPage(request: AxiosRequestConfig): Observable { + return this.httpService.request(request).pipe( + tap((response) => { + this.logger.log('Received Anchorage vaults page', { + data: response.data + }) + }), + map((response) => GetVaultsResponse.parse(response.data)) + ) + } + async getWallets(opts: RequestOptions): Promise { this.logger.log('Requesting Anchorage wallets page', { url: opts.url, diff --git a/apps/vault/src/broker/http/rest/controller/account.controller.ts b/apps/vault/src/broker/http/rest/controller/account.controller.ts index 300cc54ad..41770a439 100644 --- a/apps/vault/src/broker/http/rest/controller/account.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/account.controller.ts @@ -1,14 +1,13 @@ import { Paginated, PaginationOptions, PaginationParam } from '@narval/nestjs-shared' import { Controller, Get, HttpStatus, Param } from '@nestjs/common' import { ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger' - import { ClientId } from '../../../../shared/decorator/client-id.decorator' import { PermissionGuard } from '../../../../shared/decorator/permission-guard.decorator' import { VaultPermission } from '../../../../shared/type/domain.type' import { AccountService } from '../../../core/service/account.service' -import { ProviderAccountDto } from '../dto/response/account.dto' import { PaginatedAccountsDto } from '../dto/response/paginated-accounts.dto' import { PaginatedAddressesDto } from '../dto/response/paginated-addresses.dto' +import { ProviderAccountDto } from '../dto/response/provider-account.dto' @Controller({ path: 'accounts', @@ -27,16 +26,11 @@ export class AccountController { type: PaginatedAccountsDto, description: 'Returns a paginated list of accounts for the client' }) - async listByClientId( + async list( @ClientId() clientId: string, @PaginationParam() options: PaginationOptions ): Promise { - const { data, page } = await this.accountService.getAccounts(clientId, options) - const ret = PaginatedAccountsDto.create({ - accounts: data, - page - }) - return ret + return PaginatedAccountsDto.create(await this.accountService.getAccounts(clientId, options)) } @Get(':accountId') @@ -56,12 +50,10 @@ export class AccountController { status: HttpStatus.NOT_FOUND, description: 'Account not found' }) - async getAccountById( - @ClientId() clientId: string, - @Param('accountId') accountId: string - ): Promise { - const account = await this.accountService.getAccount(clientId, accountId) - return ProviderAccountDto.create({ account }) + async getById(@ClientId() clientId: string, @Param('accountId') accountId: string): Promise { + const data = await this.accountService.getAccount(clientId, accountId) + + return ProviderAccountDto.create({ data }) } @Get(':accountId/addresses') @@ -81,16 +73,11 @@ export class AccountController { status: HttpStatus.NOT_FOUND, description: 'Address not found' }) - async getAccountAddresses( + async listAddresses( @ClientId() clientId: string, @Param('accountId') accountId: string, @PaginationParam() options: PaginationOptions ): Promise { - const { data, page } = await this.accountService.getAccountAddresses(clientId, accountId, options) - - return PaginatedAddressesDto.create({ - addresses: data, - page - }) + return PaginatedAddressesDto.create(await this.accountService.getAccountAddresses(clientId, accountId, options)) } } diff --git a/apps/vault/src/broker/http/rest/controller/address.controller.ts b/apps/vault/src/broker/http/rest/controller/address.controller.ts index 0e1f309b9..54924337e 100644 --- a/apps/vault/src/broker/http/rest/controller/address.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/address.controller.ts @@ -5,8 +5,8 @@ import { ClientId } from '../../../../shared/decorator/client-id.decorator' import { PermissionGuard } from '../../../../shared/decorator/permission-guard.decorator' import { VaultPermission } from '../../../../shared/type/domain.type' import { AddressService } from '../../../core/service/address.service' -import { ProviderAddressDto } from '../dto/response/address.dto' import { PaginatedAddressesDto } from '../dto/response/paginated-addresses.dto' +import { ProviderAddressDto } from '../dto/response/provider-address.dto' @Controller({ path: 'addresses', @@ -29,12 +29,7 @@ export class AddressController { @ClientId() clientId: string, @PaginationParam() options: PaginationOptions ): Promise { - const { data, page } = await this.addressService.getAddresses(clientId, options) - - return PaginatedAddressesDto.create({ - addresses: data, - page - }) + return PaginatedAddressesDto.create(await this.addressService.getAddresses(clientId, options)) } @Get(':addressId') @@ -54,12 +49,9 @@ export class AddressController { status: HttpStatus.NOT_FOUND, description: 'Address not found' }) - async getAddressById( - @ClientId() clientId: string, - @Param('addressId') addressId: string - ): Promise { - const address = await this.addressService.getAddress(clientId, addressId) + async getById(@ClientId() clientId: string, @Param('addressId') addressId: string): Promise { + const data = await this.addressService.getAddress(clientId, addressId) - return ProviderAddressDto.create({ address }) + return ProviderAddressDto.create({ data }) } } diff --git a/apps/vault/src/broker/http/rest/controller/connection.controller.ts b/apps/vault/src/broker/http/rest/controller/connection.controller.ts index ee3b5d0af..bc438fc42 100644 --- a/apps/vault/src/broker/http/rest/controller/connection.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/connection.controller.ts @@ -11,12 +11,11 @@ import { WalletService } from '../../../core/service/wallet.service' import { CreateConnectionDto } from '../dto/request/create-connection.dto' import { InitiateConnectionDto } from '../dto/request/initiate-connection.dto' import { UpdateConnectionDto } from '../dto/request/update-connection.dto' -import { ConnectionListDto } from '../dto/response/connection-list.dto' -import { ProviderConnectionDto } from '../dto/response/connection.dto' import { PaginatedAccountsDto } from '../dto/response/paginated-accounts.dto' import { PaginatedConnectionsDto } from '../dto/response/paginated-connections.dto' import { PaginatedWalletsDto } from '../dto/response/paginated-wallets.dto' -import { PendingConnectionDto } from '../dto/response/pending-connection.dto' +import { ProviderConnectionDto } from '../dto/response/provider-connection.dto' +import { ProviderPendingConnectionDto } from '../dto/response/provider-pending-connection.dto' @Controller({ path: 'connections', @@ -40,16 +39,19 @@ export class ConnectionController { @ApiResponse({ description: 'Returns the public key and encryption key for the initiated connection.', status: HttpStatus.CREATED, - type: PendingConnectionDto + type: ProviderPendingConnectionDto }) - async initiate(@ClientId() clientId: string, @Body() body: InitiateConnectionDto): Promise { + async initiate( + @ClientId() clientId: string, + @Body() body: InitiateConnectionDto + ): Promise { const pendingConnection = await this.connectionService.initiate(clientId, body) const encryptionPem = pendingConnection.encryptionPublicKey ? await publicKeyToPem(pendingConnection.encryptionPublicKey, pendingConnection.encryptionPublicKey.alg) : undefined - return PendingConnectionDto.create({ + const data = { ...pendingConnection, encryptionPublicKey: { keyId: pendingConnection.encryptionPublicKey?.kid, @@ -65,7 +67,9 @@ export class ConnectionController { } } : {}) - }) + } + + return ProviderPendingConnectionDto.create({ data }) } @Post() @@ -81,9 +85,9 @@ export class ConnectionController { type: ProviderConnectionDto }) async create(@ClientId() clientId: string, @Body() body: CreateConnectionDto): Promise { - const connection = await this.connectionService.create(clientId, body) + const data = await this.connectionService.create(clientId, body) - return ProviderConnectionDto.create(connection) + return ProviderConnectionDto.create({ data }) } @Delete(':connectionId') @@ -108,22 +112,17 @@ export class ConnectionController { summary: 'List all connections', description: 'This endpoint retrieves a list of all connections associated with the client.' }) - @ApiResponse({ - description: 'Returns a list of connections associated with the client.', - type: ConnectionListDto, - status: HttpStatus.OK - }) @Paginated({ type: PaginatedConnectionsDto, - description: 'Returns a paginated list of wallets associated with the connection' + description: 'Returns a paginated list of connections associated with the client' }) async list( @ClientId() clientId: string, - @PaginationParam() options: PaginationOptions + @PaginationParam() pagination: PaginationOptions ): Promise { - const { data, page } = await this.connectionService.findAll(clientId, { pagination: options }) + const { data, page } = await this.connectionService.findAll(clientId, { pagination }) - return PaginatedConnectionsDto.create({ connections: data, page }) + return PaginatedConnectionsDto.create({ data, page }) } @Get(':connectionId') @@ -142,9 +141,9 @@ export class ConnectionController { @ClientId() clientId: string, @Param('connectionId') connectionId: string ): Promise { - const connection = await this.connectionService.findById(clientId, connectionId) + const data = await this.connectionService.findById(clientId, connectionId) - return ProviderConnectionDto.create(connection) + return ProviderConnectionDto.create({ data }) } @Patch(':connectionId') @@ -164,13 +163,13 @@ export class ConnectionController { @Param('connectionId') connectionId: string, @Body() body: UpdateConnectionDto ): Promise { - const connection = await this.connectionService.update({ + const data = await this.connectionService.update({ ...body, clientId, connectionId }) - return ProviderConnectionDto.create(connection) + return ProviderConnectionDto.create({ data }) } @Get(':connectionId/wallets') @@ -183,17 +182,17 @@ export class ConnectionController { type: PaginatedWalletsDto, description: 'Returns a paginated list of wallets associated with the connection' }) - async getWallets( + async listWallets( @ClientId() clientId: string, @Param('connectionId') connectionId: string, - @PaginationParam() options: PaginationOptions + @PaginationParam() pagination: PaginationOptions ): Promise { const { data, page } = await this.walletService.findAll(clientId, { - ...options, - filters: { connectionId } + filters: { connectionId }, + pagination }) - return PaginatedWalletsDto.create({ wallets: data, page }) + return PaginatedWalletsDto.create({ data, page }) } @Get(':connectionId/accounts') @@ -206,16 +205,16 @@ export class ConnectionController { type: PaginatedAccountsDto, description: 'Returns a paginated list of accounts associated with the connection' }) - async getAccounts( + async listAccounts( @ClientId() clientId: string, @Param('connectionId') connectionId: string, - @PaginationParam() options: PaginationOptions + @PaginationParam() pagination: PaginationOptions ): Promise { const { data, page } = await this.accountService.findAll(clientId, { - ...options, - filters: { connectionId } + filters: { connectionId }, + pagination }) - return PaginatedAccountsDto.create({ accounts: data, page }) + return PaginatedAccountsDto.create({ data, page }) } } diff --git a/apps/vault/src/broker/http/rest/controller/sync.controller.ts b/apps/vault/src/broker/http/rest/controller/sync.controller.ts index 289dc1e1b..f0b7d80c6 100644 --- a/apps/vault/src/broker/http/rest/controller/sync.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/sync.controller.ts @@ -9,7 +9,7 @@ import { SyncService } from '../../../core/service/sync.service' import { ActiveConnectionWithCredentials, ConnectionStatus } from '../../../core/type/connection.type' import { StartSyncDto } from '../dto/request/start-sync.dto' import { PaginatedSyncsDto } from '../dto/response/paginated-syncs.dto' -import { SyncStatusDto } from '../dto/response/sync-status.dto' +import { SyncStartedDto } from '../dto/response/sync-started.dto' import { SyncDto } from '../dto/response/sync.dto' @Controller({ @@ -32,13 +32,14 @@ export class SyncController { @ApiResponse({ description: 'Returns the status of the synchronization process.', status: HttpStatus.CREATED, - type: SyncStatusDto + type: SyncStartedDto }) - async start(@ClientId() clientId: string, @Body() body: StartSyncDto): Promise { + async start(@ClientId() clientId: string, @Body() body: StartSyncDto): Promise { if (body.connectionId) { const connection = await this.connectionService.findById(clientId, body.connectionId, true) + const data = await this.syncService.start([connection as ActiveConnectionWithCredentials]) - return SyncStatusDto.create(await this.syncService.start([connection as ActiveConnectionWithCredentials])) + return SyncStartedDto.create({ data }) } const { data: connections } = await this.connectionService.findAll( @@ -51,7 +52,9 @@ export class SyncController { true ) - return SyncStatusDto.create(await this.syncService.start(connections as ActiveConnectionWithCredentials[])) + const data = await this.syncService.start(connections as ActiveConnectionWithCredentials[]) + + return SyncStartedDto.create({ data }) } @Get(':syncId') @@ -66,10 +69,10 @@ export class SyncController { status: HttpStatus.OK, type: SyncDto }) - async findById(@ClientId() clientId: string, @Param('syncId') syncId: string): Promise { - const sync = await this.syncService.findById(clientId, syncId) + async getById(@ClientId() clientId: string, @Param('syncId') syncId: string): Promise { + const data = await this.syncService.findById(clientId, syncId) - return SyncDto.create(sync) + return SyncDto.create({ data }) } @Get() @@ -83,16 +86,16 @@ export class SyncController { type: PaginatedSyncsDto, description: 'Returns a paginated list of accounts associated with the connection' }) - async findAll( + async list( @ClientId() clientId: string, - @PaginationParam() options: PaginationOptions, + @PaginationParam() pagination: PaginationOptions, @Query('connectionId') connectionId?: string ): Promise { - const { data, page } = await this.syncService.findAll(clientId, { - ...options, - filters: { connectionId } - }) - - return PaginatedSyncsDto.create({ syncs: data, page: page }) + return PaginatedSyncsDto.create( + await this.syncService.findAll(clientId, { + filters: { connectionId }, + pagination + }) + ) } } diff --git a/apps/vault/src/broker/http/rest/controller/wallet.controller.ts b/apps/vault/src/broker/http/rest/controller/wallet.controller.ts index 405b778f2..b1df5f236 100644 --- a/apps/vault/src/broker/http/rest/controller/wallet.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/wallet.controller.ts @@ -8,7 +8,7 @@ import { AccountService } from '../../../core/service/account.service' import { WalletService } from '../../../core/service/wallet.service' import { PaginatedAccountsDto } from '../dto/response/paginated-accounts.dto' import { PaginatedWalletsDto } from '../dto/response/paginated-wallets.dto' -import { ProviderWalletDto } from '../dto/response/wallet.dto' +import { ProviderWalletDto } from '../dto/response/provider-wallet.dto' @Controller({ path: 'wallets', @@ -30,16 +30,11 @@ export class WalletController { type: PaginatedWalletsDto, description: 'Returns a paginated list of wallets for the client' }) - async listByClientId( + async list( @ClientId() clientId: string, @PaginationParam() options: PaginationOptions ): Promise { - const { data, page } = await this.walletService.getWallets(clientId, options) - const ret = PaginatedWalletsDto.create({ - wallets: data, - page - }) - return ret + return PaginatedWalletsDto.create(await this.walletService.getWallets(clientId, options)) } @Get(':walletId') @@ -59,9 +54,10 @@ export class WalletController { status: HttpStatus.NOT_FOUND, description: 'Wallet not found' }) - async getWalletById(@ClientId() clientId: string, @Param('walletId') walletId: string): Promise { - const wallet = await this.walletService.getWallet(clientId, walletId) - return ProviderWalletDto.create({ wallet }) + async getById(@ClientId() clientId: string, @Param('walletId') walletId: string): Promise { + const data = await this.walletService.getWallet(clientId, walletId) + + return ProviderWalletDto.create({ data }) } @Get(':walletId/accounts') @@ -81,19 +77,16 @@ export class WalletController { status: HttpStatus.NOT_FOUND, description: 'Wallet not found' }) - async getWalletAccounts( + async listAccounts( @ClientId() clientId: string, @Param('walletId') walletId: string, @PaginationParam() options: PaginationOptions ): Promise { - const { data, page } = await this.accountService.findAll(clientId, { - ...options, - filters: { walletId } - }) - - return PaginatedAccountsDto.create({ - accounts: data, - page - }) + return PaginatedAccountsDto.create( + await this.accountService.findAllPaginated(clientId, { + ...options, + filters: { walletId } + }) + ) } } diff --git a/apps/vault/src/broker/http/rest/dto/response/connection.dto.ts b/apps/vault/src/broker/http/rest/dto/response/connection.dto.ts deleted file mode 100644 index 748fa8d48..000000000 --- a/apps/vault/src/broker/http/rest/dto/response/connection.dto.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { createZodDto } from 'nestjs-zod' -import { BaseConnection } from '../../../../core/type/connection.type' - -export class ProviderConnectionDto extends createZodDto(BaseConnection) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/paginated-accounts.dto.ts b/apps/vault/src/broker/http/rest/dto/response/paginated-accounts.dto.ts index 8d122075d..2d137af08 100644 --- a/apps/vault/src/broker/http/rest/dto/response/paginated-accounts.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/paginated-accounts.dto.ts @@ -5,7 +5,7 @@ import { Account } from '../../../../core/type/indexed-resources.type' export class PaginatedAccountsDto extends createZodDto( z.object({ - accounts: z.array(Account), + data: z.array(Account), page: Page }) ) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/paginated-addresses.dto.ts b/apps/vault/src/broker/http/rest/dto/response/paginated-addresses.dto.ts index 7439a35c0..1f6261d7f 100644 --- a/apps/vault/src/broker/http/rest/dto/response/paginated-addresses.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/paginated-addresses.dto.ts @@ -5,7 +5,7 @@ import { Address } from '../../../../core/type/indexed-resources.type' export class PaginatedAddressesDto extends createZodDto( z.object({ - addresses: z.array(Address), + data: z.array(Address), page: Page }) ) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/paginated-connections.dto.ts b/apps/vault/src/broker/http/rest/dto/response/paginated-connections.dto.ts index d9bad9785..8ade32dc6 100644 --- a/apps/vault/src/broker/http/rest/dto/response/paginated-connections.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/paginated-connections.dto.ts @@ -5,7 +5,7 @@ import { BaseConnection } from '../../../../core/type/connection.type' export class PaginatedConnectionsDto extends createZodDto( z.object({ - connections: z.array(BaseConnection), + data: z.array(BaseConnection), page: Page }) ) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/paginated-syncs.dto.ts b/apps/vault/src/broker/http/rest/dto/response/paginated-syncs.dto.ts index 71b52084f..b0ea51922 100644 --- a/apps/vault/src/broker/http/rest/dto/response/paginated-syncs.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/paginated-syncs.dto.ts @@ -5,7 +5,7 @@ import { Sync } from '../../../../core/type/sync.type' export class PaginatedSyncsDto extends createZodDto( z.object({ - page: Page, - syncs: z.array(Sync) + data: z.array(Sync), + page: Page }) ) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/paginated-wallets.dto.ts b/apps/vault/src/broker/http/rest/dto/response/paginated-wallets.dto.ts index e2b53673d..d278e1b8c 100644 --- a/apps/vault/src/broker/http/rest/dto/response/paginated-wallets.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/paginated-wallets.dto.ts @@ -5,7 +5,7 @@ import { PublicWallet } from '../../../../core/type/indexed-resources.type' export class PaginatedWalletsDto extends createZodDto( z.object({ - wallets: z.array(PublicWallet), + data: z.array(PublicWallet), page: Page }) ) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/account.dto.ts b/apps/vault/src/broker/http/rest/dto/response/provider-account.dto.ts similarity index 91% rename from apps/vault/src/broker/http/rest/dto/response/account.dto.ts rename to apps/vault/src/broker/http/rest/dto/response/provider-account.dto.ts index fad350f21..77e483ede 100644 --- a/apps/vault/src/broker/http/rest/dto/response/account.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/provider-account.dto.ts @@ -4,6 +4,6 @@ import { Account } from '../../../../core/type/indexed-resources.type' export class ProviderAccountDto extends createZodDto( z.object({ - account: Account + data: Account }) ) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/address.dto.ts b/apps/vault/src/broker/http/rest/dto/response/provider-address.dto.ts similarity index 91% rename from apps/vault/src/broker/http/rest/dto/response/address.dto.ts rename to apps/vault/src/broker/http/rest/dto/response/provider-address.dto.ts index 866bc2468..b2a4f1a31 100644 --- a/apps/vault/src/broker/http/rest/dto/response/address.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/provider-address.dto.ts @@ -4,6 +4,6 @@ import { Address } from '../../../../core/type/indexed-resources.type' export class ProviderAddressDto extends createZodDto( z.object({ - address: Address + data: Address }) ) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/connection-list.dto.ts b/apps/vault/src/broker/http/rest/dto/response/provider-connection.dto.ts similarity index 56% rename from apps/vault/src/broker/http/rest/dto/response/connection-list.dto.ts rename to apps/vault/src/broker/http/rest/dto/response/provider-connection.dto.ts index ee4ca2973..a3d4ef079 100644 --- a/apps/vault/src/broker/http/rest/dto/response/connection-list.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/provider-connection.dto.ts @@ -2,4 +2,8 @@ import { createZodDto } from 'nestjs-zod' import { z } from 'zod' import { BaseConnection } from '../../../../core/type/connection.type' -export class ConnectionListDto extends createZodDto(z.object({ connections: z.array(BaseConnection) })) {} +export class ProviderConnectionDto extends createZodDto( + z.object({ + data: BaseConnection + }) +) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/provider-pending-connection.dto.ts b/apps/vault/src/broker/http/rest/dto/response/provider-pending-connection.dto.ts new file mode 100644 index 000000000..74eae3633 --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/response/provider-pending-connection.dto.ts @@ -0,0 +1,30 @@ +import { hexSchema } from '@narval/policy-engine-shared' +import { publicKeySchema } from '@narval/signature' +import { createZodDto } from 'nestjs-zod' +import { z } from 'zod' +import { PendingConnection } from '../../../../core/type/connection.type' + +export class ProviderPendingConnectionDto extends createZodDto( + z.object({ + data: PendingConnection.pick({ + clientId: true, + connectionId: true, + provider: true, + status: true, + createdAt: true + }).extend({ + publicKey: z + .object({ + keyId: z.string().optional(), + jwk: publicKeySchema.optional(), + hex: hexSchema.optional() + }) + .optional(), + encryptionPublicKey: z.object({ + keyId: z.string().optional(), + jwk: publicKeySchema.optional().describe('JWK format of the public key'), + pem: z.string().optional().describe('Base64url encoded PEM public key') + }) + }) + }) +) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/wallet.dto.ts b/apps/vault/src/broker/http/rest/dto/response/provider-wallet.dto.ts similarity index 89% rename from apps/vault/src/broker/http/rest/dto/response/wallet.dto.ts rename to apps/vault/src/broker/http/rest/dto/response/provider-wallet.dto.ts index 3f5c6f10f..5135341e1 100644 --- a/apps/vault/src/broker/http/rest/dto/response/wallet.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/provider-wallet.dto.ts @@ -4,6 +4,6 @@ import { PublicWallet } from '../../../../core/type/indexed-resources.type' export class ProviderWalletDto extends createZodDto( z.object({ - wallet: PublicWallet + data: PublicWallet }) ) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/sync-list.dto.ts b/apps/vault/src/broker/http/rest/dto/response/sync-list.dto.ts deleted file mode 100644 index aaf9ef534..000000000 --- a/apps/vault/src/broker/http/rest/dto/response/sync-list.dto.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { createZodDto } from 'nestjs-zod' -import { z } from 'zod' -import { Sync } from '../../../../core/type/sync.type' - -export class SyncListDto extends createZodDto( - z.object({ - syncs: z.array(Sync) - }) -) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/sync-started.dto.ts b/apps/vault/src/broker/http/rest/dto/response/sync-started.dto.ts new file mode 100644 index 000000000..6880fcdd4 --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/response/sync-started.dto.ts @@ -0,0 +1,9 @@ +import { createZodDto } from 'nestjs-zod' +import { z } from 'zod' +import { SyncStarted } from '../../../../core/type/sync.type' + +export class SyncStartedDto extends createZodDto( + z.object({ + data: SyncStarted + }) +) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/sync-status.dto.ts b/apps/vault/src/broker/http/rest/dto/response/sync-status.dto.ts index 2560f4489..6880fcdd4 100644 --- a/apps/vault/src/broker/http/rest/dto/response/sync-status.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/sync-status.dto.ts @@ -1,10 +1,9 @@ import { createZodDto } from 'nestjs-zod' import { z } from 'zod' -import { Sync } from '../../../../core/type/sync.type' +import { SyncStarted } from '../../../../core/type/sync.type' -export class SyncStatusDto extends createZodDto( +export class SyncStartedDto extends createZodDto( z.object({ - started: z.boolean(), - syncs: z.array(Sync) + data: SyncStarted }) ) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/sync.dto.ts b/apps/vault/src/broker/http/rest/dto/response/sync.dto.ts index a4988ffb5..e84025fbb 100644 --- a/apps/vault/src/broker/http/rest/dto/response/sync.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/sync.dto.ts @@ -1,4 +1,9 @@ import { createZodDto } from 'nestjs-zod' +import { z } from 'zod' import { Sync } from '../../../../core/type/sync.type' -export class SyncDto extends createZodDto(Sync) {} +export class SyncDto extends createZodDto( + z.object({ + data: Sync + }) +) {} diff --git a/apps/vault/src/shared/module/persistence/schema/schema.prisma b/apps/vault/src/shared/module/persistence/schema/schema.prisma index e9570b6cf..733b3d5aa 100644 --- a/apps/vault/src/shared/module/persistence/schema/schema.prisma +++ b/apps/vault/src/shared/module/persistence/schema/schema.prisma @@ -111,6 +111,7 @@ model ProviderWallet { sourceTransfers ProviderTransfer[] @relation("SourceWallet") @@unique([clientId, externalId]) + @@map("provider_wallet") } @@ -131,6 +132,7 @@ model ProviderAccount { sourceTransfers ProviderTransfer[] @relation("SourceAccount") @@unique([clientId, externalId]) + @@map("provider_account") } @@ -149,6 +151,7 @@ model ProviderAddress { sourceTransfers ProviderTransfer[] @relation("SourceAddress") @@unique([clientId, externalId]) + @@map("provider_address") } @@ -168,6 +171,7 @@ model ProviderKnownDestination { connection ProviderConnection @relation(fields: [connectionId], references: [id]) @@unique([clientId, externalId]) + @@map("provider_known_destination") } From 819fdb1d8d167a2b2e41e4518e04ca82446b08c3 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Wed, 18 Dec 2024 15:36:15 +0100 Subject: [PATCH 045/120] Fix Anchorage signed request for paginated responses (#45) --- .../__test__/unit/anchorage.client.spec.ts | 25 ++++++ .../http/client/anchorage-request-builder.ts | 80 ------------------- .../broker/http/client/anchorage.client.ts | 28 ++----- 3 files changed, 31 insertions(+), 102 deletions(-) delete mode 100644 apps/vault/src/broker/http/client/anchorage-request-builder.ts diff --git a/apps/vault/src/broker/http/client/__test__/unit/anchorage.client.spec.ts b/apps/vault/src/broker/http/client/__test__/unit/anchorage.client.spec.ts index 9b7e4e1fb..7e246099d 100644 --- a/apps/vault/src/broker/http/client/__test__/unit/anchorage.client.spec.ts +++ b/apps/vault/src/broker/http/client/__test__/unit/anchorage.client.spec.ts @@ -84,6 +84,31 @@ describe(AnchorageClient.name, () => { ) }) + it('adds params as query string', () => { + const request: AxiosRequestConfig = { + method: 'POST', + url: '/v2/accounts', + data: undefined, + params: { foo: 'bar' } + } + + expect(client.buildSignatureMessage(request, nowTimestamp)).toEqual(`${nowTimestamp}POST/v2/accounts?foo=bar`) + }) + + it('does not add ? to the url when params is defined with undefined items', () => { + const request: AxiosRequestConfig = { + method: 'POST', + url: '/v2/accounts', + data: undefined, + params: { + foo: undefined, + bar: undefined + } + } + + expect(client.buildSignatureMessage(request, nowTimestamp)).toEqual(`${nowTimestamp}POST/v2/accounts`) + }) + it('handles undefined data for non-get requests', () => { const request: AxiosRequestConfig = { method: 'POST', diff --git a/apps/vault/src/broker/http/client/anchorage-request-builder.ts b/apps/vault/src/broker/http/client/anchorage-request-builder.ts deleted file mode 100644 index 2958ed88c..000000000 --- a/apps/vault/src/broker/http/client/anchorage-request-builder.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { Ed25519PrivateKey, privateKeyToHex } from '@narval/signature' -import { sign } from '@noble/ed25519' -import { AxiosRequestConfig } from 'axios' -import { z } from 'zod' -import { UrlParserException } from '../../core/exception/url-parser.exception' - -export const HttpMethod = z.union([ - z.literal('GET'), - z.literal('POST'), - z.literal('PATCH'), - z.literal('PUT'), - z.literal('DELETE') -]) -export type HttpMethod = z.infer - -export type BuildAnchorageRequestParams = { - url: string - method: HttpMethod - body?: unknown - apiKey: string - signKey: Ed25519PrivateKey - now?: Date -} - -export const parseUrl = (url: string): string => { - const regex = /(\/v\d+(?:\/.*)?)$/ - const match = url.match(regex) - - if (!match) { - throw new UrlParserException({ - message: 'No version pattern found in the URL', - url - }) - } - - return match[1] -} - -export const serializePayload = (time: number, method: HttpMethod, endpoint: string, body: unknown): string => { - return `${time}${method}${endpoint}${body && method !== 'GET' ? JSON.stringify(body) : ''}` -} - -export const buildAnchorageSignedRequest = async ({ - url, - method, - body, - apiKey, - signKey, - now -}: BuildAnchorageRequestParams): Promise => { - const timestamp = now ? now.getTime() : new Date().getTime() - const time = Math.floor(timestamp / 1000) - - const endpoint = parseUrl(url) - const serializedPayload = serializePayload(time, method, endpoint, body) - - const signatureRequest = Buffer.from(serializedPayload, 'utf8').toString('hex') - - const signHexKey = await privateKeyToHex(signKey) - const hexSignature = await sign(signatureRequest, signHexKey.slice(2)) - const signature = Buffer.from(hexSignature).toString('hex') - - const headers = { - 'Api-Access-Key': apiKey, - 'Api-Signature': signature, - 'Api-Timestamp': time, - 'Content-Type': 'application/json' - } - - const data = body && method !== 'GET' ? body : undefined - - const config: AxiosRequestConfig = { - url, - method, - headers, - data - } - - return config -} diff --git a/apps/vault/src/broker/http/client/anchorage.client.ts b/apps/vault/src/broker/http/client/anchorage.client.ts index f9ba690fa..6568e31ab 100644 --- a/apps/vault/src/broker/http/client/anchorage.client.ts +++ b/apps/vault/src/broker/http/client/anchorage.client.ts @@ -4,12 +4,12 @@ import { HttpService } from '@nestjs/axios' import { HttpStatus, Injectable } from '@nestjs/common' import { sign } from '@noble/ed25519' import axios, { AxiosRequestConfig, AxiosResponse } from 'axios' +import { isNil, omitBy } from 'lodash' import { EMPTY, Observable, catchError, expand, from, lastValueFrom, map, reduce, switchMap, tap } from 'rxjs' import { ZodType, z } from 'zod' import { BrokerException } from '../../core/exception/broker.exception' import { ProxyRequestException } from '../../core/exception/proxy-request.exception' import { UrlParserException } from '../../core/exception/url-parser.exception' -import { HttpMethod, buildAnchorageSignedRequest } from './anchorage-request-builder' const Amount = z.object({ quantity: z.string(), @@ -223,8 +223,10 @@ export class AnchorageClient { const endpoint = this.parseEndpoint(request.url) const method = request.method.toUpperCase() + const queryParams = new URLSearchParams(omitBy(request.params, isNil)).toString() + const path = queryParams ? `${endpoint}?${queryParams}` : endpoint - return `${timestamp}${method}${endpoint}${request.data && method !== 'GET' ? JSON.stringify(request.data) : ''}` + return `${timestamp}${method}${path}${request.data && method !== 'GET' ? JSON.stringify(request.data) : ''}` } private sendSignedRequest(opts: { @@ -234,15 +236,8 @@ export class AnchorageClient { apiKey: string }): Observable { return from( - // this.authorize({ - // request: opts.request, - // apiKey: opts.apiKey, - // signKey: opts.signKey - // }) - buildAnchorageSignedRequest({ - url: opts.request.url as string, - method: opts.request.method as HttpMethod, - body: opts.request.data, + this.authorize({ + request: opts.request, apiKey: opts.apiKey, signKey: opts.signKey }) @@ -323,17 +318,6 @@ export class AnchorageClient { ) } - private getVaultsPage(request: AxiosRequestConfig): Observable { - return this.httpService.request(request).pipe( - tap((response) => { - this.logger.log('Received Anchorage vaults page', { - data: response.data - }) - }), - map((response) => GetVaultsResponse.parse(response.data)) - ) - } - async getWallets(opts: RequestOptions): Promise { this.logger.log('Requesting Anchorage wallets page', { url: opts.url, From a8a3777aed768cdd1d47747dd8918b791b6cfbd3 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Wed, 18 Dec 2024 15:45:58 +0100 Subject: [PATCH 046/120] Refactor encryption key endpoint to use the same logic (#44) --- .../shared/decorator/client-id.decorator.ts | 4 +- .../__test__/e2e/encryption-key.spec.ts | 34 +++++++++++-- .../dto/response/encryption-key.dto.ts | 18 +++++++ .../rest/encryption-key.controller.ts | 48 +++++++++++++++++++ .../transit-encryption.module.ts | 11 ++++- .../__test__/unit/import.service.spec.ts | 16 ++++++- .../src/vault/core/service/import.service.ts | 45 +++-------------- .../controller/encryption-key.controller.ts | 36 -------------- .../vault/http/rest/dto/encryption-key.dto.ts | 9 ---- apps/vault/src/vault/vault.module.ts | 6 +-- 10 files changed, 131 insertions(+), 96 deletions(-) rename apps/vault/src/{vault => transit-encryption}/__test__/e2e/encryption-key.spec.ts (83%) create mode 100644 apps/vault/src/transit-encryption/http/rest/controller/dto/response/encryption-key.dto.ts create mode 100644 apps/vault/src/transit-encryption/http/rest/controller/rest/encryption-key.controller.ts delete mode 100644 apps/vault/src/vault/http/rest/controller/encryption-key.controller.ts delete mode 100644 apps/vault/src/vault/http/rest/dto/encryption-key.dto.ts diff --git a/apps/vault/src/shared/decorator/client-id.decorator.ts b/apps/vault/src/shared/decorator/client-id.decorator.ts index aa79484bd..87f11a7a0 100644 --- a/apps/vault/src/shared/decorator/client-id.decorator.ts +++ b/apps/vault/src/shared/decorator/client-id.decorator.ts @@ -1,11 +1,11 @@ import { REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' -import { createParamDecorator, ExecutionContext } from '@nestjs/common' +import { BadRequestException, createParamDecorator, ExecutionContext } from '@nestjs/common' export const ClientId = createParamDecorator((_data: unknown, context: ExecutionContext): string => { const req = context.switchToHttp().getRequest() const clientId = req.headers[REQUEST_HEADER_CLIENT_ID] if (!clientId || typeof clientId !== 'string') { - throw new Error(`Missing or invalid ${REQUEST_HEADER_CLIENT_ID} header`) + throw new BadRequestException(`Missing or invalid ${REQUEST_HEADER_CLIENT_ID} header`) } return clientId diff --git a/apps/vault/src/vault/__test__/e2e/encryption-key.spec.ts b/apps/vault/src/transit-encryption/__test__/e2e/encryption-key.spec.ts similarity index 83% rename from apps/vault/src/vault/__test__/e2e/encryption-key.spec.ts rename to apps/vault/src/transit-encryption/__test__/e2e/encryption-key.spec.ts index 788ef8b7d..5710aa5d8 100644 --- a/apps/vault/src/vault/__test__/e2e/encryption-key.spec.ts +++ b/apps/vault/src/transit-encryption/__test__/e2e/encryption-key.spec.ts @@ -22,7 +22,7 @@ import { Client } from '../../../shared/type/domain.type' const PRIVATE_KEY = '0x7cfef3303797cbc7515d9ce22ffe849c701b0f2812f999b0847229c47951fca5' -describe('Encryption-keys', () => { +describe('Transit Encryption Key', () => { let app: INestApplication let module: TestingModule let testPrismaService: TestPrismaService @@ -128,14 +128,14 @@ describe('Encryption-keys', () => { await clientService.save(client) }) - describe('POST', () => { + describe('POST /encryption-keys', () => { it('responds with unauthorized when client secret is missing', async () => { const { status } = await request(app.getHttpServer()).post('/encryption-keys').send() expect(status).toEqual(HttpStatus.UNAUTHORIZED) }) - it('generates an RSA keypair', async () => { + it('generates an RSA key pair', async () => { const accessToken = await getAccessToken([Permission.WALLET_IMPORT]) const { status, body } = await request(app.getHttpServer()) @@ -144,7 +144,7 @@ describe('Encryption-keys', () => { .set('authorization', `GNAP ${accessToken}`) .send({}) - expect(body).toEqual({ + expect(body).toMatchObject({ publicKey: expect.objectContaining({ kid: expect.any(String), kty: 'RSA', @@ -154,6 +154,32 @@ describe('Encryption-keys', () => { e: expect.any(String) }) }) + + expect(status).toEqual(HttpStatus.CREATED) + }) + + it('responds with rsa public key in different formats', async () => { + const accessToken = await getAccessToken([Permission.WALLET_IMPORT]) + + const { status, body } = await request(app.getHttpServer()) + .post('/encryption-keys') + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set('authorization', `GNAP ${accessToken}`) + .send({}) + + expect(body.data).toEqual({ + keyId: expect.any(String), + jwk: expect.objectContaining({ + kid: expect.any(String), + kty: 'RSA', + use: 'enc', + alg: 'RS256', + n: expect.any(String), + e: expect.any(String) + }), + pem: expect.any(String) + }) + expect(status).toEqual(HttpStatus.CREATED) }) }) diff --git a/apps/vault/src/transit-encryption/http/rest/controller/dto/response/encryption-key.dto.ts b/apps/vault/src/transit-encryption/http/rest/controller/dto/response/encryption-key.dto.ts new file mode 100644 index 000000000..28a9de6ce --- /dev/null +++ b/apps/vault/src/transit-encryption/http/rest/controller/dto/response/encryption-key.dto.ts @@ -0,0 +1,18 @@ +import { publicKeySchema, rsaPublicKeySchema } from '@narval/signature' +import { createZodDto } from 'nestjs-zod' +import { z } from 'zod' + +export class EncryptionKeyDto extends createZodDto( + z.object({ + /** + * @deprecated Use `data.jwk` instead. Requires Vault encryption flows to + * move from `publicKey` to `data.jwk`. + */ + publicKey: rsaPublicKeySchema.describe('(DEPRECATED: use data.jwk instead) JWK format of the public key'), + data: z.object({ + keyId: z.string().optional(), + jwk: publicKeySchema.optional().describe('JWK format of the public key'), + pem: z.string().optional().describe('Base64url encoded PEM public key') + }) + }) +) {} diff --git a/apps/vault/src/transit-encryption/http/rest/controller/rest/encryption-key.controller.ts b/apps/vault/src/transit-encryption/http/rest/controller/rest/encryption-key.controller.ts new file mode 100644 index 000000000..faeba1832 --- /dev/null +++ b/apps/vault/src/transit-encryption/http/rest/controller/rest/encryption-key.controller.ts @@ -0,0 +1,48 @@ +import { Permission } from '@narval/armory-sdk' +import { REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' +import { publicKeyToPem } from '@narval/signature' +import { Controller, HttpStatus, Post } from '@nestjs/common' +import { ApiHeader, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' +import { ClientId } from '../../../../../shared/decorator/client-id.decorator' +import { PermissionGuard } from '../../../../../shared/decorator/permission-guard.decorator' +import { EncryptionKeyService } from '../../../../core/service/encryption-key.service' +import { EncryptionKeyDto } from '../dto/response/encryption-key.dto' + +@Controller({ + path: '/encryption-keys', + version: '1' +}) +@PermissionGuard(Permission.WALLET_IMPORT) +@ApiTags('Encryption Key') +@ApiHeader({ + name: REQUEST_HEADER_CLIENT_ID, + required: true +}) +export class EncryptionKeyController { + constructor(private readonly encryptionKeyService: EncryptionKeyService) {} + + @Post() + @ApiOperation({ + summary: 'Generates an encryption key pair used to secure end-to-end communication containing sensitive information' + }) + @ApiResponse({ + status: HttpStatus.CREATED, + type: EncryptionKeyDto + }) + async generate(@ClientId() clientId: string): Promise { + const encryptionKey = await this.encryptionKeyService.generate(clientId) + + const encryptionPem = encryptionKey.publicKey + ? await publicKeyToPem(encryptionKey.publicKey, encryptionKey.publicKey.alg) + : undefined + + return EncryptionKeyDto.create({ + publicKey: encryptionKey.publicKey, + data: { + keyId: encryptionKey.publicKey?.kid, + jwk: encryptionKey.publicKey, + pem: encryptionPem ? Buffer.from(encryptionPem).toString('base64') : undefined + } + }) + } +} diff --git a/apps/vault/src/transit-encryption/transit-encryption.module.ts b/apps/vault/src/transit-encryption/transit-encryption.module.ts index 838560ca8..dc0873800 100644 --- a/apps/vault/src/transit-encryption/transit-encryption.module.ts +++ b/apps/vault/src/transit-encryption/transit-encryption.module.ts @@ -1,11 +1,18 @@ import { Module } from '@nestjs/common' +import { ClientModule } from '../client/client.module' import { PersistenceModule } from '../shared/module/persistence/persistence.module' import { EncryptionKeyService } from './core/service/encryption-key.service' +import { EncryptionKeyController } from './http/rest/controller/rest/encryption-key.controller' import { EncryptionKeyRepository } from './persistence/encryption-key.repository' @Module({ - imports: [PersistenceModule], + imports: [ + PersistenceModule, + // Required by the AuthorizationGuard. + ClientModule + ], providers: [EncryptionKeyRepository, EncryptionKeyService], - exports: [EncryptionKeyService] + exports: [EncryptionKeyService], + controllers: [EncryptionKeyController] }) export class TransitEncryptionModule {} diff --git a/apps/vault/src/vault/core/service/__test__/unit/import.service.spec.ts b/apps/vault/src/vault/core/service/__test__/unit/import.service.spec.ts index 827c718f3..20fa8cdb1 100644 --- a/apps/vault/src/vault/core/service/__test__/unit/import.service.spec.ts +++ b/apps/vault/src/vault/core/service/__test__/unit/import.service.spec.ts @@ -1,3 +1,4 @@ +import { ConfigModule } from '@narval/config-module' import { LoggerModule, MetricService, @@ -7,7 +8,9 @@ import { } from '@narval/nestjs-shared' import { Test, TestingModule } from '@nestjs/testing' import { MockProxy, mock } from 'jest-mock-extended' +import { load } from '../../../../../main.config' import { Origin, PrivateAccount } from '../../../../../shared/type/domain.type' +import { EncryptionKeyService } from '../../../../../transit-encryption/core/service/encryption-key.service' import { AccountRepository } from '../../../../persistence/repository/account.repository' import { ImportRepository } from '../../../../persistence/repository/import.repository' import { ImportService } from '../../import.service' @@ -27,7 +30,14 @@ describe('ImportService', () => { importRepositoryMock = mock() const module: TestingModule = await Test.createTestingModule({ - imports: [LoggerModule.forTest(), OpenTelemetryModule.forTest()], + imports: [ + LoggerModule.forTest(), + OpenTelemetryModule.forTest(), + ConfigModule.forRoot({ + load: [load], + isGlobal: true + }) + ], providers: [ ImportService, { @@ -49,6 +59,10 @@ describe('ImportService', () => { { provide: KeyGenerationService, useValue: {} + }, + { + provide: EncryptionKeyService, + useValue: mock() } ] }).compile() diff --git a/apps/vault/src/vault/core/service/import.service.ts b/apps/vault/src/vault/core/service/import.service.ts index 5b5a522d0..8658f8634 100644 --- a/apps/vault/src/vault/core/service/import.service.ts +++ b/apps/vault/src/vault/core/service/import.service.ts @@ -1,26 +1,16 @@ import { resourceId } from '@narval/armory-sdk' import { LoggerService, MetricService, OTEL_ATTR_CLIENT_ID } from '@narval/nestjs-shared' import { Hex } from '@narval/policy-engine-shared' -import { - Alg, - RsaPrivateKey, - RsaPublicKey, - generateJwk, - privateKeyToJwk, - publicKeyToHex, - rsaDecrypt, - rsaPrivateKeyToPublicKey -} from '@narval/signature' +import { RsaPublicKey, privateKeyToJwk, publicKeyToHex } from '@narval/signature' import { HttpStatus, Inject, Injectable } from '@nestjs/common' import { Counter } from '@opentelemetry/api' -import { decodeProtectedHeader } from 'jose' import { isHex } from 'viem' import { privateKeyToAddress } from 'viem/accounts' import { ApplicationException } from '../../../shared/exception/application.exception' import { Origin, PrivateAccount } from '../../../shared/type/domain.type' +import { EncryptionKeyService } from '../../../transit-encryption/core/service/encryption-key.service' import { ImportWalletDto } from '../../http/rest/dto/import-wallet.dto' import { AccountRepository } from '../../persistence/repository/account.repository' -import { ImportRepository } from '../../persistence/repository/import.repository' import { getRootKey } from '../util/key-generation.util' import { KeyGenerationService } from './key-generation.service' @@ -32,8 +22,8 @@ export class ImportService { constructor( private accountRepository: AccountRepository, - private importRepository: ImportRepository, private keyGenerationService: KeyGenerationService, + private encryptionKeyService: EncryptionKeyService, private logger: LoggerService, @Inject(MetricService) private metricService: MetricService ) { @@ -42,13 +32,9 @@ export class ImportService { } async generateEncryptionKey(clientId: string): Promise { - const privateKey = await generateJwk(Alg.RS256, { use: 'enc' }) - const publicKey = rsaPrivateKeyToPublicKey(privateKey) + const encryptionKey = await this.encryptionKeyService.generate(clientId) - // Save the privateKey - await this.importRepository.save(clientId, privateKey) - - return publicKey + return encryptionKey.publicKey } async importPrivateKey(clientId: string, privateKey: Hex, accountId?: string): Promise { @@ -72,26 +58,7 @@ export class ImportService { } async #decrypt(clientId: string, encryptedData: string): Promise { - const header = decodeProtectedHeader(encryptedData) - const kid = header.kid - - if (!kid) { - throw new ApplicationException({ - message: 'Missing kid in JWE header', - suggestedHttpStatusCode: HttpStatus.BAD_REQUEST - }) - } - - const encryptionPrivateKey = await this.importRepository.findById(clientId, kid) - - if (!encryptionPrivateKey) { - throw new ApplicationException({ - message: 'Encryption Key Not Found', - suggestedHttpStatusCode: HttpStatus.NOT_FOUND - }) - } - - return rsaDecrypt(encryptedData, encryptionPrivateKey.jwk) + return this.encryptionKeyService.decrypt(clientId, encryptedData) } async importEncryptedPrivateKey( diff --git a/apps/vault/src/vault/http/rest/controller/encryption-key.controller.ts b/apps/vault/src/vault/http/rest/controller/encryption-key.controller.ts deleted file mode 100644 index 2d977fa28..000000000 --- a/apps/vault/src/vault/http/rest/controller/encryption-key.controller.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { Permission } from '@narval/armory-sdk' -import { REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' -import { Controller, HttpStatus, Post } from '@nestjs/common' -import { ApiHeader, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' -import { ClientId } from '../../../../shared/decorator/client-id.decorator' -import { PermissionGuard } from '../../../../shared/decorator/permission-guard.decorator' -import { ImportService } from '../../../core/service/import.service' -import { EncryptionKeyDto } from '../dto/encryption-key.dto' - -@Controller({ - path: '/encryption-keys', - version: '1' -}) -@PermissionGuard(Permission.WALLET_IMPORT) -@ApiTags('Encryption Key') -@ApiHeader({ - name: REQUEST_HEADER_CLIENT_ID, - required: true -}) -export class EncryptionKeyController { - constructor(private importService: ImportService) {} - - @Post() - @ApiOperation({ - summary: 'Generates an encryption key pair used to secure end-to-end communication containing sensitive information' - }) - @ApiResponse({ - status: HttpStatus.CREATED, - type: EncryptionKeyDto - }) - async generate(@ClientId() clientId: string): Promise { - const publicKey = await this.importService.generateEncryptionKey(clientId) - - return EncryptionKeyDto.create({ publicKey }) - } -} diff --git a/apps/vault/src/vault/http/rest/dto/encryption-key.dto.ts b/apps/vault/src/vault/http/rest/dto/encryption-key.dto.ts deleted file mode 100644 index b9cbf7d07..000000000 --- a/apps/vault/src/vault/http/rest/dto/encryption-key.dto.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { rsaPublicKeySchema } from '@narval/signature' -import { createZodDto } from 'nestjs-zod' -import { z } from 'zod' - -export class EncryptionKeyDto extends createZodDto( - z.object({ - publicKey: rsaPublicKeySchema - }) -) {} diff --git a/apps/vault/src/vault/vault.module.ts b/apps/vault/src/vault/vault.module.ts index 4fea2a917..edb697513 100644 --- a/apps/vault/src/vault/vault.module.ts +++ b/apps/vault/src/vault/vault.module.ts @@ -9,13 +9,13 @@ import { ZodExceptionFilter } from '../shared/filter/zod-exception.filter' import { NonceGuard } from '../shared/guard/nonce.guard' import { KeyValueModule } from '../shared/module/key-value/key-value.module' import { PersistenceModule } from '../shared/module/persistence/persistence.module' +import { TransitEncryptionModule } from '../transit-encryption/transit-encryption.module' import { AdminService } from './core/service/admin.service' import { ImportService } from './core/service/import.service' import { KeyGenerationService } from './core/service/key-generation.service' import { NonceService } from './core/service/nonce.service' import { SigningService } from './core/service/signing.service' import { AccountController } from './http/rest/controller/account.controller' -import { EncryptionKeyController } from './http/rest/controller/encryption-key.controller' import { SignController } from './http/rest/controller/sign.controller' import { WalletController } from './http/rest/controller/wallet.controller' import { AccountRepository } from './persistence/repository/account.repository' @@ -25,8 +25,8 @@ import { RootKeyRepository } from './persistence/repository/root-key.repository' import { VaultController } from './vault.controller' @Module({ - imports: [HttpModule, PersistenceModule, KeyValueModule, ClientModule], - controllers: [VaultController, WalletController, SignController, AccountController, EncryptionKeyController], + imports: [HttpModule, PersistenceModule, KeyValueModule, ClientModule, TransitEncryptionModule], + controllers: [VaultController, WalletController, SignController, AccountController], providers: [ AppRepository, AdminService, From 7e7517c21cad07e9b488210d0bf298ff8f21a895 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Wed, 18 Dec 2024 17:16:08 +0100 Subject: [PATCH 047/120] Add CONNECTION_WRITE permission in the enc key (#46) --- .../http/rest/controller/rest/encryption-key.controller.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/vault/src/transit-encryption/http/rest/controller/rest/encryption-key.controller.ts b/apps/vault/src/transit-encryption/http/rest/controller/rest/encryption-key.controller.ts index faeba1832..70fc018d9 100644 --- a/apps/vault/src/transit-encryption/http/rest/controller/rest/encryption-key.controller.ts +++ b/apps/vault/src/transit-encryption/http/rest/controller/rest/encryption-key.controller.ts @@ -5,6 +5,7 @@ import { Controller, HttpStatus, Post } from '@nestjs/common' import { ApiHeader, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../../shared/decorator/client-id.decorator' import { PermissionGuard } from '../../../../../shared/decorator/permission-guard.decorator' +import { VaultPermission } from '../../../../../shared/type/domain.type' import { EncryptionKeyService } from '../../../../core/service/encryption-key.service' import { EncryptionKeyDto } from '../dto/response/encryption-key.dto' @@ -12,7 +13,7 @@ import { EncryptionKeyDto } from '../dto/response/encryption-key.dto' path: '/encryption-keys', version: '1' }) -@PermissionGuard(Permission.WALLET_IMPORT) +@PermissionGuard(Permission.WALLET_IMPORT, VaultPermission.CONNECTION_WRITE) @ApiTags('Encryption Key') @ApiHeader({ name: REQUEST_HEADER_CLIENT_ID, From 4b911a3d1c049a26260b2d599d87b9364e501814 Mon Sep 17 00:00:00 2001 From: Matt Schoch Date: Thu, 19 Dec 2024 10:26:52 +0100 Subject: [PATCH 048/120] vault config.yaml and .env default file cleanup, dev config & setup smoother --- .gitignore | 4 ++ apps/vault/.env.default | 39 ++-------- apps/vault/.env.template | 71 +++++++++++++++++++ .../client/core/service/bootstrap.service.ts | 2 +- apps/vault/src/main.config.ts | 3 +- ...nfig.local.yml => vault-config.local.yaml} | 37 +++++++--- ...emplate.yml => vault-config.template.yaml} | 0 7 files changed, 111 insertions(+), 45 deletions(-) create mode 100644 apps/vault/.env.template rename config/{vault-config.local.yml => vault-config.local.yaml} (84%) rename config/{vault-config.template.yml => vault-config.template.yaml} (100%) diff --git a/.gitignore b/.gitignore index 834336bcf..0f03c2cb3 100644 --- a/.gitignore +++ b/.gitignore @@ -55,6 +55,10 @@ Thumbs.db .env.production .env.test +config/* +!config/*.local.yaml +!config/*.template.yaml + /rego-build /apps/devtool/storage.json diff --git a/apps/vault/.env.default b/apps/vault/.env.default index 8f718ea0a..9cf4abfad 100644 --- a/apps/vault/.env.default +++ b/apps/vault/.env.default @@ -1,23 +1,15 @@ -NODE_ENV=development - -PORT=3011 - -APP_UID=local-dev-vault-instance-1 +# Note: this is a default configuration for development. Reference `.env.template` for all available options. +# We prefer to use the config.yaml file, rather than the .env options, so most options are set there. -# Absolute path to the config file, otherwise defaults to project root `./config/vault-config.yml` -# CONFIG_FILE="/config/vault-config.yml" +NODE_ENV=development -# OPTIONAL: Sets the admin API key instead of generating a new one during the -# provision. -# -# Key should be hashed, like this: `echo -n "my-api-key" | openssl dgst -sha256 | awk '{print $2}'` -# Plain text API key: vault-admin-api-key -ADMIN_API_KEY=d4a6b4c1cb71dbdb68a1dd429ad737369f74b9e264b9dfa639258753987caaad +# Relative path to the config file from where the node process is started, defaults to `./config/vault-config.yaml` +CONFIG_FILE_RELATIVE_PATH="./config/vault-config.local.yaml" # === Database === # APP db connection string -APP_DATABASE_URL=postgresql://postgres:postgres@localhost:5432/vault?schema=public +# APP_DATABASE_URL=postgresql://postgres:postgres@localhost:5432/vault?schema=public # Migrator db credentials. # host/port/name should be the same, username&password may be different @@ -27,23 +19,6 @@ APP_DATABASE_HOST=host.docker.internal APP_DATABASE_PORT=5432 APP_DATABASE_NAME=vault -# === Encryption === - -# Determine the encryption module keyring type. -# Either "awskms" or "raw". -KEYRING_TYPE=raw - -# If using raw keyring, master password for encrypting data -MASTER_PASSWORD=unsafe-local-dev-master-password - -# If using awskms keyring, provide the ARN of the KMS encryption key instead of a master password -MASTER_AWS_KMS_ARN= - -HMAC_SECRET=unsafe-local-dev-hmac-secret - -# Base URL where the Vault is deployed. Will be used to verify jwsd request -# signatures. -BASE_URL=http://localhost:3011 # === OpenTelemetry configuration === @@ -56,7 +31,7 @@ OTEL_LOGS_EXPORTER=otlp OTEL_LOG_LEVEL=error OTEL_RESOURCE_ATTRIBUTES=deployment.environment=local -# === External Api Keys === +# === External Api Keys, for local dev db seeding === # Used to generate a valid connection to Anchorage sandbox access using your credentials ANCHORAGE_API_KEY= diff --git a/apps/vault/.env.template b/apps/vault/.env.template new file mode 100644 index 000000000..c5893cda9 --- /dev/null +++ b/apps/vault/.env.template @@ -0,0 +1,71 @@ +# Template of all the available ENV variables. + +# === Node environment === + +NODE_ENV=development + +# === Server === + +PORT=3011 + +# === Application === + +APP_UID=local-dev-vault-instance-1 + +# === Config === + +# Absolute path to the config file. If not set, uses the relative path. +# CONFIG_FILE_ABSOLUTE_PATH="/config/vault-config.yaml" + +# Relative path to the config file from where the node process is started, defaults to `./config/vault-config.yaml` +CONFIG_FILE_RELATIVE_PATH="./config/vault-config.local.yaml" + +# === Admin API key === + +# OPTIONAL: Sets the admin API key used for app-level admin operations (e.g. creating clients) +# +# Key should be hashed, like this: `echo -n "vault-admin-api-key" | openssl dgst -sha256 | awk '{print $2}'` +# Plain text API key: vault-admin-api-key +ADMIN_API_KEY=d4a6b4c1cb71dbdb68a1dd429ad737369f74b9e264b9dfa639258753987caaad + +# === Database === + +# APP db connection string, used for app runtime. +APP_DATABASE_URL=postgresql://postgres:postgres@localhost:5432/vault?schema=public + +# Migrator db credentials. This is needed for db migrations where we can't use the APP_DATABASE_URL. Can be the same or different credentials. +# host/port/name should be the same, username&password may be different +APP_DATABASE_USERNAME=postgres +APP_DATABASE_PASSWORD=postgres +APP_DATABASE_HOST=host.docker.internal +APP_DATABASE_PORT=5432 +APP_DATABASE_NAME=vault + +# === Encryption === + +# Determine the encryption module keyring type. +# Either "awskms" or "raw". +KEYRING_TYPE=raw + +# If using raw keyring, master password for encrypting data +MASTER_PASSWORD=unsafe-local-dev-master-password + +# If using awskms keyring, provide the ARN of the KMS encryption key instead of a master password +# MASTER_AWS_KMS_ARN= + +# HMAC secret for integrity verification of data in the database. +HMAC_SECRET=unsafe-local-dev-hmac-secret + +# Base URL where the Vault is deployed. Will be used to verify jwsd request signatures. +BASE_URL=http://localhost:3011 + +# === OpenTelemetry configuration === + +# See https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/ +OTEL_SDK_DISABLED=true +# OTEL Collector container HTTP port. +OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 +OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf +OTEL_LOGS_EXPORTER=otlp +OTEL_LOG_LEVEL=error +OTEL_RESOURCE_ATTRIBUTES=deployment.environment=local diff --git a/apps/vault/src/client/core/service/bootstrap.service.ts b/apps/vault/src/client/core/service/bootstrap.service.ts index 2a9c85885..60c33fe84 100644 --- a/apps/vault/src/client/core/service/bootstrap.service.ts +++ b/apps/vault/src/client/core/service/bootstrap.service.ts @@ -65,7 +65,7 @@ export class BootstrapService { })) for (const client of declarativeClients) { - await this.clientService.save(client) + await this.clientService.save(client, true) } } diff --git a/apps/vault/src/main.config.ts b/apps/vault/src/main.config.ts index 30788a33a..1a66905eb 100644 --- a/apps/vault/src/main.config.ts +++ b/apps/vault/src/main.config.ts @@ -284,9 +284,10 @@ export type Config = z.output export const load = (): Config => { const configFilePathEnv = process.env.CONFIG_FILE + const configFileRelativePathEnv = process.env.CONFIG_FILE_RELATIVE_PATH const filePath = configFilePathEnv ? path.resolve(configFilePathEnv) - : path.resolve(process.cwd(), 'config/vault-config.yml') + : path.resolve(process.cwd(), configFileRelativePathEnv || 'config/vault-config.yaml') let yamlConfigRaw = {} try { if (fs.existsSync(filePath)) { diff --git a/config/vault-config.local.yml b/config/vault-config.local.yaml similarity index 84% rename from config/vault-config.local.yml rename to config/vault-config.local.yaml index d485ad91b..67d4099bd 100644 --- a/config/vault-config.local.yml +++ b/config/vault-config.local.yaml @@ -30,6 +30,10 @@ app: oidc: null # Local authentication options, either signed requests or basic api key local: + # [optional]: Sets the admin API key for client provisioning operations + # + # Key should be hashed, like this: `echo -n "my-api-key" | openssl dgst -sha256 | awk '{print $2}'` + # Plain text API key: vault-admin-api-key adminApiKeyHash: d4a6b4c1cb71dbdb68a1dd429ad737369f74b9e264b9dfa639258753987caaad # Auth config for requests from this service outgoing: null @@ -63,7 +67,7 @@ clients: auth: # Disable all auth; only useful in dev - disabled: true + disabled: false # OIDC configuration to use an external auth provider oidc: null # TODO: add OIDC # Local authentication options, either signed requests or basic api key @@ -88,22 +92,33 @@ clients: # Otherwise, any key can authenticate if it matches the authorized credential in a bound token. ## # [optional] URL of the JWKS endpoint that includes any keys that are valid "users" - allowedUsersJwksUrl: https://armory/.well-known/jwks.json - # [optional]: List of allowed users, pinning specific keys instead of jwskUrl + # allowedUsersJwksUrl: https://armory/.well-known/jwks.json + + # [optional]: List of allowed users, pinning specific keys instead of jwskUr allowedUsers: - - userId: armory + ## Private Key for the below Public Key: + # kty: 'OKP' + # crv: 'Ed25519' + # alg: 'EDDSA' + # kid: '0x153ca7ec6216e131a7872c0330872d81c5388d0a3977960a9ee12267e3fc6b94' + # x: 'P8RMuLMuHwb13OfphR_zcvNsKvZN8kCawYeYtlD9aqI' + # d: 'CmvVBDCA64Oo26jeGTTUHaBSJJ2TuRiWGc7ILn4Z6K8' + + # Hex Private Key: 0x0a6bd5043080eb83a8dba8de1934d41da052249d93b9189619cec82e7e19e8af + # Hex Public Key: 0x3fc44cb8b32e1f06f5dce7e9851ff372f36c2af64df2409ac18798b650fd6aa2 + ## + - userId: dev-user-1 publicKey: - kid: 'ZvO6VhPB2Ebe6qmk2RH5ly6qOb2O' # armory staging dev-client-1 - kty: 'EC' - crv: 'secp256k1' - alg: 'ES256K' - x: 'PismhbGayPpeTjyxi021v6Z3gwaVak1A7l8PQC337XM' - y: 'I2pO8D3v9CFgcZo0ej9jhFHwI3QSVFlaw3l4Gx8QbGI' + kty: 'OKP' + crv: 'Ed25519' + alg: 'EDDSA' + kid: '0x153ca7ec6216e131a7872c0330872d81c5388d0a3977960a9ee12267e3fc6b94' + x: 'P8RMuLMuHwb13OfphR_zcvNsKvZN8kCawYeYtlD9aqI' # Authorization options, typically this will be used to pin the policy engine's public signing key. tokenValidation: # (optional) if you want to disable authorization for this client. DO NOT USE IN PRODUCTION. - disabled: false + disabled: true # The GNAP Authorization Server that issues tokens url: 'http://armory' # [optional] JWKS endpoint for the auth server; used for jwt verification. Or you can pin the key. diff --git a/config/vault-config.template.yml b/config/vault-config.template.yaml similarity index 100% rename from config/vault-config.template.yml rename to config/vault-config.template.yaml From 4711e6776af4376a54faf01818ea023e25c4c854 Mon Sep 17 00:00:00 2001 From: Matt Schoch Date: Thu, 19 Dec 2024 10:33:17 +0100 Subject: [PATCH 049/120] Adding config.example.yaml and gitignoring local.yaml --- .gitignore | 2 +- apps/vault/Makefile | 1 + config/{vault-config.local.yaml => vault-config.example.yaml} | 0 3 files changed, 2 insertions(+), 1 deletion(-) rename config/{vault-config.local.yaml => vault-config.example.yaml} (100%) diff --git a/.gitignore b/.gitignore index 0f03c2cb3..9d4a1a157 100644 --- a/.gitignore +++ b/.gitignore @@ -56,7 +56,7 @@ Thumbs.db .env.test config/* -!config/*.local.yaml +!config/*.example.yaml !config/*.template.yaml /rego-build diff --git a/apps/vault/Makefile b/apps/vault/Makefile index d6a23932f..c5db6932e 100644 --- a/apps/vault/Makefile +++ b/apps/vault/Makefile @@ -20,6 +20,7 @@ vault/setup: vault/copy-default-env: cp ${VAULT_PROJECT_DIR}/.env.default ${VAULT_PROJECT_DIR}/.env cp ${VAULT_PROJECT_DIR}/.env.test.default ${VAULT_PROJECT_DIR}/.env.test + cp ./config/vault-config.example.yaml ./config/vault-config.local.yaml # === Build === diff --git a/config/vault-config.local.yaml b/config/vault-config.example.yaml similarity index 100% rename from config/vault-config.local.yaml rename to config/vault-config.example.yaml From 515aef59805a314cba082b54b7c68a850acb275b Mon Sep 17 00:00:00 2001 From: Matt Schoch Date: Thu, 19 Dec 2024 12:24:25 +0100 Subject: [PATCH 050/120] Moving db connection back to .env instead of config.yaml because Migrations need it --- apps/vault/.env.default | 2 +- config/vault-config.example.yaml | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/apps/vault/.env.default b/apps/vault/.env.default index 9cf4abfad..cb83b91c4 100644 --- a/apps/vault/.env.default +++ b/apps/vault/.env.default @@ -9,7 +9,7 @@ CONFIG_FILE_RELATIVE_PATH="./config/vault-config.local.yaml" # === Database === # APP db connection string -# APP_DATABASE_URL=postgresql://postgres:postgres@localhost:5432/vault?schema=public +APP_DATABASE_URL=postgresql://postgres:postgres@localhost:5432/vault?schema=public # Migrator db credentials. # host/port/name should be the same, username&password may be different diff --git a/config/vault-config.example.yaml b/config/vault-config.example.yaml index 67d4099bd..026dcac32 100644 --- a/config/vault-config.example.yaml +++ b/config/vault-config.example.yaml @@ -14,10 +14,6 @@ cors: [] # Base URL where the Vault is deployed. Used to verify jwsd request signatures. baseUrl: http://localhost:3011 -# Database configuration -database: - url: postgresql://postgres:postgres@localhost:5432/vault?schema=public - # Application identity and security app: id: local-dev-vault-instance-1 From e88a971d0093c0ca53004eee09165659b6f41eb7 Mon Sep 17 00:00:00 2001 From: Ptroger <44851272+Ptroger@users.noreply.github.com> Date: Fri, 20 Dec 2024 11:39:37 +0100 Subject: [PATCH 051/120] activate endpoint overrides private key when provided (#43) * activate endpoint overrides private key when provided * format on con service * also overrides public key * test do round trip conversion on privateKey --- .../broker/__test__/e2e/connection.spec.ts | 95 +++++++++++++++++++ .../broker/core/service/connection.service.ts | 18 ++-- 2 files changed, 107 insertions(+), 6 deletions(-) diff --git a/apps/vault/src/broker/__test__/e2e/connection.spec.ts b/apps/vault/src/broker/__test__/e2e/connection.spec.ts index 30ce71dfd..5002e3f0e 100644 --- a/apps/vault/src/broker/__test__/e2e/connection.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/connection.spec.ts @@ -497,6 +497,101 @@ describe('Connection', () => { fail('expected an active connection') } }) + + it('overrides the existing connection privateKey when providing a new one on pending connection activation', async () => { + expect.assertions(6) + + const connectionId = uuid() + const provider = Provider.ANCHORAGE + const label = 'Test Anchorage Connection' + const credentials = { + apiKey: 'test-api-key', + privateKey: '0x9ead9e0c93e9f4d02a09d4d3fdd35eac82452717a04ca98580302c16485b2480' // Adding private key to test override + } + + // First create a pending connection + const { body: pendingConnection } = await request(app.getHttpServer()) + .post('/provider/connections/initiate') + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk, + requestUrl: '/provider/connections/initiate', + payload: { connectionId, provider } + }) + ) + .send({ connectionId, provider }) + + // Encrypt the credentials including the new private key + const encryptedCredentials = await rsaEncrypt( + JSON.stringify(credentials), + pendingConnection.data.encryptionPublicKey.jwk + ) + + // Activate the connection with the new credentials + const { status, body } = await request(app.getHttpServer()) + .post('/provider/connections') + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk, + requestUrl: '/provider/connections', + payload: { + provider, + connectionId, + label, + url, + encryptedCredentials + } + }) + ) + .send({ + provider, + connectionId, + label, + url, + encryptedCredentials + }) + + // Verify the response structure + expect(body.data).toEqual({ + clientId, + connectionId, + label, + provider, + url, + createdAt: expect.any(String), + status: ConnectionStatus.ACTIVE, + updatedAt: expect.any(String) + }) + expect(status).toEqual(HttpStatus.CREATED) + + // Verify the created connection in the database + const createdConnection = await connectionService.findById(clientId, connectionId, true) + + expect(createdConnection).toMatchObject({ + clientId, + connectionId, + label, + provider, + url, + createdAt: expect.any(Date), + status: ConnectionStatus.ACTIVE, + updatedAt: expect.any(Date) + }) + + if (isActiveConnection(createdConnection)) { + // Verify the private key was actually changed + expect(createdConnection.credentials.privateKey.d).not.toEqual(pendingConnection.data.privateKey?.d) + expect(createdConnection.credentials.publicKey.x).not.toEqual(pendingConnection.data.publicKey?.x) + const createdHex = await privateKeyToHex(createdConnection.credentials.privateKey) + expect(createdHex).toEqual(credentials.privateKey) + } else { + fail('expected an active connection') + } + }) }) describe('DELETE /provider/connections/:id', () => { diff --git a/apps/vault/src/broker/core/service/connection.service.ts b/apps/vault/src/broker/core/service/connection.service.ts index 860644b00..1e0913095 100644 --- a/apps/vault/src/broker/core/service/connection.service.ts +++ b/apps/vault/src/broker/core/service/connection.service.ts @@ -182,6 +182,17 @@ export class ConnectionService { const credentials = await this.getInputCredentials(clientId, input) + const mergedCredentials = { + ...pendingConnection.credentials, + apiKey: credentials.apiKey + } + + // If a private key is provided in the input, it overrides the private and public key from the pending connection. + if (credentials.privateKey) { + mergedCredentials.privateKey = privateKeyToJwk(credentials.privateKey, Alg.EDDSA) + mergedCredentials.publicKey = getPublicKey(mergedCredentials.privateKey) + } + const connection: ActiveConnectionWithCredentials = { ...pendingConnection, clientId, @@ -191,14 +202,9 @@ export class ConnectionService { url: input.url, updatedAt: now, createdAt: pendingConnection.createdAt, - credentials: { - ...pendingConnection.credentials, - apiKey: credentials.apiKey - } + credentials: mergedCredentials } - await this.connectionRepository.update(connection) - this.eventEmitter.emit(ConnectionActivatedEvent.EVENT_NAME, new ConnectionActivatedEvent(connection)) return connection From e7914d70f7025d1985ba725a6a0f85f1cab5de30 Mon Sep 17 00:00:00 2001 From: Ptroger <44851272+Ptroger@users.noreply.github.com> Date: Fri, 20 Dec 2024 14:10:00 +0100 Subject: [PATCH 052/120] indexed createdAt and clientId on provider data (#47) * indexed createdAt and clientId on provider data * changed to a coumpound index createdAt, clientId, id * change compound index to be createdAt-Id --- .../migration.sql | 26 +++++++++++++++++++ .../module/persistence/schema/schema.prisma | 25 ++++++++++-------- 2 files changed, 40 insertions(+), 11 deletions(-) create mode 100644 apps/vault/src/shared/module/persistence/schema/migrations/20241220105006_index_created_at_client_id_on_provider_indexed_data/migration.sql diff --git a/apps/vault/src/shared/module/persistence/schema/migrations/20241220105006_index_created_at_client_id_on_provider_indexed_data/migration.sql b/apps/vault/src/shared/module/persistence/schema/migrations/20241220105006_index_created_at_client_id_on_provider_indexed_data/migration.sql new file mode 100644 index 000000000..b2349ff30 --- /dev/null +++ b/apps/vault/src/shared/module/persistence/schema/migrations/20241220105006_index_created_at_client_id_on_provider_indexed_data/migration.sql @@ -0,0 +1,26 @@ +/* + Warnings: + + - A unique constraint covering the columns `[client_id,external_id]` on the table `provider_transfer` will be added. If there are existing duplicate values, this will fail. + +*/ +-- CreateIndex +CREATE INDEX "provider_account_created_at_client_id_idx" ON "provider_account"("created_at", "client_id"); + +-- CreateIndex +CREATE INDEX "provider_address_created_at_client_id_idx" ON "provider_address"("created_at", "client_id"); + +-- CreateIndex +CREATE INDEX "provider_connection_created_at_client_id_idx" ON "provider_connection"("created_at", "client_id"); + +-- CreateIndex +CREATE INDEX "provider_known_destination_created_at_client_id_idx" ON "provider_known_destination"("created_at", "client_id"); + +-- CreateIndex +CREATE INDEX "provider_transfer_created_at_client_id_idx" ON "provider_transfer"("created_at", "client_id"); + +-- CreateIndex +CREATE UNIQUE INDEX "provider_transfer_client_id_external_id_key" ON "provider_transfer"("client_id", "external_id"); + +-- CreateIndex +CREATE INDEX "provider_wallet_created_at_client_id_idx" ON "provider_wallet"("created_at", "client_id"); diff --git a/apps/vault/src/shared/module/persistence/schema/schema.prisma b/apps/vault/src/shared/module/persistence/schema/schema.prisma index 733b3d5aa..47e9eb22b 100644 --- a/apps/vault/src/shared/module/persistence/schema/schema.prisma +++ b/apps/vault/src/shared/module/persistence/schema/schema.prisma @@ -14,15 +14,15 @@ datasource db { } model Vault { - id String @id + id String @id // Encryption options, possibly set from Config file - encryptionKeyringType String @map("encryption_keyring_type") // raw | awskms - encryptionMasterKeySpelling String? @map("enncryption_master_key") /// @encrypted by masterPassword KEK @ignore - encryptionMasterKey String? @map("encryption_master_key") /// @encrypted by masterPassword KEK - encryptionMasterAwsKmsArn String? @map("encryption_master_aws_kms_arn") // only if type = awskms + encryptionKeyringType String @map("encryption_keyring_type") // raw | awskms + encryptionMasterKeySpelling String? @map("enncryption_master_key") /// @encrypted by masterPassword KEK @ignore + encryptionMasterKey String? @map("encryption_master_key") /// @encrypted by masterPassword KEK + encryptionMasterAwsKmsArn String? @map("encryption_master_aws_kms_arn") // only if type = awskms // Auth Options, set from Config file - authDisabled Boolean? @map("auth_disabled") - adminApiKeyHash String? @map("admin_api_key_hash") /// hash, not plaintext + authDisabled Boolean? @map("auth_disabled") + adminApiKeyHash String? @map("admin_api_key_hash") /// hash, not plaintext @@map("vault") } @@ -111,7 +111,7 @@ model ProviderWallet { sourceTransfers ProviderTransfer[] @relation("SourceWallet") @@unique([clientId, externalId]) - + @@index([createdAt, clientId]) @@map("provider_wallet") } @@ -132,7 +132,7 @@ model ProviderAccount { sourceTransfers ProviderTransfer[] @relation("SourceAccount") @@unique([clientId, externalId]) - + @@index([createdAt, clientId]) @@map("provider_account") } @@ -151,7 +151,7 @@ model ProviderAddress { sourceTransfers ProviderTransfer[] @relation("SourceAddress") @@unique([clientId, externalId]) - + @@index([createdAt, clientId]) @@map("provider_address") } @@ -171,7 +171,7 @@ model ProviderKnownDestination { connection ProviderConnection @relation(fields: [connectionId], references: [id]) @@unique([clientId, externalId]) - + @@index([createdAt, clientId]) @@map("provider_known_destination") } @@ -194,6 +194,7 @@ model ProviderConnection { connections ProviderWalletConnection[] syncs ProviderSync[] + @@index([createdAt, clientId]) @@map("provider_connection") } @@ -241,5 +242,7 @@ model ProviderTransfer { sourceAccount ProviderAccount? @relation("SourceAccount", fields: [sourceAccountId], references: [id]) sourceAddress ProviderAddress? @relation("SourceAddress", fields: [sourceAddressId], references: [id]) + @@unique([clientId, externalId]) + @@index([createdAt, clientId]) @@map("provider_transfer") } From 369cdaef7264e9a8ef7a68ae9d055ffd52cc04a3 Mon Sep 17 00:00:00 2001 From: Ptroger <44851272+Ptroger@users.noreply.github.com> Date: Fri, 20 Dec 2024 17:19:24 +0100 Subject: [PATCH 053/120] Feature/nar 2016 sync known addresses (#49) * indexed createdAt and clientId on provider data * migration for m2m conn<>knownDest + label column * migration to cascade deletion on join tables * known destination sync create updates and deletes * removed index migration and schema changes * modified migration to be non breaking * insert clientId from initial table - remove hardcoded temp table * added knownDest<>conn join row * removed the migration script --- apps/vault/src/broker/broker.module.ts | 4 + .../anchorage-sync.service.spec.ts | 91 ++++- .../integration/mocks/anchorage/handlers.ts | 23 +- .../response/trusted-destinations-1.json | 44 +++ .../response/trusted-destinations-2.json | 35 ++ .../response/trusted-destinations-3.json | 16 + .../core/service/anchorage-sync.service.ts | 114 ++++++- .../core/service/know-destination.service.ts | 45 +++ .../core/type/indexed-resources.type.ts | 17 +- .../broker/http/client/anchorage.client.ts | 78 +++++ .../known-destination.repository.ts | 311 ++++++++++++++++++ .../migration.sql | 27 ++ .../migration.sql | 11 + .../module/persistence/schema/schema.prisma | 27 +- .../src/shared/module/persistence/seed.ts | 14 +- examples/unified-api/unified-api.example.zip | Bin 0 -> 10353 bytes 16 files changed, 843 insertions(+), 14 deletions(-) create mode 100644 apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/trusted-destinations-1.json create mode 100644 apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/trusted-destinations-2.json create mode 100644 apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/trusted-destinations-3.json create mode 100644 apps/vault/src/broker/core/service/know-destination.service.ts create mode 100644 apps/vault/src/broker/persistence/repository/known-destination.repository.ts create mode 100644 apps/vault/src/shared/module/persistence/schema/migrations/20241219140123_add_m2m_known_dest_conn_and_label_to_known_dest/migration.sql create mode 100644 apps/vault/src/shared/module/persistence/schema/migrations/20241219150752_cascade_deletion_on_m2m_tables/migration.sql create mode 100644 examples/unified-api/unified-api.example.zip diff --git a/apps/vault/src/broker/broker.module.ts b/apps/vault/src/broker/broker.module.ts index 681d84ca4..c6e514b2b 100644 --- a/apps/vault/src/broker/broker.module.ts +++ b/apps/vault/src/broker/broker.module.ts @@ -11,6 +11,7 @@ import { AccountService } from './core/service/account.service' import { AddressService } from './core/service/address.service' import { AnchorageSyncService } from './core/service/anchorage-sync.service' import { ConnectionService } from './core/service/connection.service' +import { KnownDestinationService } from './core/service/know-destination.service' import { ProxyService } from './core/service/proxy.service' import { SyncService } from './core/service/sync.service' import { WalletService } from './core/service/wallet.service' @@ -26,6 +27,7 @@ import { ConnectionSeedService } from './persistence/connection.seed' import { AccountRepository } from './persistence/repository/account.repository' import { AddressRepository } from './persistence/repository/address.repository' import { ConnectionRepository } from './persistence/repository/connection.repository' +import { KnownDestinationRepository } from './persistence/repository/known-destination.repository' import { SyncRepository } from './persistence/repository/sync.repository' import { WalletRepository } from './persistence/repository/wallet.repository' @@ -64,6 +66,8 @@ import { WalletRepository } from './persistence/repository/wallet.repository' ConnectionSyncEventHandler, EncryptionKeyRepository, EncryptionKeyService, + KnownDestinationRepository, + KnownDestinationService, ProxyService, SyncRepository, SyncService, diff --git a/apps/vault/src/broker/core/service/__test__/integration/anchorage-sync.service.spec.ts b/apps/vault/src/broker/core/service/__test__/integration/anchorage-sync.service.spec.ts index c879b1f22..1dcb3152b 100644 --- a/apps/vault/src/broker/core/service/__test__/integration/anchorage-sync.service.spec.ts +++ b/apps/vault/src/broker/core/service/__test__/integration/anchorage-sync.service.spec.ts @@ -21,7 +21,9 @@ import { AccountService } from '../../account.service' import { AddressService } from '../../address.service' import { AnchorageSyncService } from '../../anchorage-sync.service' import { ConnectionService } from '../../connection.service' +import { KnownDestinationService } from '../../know-destination.service' import { WalletService } from '../../wallet.service' +import { trustedDestinationsHandlers } from './mocks/anchorage/handlers' import { ANCHORAGE_TEST_API_BASE_URL, setupMockServer } from './mocks/anchorage/server' describe(AnchorageSyncService.name, () => { @@ -34,12 +36,13 @@ describe(AnchorageSyncService.name, () => { let walletService: WalletRepository let accountService: AccountService let addressService: AddressService + let knownDestinationService: KnownDestinationService let provisionService: ProvisionService let clientService: ClientService - setupMockServer() + const server = setupMockServer() - const clientId = uuid() + const clientId = 'test-client-id' beforeAll(async () => { module = await Test.createTestingModule({ @@ -67,6 +70,7 @@ describe(AnchorageSyncService.name, () => { walletService = module.get(WalletService) accountService = module.get(AccountService) addressService = module.get(AddressService) + knownDestinationService = module.get(KnownDestinationService) provisionService = module.get(ProvisionService) clientService = module.get(ClientService) @@ -172,4 +176,87 @@ describe(AnchorageSyncService.name, () => { expect(second.length).toEqual(0) }) }) + + describe('syncKnownDestinations', () => { + it('fetches anchorage addresses and persist them as known-addresses', async () => { + const { created } = await anchorageSyncService.syncKnownDestinations(connection) + const { data: knownDestinations } = await knownDestinationService.findAll(connection.clientId) + + expect(created).toEqual(expect.arrayContaining(knownDestinations)) + }) + + it('updates anchorage knownDestination when it already exists', async () => { + const { credentials, ...expectedConnection } = connection + + // First sync - create initial destinations + server.use(trustedDestinationsHandlers(ANCHORAGE_TEST_API_BASE_URL).findAll) + await anchorageSyncService.syncKnownDestinations(connection) + + const { data: initialDestinations } = await knownDestinationService.findAll(connection.clientId) + // Second sync with updated data + server.use(trustedDestinationsHandlers(ANCHORAGE_TEST_API_BASE_URL).deleteAndUpdate) + const { created, updated, deleted } = await anchorageSyncService.syncKnownDestinations(connection) + + // Verify basic operations + expect(created).toEqual([]) + expect(deleted).toEqual(1) + + // Only the modified destination should be in updated + expect(updated).toHaveLength(1) + expect(updated[0]).toMatchObject({ + externalId: 'toBeUpdated', + address: '0x8Bc2B8F33e5AeF847B8973Fa669B948A3028D6bd', + label: 'new memo', + assetId: 'USDC', + networkId: 'ETH', + connections: expect.arrayContaining([expectedConnection]) + }) + + // Verify the update timestamp is newer + expect(updated[0].updatedAt.getTime()).toBeGreaterThan(updated[0].createdAt.getTime()) + + // Verify other destinations weren't affected + const { data: allDestinations } = await knownDestinationService.findAll(connection.clientId) + const unchangedDestination = allDestinations.find((d) => d.externalId === 'neverChanges') + const initialUnchangedDestination = initialDestinations.find((d) => d.externalId === 'neverChanges') + expect(unchangedDestination).toEqual(initialUnchangedDestination) + }) + + it('connects known-destination with the new connection', async () => { + const { credentials: firstCredentials, ...firstConnection } = connection + const secondConnectionWithCredentials = await connectionService.create(clientId, { + connectionId: uuid(), + provider: Provider.ANCHORAGE, + url: ANCHORAGE_TEST_API_BASE_URL, + credentials: { + apiKey: 'test-api-key', + privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) + } + }) + + const { credentials: secondCredentials, ...secondConnection } = secondConnectionWithCredentials + + // First sync - should create all destinations + server.use(trustedDestinationsHandlers(ANCHORAGE_TEST_API_BASE_URL).findAll) + await anchorageSyncService.syncKnownDestinations(connection) + + // Second sync with new connection that only finds one destination + server.use(trustedDestinationsHandlers(ANCHORAGE_TEST_API_BASE_URL).connect) + const { updated } = await anchorageSyncService.syncKnownDestinations(secondConnectionWithCredentials) + + // We expect only one item to be updated - the one with connections to both accounts + expect(updated).toHaveLength(1) + expect(updated[0]).toMatchObject({ + externalId: 'toBeConnected', + connections: expect.arrayContaining([firstConnection, secondConnection]) + }) + + // Verify other destinations weren't affected + const { data: allDestinations } = await knownDestinationService.findAll(connection.clientId) + const unchangedDestinations = allDestinations.filter((d) => d.externalId !== 'toBeConnected') + unchangedDestinations.forEach((dest) => { + expect(dest.connections).toEqual(expect.arrayContaining([firstConnection])) + }) + }) + }) }) diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/handlers.ts b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/handlers.ts index 6e089fe81..a6a24abb4 100644 --- a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/handlers.ts +++ b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/handlers.ts @@ -1,8 +1,27 @@ import { HttpResponse, http } from 'msw' +import trustedDestinationsFirst from './response/trusted-destinations-1.json' +import trustedDestinationsSecond from './response/trusted-destinations-2.json' +import trustedDestinationsThird from './response/trusted-destinations-3.json' import vaultAddressesOk from './response/vaults-addresses-ok.json' import vaultsOk from './response/vaults-ok.json' import walletsOk from './response/wallets-ok.json' +export const trustedDestinationsHandlers = (baseUrl: string) => { + return { + findAll: http.get(`${baseUrl}/v2/trusted-destinations`, () => { + return new HttpResponse(JSON.stringify(trustedDestinationsFirst)) + }), + + deleteAndUpdate: http.get(`${baseUrl}/v2/trusted-destinations`, () => { + return new HttpResponse(JSON.stringify(trustedDestinationsSecond)) + }), + + connect: http.get(`${baseUrl}/v2/trusted-destinations`, () => { + return new HttpResponse(JSON.stringify(trustedDestinationsThird)) + }) + } +} + export const getHandlers = (baseUrl: string) => [ http.get(`${baseUrl}/v2/vaults/:vaultId/addresses`, () => { return new HttpResponse(JSON.stringify(vaultAddressesOk)) @@ -14,5 +33,7 @@ export const getHandlers = (baseUrl: string) => [ http.get(`${baseUrl}/v2/wallets`, () => { return new HttpResponse(JSON.stringify(walletsOk)) - }) + }), + + trustedDestinationsHandlers(baseUrl).findAll ] diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/trusted-destinations-1.json b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/trusted-destinations-1.json new file mode 100644 index 000000000..51dc594bd --- /dev/null +++ b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/trusted-destinations-1.json @@ -0,0 +1,44 @@ +{ + "data": [ + { + "id": "toBeConnected", + "type": "crypto", + "crypto": { + "address": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", + "networkId": "ETH", + "assetType": "ETH" + } + }, + { + "id": "neverChanges", + "type": "crypto", + "crypto": { + "address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh", + "networkId": "BTC", + "assetType": "BTC" + } + }, + { + "id": "toBeUpdated", + "type": "crypto", + "crypto": { + "address": "0x8Bc2B8F33e5AeF847B8973Fa669B948A3028D6bd", + "networkId": "ETH", + "assetType": "USDC" + } + }, + { + "id": "toBeDeleted", + "type": "crypto", + "crypto": { + "address": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", + "networkId": "XRP", + "assetType": "XRP", + "memo": "123456" + } + } + ], + "page": { + "next": null + } +} diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/trusted-destinations-2.json b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/trusted-destinations-2.json new file mode 100644 index 000000000..cd627749f --- /dev/null +++ b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/trusted-destinations-2.json @@ -0,0 +1,35 @@ +{ + "data": [ + { + "id": "toBeConnected", + "type": "crypto", + "crypto": { + "address": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", + "networkId": "ETH", + "assetType": "ETH" + } + }, + { + "id": "neverChanges", + "type": "crypto", + "crypto": { + "address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh", + "networkId": "BTC", + "assetType": "BTC" + } + }, + { + "id": "toBeUpdated", + "type": "crypto", + "crypto": { + "address": "0x8Bc2B8F33e5AeF847B8973Fa669B948A3028D6bd", + "networkId": "ETH", + "assetType": "USDC", + "memo": "new memo" + } + } + ], + "page": { + "next": null + } +} diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/trusted-destinations-3.json b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/trusted-destinations-3.json new file mode 100644 index 000000000..5985e2f1b --- /dev/null +++ b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/trusted-destinations-3.json @@ -0,0 +1,16 @@ +{ + "data": [ + { + "id": "toBeConnected", + "type": "crypto", + "crypto": { + "address": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", + "networkId": "ETH", + "assetType": "ETH" + } + } + ], + "page": { + "next": null + } +} diff --git a/apps/vault/src/broker/core/service/anchorage-sync.service.ts b/apps/vault/src/broker/core/service/anchorage-sync.service.ts index 3add04bee..c3965161b 100644 --- a/apps/vault/src/broker/core/service/anchorage-sync.service.ts +++ b/apps/vault/src/broker/core/service/anchorage-sync.service.ts @@ -7,9 +7,10 @@ import { AnchorageClient } from '../../http/client/anchorage.client' import { ConnectionInvalidException } from '../exception/connection-invalid.exception' import { SyncException } from '../exception/sync.exception' import { ActiveConnection, ActiveConnectionWithCredentials, Provider } from '../type/connection.type' -import { Account, Address, Wallet } from '../type/indexed-resources.type' +import { Account, Address, KnownDestination, Wallet } from '../type/indexed-resources.type' import { AccountService } from './account.service' import { AddressService } from './address.service' +import { KnownDestinationService } from './know-destination.service' import { WalletService } from './wallet.service' @Injectable() @@ -19,6 +20,7 @@ export class AnchorageSyncService { private readonly walletService: WalletService, private readonly accountService: AccountService, private readonly addressService: AddressService, + private readonly knownDestinationService: KnownDestinationService, private readonly logger: LoggerService ) {} @@ -26,6 +28,7 @@ export class AnchorageSyncService { await this.syncWallets(connection) await this.syncAccounts(connection) await this.syncAddresses(connection) + await this.syncKnownDestinations(connection) } async syncWallets(connection: ActiveConnectionWithCredentials) { @@ -259,6 +262,115 @@ export class AnchorageSyncService { return addresses } + async syncKnownDestinations(connection: ActiveConnectionWithCredentials): Promise<{ + created: KnownDestination[] + updated: KnownDestination[] + deleted: number + }> { + this.logger.log('Sync Anchorage known destinations', { + connectionId: connection.credentials, + clientId: connection.clientId, + url: connection.url + }) + + this.validateConnection(connection) + + // Fetch current state from Anchorage + const anchorageTrustedDestinations = await this.anchorageClient.getTrustedDestinations({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey + }) + + const now = new Date() + + const { data: existingKnownDestinations } = await this.knownDestinationService.findAll(connection.clientId) + + const incomingMap = new Map(anchorageTrustedDestinations.map((dest) => [dest.id, dest])) + const existingMap = new Map(existingKnownDestinations.map((dest) => [dest.externalId, dest])) + + const toBeUpdated = anchorageTrustedDestinations + .filter((incoming) => { + // First check if we have an existing destination + const existing = existingMap.get(incoming.id) + if (!existing) return false + + // Check if the connection is already tied to this destination + const hasConnection = existing.connections.some((conn) => conn.connectionId === connection.connectionId) + + // Check if any data has changed + const hasDataChanges = + (existing.label || undefined) !== incoming.crypto.memo || + (existing.assetId || undefined) !== incoming.crypto.assetType + + // Only include if there are data changes or it needs the new connection + return hasDataChanges || !hasConnection + }) + .map((incoming) => { + const lookup = existingMap.get(incoming.id)! + return { + ...lookup, + label: incoming.crypto.memo, + assetId: incoming.crypto.assetType, + updatedAt: now, + connections: [...lookup.connections, connection] + } + }) + + const toBeCreated: KnownDestination[] = anchorageTrustedDestinations + .filter((anchorageDest) => !existingMap.has(anchorageDest.id)) + .map((anchorageDest) => + KnownDestination.parse({ + knownDestinationId: uuid(), + address: anchorageDest.crypto.address, + clientId: connection.clientId, + externalId: anchorageDest.id, + label: anchorageDest.crypto.memo, + assetId: anchorageDest.crypto.assetType, + provider: Provider.ANCHORAGE, + networkId: anchorageDest.crypto.networkId, + createdAt: now, + updatedAt: now, + connections: [connection] + }) + ) + + const toBeDeleted = existingKnownDestinations.filter((dest) => !incomingMap.has(dest.externalId)) + + try { + this.logger.log('Deleting removed trusted destinations in anchorage from known destinations', { + deleting: toBeDeleted.map((dest) => ({ + anchorageId: dest.externalId, + knownDestinationId: dest.knownDestinationId + })), + clientId: connection.clientId + }) + + const created = await this.knownDestinationService.bulkCreate(toBeCreated) + const deleted = await this.knownDestinationService.bulkDelete(toBeDeleted) + const updated = await this.knownDestinationService.bulkUpdate(toBeUpdated) + + this.logger.log('Known destinations sync completed', { + totalCreated: created.length, + totalUpdated: updated.length, + totalDeleted: deleted, + clientId: connection.clientId + }) + + return { + created, + updated, + deleted + } + } catch (error) { + throw new SyncException({ + message: 'Failed to sync known destinations', + suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, + origin: error + }) + } + } + private validateConnection( connection: ActiveConnectionWithCredentials ): asserts connection is ActiveConnectionWithCredentials & { diff --git a/apps/vault/src/broker/core/service/know-destination.service.ts b/apps/vault/src/broker/core/service/know-destination.service.ts new file mode 100644 index 000000000..db1bdf7dd --- /dev/null +++ b/apps/vault/src/broker/core/service/know-destination.service.ts @@ -0,0 +1,45 @@ +import { PaginatedResult, PaginationOptions } from '@narval/nestjs-shared' +import { Injectable } from '@nestjs/common' +import { + FindAllOptions, + KnownDestinationRepository, + UpdateKnownDestination +} from '../../persistence/repository/known-destination.repository' +import { KnownDestination } from '../type/indexed-resources.type' + +@Injectable() +export class KnownDestinationService { + constructor(private readonly knownDestinationRepository: KnownDestinationRepository) {} + + async getKnownDestinations( + clientId: string, + options?: PaginationOptions + ): Promise> { + return this.knownDestinationRepository.findByClientId(clientId, options) + } + + async getKnownDestination(clientId: string, KnownDestinationId: string): Promise { + return this.knownDestinationRepository.findById(clientId, KnownDestinationId) + } + + async bulkCreate(knownDestinations: KnownDestination[]): Promise { + return this.knownDestinationRepository.bulkCreate(knownDestinations) + } + + async bulkDelete(knownDestinationId: KnownDestination[]): Promise { + return this.knownDestinationRepository.bulkDelete(knownDestinationId) + } + + async bulkUpdate(knownDestinations: KnownDestination[]): Promise { + return Promise.all( + knownDestinations.map((knownDestination) => this.update(knownDestination.knownDestinationId, knownDestination)) + ) + } + async update(knownDestinationId: string, data: UpdateKnownDestination): Promise { + return this.knownDestinationRepository.update(knownDestinationId, data) + } + + async findAll(clientId: string, opts?: FindAllOptions): Promise> { + return this.knownDestinationRepository.findAll(clientId, opts) + } +} diff --git a/apps/vault/src/broker/core/type/indexed-resources.type.ts b/apps/vault/src/broker/core/type/indexed-resources.type.ts index f97ae1dd9..0b6801ea5 100644 --- a/apps/vault/src/broker/core/type/indexed-resources.type.ts +++ b/apps/vault/src/broker/core/type/indexed-resources.type.ts @@ -1,7 +1,22 @@ import { z } from 'zod' import { BaseConnection, Provider, PublicConnection } from './connection.type' -// Base schemas without relationships +export const KnownDestination = z.object({ + knownDestinationId: z.string(), + clientId: z.string(), + connections: z.array(BaseConnection), + provider: z.nativeEnum(Provider), + label: z.string().nullable().optional(), + externalId: z.string(), + externalClassification: z.string().nullable().optional(), + address: z.string(), + assetId: z.string().nullable().optional(), + networkId: z.string(), + createdAt: z.date(), + updatedAt: z.date() +}) +export type KnownDestination = z.infer + export const Address = z.object({ addressId: z.string(), clientId: z.string(), diff --git a/apps/vault/src/broker/http/client/anchorage.client.ts b/apps/vault/src/broker/http/client/anchorage.client.ts index 6568e31ab..54fe29f0c 100644 --- a/apps/vault/src/broker/http/client/anchorage.client.ts +++ b/apps/vault/src/broker/http/client/anchorage.client.ts @@ -101,6 +101,28 @@ const GetVaultAddressesResponse = z.object({ }) type GetVaultAddressesResponse = z.infer +export const TrustedDestination = z.object({ + id: z.string(), + type: z.literal('crypto'), + crypto: z.object({ + address: z.string(), + networkId: z.string(), + // Asset type is optional. If it is not provided, then the destination will accept any network compatible transfer + // e.g: ETH network can accept only one specific token on ETH network + assetType: z.string().optional(), + memo: z.string().optional() + }) +}) +export type TrustedDestination = z.infer + +const GetTrustedDestinationsResponse = z.object({ + data: z.array(TrustedDestination), + page: z.object({ + next: z.string().nullish() + }) +}) +type GetTrustedDestinationsResponse = z.infer + interface RequestOptions { url: string apiKey: string @@ -375,6 +397,62 @@ export class AnchorageClient { ) } + async getTrustedDestinations(opts: RequestOptions): Promise { + this.logger.log('Requesting Anchorage known addresses page', { + url: opts.url, + limit: opts.limit + }) + const { apiKey, signKey, url } = opts + + return lastValueFrom( + this.sendSignedRequest({ + schema: GetTrustedDestinationsResponse, + request: { + url: `${url}/v2/trusted-destinations`, + method: 'GET' + }, + apiKey, + signKey + }).pipe( + expand((response) => { + if (response.page.next) { + return this.sendSignedRequest({ + schema: GetTrustedDestinationsResponse, + request: { + url: response.page.next + }, + apiKey, + signKey + }) + } + + return EMPTY + }), + tap((response) => { + if (response.page.next) { + this.logger.log('Requesting Anchorage trusted-destinations next page', { + url: response.page.next, + limit: opts.limit + }) + } else { + this.logger.log('Reached Anchorage trusted-destinations last page') + } + }), + reduce((trustedDestinations: TrustedDestination[], response) => [...trustedDestinations, ...response.data], []), + tap((trustedDestinations) => { + this.logger.log('Completed fetching all trusted-destinations', { + trustedDestinationsCount: trustedDestinations.length, + url: opts.url + }) + }), + catchError((error) => { + this.logger.error('Failed to get Anchorage trusted-destinations', { error }) + throw error + }) + ) + ) + } + async getVaultAddresses(opts: RequestOptions & { vaultId: string; assetType: string }): Promise { this.logger.log('Requesting Anchorage vault addresses page', { url: opts.url, diff --git a/apps/vault/src/broker/persistence/repository/known-destination.repository.ts b/apps/vault/src/broker/persistence/repository/known-destination.repository.ts new file mode 100644 index 000000000..117c8b227 --- /dev/null +++ b/apps/vault/src/broker/persistence/repository/known-destination.repository.ts @@ -0,0 +1,311 @@ +import { PaginatedResult, PaginationOptions, applyPagination, getPaginatedResult } from '@narval/nestjs-shared' +import { Injectable } from '@nestjs/common' +import { ProviderConnection, ProviderKnownDestination, ProviderKnownDestinationConnection } from '@prisma/client/vault' +import { z } from 'zod' +import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' +import { NotFoundException } from '../../core/exception/not-found.exception' +import { Provider } from '../../core/type/connection.type' +import { KnownDestination } from '../../core/type/indexed-resources.type' +import { ConnectionRepository, connectionSelectWithoutCredentials } from './connection.repository' + +type FindAllFilters = { + filters?: { + externalIds?: string[] + } +} + +type ProviderKnownDestinationAndRelations = ProviderKnownDestination & { + connections: { connection: Partial }[] +} + +export type FindAllOptions = FindAllFilters & { pagination?: PaginationOptions } + +const UpdateKnownDestination = KnownDestination.pick({ + label: true, + connections: true, + externalClassification: true, + assetId: true +}) +export type UpdateKnownDestination = z.infer + +@Injectable() +export class KnownDestinationRepository { + constructor(private prismaService: PrismaService) {} + + static parseModel(model: ProviderKnownDestinationAndRelations): KnownDestination { + const { connections, id, ...rest } = model + + const validConnections = connections.map((join) => { + return ConnectionRepository.parseModel(join.connection) + }) + + return { + ...rest, + connections: validConnections, + knownDestinationId: id, + provider: z.nativeEnum(Provider).parse(model.provider) + } + } + + static parseEntity(entity: KnownDestination): ProviderKnownDestination { + return { + id: entity.knownDestinationId, + clientId: entity.clientId, + label: entity.label || null, + provider: entity.provider, + externalId: entity.externalId, + externalClassification: entity.externalClassification || null, + address: entity.address, + assetId: entity.assetId || null, + networkId: entity.networkId, + createdAt: entity.createdAt, + updatedAt: entity.updatedAt + } + } + + async findByClientId(clientId: string, opts?: PaginationOptions): Promise> { + const pagination = applyPagination(opts) + + const result = await this.prismaService.providerKnownDestination.findMany({ + where: { clientId }, + include: { + connections: { + include: { + connection: { + select: connectionSelectWithoutCredentials + } + } + } + }, + ...pagination + }) + + const { data, page } = getPaginatedResult({ items: result, pagination }) + return { + data: data.map(KnownDestinationRepository.parseModel), + page + } + } + + async findById(clientId: string, knownDestinationId: string): Promise { + const knownDestination = await this.prismaService.providerKnownDestination.findUnique({ + where: { clientId, id: knownDestinationId }, + include: { + connections: { + include: { + connection: { + select: connectionSelectWithoutCredentials + } + } + } + } + }) + if (!knownDestination) { + throw new NotFoundException({ + message: 'Address not found', + context: { knownDestinationId } + }) + } + + return KnownDestinationRepository.parseModel(knownDestination) + } + + async findAll(clientId: string, opts?: FindAllOptions): Promise> { + const pagination = applyPagination(opts?.pagination) + + const models = await this.prismaService.providerKnownDestination.findMany({ + where: { + clientId, + ...(opts?.filters?.externalIds + ? { + externalId: { + in: opts.filters.externalIds + } + } + : {}) + }, + include: { + connections: { + include: { + connection: { + select: connectionSelectWithoutCredentials + } + } + } + }, + ...pagination + }) + + const { data, page } = getPaginatedResult({ items: models, pagination }) + + return { + data: data.map(KnownDestinationRepository.parseModel), + page + } + } + + async bulkCreate(knownDestinations: KnownDestination[]): Promise { + const providerKnownDestinations: ProviderKnownDestination[] = knownDestinations.map( + KnownDestinationRepository.parseEntity + ) + const providerKnownDestinationConnections: ProviderKnownDestinationConnection[] = knownDestinations.flatMap( + this.getKnownDestinationConnectionModel + ) + + await this.prismaService.$transaction(async (tx) => { + await tx.providerKnownDestination.createMany({ + data: providerKnownDestinations, + skipDuplicates: true + }) + + await tx.providerKnownDestinationConnection.createMany({ + data: providerKnownDestinationConnections, + skipDuplicates: true + }) + }) + + const created = await this.prismaService.providerKnownDestination.findMany({ + where: { + id: { + in: knownDestinations.map((kd) => kd.knownDestinationId) + } + }, + include: { + connections: { + include: { + connection: { + select: connectionSelectWithoutCredentials + } + } + } + } + }) + + // Use the same parsing logic as findAll + return created.map(KnownDestinationRepository.parseModel) + } + async bulkDelete(knownDestinations: KnownDestination[]): Promise { + await this.prismaService.providerKnownDestinationConnection.deleteMany({ + where: { + knownDestinationId: { + in: knownDestinations.map((d) => d.knownDestinationId) + } + } + }) + + const { count } = await this.prismaService.providerKnownDestination.deleteMany({ + where: { + id: { + in: knownDestinations.map((d) => d.knownDestinationId) + } + } + }) + return count + } + + async connect(clientId: string, knownDestinationId: string, connectionId: string) { + const alreadyConnected = await this.prismaService.providerKnownDestinationConnection.findFirst({ + where: { + clientId, + knownDestinationId, + connectionId + } + }) + + if (alreadyConnected) { + return + } + + const connectionExists = await this.prismaService.providerConnection.findUnique({ + where: { clientId, id: connectionId } + }) + + if (!connectionExists) { + throw new NotFoundException({ + message: 'Connection not found', + context: { clientId, connectionId } + }) + } + + const knownDestinationExists = await this.prismaService.providerKnownDestination.findUnique({ + where: { clientId, id: knownDestinationId } + }) + + if (!knownDestinationExists) { + throw new NotFoundException({ + message: 'Known destination not found', + context: { clientId, knownDestinationId } + }) + } + + await this.prismaService.providerKnownDestinationConnection.create({ + data: { + clientId, + knownDestinationId, + connectionId + } + }) + } + + async update(knownDestinationId: string, data: UpdateKnownDestination) { + const existingDest = await this.prismaService.providerKnownDestination.findUnique({ + where: { id: knownDestinationId }, + include: { + connections: { + include: { + connection: { + select: connectionSelectWithoutCredentials + } + } + } + } + }) + + if (!existingDest) { + throw new NotFoundException({ + message: 'Destination not found', + context: { id: knownDestinationId } + }) + } + + const existingEntity = KnownDestinationRepository.parseModel(existingDest) + + await Promise.all( + data.connections + .filter((connection) => !existingEntity.connections.find((c) => c.connectionId === connection.connectionId)) + .map(async (connection) => { + await this.connect(existingEntity.clientId, knownDestinationId, connection.connectionId) + }) + ) + + const updatedKnownDest = await this.prismaService.providerKnownDestination.update({ + where: { id: knownDestinationId }, + data: KnownDestinationRepository.parseEntity({ + ...existingEntity, + ...data + }), + include: { + connections: { + include: { + connection: { + select: connectionSelectWithoutCredentials + } + } + } + } + }) + + return KnownDestinationRepository.parseModel(updatedKnownDest) + } + + private getKnownDestinationConnectionModel(knownDestination: KnownDestination): ProviderKnownDestinationConnection[] { + return knownDestination.connections.map((connection) => { + return { + clientId: knownDestination.clientId, + knownDestinationId: knownDestination.knownDestinationId, + connectionId: connection.connectionId, + createdAt: knownDestination.createdAt + } + }) + } +} diff --git a/apps/vault/src/shared/module/persistence/schema/migrations/20241219140123_add_m2m_known_dest_conn_and_label_to_known_dest/migration.sql b/apps/vault/src/shared/module/persistence/schema/migrations/20241219140123_add_m2m_known_dest_conn_and_label_to_known_dest/migration.sql new file mode 100644 index 000000000..82237d0b0 --- /dev/null +++ b/apps/vault/src/shared/module/persistence/schema/migrations/20241219140123_add_m2m_known_dest_conn_and_label_to_known_dest/migration.sql @@ -0,0 +1,27 @@ +/* + Warnings: + - You are about to drop the column `connection_id` on the `provider_known_destination` table. All the data in the column will be lost. +*/ + +-- DropForeignKey +ALTER TABLE "provider_known_destination" DROP CONSTRAINT "provider_known_destination_connection_id_fkey"; + +-- AlterTable +ALTER TABLE "provider_known_destination" DROP COLUMN "connection_id", +ADD COLUMN "label" TEXT; + +-- CreateTable +CREATE TABLE "provider_known_destination_connection" ( + "client_id" TEXT NOT NULL, + "connection_id" TEXT NOT NULL, + "known_destination_id" TEXT NOT NULL, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "provider_known_destination_connection_pkey" PRIMARY KEY ("client_id","connection_id","known_destination_id") +); + +-- AddForeignKey +ALTER TABLE "provider_known_destination_connection" ADD CONSTRAINT "provider_known_destination_connection_connection_id_fkey" FOREIGN KEY ("connection_id") REFERENCES "provider_connection"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "provider_known_destination_connection" ADD CONSTRAINT "provider_known_destination_connection_known_destination_id_fkey" FOREIGN KEY ("known_destination_id") REFERENCES "provider_known_destination"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/apps/vault/src/shared/module/persistence/schema/migrations/20241219150752_cascade_deletion_on_m2m_tables/migration.sql b/apps/vault/src/shared/module/persistence/schema/migrations/20241219150752_cascade_deletion_on_m2m_tables/migration.sql new file mode 100644 index 000000000..08a128ddb --- /dev/null +++ b/apps/vault/src/shared/module/persistence/schema/migrations/20241219150752_cascade_deletion_on_m2m_tables/migration.sql @@ -0,0 +1,11 @@ +-- DropForeignKey +ALTER TABLE "provider_wallet_connection" DROP CONSTRAINT "provider_wallet_connection_connection_id_fkey"; + +-- DropForeignKey +ALTER TABLE "provider_wallet_connection" DROP CONSTRAINT "provider_wallet_connection_wallet_id_fkey"; + +-- AddForeignKey +ALTER TABLE "provider_wallet_connection" ADD CONSTRAINT "provider_wallet_connection_connection_id_fkey" FOREIGN KEY ("connection_id") REFERENCES "provider_connection"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "provider_wallet_connection" ADD CONSTRAINT "provider_wallet_connection_wallet_id_fkey" FOREIGN KEY ("wallet_id") REFERENCES "provider_wallet"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/apps/vault/src/shared/module/persistence/schema/schema.prisma b/apps/vault/src/shared/module/persistence/schema/schema.prisma index 47e9eb22b..b9c844d57 100644 --- a/apps/vault/src/shared/module/persistence/schema/schema.prisma +++ b/apps/vault/src/shared/module/persistence/schema/schema.prisma @@ -158,17 +158,17 @@ model ProviderAddress { model ProviderKnownDestination { id String @id clientId String @map("client_id") - connectionId String @map("connection_id") provider String externalId String @map("external_id") externalClassification String? @map("external_classification") address String + label String? assetId String? @map("asset_id") networkId String @map("network_id") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") - connection ProviderConnection @relation(fields: [connectionId], references: [id]) + connections ProviderKnownDestinationConnection[] @@unique([clientId, externalId]) @@index([createdAt, clientId]) @@ -190,22 +190,35 @@ model ProviderConnection { updatedAt DateTime @map("updated_at") revokedAt DateTime? @map("revoked_at") - knownDestinations ProviderKnownDestination[] - connections ProviderWalletConnection[] - syncs ProviderSync[] + knownDestinationConnections ProviderKnownDestinationConnection[] + connections ProviderWalletConnection[] + syncs ProviderSync[] @@index([createdAt, clientId]) @@map("provider_connection") } +model ProviderKnownDestinationConnection { + clientId String @map("client_id") + connectionId String @map("connection_id") + knownDestinationId String @map("known_destination_id") + createdAt DateTime @default(now()) @map("created_at") + + connection ProviderConnection @relation(fields: [connectionId], references: [id], onDelete: Cascade) + knownDestination ProviderKnownDestination @relation(fields: [knownDestinationId], references: [id], onDelete: Cascade) + + @@id([clientId, connectionId, knownDestinationId]) + @@map("provider_known_destination_connection") +} + model ProviderWalletConnection { clientId String @map("client_id") connectionId String @map("connection_id") walletId String @map("wallet_id") createdAt DateTime @default(now()) @map("created_at") - connection ProviderConnection @relation(fields: [connectionId], references: [id]) - wallet ProviderWallet @relation(fields: [walletId], references: [id]) + connection ProviderConnection @relation(fields: [connectionId], references: [id], onDelete: Cascade) + wallet ProviderWallet @relation(fields: [walletId], references: [id], onDelete: Cascade) @@id([clientId, connectionId, walletId]) @@map("provider_wallet_connection") diff --git a/apps/vault/src/shared/module/persistence/seed.ts b/apps/vault/src/shared/module/persistence/seed.ts index 38b4d6297..1f0cb316d 100644 --- a/apps/vault/src/shared/module/persistence/seed.ts +++ b/apps/vault/src/shared/module/persistence/seed.ts @@ -121,6 +121,7 @@ const ANCHORAGE_CONNECTIONS = [ { id: 'dest1', clientId, + label: 'Destination 1', provider: 'anchorage', assetId: 'BTC', externalId: 'dest1', @@ -252,8 +253,13 @@ async function main() { ) const knownDestinations = group.knownDestinations.map((dest) => ({ - ...dest, - connectionId: group.connection.connectionId + ...dest + })) + + const knownDestinationConnection = knownDestinations.map((dest) => ({ + clientId: dest.clientId, + connectionId: connection.connectionId, + knownDestinationId: dest.id })) const sync = { @@ -286,6 +292,10 @@ async function main() { await txn.providerSync.create({ data: sync }) + + await txn.providerKnownDestinationConnection.createMany({ + data: knownDestinationConnection + }) } }) logger.log('Vault database germinated 🌱') diff --git a/examples/unified-api/unified-api.example.zip b/examples/unified-api/unified-api.example.zip new file mode 100644 index 0000000000000000000000000000000000000000..e9914198a344f5fe82563c040fdcaa9bf4c7bfce GIT binary patch literal 10353 zcma)C1yEdDwr$)kxVyVG?(Xj1xD#B0y9I~f7D6Csa0^Z#gy0a|8u#Fu-066V4$|u228~Du4vQX6@q5W@T+- z;pOD1qm2ZBseJ(1p21t%dikONpkS{cKl|Iios%RS!^JTpPoLvLNrY#YQ3Ra6PO&vH zIY0}Hyf-rW&j0a*=<#L+82YZP<>nK@#i~;gc$O0b=thTdA+G9U4t`soVUB==;y`a( zl+?kEOnfXs&1ksnV`Zn2KcCO-aAc7=r}F8*t$_y^@$P~v z2D^8<5--|>0RFV9%2#7IlD|G~-u3ZO=B5gKRWI+oVSdab=GuZH=uFLn&*cclucamu z<8#=50skqg?A%ee4j=tx<~!jU>CC=Z+^}P8Q+Tnn)d#?{rx*@U z0e3t`M^EuBI)&>0benU0s=<00e*_rf3v*Zi01e_cPF4#`PkV0*Pir<$kH7it_y%N4 zcnkWo-vYH%Tyw=SyH0E0TIE+`%DmvdQJz6S>=v{SM130xD<`Z_CPY2wuBg= zYGKTA%cyOmgvqB=Fr)X!cza~ zJbpJv&~2?`+bGIlzbLs}Jh01+@Fn9g)lDO%P_%_0@$7;_0b4|HfIb`OP<~&znpxBh zSJv_v>drn!Wc#k{?CB-wk`TIhdnkFBBZf^EkN1NYe|t?9h0cJQAms&XRnohCNy-9JXzufcHsa|hyTMK+J(3DbrYo#ZydzAxd@Hoe0`j&*Y5*6g;iPN;7q3E z5`^)q_0Mt0EFPU-1Z@Lj3wbeSF=g0vIHQawC}z}R>(IwYQJ~~dcWn?(ldsyFUq8Q& z1|ystRghLoubrv_Y6F?B`OTW_+i13eXy6mOL>ymOyljN}qdka|hft9aTV@~&8)6U7 z|Jq|^0-L{>919sLVh((M|7RYTyQtxkmMTnXV)`|0|P-j`vCD`L|kJ{Qw zOwrZn)Q-}>S`X$H=vKeh34Q@yQ$2nb{QliA>0&g@GYqiE!WeFA z6A#9?T`|xH@mZP{KG3SN1gE5IZmxs%SesJ%Ug>KSC4vXX`4P)|=$-L1YJlNHgo(1b zm>#WWJm*2W*uH*>%$5E!5Dkz5)3$;tx-DCywWEnD>{lU^{h3Cx>#oxb1M`9Lj02iZ z7Cd_wLVeFK;TY^GEUD(mX}*6r!R0rvextN|XttU)+LAT98Q5mfxr4qK)}9T-S>et8 zqW7K?mOTCO{e*Ocs!r=>=-c%La+tj#`AT&>w9g!Ox%wjDW$WeCfbl6bv#8so42Sj^ zikCT{mvb_JJaBd>&zub}*g5N+`<%im4V&|)fnl(+%_F{)x6Ps$!Bk`-O!YWu=EK{f z`)TBqlQ9hC?IqsR$%^aPtJ#dTipxC{%__$FsAE$Td$Sm`KZY_(Y?ML}5=td#0Du4z zN+7GPwdX(M$m-!~;pz3CGSoU%%(agLbI>O^?hwaF@}#i-g^3*k-g|9eM6z|Bn#z>Juy92yam ze-xNqoTRxj@Wz`yaPJOWd}76NAJTZxmH#=tt2Nz#k39InD>^ltQs~QLZ6d>KXw6K!U_VQ$|8sMTX7U>Tl&< z@!zybI!i7~{Fs5edZ?ROY?vKOG_1%leiMrh^YS2s=IPNiNhQm8;@Fwgbasa8H6Qse zsfXY}%qWi?_noh;^Wk!dL_ez|vGC9=yG${tvUe0O&?GPUL*W+NK}Y445>z(kxZqdu zJ!QeF8R>5fi)rkZ5iJ>w;e{+N*uK#oxu@)`W83pc;q}7PI=GD7XvDJy_K=dTuY^u% z8#>EGnR~FTV1QerD@}2!BJqVEdrOiR%_}Dbu{#|(2&>TPuTYR$)jZht1FCt{J)f9} zj4GRnVm@!lfRBbkM>1^R#HHe+o4FtMdm>4WM!bDymzZ}SwrWCfymlTIg(KGQ&urru zP|^sgbkCYtBn{pw$mu5N8!UXtJ^avX?)DPtbPbzZjtWt+v&9dIK%Uwvh&}ES+sj|3;+-;i1wvsLc#1$WzCj74}7E08G zKEjMO{YdA($km8CI!uv9r}dF^6aFZp1s#cKP02I(pztTnyk8S2|sBX3FopXFqd|Q z;oJ0lmnIsG@B3_iVc2K*;p4u{lhl25LPWl1bTnl^rVi5P0_VxFLA(m-M{cTqNt67S z@$Srxsb!8HqfP4{`i_TPVJ3z<}m!gg$V&siyV-Mav={3frmES!%SH}-jg5Rbl2hBL&7|@q4coHRLrY+3q^j|4X z5ba4xF0E4)3K!x@VXLX49H`1}s>=2mMHa#qncSG0#@591iI^~t(M}*;!HVSk$eE86 zSt94lq2JnhY@)Lr+7ubN%s5a8qRq<2|5Usc$wiyrfB_Q|gHyZlni75@ClSNbotQDC zL*(;jQ6`90-hXCk0;+Ij^w^?TVHn+$bgnmkfC*n=O8_hhLs6s70WS)Y)Jl za)oO`54QRo*WMO%;5yNqaUI^x>?@G;E}q?!kZ#NNTI~N0@ox#K2A`J%zkng#MGxd4 z$ABChw$?7z?!W4>qqW~ZN^!(J$hHQu{&dTVOj2^`r@)N5$pd+Zfcfd=XXPt!ct@|H z)0IiBh^sjLCWd|3Z#7b!+QYN&p6`Yl^Qkd>z5{ija1Cj;&z}tY0c&8x^;+FY8Qu>@ zw+74(q>(zoRRY{73n^{VJ0Tm>$LG4@KFpmxb15IuuOQ^L|!P^YKe^wS==7!?lAYvib ziv=T$R1=V6L&L*Z8I-xKgO!oFtrU4gWyb68 zQb732(5jJwb<)$yN{-6{<4yscnba@RvKzxmY5%j`MvrM%OAyMC zB#?st2&FHy7X-zx3EQjr!?0$=L)b9*r(X$~3d5f3X$Rpq3rP-$W79E+D9~8ng<1vji+-(m zYZ8W?TFz70G%nEb4pT;DqJx>HK$@^CW=E5)l%|v>Ym(R0`Xk=vV4Tf9K?(h%-ca;{ z@*Va51wQ+A5ECUay~oEMMV`-~8nF?ZK2uAHpvMjB@tKj269siXhs<7Y)inr!QpX`E zt_;|LJ+I!Asg8&-Q_+Bh${L^ps$6rOoe%eFmA`?c6T_quX9aNY{ zPF55clSV5YqrQ*3tE;wMM4&k@NcNh(bowG~x?e0RZSwA6vQYQw%1v1Cr?3CagwN+L zvV5wa3j2?v_?H81>f@@M6J^OB-{u(T9eFnMUakqflLU}5O>)0p?Dds!-F?wzY_@Oi zP8pj$!NeJWnZe0dD(bVqUE99iF7&OC<}_sONf_s;A!o*wr1ItdYAfc}`wcHL%0 zrK8ADjES+NPceHLA{7I#57c6CMJZ?Ou6lK#XTr8{o((FpHvlWr?Ery6GGM$w1STZ^ z2d%i(qB2y|kan}tc&#nr3|p=Mj-G951r|7CY!hCR5}2PbfvaL9$W->G!ZfcCq z_8#)r?NM&cVNu;+9KEhIjICG^vzJ7rYHF@5CyGaJIs^Q*B)cE1F0n=6DN%cd@&Gn3 zn@IL_EQ@X(zTM&`QivzZ7NjzcDIm*wdpV(KuY5fxO<~%*Vzx$<6rgWA?N`vyizq=% zEM8O^(0xIaS_G#uodA#vIn}ZglMusBOD807W9#A5M;hcRow|`^pFlReoL^m|xDpQR zLrUmeM(k6P^(gP0magAa65$|LiPCd-i3Tm$;qA9t+Q3)Jd=EqZ;bC<9@!J;BtLEH5 z7`cXH7eCI3oe=1(RV8v9U(2~199lsYt|6^hxZ@FVn^@z@2* z_cb<(%VHR{mkBVl{nTlr+K`cOtTnw2Wcw1vUimuj4&0sHpHy%GT^o_U1L6QUxlfYy z3>}(|#W_6JwRG=D9}I9OYpM?|l7l>Gelkl=oY?Y@#*l&Va@S9A=6AkrO+7ekkDLUL z$%8zkP2d~@ak%o|Znf6Oq} z*agNJZ@sDy2P>&z%*bLj=8vrby!mY02W0TdVCncTk$%NIU*K9D+uK`5snRb_>)e** zrVa)Zm5FIP%=er1oeuZ$Qwq_NUdM60xy-woFh;5fTv*y_FPG2Ia1G27uT4rc4r zuV=Uis+*Z~bG=5!xqJ_JA(oWKXwiS{Z`tTg&{TngOQ_ydt<9|6uh4C!jdY;lV0gMF zYDzxQSaWNM)ctcXP(iDJchBARQFQh!zF;-|-OBa+^Qg;6L%w_(wStY2S?()Rdc zc}c)!AnBW>p}f*XQ)y)OaORJJ92@PrTQBlHfBQNCeetJq2$0f#bVG;KLyo`C89hBL zU0rPKZU0yg+5cJ(s|}r9savp~gSx}cvYatemv^+VaAaNuDLChiBOK=8F~o%|meCA# zfHT31y5WyE-%v+PPU1~Tc=#zY8^N7!JK45T4~Gat-v)BAE9-368X5*SNuC9A9h)+9 z2jh(DZwDQ`fZ+(^;|nd(9}upkjuTc9FGRRYrr5*UsvD2Im~pnOkqTk8HZ!V;GlVK| z*~^wV4Q9*UN4S@mYfegSCT?YA_Bx#FIxam~#qY`_$1E|S3H8;gZiz1PHv`*28M=!x zhTJvYxQ|V@Av@sqN^8ciQi)TORc0HG-;byt6b$#j&$TTE1qXdAyes)w-PGEF)oI>} zyT!c1@47(bZAm`9MQ4`yECc@5Y?j}^UEwY@cm4t_FdaiEbW48J0A6p8Z1^CX8L924 z62?*qwazP*C|Wzf^hnH@!N zwrk!^`a807Y+s~F^}=|4LA6uPOQ(tYDAd|)_l5!wNQs?r)UG|Uag7%}DUpG#x$1qz`Nz)pSd9wOCo@hJ~YS->@rL4d69OqQ9kv6TQ4`tmEu$z3hIt3QP;QmJcax7nCv=Xz6pEx!?e#@zD5F~ z+~(;m3I>+pP@-u>y(dkwOi3zwD7_#0wm58t3gw=!xQy_rW(_J|$EEsyl}&Z|I?}|Z z*-z0N1MK>**|?tSA7pW98F(n!N&q(Ilq_}~KSZy|%-?CK>V_2Lr}@+0#Rp2UORO7O zm=16>pdZ}CNuFl@giQ)D0^9>7k<^uNM6dvJee#9=dQ|gg5x{G}rYA)jn{{)A$eVtw z3{d}t$`oK!G0po^5yq!;fPi``f`2Y6#U7T%k>0h3SyoY zXyX#0r2Y@BS<%T+rlt>Qi;9E*T#p%Y;Jc&Jkn+8kjR8Xg&|G|_uK0kEqN^tMDnb~g zkIq2N=`*zFpqzGWhat2V;*>Iz9*1YSB30gMhpmNrtxr5N51C9|a>rYus+TpMlj83U z?irvm<(FOy9eD)T71zHHh9{!v4Yl1l+x`5>|MCgn6v^m9tC6@}rxvle%ztvcH_hND z2Y$~h3aBRN8L*d$BB%RHSwpMpv;ZQer|ggenirTn2{PkbRB-^%EC^@2hvg0njd37H zYO*&PZxEzD-*c)5V$Eos-1!KeTb0+qLkOXwJGk0@iu}Ca<`putjN<{juj!81PtpSI zjZ_$UOR9)C>!K=*&`XW6hur!PxGiSkeo!I}pIg;MJ#BV$<9MCUK2aQn) zQ>$w@mMAWZNFMeA`JxG*W0<)@;`VsJK~!gy(kL+jcPYki@Gyj@U=&}zr4EfsEwoTE z-)8{iJ8^C04%KdqDMdf0SGv3Z#@T%L^%*PyK}k%^Tbz~fk;6c)qJ6jbNku~=f^Un2 zG{X#INQyTM>YQHIP`nO82aN}d8vu!8#a13a`Bv_S435h`?G=UNLw~*qM4kd?h+iye z%Cgd{O&6DAUx};foLg4tb#@LHHwZ|3rfO|mvV8Gx?*~LYUU&U;S*V)-aZJNb zVV{{vl{|%>2rs)mUwWRo7_-rKK@sRwR@-v+l`kL>8;ZDnm(j?GIZZstNiY;%Q@Jsh zH3avuJk+y^C3iepA6veDBqkSypDl#NSJl1>set9{Zs?;->NVhs6GaZ~j-O#F0?sT@ zd)c76W=(!65CKtF!~jcB)lj-0BNM5c?Lx+OZ;HUX7hlfv%q6HB-Qq?>P*w@}wOO??iRgMlom2nLGtBEtkFUxlod zM;TMuzbXoXS>(2S{Vyg4x6EOX)QNkzk6g@Xnwm;8(H!}CO&sJ0$hvw@-wab=m0lv3 z7eJjtH_Nr98GMQ8ZbrOrVd+7ZX0%eZvN2IQ8B>^=g2t3Y?5)=fjS~q_v`tm@BW!Oh z&N@Yh*_fb9!XNo`+=!xy@3|gTmoSXP(8$?o*jSM~3A^Qj#Gw9Je!xbb0A{6_kG!Bk zD?i8VUewyMC2onEg!8_qXP>6^rK-{OE|O&%Zm`q=*z)n4Y3!o2M64Kj+(r6wkG}!0 z4vi~Z%_&i>_gn5C34+s^S13?A$_4Jz(PXaCVi8A^%V4BcE+5tnl-v?odlf}rLzRyA%!4* zh|zo%fqKBvD~B}=o)etY+c9lfQ?Fj3xHp_x9uHsKQry_$a`dh!Br52QSn5g|GT8xL z_o>x=aV>@9zCc)6Jp8HG4D95)sj5 zO>>oPavT=6J23`EnGF4FwXwBEc|g$Ykd1}kziNWZ#51p z7n~%s+B1vNZPQ&g-E`pjYOqjDWVt&DY(DIEeR*v2jDKy9up>qwT^it0ut09!A|{)m3!={G z>w))?-XpR|e^Fc5i{&fb#yDTTA{;?Xq93mcYY3yC-w_fU_-bFS42FD}$yYPqdsh(7 zsLNigY!{E+x`Ev4J3k6pa?}cIt!EIT^`K{g<>@rljns}e zOe&`N2wsUtS2yi+R=qib6gf4G>v-~fRN3W2;fKY(SDvx>U*;#GNiGza*4)H`%9rfu z%)Nl^>H9C-VX;R_%QJR2%tblcyx+xGd>92@w(l82+5*uWL=vMpCudLciSV|-T-vXU9syRrzGpCF-nLEabvLQURt8|DG z&|@Vovo|J$-_&IJj%PfIHHOpqr=LqB`gSfR)zN$tT*y=`PbMQ>zGgohL%1M zy1wMw!k-fYO3NfK;6}KZ=EIWWIEMCLUw&z}v>sM!YB%yuQ)%yfF(b1yVS7?9;HaP; zfWdyASp2LapO}bFn>Ho@!O@o!f>p5z29o6~NdSj?=;CFNBxgp0oy5*nO^& zV^4T4ROl_wGDOtGNrJH)peRYrg^CMO zdZ3_iO0u!P1j6xS4IR7SQXsN#2jASVRlDLK}ZB36@kY zFqoh|MPT~M$9MYc1%1!U7f?s6fOKUOp!yzsNWXKU3($xmsBg8B);#dj%4t3fa&^a8 zowWafqrDiS3d4w2;Cvc#>8+95VlKmL;|Zz^CV!b8vk-N`hqEFyfZL;yxPFt{t_c14 zS=eb5-sc+ccIoLLD3czP&O%D&;(d54Mq%_Q2h3Lcs(cH|uF;84@+o#WrPD&|@VAtH zRtgs?$-)!KJXFu1@Ukf(4*n1}optpBxE^tozQDqD6s~@vliE=c@v{tmbj+?fR}!3J zMkf1OMul7C8N4jB1M1Ii+L|4+MIRt+%_}w17kHm-?Pmiry+TgM-DR$h>=aD Date: Mon, 23 Dec 2024 14:05:53 +0100 Subject: [PATCH 054/120] Prevent usage of plain credentials in production (#50) * Prevent usage of plain credentials in production * Move check to getInputCredentials --- .../src/broker/core/service/connection.service.ts | 15 +++++++++++++-- apps/vault/src/main.config.ts | 10 ++-------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/apps/vault/src/broker/core/service/connection.service.ts b/apps/vault/src/broker/core/service/connection.service.ts index 1e0913095..38e559844 100644 --- a/apps/vault/src/broker/core/service/connection.service.ts +++ b/apps/vault/src/broker/core/service/connection.service.ts @@ -1,3 +1,4 @@ +import { ConfigService } from '@narval/config-module' import { LoggerService, PaginatedResult } from '@narval/nestjs-shared' import { Alg, @@ -8,13 +9,15 @@ import { getPublicKey, privateKeyToJwk } from '@narval/signature' -import { Injectable, NotImplementedException } from '@nestjs/common' +import { HttpStatus, Injectable, NotImplementedException } from '@nestjs/common' import { EventEmitter2 } from '@nestjs/event-emitter' import { SetRequired } from 'type-fest' import { v4 as uuid } from 'uuid' +import { Config, Env } from '../../../main.config' import { EncryptionKeyService } from '../../../transit-encryption/core/service/encryption-key.service' import { ConnectionRepository, FindAllOptions } from '../../persistence/repository/connection.repository' import { ConnectionActivatedEvent } from '../../shared/event/connection-activated.event' +import { BrokerException } from '../exception/broker.exception' import { ConnectionInvalidCredentialsException } from '../exception/connection-invalid-credentials.exception' import { ConnectionInvalidPrivateKeyException } from '../exception/connection-invalid-private-key.exception' import { ConnectionInvalidStatusException } from '../exception/connection-invalid-status.exception' @@ -43,7 +46,8 @@ export class ConnectionService { private readonly connectionRepository: ConnectionRepository, private readonly encryptionKeyService: EncryptionKeyService, private readonly logger: LoggerService, - private readonly eventEmitter: EventEmitter2 + private readonly eventEmitter: EventEmitter2, + private readonly configService: ConfigService ) {} async initiate(clientId: string, input: InitiateConnection): Promise { @@ -347,6 +351,13 @@ export class ConnectionService { } if (input.credentials) { + if (this.configService.get('env') === Env.PRODUCTION) { + throw new BrokerException({ + message: 'Cannot create connection with plain credentials in production', + suggestedHttpStatusCode: HttpStatus.FORBIDDEN + }) + } + return input.credentials } diff --git a/apps/vault/src/main.config.ts b/apps/vault/src/main.config.ts index 1a66905eb..d94025882 100644 --- a/apps/vault/src/main.config.ts +++ b/apps/vault/src/main.config.ts @@ -157,9 +157,10 @@ const keyringSchema = z.union([ const LoadConfig = VaultConfigSchema.transform((yaml, ctx) => { const appId = process.env.APP_UID || yaml.app?.id const databaseUrl = process.env.APP_DATABASE_URL || yaml.database?.url - const env = process.env.NODE_ENV || yaml.env + const env = z.nativeEnum(Env).parse(process.env.NODE_ENV || yaml.env) const port = process.env.PORT || yaml.port const baseUrl = process.env.BASE_URL || yaml.baseUrl + if (!appId) { ctx.addIssue({ code: z.ZodIssueCode.custom, @@ -174,13 +175,6 @@ const LoadConfig = VaultConfigSchema.transform((yaml, ctx) => { }) return z.NEVER } - if (!env) { - ctx.addIssue({ - code: z.ZodIssueCode.custom, - message: 'NODE_ENV is required' - }) - return z.NEVER - } if (!port) { ctx.addIssue({ code: z.ZodIssueCode.custom, From e9dde875add3ffe50345e52504e027bf4ec88995 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Mon, 23 Dec 2024 14:06:14 +0100 Subject: [PATCH 055/120] Send transfer to Anchorage (#48) * Add migration to normalize provider transfer * Send transfers to Anchorage * Increase test coverage in the whole flow * Add unique constraint on clientId and idempotenceId * Handle transfer status * Propagate provider HTTP exception * Update swagger docs * Fix sign E2E spec * Default RSA modulus size to 2048 outside production * Support destination address * Handle provider specific property * Add logs to the Anchorage transfer service * Resolve transfer party with known destination * Add permission CONNECTION_READ in the transfer get * Use text instead of jsonb in the database --- .../src/broker/__test__/e2e/transfer.spec.ts | 379 +++++++++++++++ apps/vault/src/broker/broker.module.ts | 34 +- .../core/exception/provider-http.exception.ts | 36 ++ .../core/lib/anchorage-request-builder.ts | 51 -- .../anchorage-transfer.service.spec.ts | 436 ++++++++++++++++++ .../integration/mocks/anchorage/handlers.ts | 22 +- .../anchorage/response/get-transfer-200.json | 28 ++ .../{vaults-ok.json => get-vaults-200.json} | 0 ...-ok.json => get-vaults-addresses-200.json} | 0 .../{wallets-ok.json => get-wallets-200.json} | 0 .../anchorage/response/post-transfer-201.json | 6 + .../anchorage/response/post-transfer-400.json | 4 + .../integration/mocks/anchorage/server.ts | 22 +- .../service/anchorage-transfer.service.ts | 216 +++++++++ .../core/service/transfer-party.service.ts | 89 ++++ .../broker/core/service/transfer.service.ts | 53 +++ .../src/broker/core/type/connection.type.ts | 1 + .../core/type/indexed-resources.type.ts | 28 +- .../src/broker/core/type/transfer.type.ts | 110 +++++ .../broker/http/client/anchorage.client.ts | 228 +++++++-- .../rest/controller/transfer.controller.ts | 51 ++ .../rest/dto/request/send-transfer.dto.ts | 4 + .../http/rest/dto/response/transfer.dto.ts | 9 + .../repository/address.repository.ts | 18 +- .../known-destination.repository.ts | 9 + .../repository/transfer.repository.ts | 173 +++++++ .../filter/application-exception.filter.ts | 39 +- .../filter/provider-http-exception.filter.ts | 62 +++ .../src/shared/filter/zod-exception.filter.ts | 32 +- .../persistence/exception/parse.exception.ts | 11 + .../exception/persistence.exception.ts | 1 + .../migration.sql | 41 ++ .../module/persistence/schema/schema.prisma | 47 +- .../persistence/service/prisma.service.ts | 47 ++ .../src/shared/type/http-exception.type.ts | 11 + .../core/service/encryption-key.service.ts | 39 +- .../vault/src/vault/__test__/e2e/sign.spec.ts | 12 +- 37 files changed, 2163 insertions(+), 186 deletions(-) create mode 100644 apps/vault/src/broker/__test__/e2e/transfer.spec.ts create mode 100644 apps/vault/src/broker/core/exception/provider-http.exception.ts delete mode 100644 apps/vault/src/broker/core/lib/anchorage-request-builder.ts create mode 100644 apps/vault/src/broker/core/service/__test__/integration/anchorage-transfer.service.spec.ts create mode 100644 apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-transfer-200.json rename apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/{vaults-ok.json => get-vaults-200.json} (100%) rename apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/{vaults-addresses-ok.json => get-vaults-addresses-200.json} (100%) rename apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/{wallets-ok.json => get-wallets-200.json} (100%) create mode 100644 apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/post-transfer-201.json create mode 100644 apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/post-transfer-400.json create mode 100644 apps/vault/src/broker/core/service/anchorage-transfer.service.ts create mode 100644 apps/vault/src/broker/core/service/transfer-party.service.ts create mode 100644 apps/vault/src/broker/core/service/transfer.service.ts create mode 100644 apps/vault/src/broker/core/type/transfer.type.ts create mode 100644 apps/vault/src/broker/http/rest/controller/transfer.controller.ts create mode 100644 apps/vault/src/broker/http/rest/dto/request/send-transfer.dto.ts create mode 100644 apps/vault/src/broker/http/rest/dto/response/transfer.dto.ts create mode 100644 apps/vault/src/broker/persistence/repository/transfer.repository.ts create mode 100644 apps/vault/src/shared/filter/provider-http-exception.filter.ts create mode 100644 apps/vault/src/shared/module/persistence/exception/parse.exception.ts create mode 100644 apps/vault/src/shared/module/persistence/exception/persistence.exception.ts create mode 100644 apps/vault/src/shared/module/persistence/schema/migrations/20241223121950_normalize_transfer_provider/migration.sql create mode 100644 apps/vault/src/shared/type/http-exception.type.ts diff --git a/apps/vault/src/broker/__test__/e2e/transfer.spec.ts b/apps/vault/src/broker/__test__/e2e/transfer.spec.ts new file mode 100644 index 000000000..f5e782925 --- /dev/null +++ b/apps/vault/src/broker/__test__/e2e/transfer.spec.ts @@ -0,0 +1,379 @@ +import { EncryptionModuleOptionProvider } from '@narval/encryption-module' +import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' +import { Ed25519PrivateKey, getPublicKey } from '@narval/signature' +import { HttpStatus, INestApplication } from '@nestjs/common' +import { EventEmitter2 } from '@nestjs/event-emitter' +import { Test, TestingModule } from '@nestjs/testing' +import { mock } from 'jest-mock-extended' +import { HttpResponse, http } from 'msw' +import request from 'supertest' +import { v4 as uuid } from 'uuid' +import { ClientService } from '../../../client/core/service/client.service' +import { MainModule } from '../../../main.module' +import { ProvisionService } from '../../../provision.service' +import { KeyValueRepository } from '../../../shared/module/key-value/core/repository/key-value.repository' +import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' +import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' +import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' +import postAnchorageTransferBadRequest from '../../core/service/__test__/integration/mocks/anchorage/response/post-transfer-400.json' +import { + ANCHORAGE_TEST_API_BASE_URL, + setupMockServer +} from '../../core/service/__test__/integration/mocks/anchorage/server' +import { ActiveConnectionWithCredentials, ConnectionStatus, Provider } from '../../core/type/connection.type' +import { Account, Wallet } from '../../core/type/indexed-resources.type' +import { + InternalTransfer, + NetworkFeeAttribution, + TransferPartyType, + TransferStatus +} from '../../core/type/transfer.type' +import { AccountRepository } from '../../persistence/repository/account.repository' +import { ConnectionRepository } from '../../persistence/repository/connection.repository' +import { TransferRepository } from '../../persistence/repository/transfer.repository' +import { WalletRepository } from '../../persistence/repository/wallet.repository' +import { getJwsd, testClient, testUserPrivateJwk } from '../util/mock-data' + +const ENDPOINT = '/provider/transfers' + +describe('Transfer', () => { + let app: INestApplication + let module: TestingModule + let testPrismaService: TestPrismaService + let provisionService: ProvisionService + let clientService: ClientService + + let transferRepository: TransferRepository + let connectionRepository: ConnectionRepository + let accountRepository: AccountRepository + let walletRepository: WalletRepository + + const clientId = testClient.clientId + + const externalId = '008d3ec72558ce907571886df63ef51594b5bd8cf106a0b7fa8f12a30dfc867f' + + const walletId = uuid() + + const eddsaPrivateKey: Ed25519PrivateKey = { + kty: 'OKP', + crv: 'Ed25519', + alg: 'EDDSA', + kid: '0xa6fe705025aa4c48abbb3a1ed679d7dc7d18e7994b4d5cb1884479fddeb2e706', + x: 'U4WSOMzD7gor6jiVz42jT22JGBcfGfzMomt8PFC_-_U', + d: 'evo-fY2BX60V1n3Z690LadH5BvizcM9bESaYk0LsxyQ' + } + + const connection: ActiveConnectionWithCredentials = { + clientId, + connectionId: uuid(), + createdAt: new Date(), + provider: Provider.ANCHORAGE, + status: ConnectionStatus.ACTIVE, + updatedAt: new Date(), + url: ANCHORAGE_TEST_API_BASE_URL, + credentials: { + privateKey: eddsaPrivateKey, + publicKey: getPublicKey(eddsaPrivateKey), + apiKey: 'test-api-key' + } + } + + const accountOne: Account = { + accountId: uuid(), + addresses: [], + clientId, + createdAt: new Date(), + externalId: uuid(), + label: 'Account 1', + networkId: 'BTC', + provider: Provider.ANCHORAGE, + updatedAt: new Date(), + walletId + } + + const accountTwo: Account = { + accountId: uuid(), + addresses: [], + clientId, + createdAt: new Date(), + externalId: uuid(), + label: 'Account 2', + networkId: 'BTC', + provider: Provider.ANCHORAGE, + updatedAt: new Date(), + walletId + } + + const wallet: Wallet = { + clientId, + connections: [connection], + createdAt: new Date(), + externalId: uuid(), + label: null, + provider: Provider.ANCHORAGE, + updatedAt: new Date(), + walletId + } + + const internalTransfer: InternalTransfer = { + clientId, + assetId: 'BTC', + createdAt: new Date(), + customerRefId: null, + destination: { + type: TransferPartyType.ACCOUNT, + id: accountTwo.accountId + }, + externalId: uuid(), + grossAmount: '0.00001', + idempotenceId: null, + memo: 'Test transfer', + networkFeeAttribution: NetworkFeeAttribution.DEDUCT, + provider: Provider.ANCHORAGE, + source: { + type: TransferPartyType.ACCOUNT, + id: accountOne.accountId + }, + status: TransferStatus.SUCCESS, + transferId: uuid() + } + + const mockServer = setupMockServer() + + beforeAll(async () => { + module = await Test.createTestingModule({ + imports: [MainModule] + }) + .overrideModule(LoggerModule) + .useModule(LoggerModule.forTest()) + .overrideProvider(KeyValueRepository) + .useValue(new InMemoryKeyValueRepository()) + .overrideProvider(EncryptionModuleOptionProvider) + .useValue({ + keyring: getTestRawAesKeyring() + }) + // Mock the event emitter because we don't want to send a + // connection.activated event after the creation. + .overrideProvider(EventEmitter2) + .useValue(mock()) + .compile() + + app = module.createNestApplication() + + testPrismaService = module.get(TestPrismaService) + provisionService = module.get(ProvisionService) + clientService = module.get(ClientService) + + transferRepository = module.get(TransferRepository) + connectionRepository = module.get(ConnectionRepository) + walletRepository = module.get(WalletRepository) + accountRepository = module.get(AccountRepository) + + await testPrismaService.truncateAll() + }) + + afterAll(async () => { + await testPrismaService.truncateAll() + await module.close() + await app.close() + }) + + beforeEach(async () => { + await testPrismaService.truncateAll() + + await provisionService.provision() + await clientService.save(testClient) + + await connectionRepository.create(connection) + await walletRepository.bulkCreate([wallet]) + await accountRepository.bulkCreate([accountOne, accountTwo]) + await transferRepository.bulkCreate([internalTransfer]) + + await app.init() + }) + + describe(`POST ${ENDPOINT}`, () => { + const requiredPayload = { + source: { + type: TransferPartyType.ACCOUNT, + id: accountOne.accountId + }, + destination: { + type: TransferPartyType.ACCOUNT, + id: accountTwo.accountId + }, + amount: '0.0001', + assetId: 'BTC_S' + } + + it('sends transfer to anchorage', async () => { + const { status, body } = await request(app.getHttpServer()) + .post(ENDPOINT) + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + payload: requiredPayload, + userPrivateJwk: testUserPrivateJwk, + requestUrl: ENDPOINT, + htm: 'POST' + }) + ) + .send(requiredPayload) + + expect(body).toEqual({ + data: { + clientId, + externalId, + assetId: requiredPayload.assetId, + createdAt: expect.any(String), + customerRefId: null, + destination: requiredPayload.destination, + grossAmount: requiredPayload.amount, + idempotenceId: null, + memo: null, + networkFeeAttribution: NetworkFeeAttribution.ON_TOP, + provider: accountOne.provider, + providerSpecific: null, + source: requiredPayload.source, + status: TransferStatus.PROCESSING, + transferId: expect.any(String) + } + }) + + expect(status).toEqual(HttpStatus.CREATED) + }) + + it('sends transfer with optional properties', async () => { + const payload = { + ...requiredPayload, + memo: 'Test transfer', + networkFeeAttribution: NetworkFeeAttribution.DEDUCT, + customerRefId: uuid(), + idempotenceId: uuid() + } + + const { body } = await request(app.getHttpServer()) + .post(ENDPOINT) + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + payload, + userPrivateJwk: testUserPrivateJwk, + requestUrl: ENDPOINT, + htm: 'POST' + }) + ) + .send(payload) + + const actualTransfer = await transferRepository.findById(clientId, body.data.transferId) + + expect(actualTransfer.memo).toEqual(payload.memo) + expect(body.data.memo).toEqual(payload.memo) + + expect(actualTransfer.networkFeeAttribution).toEqual(payload.networkFeeAttribution) + expect(body.data.networkFeeAttribution).toEqual(payload.networkFeeAttribution) + + expect(actualTransfer.customerRefId).toEqual(payload.customerRefId) + expect(body.data.customerRefId).toEqual(payload.customerRefId) + + expect(actualTransfer.idempotenceId).toEqual(payload.idempotenceId) + expect(body.data.idempotenceId).toEqual(payload.idempotenceId) + }) + + it('propagates provider http errors', async () => { + mockServer.use( + http.post(`${ANCHORAGE_TEST_API_BASE_URL}/v2/transfers`, () => { + return new HttpResponse(JSON.stringify(postAnchorageTransferBadRequest), { + status: HttpStatus.BAD_REQUEST + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } as unknown as any) + }) + ) + + const { status, body } = await request(app.getHttpServer()) + .post(ENDPOINT) + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + payload: requiredPayload, + userPrivateJwk: testUserPrivateJwk, + requestUrl: ENDPOINT, + htm: 'POST' + }) + ) + .send(requiredPayload) + + expect(body).toMatchObject({ + statusCode: 400, + message: 'Provider ANCHORAGE responded with 400 error', + context: { + provider: 'anchorage', + error: { + errorType: 'InternalError', + message: "Missing required field 'amount'." + } + } + }) + + expect(status).toEqual(HttpStatus.BAD_REQUEST) + }) + }) + + describe(`GET ${ENDPOINT}/:transferId`, () => { + const transfer = { + assetId: 'BTC', + clientId: connection.clientId, + createdAt: new Date(), + customerRefId: uuid(), + destination: { + type: TransferPartyType.ACCOUNT, + id: accountTwo.accountId + }, + externalId: uuid(), + grossAmount: '0.1', + idempotenceId: uuid(), + memo: 'Test transfer', + networkFeeAttribution: NetworkFeeAttribution.DEDUCT, + provider: Provider.ANCHORAGE, + providerSpecific: null, + source: { + type: TransferPartyType.ACCOUNT, + id: accountOne.accountId + }, + status: TransferStatus.PROCESSING, + transferId: uuid() + } + + beforeEach(async () => { + await transferRepository.bulkCreate([transfer]) + }) + + it('responds with the specific transfer', async () => { + const { status, body } = await request(app.getHttpServer()) + .get(`${ENDPOINT}/${transfer.transferId}`) + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + payload: {}, + userPrivateJwk: testUserPrivateJwk, + requestUrl: `${ENDPOINT}/${transfer.transferId}`, + htm: 'GET' + }) + ) + .send() + + expect(body).toEqual({ + data: { + ...transfer, + createdAt: transfer.createdAt.toISOString() + } + }) + + expect(status).toEqual(HttpStatus.OK) + }) + }) +}) diff --git a/apps/vault/src/broker/broker.module.ts b/apps/vault/src/broker/broker.module.ts index c6e514b2b..a1d240b20 100644 --- a/apps/vault/src/broker/broker.module.ts +++ b/apps/vault/src/broker/broker.module.ts @@ -1,8 +1,10 @@ import { HttpModule, OpenTelemetryModule } from '@narval/nestjs-shared' import { Module } from '@nestjs/common' +import { APP_FILTER } from '@nestjs/core' import { EventEmitterModule } from '@nestjs/event-emitter' import { ClientModule } from '../client/client.module' import { DEFAULT_HTTP_MODULE_PROVIDERS } from '../shared/constant' +import { ProviderHttpExceptionFilter } from '../shared/filter/provider-http-exception.filter' import { PersistenceModule } from '../shared/module/persistence/persistence.module' import { EncryptionKeyService } from '../transit-encryption/core/service/encryption-key.service' import { EncryptionKeyRepository } from '../transit-encryption/persistence/encryption-key.repository' @@ -10,10 +12,13 @@ import { TransitEncryptionModule } from '../transit-encryption/transit-encryptio import { AccountService } from './core/service/account.service' import { AddressService } from './core/service/address.service' import { AnchorageSyncService } from './core/service/anchorage-sync.service' +import { AnchorageTransferService } from './core/service/anchorage-transfer.service' import { ConnectionService } from './core/service/connection.service' import { KnownDestinationService } from './core/service/know-destination.service' import { ProxyService } from './core/service/proxy.service' import { SyncService } from './core/service/sync.service' +import { TransferPartyService } from './core/service/transfer-party.service' +import { TransferService } from './core/service/transfer.service' import { WalletService } from './core/service/wallet.service' import { ConnectionSyncEventHandler } from './event/handler/connection-sync.event-handler' import { AnchorageClient } from './http/client/anchorage.client' @@ -22,6 +27,7 @@ import { AddressController } from './http/rest/controller/address.controller' import { ConnectionController } from './http/rest/controller/connection.controller' import { ProxyController } from './http/rest/controller/proxy.controller' import { SyncController } from './http/rest/controller/sync.controller' +import { TransferController } from './http/rest/controller/transfer.controller' import { WalletController } from './http/rest/controller/wallet.controller' import { ConnectionSeedService } from './persistence/connection.seed' import { AccountRepository } from './persistence/repository/account.repository' @@ -29,37 +35,40 @@ import { AddressRepository } from './persistence/repository/address.repository' import { ConnectionRepository } from './persistence/repository/connection.repository' import { KnownDestinationRepository } from './persistence/repository/known-destination.repository' import { SyncRepository } from './persistence/repository/sync.repository' +import { TransferRepository } from './persistence/repository/transfer.repository' import { WalletRepository } from './persistence/repository/wallet.repository' @Module({ imports: [ - PersistenceModule, - TransitEncryptionModule, + ClientModule, EventEmitterModule.forRoot(), + HttpModule.register({ retry: { retries: 3 } }), OpenTelemetryModule.forRoot(), - HttpModule.register({ - retry: { - retries: 3 - } - }), - ClientModule + PersistenceModule, + TransitEncryptionModule ], controllers: [ - ConnectionController, - WalletController, AccountController, AddressController, + ConnectionController, + ProxyController, SyncController, - ProxyController + TransferController, + WalletController ], providers: [ ...DEFAULT_HTTP_MODULE_PROVIDERS, + { + provide: APP_FILTER, + useClass: ProviderHttpExceptionFilter + }, AccountRepository, AccountService, AddressRepository, AddressService, AnchorageClient, AnchorageSyncService, + AnchorageTransferService, ConnectionRepository, ConnectionSeedService, ConnectionService, @@ -71,6 +80,9 @@ import { WalletRepository } from './persistence/repository/wallet.repository' ProxyService, SyncRepository, SyncService, + TransferPartyService, + TransferRepository, + TransferService, WalletRepository, WalletService ] diff --git a/apps/vault/src/broker/core/exception/provider-http.exception.ts b/apps/vault/src/broker/core/exception/provider-http.exception.ts new file mode 100644 index 000000000..218757825 --- /dev/null +++ b/apps/vault/src/broker/core/exception/provider-http.exception.ts @@ -0,0 +1,36 @@ +import { AxiosError } from 'axios' +import { Provider } from '../type/connection.type' + +type ProviderHttpResponse = { + status: number + body: unknown +} + +type ProviderHttpExceptionParams = { + message?: string + provider: Provider + origin: AxiosError + response: ProviderHttpResponse + context?: unknown +} + +export class ProviderHttpException extends Error { + readonly response: ProviderHttpResponse + readonly provider: Provider + readonly origin: AxiosError + readonly context?: unknown + + constructor({ message, provider, origin, response, context }: ProviderHttpExceptionParams) { + super(message ?? `Provider ${provider.toUpperCase()} responded with ${response.status} error`) + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, ProviderHttpException) + } + + this.name = this.constructor.name + this.response = response + this.provider = provider + this.origin = origin + this.context = context + } +} diff --git a/apps/vault/src/broker/core/lib/anchorage-request-builder.ts b/apps/vault/src/broker/core/lib/anchorage-request-builder.ts deleted file mode 100644 index c272b2c8b..000000000 --- a/apps/vault/src/broker/core/lib/anchorage-request-builder.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { sign } from '@noble/ed25519' -import { AxiosRequestConfig } from 'axios' - -type HttpMethod = 'GET' | 'POST' - -export type BuildAnchorageRequestParams = { - url: string - method: HttpMethod - body?: Record - endpoint: string - apiKey: string - signKey: string -} - -export const extractVersion = (url: string): string => '/v2' -export const buildAnchorageSignedRequest = async ({ - url, - method, - endpoint, - body, - apiKey, - signKey -}: BuildAnchorageRequestParams): Promise => { - const time = Math.floor(new Date().getTime() / 1000) - const version = extractVersion(url) - const serializedPayload = body - ? `${time}${method}${version}${endpoint}${JSON.stringify(body)}` - : `${time}${method}${version}${endpoint}` - - const signatureRequest = Buffer.from(serializedPayload, 'utf8').toString('hex') - const hexSignature = await sign(signatureRequest, signKey.slice(2)) - - const signature = Buffer.from(hexSignature).toString('hex') - - const finalUrl = `${url}/v2${endpoint}` - const headers = { - 'Api-Access-Key': apiKey, - 'Api-Signature': signature, - 'Api-Timestamp': time, - 'Content-Type': 'application/json' - } - - const config: AxiosRequestConfig = { - url: finalUrl, - method, - headers, - data: body - } - - return config -} diff --git a/apps/vault/src/broker/core/service/__test__/integration/anchorage-transfer.service.spec.ts b/apps/vault/src/broker/core/service/__test__/integration/anchorage-transfer.service.spec.ts new file mode 100644 index 000000000..5bacc4d6f --- /dev/null +++ b/apps/vault/src/broker/core/service/__test__/integration/anchorage-transfer.service.spec.ts @@ -0,0 +1,436 @@ +import { EncryptionModuleOptionProvider } from '@narval/encryption-module' +import { LoggerModule } from '@narval/nestjs-shared' +import { Ed25519PrivateKey, getPublicKey } from '@narval/signature' +import { INestApplication } from '@nestjs/common' +import { Test, TestingModule } from '@nestjs/testing' +import { v4 as uuid } from 'uuid' +import { ClientService } from '../../../../../client/core/service/client.service' +import { MainModule } from '../../../../../main.module' +import { ProvisionService } from '../../../../../provision.service' +import { KeyValueRepository } from '../../../../../shared/module/key-value/core/repository/key-value.repository' +import { InMemoryKeyValueRepository } from '../../../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' +import { TestPrismaService } from '../../../../../shared/module/persistence/service/test-prisma.service' +import { getTestRawAesKeyring } from '../../../../../shared/testing/encryption.testing' +import { testClient } from '../../../../__test__/util/mock-data' +import { AccountRepository } from '../../../../persistence/repository/account.repository' +import { AddressRepository } from '../../../../persistence/repository/address.repository' +import { ConnectionRepository } from '../../../../persistence/repository/connection.repository' +import { KnownDestinationRepository } from '../../../../persistence/repository/known-destination.repository' +import { TransferRepository } from '../../../../persistence/repository/transfer.repository' +import { WalletRepository } from '../../../../persistence/repository/wallet.repository' +import { ActiveConnectionWithCredentials, ConnectionStatus, Provider } from '../../../type/connection.type' +import { Account, Address, KnownDestination, Wallet } from '../../../type/indexed-resources.type' +import { InternalTransfer, NetworkFeeAttribution, TransferPartyType, TransferStatus } from '../../../type/transfer.type' +import { AnchorageTransferService } from '../../anchorage-transfer.service' +import { ANCHORAGE_TEST_API_BASE_URL, setupMockServer, useRequestSpy } from './mocks/anchorage/server' + +describe(AnchorageTransferService.name, () => { + let app: INestApplication + let module: TestingModule + let testPrismaService: TestPrismaService + let anchorageTransferService: AnchorageTransferService + let provisionService: ProvisionService + let clientService: ClientService + + let transferRepository: TransferRepository + let connectionRepository: ConnectionRepository + let walletRepository: WalletRepository + let accountRepository: AccountRepository + let addressRepository: AddressRepository + let knownDestinationRepository: KnownDestinationRepository + + const server = setupMockServer() + + const clientId = uuid() + + const externalId = '60a0676772fdbd7a041e9451c61c3cb6b28ee901186e40ac99433308604e2e20' + + const walletId = uuid() + + const eddsaPrivateKey: Ed25519PrivateKey = { + kty: 'OKP', + crv: 'Ed25519', + alg: 'EDDSA', + kid: '0xa6fe705025aa4c48abbb3a1ed679d7dc7d18e7994b4d5cb1884479fddeb2e706', + x: 'U4WSOMzD7gor6jiVz42jT22JGBcfGfzMomt8PFC_-_U', + d: 'evo-fY2BX60V1n3Z690LadH5BvizcM9bESaYk0LsxyQ' + } + + const connection: ActiveConnectionWithCredentials = { + clientId, + connectionId: uuid(), + createdAt: new Date(), + provider: Provider.ANCHORAGE, + status: ConnectionStatus.ACTIVE, + updatedAt: new Date(), + url: ANCHORAGE_TEST_API_BASE_URL, + credentials: { + privateKey: eddsaPrivateKey, + publicKey: getPublicKey(eddsaPrivateKey), + apiKey: 'test-api-key' + } + } + + const accountOne: Account = { + accountId: uuid(), + addresses: [], + clientId, + createdAt: new Date(), + externalId: uuid(), + label: 'Account 1', + networkId: 'BTC', + provider: Provider.ANCHORAGE, + updatedAt: new Date(), + walletId + } + + const accountTwo: Account = { + accountId: uuid(), + addresses: [], + clientId, + createdAt: new Date(), + externalId: uuid(), + label: 'Account 2', + networkId: 'BTC', + provider: Provider.ANCHORAGE, + updatedAt: new Date(), + walletId + } + + const address: Address = { + accountId: accountTwo.accountId, + address: '0x2c4895215973cbbd778c32c456c074b99daf8bf1', + addressId: uuid(), + clientId, + createdAt: new Date(), + externalId: uuid(), + provider: Provider.ANCHORAGE, + updatedAt: new Date() + } + + const wallet: Wallet = { + clientId, + connections: [connection], + createdAt: new Date(), + externalId: uuid(), + label: null, + provider: Provider.ANCHORAGE, + updatedAt: new Date(), + walletId + } + + const knownDestination: KnownDestination = { + address: '0x04b12f0863b83c7162429f0ebb0dfda20e1aa97b', + clientId, + connections: [], + createdAt: new Date(), + externalId: uuid(), + knownDestinationId: uuid(), + networkId: 'BTC', + provider: Provider.ANCHORAGE, + updatedAt: new Date() + } + + const internalTransfer: InternalTransfer = { + clientId, + customerRefId: null, + idempotenceId: null, + destination: { + type: TransferPartyType.ACCOUNT, + id: accountTwo.accountId + }, + externalId, + assetId: 'BTC', + memo: 'Test transfer', + grossAmount: '0.00001', + networkFeeAttribution: NetworkFeeAttribution.DEDUCT, + provider: Provider.ANCHORAGE, + source: { + type: TransferPartyType.ACCOUNT, + id: accountOne.accountId + }, + transferId: uuid(), + createdAt: new Date() + } + + beforeAll(async () => { + module = await Test.createTestingModule({ + imports: [MainModule] + }) + .overrideModule(LoggerModule) + .useModule(LoggerModule.forTest()) + .overrideProvider(KeyValueRepository) + .useValue(new InMemoryKeyValueRepository()) + .overrideProvider(EncryptionModuleOptionProvider) + .useValue({ + keyring: getTestRawAesKeyring() + }) + .compile() + + app = module.createNestApplication() + + testPrismaService = module.get(TestPrismaService) + anchorageTransferService = module.get(AnchorageTransferService) + provisionService = module.get(ProvisionService) + clientService = module.get(ClientService) + + transferRepository = module.get(TransferRepository) + connectionRepository = module.get(ConnectionRepository) + walletRepository = module.get(WalletRepository) + accountRepository = module.get(AccountRepository) + addressRepository = module.get(AddressRepository) + knownDestinationRepository = module.get(KnownDestinationRepository) + + await testPrismaService.truncateAll() + }) + + afterAll(async () => { + await testPrismaService.truncateAll() + await module.close() + await app.close() + }) + + beforeEach(async () => { + await testPrismaService.truncateAll() + + await provisionService.provision() + await clientService.save(testClient) + + await connectionRepository.create(connection) + await walletRepository.bulkCreate([wallet]) + await accountRepository.bulkCreate([accountOne, accountTwo]) + await addressRepository.bulkCreate([address]) + await transferRepository.bulkCreate([internalTransfer]) + await knownDestinationRepository.bulkCreate([knownDestination]) + + await app.init() + }) + + describe('findById', () => { + it('maps data from internal transfer', async () => { + const transfer = await anchorageTransferService.findById(connection, internalTransfer.transferId) + + expect(transfer).toMatchObject({ + assetId: internalTransfer.assetId, + clientId: internalTransfer.clientId, + customerRefId: internalTransfer.customerRefId, + destination: internalTransfer.destination, + externalId: internalTransfer.externalId, + idempotenceId: internalTransfer.idempotenceId, + networkFeeAttribution: internalTransfer.networkFeeAttribution, + provider: internalTransfer.provider, + source: internalTransfer.source, + transferId: internalTransfer.transferId + }) + }) + + it('maps gross amount from inbound transfer', async () => { + const transfer = await anchorageTransferService.findById(connection, internalTransfer.transferId) + + expect(transfer.grossAmount).toEqual('0.00001') + }) + + it('maps status from inbound transfer', async () => { + const transfer = await anchorageTransferService.findById(connection, internalTransfer.transferId) + + expect(transfer.status).toEqual(TransferStatus.SUCCESS) + }) + + it('maps memo from internal transfer when inbound transferMemo is undefined', async () => { + const transfer = await anchorageTransferService.findById(connection, internalTransfer.transferId) + + expect(transfer.memo).toEqual(internalTransfer.memo) + }) + + it('maps network fee from inbound anchorage transfer', async () => { + const transfer = await anchorageTransferService.findById(connection, internalTransfer.transferId) + + expect(transfer.fees).toEqual([ + { + amount: '0.00001771', + assetId: 'BTC_S', + attribution: internalTransfer.networkFeeAttribution, + type: 'network' + } + ]) + }) + }) + + describe('send', () => { + const requiredSendTransfer = { + source: { + type: TransferPartyType.ACCOUNT, + id: accountOne.accountId + }, + destination: { + type: TransferPartyType.ACCOUNT, + id: accountTwo.accountId + }, + amount: '0.00005', + assetId: 'BTC' + } + + const transferAmlQuestionnaire = { + destinationType: 'SELFHOSTED_WALLET', + recipientType: 'PERSON', + purpose: 'INVESTMENT', + originatorType: 'MY_ORGANIZATION', + selfhostedDescription: 'a wallet description', + recipientFirstName: 'John', + recipientLastName: 'Recipient', + recipientFullName: 'John Recipient Full Name', + recipientCountry: 'US', + recipientStreetAddress: 'Some Recipient Street', + recipientCity: 'New York', + recipientStateProvince: 'NY', + recipientPostalCode: '10101' + } + + it('creates an internal transfer on success', async () => { + const internalTransfer = await anchorageTransferService.send(connection, requiredSendTransfer) + const actualInternalTransfer = await transferRepository.findById(clientId, internalTransfer.transferId) + + expect(actualInternalTransfer).toEqual(internalTransfer) + }) + + it('creates with optional properties', async () => { + const sendTransfer = { + ...requiredSendTransfer, + memo: 'Integration test transfer', + networkFeeAttribution: NetworkFeeAttribution.DEDUCT, + customerRefId: uuid(), + idempotenceId: uuid() + } + + const internalTransfer = await anchorageTransferService.send(connection, sendTransfer) + const actualInternalTransfer = await transferRepository.findById(clientId, internalTransfer.transferId) + + expect(actualInternalTransfer.idempotenceId).toEqual(sendTransfer.idempotenceId) + expect(actualInternalTransfer.memo).toEqual(sendTransfer.memo) + expect(actualInternalTransfer.customerRefId).toEqual(sendTransfer.customerRefId) + expect(actualInternalTransfer.networkFeeAttribution).toEqual(sendTransfer.networkFeeAttribution) + }) + + it('defaults network fee attribution to on_top', async () => { + const internalTransfer = await anchorageTransferService.send(connection, requiredSendTransfer) + + expect(internalTransfer.networkFeeAttribution).toEqual(NetworkFeeAttribution.ON_TOP) + }) + + it('calls Anchorage', async () => { + const [spy] = useRequestSpy(server) + const sendTransfer = { + ...requiredSendTransfer, + memo: 'Integration test transfer', + customerRefId: uuid(), + idempotenceId: uuid() + } + + await anchorageTransferService.send(connection, sendTransfer) + + expect(spy).toHaveBeenCalledWith( + expect.objectContaining({ + body: { + source: { + type: 'WALLET', + id: accountOne.externalId + }, + destination: { + type: 'WALLET', + id: accountTwo.externalId + }, + assetType: sendTransfer.assetId, + amount: sendTransfer.amount, + customerRefId: sendTransfer.customerRefId, + transferMemo: sendTransfer.memo, + idempotenceId: sendTransfer.idempotenceId, + // Default `deductFeeFromAmountIfSameType` to false. + deductFeeFromAmountIfSameType: false + } + }) + ) + }) + + it('handles provider specific', async () => { + const [spy] = useRequestSpy(server) + const sendTransfer = { + ...requiredSendTransfer, + provider: Provider.ANCHORAGE, + providerSpecific: { transferAmlQuestionnaire } + } + + const internalTransfer = await anchorageTransferService.send(connection, sendTransfer) + const actualInternalTransfer = await transferRepository.findById(clientId, internalTransfer.transferId) + + expect(spy).toHaveBeenCalledWith( + expect.objectContaining({ + body: expect.objectContaining({ ...sendTransfer.providerSpecific }) + }) + ) + + expect(actualInternalTransfer.providerSpecific).toEqual(sendTransfer.providerSpecific) + }) + + it('maps networkFeeAttribution on_top to deductFeeFromAmountIfSameType false', async () => { + const [spy] = useRequestSpy(server) + + await anchorageTransferService.send(connection, { + ...requiredSendTransfer, + networkFeeAttribution: NetworkFeeAttribution.ON_TOP + }) + + expect(spy).toHaveBeenCalledWith( + expect.objectContaining({ + body: expect.objectContaining({ + deductFeeFromAmountIfSameType: false + }) + }) + ) + }) + + it('maps networkFeeAttribution deduct to deductFeeFromAmountIfSameType true', async () => { + const [spy] = useRequestSpy(server) + + await anchorageTransferService.send(connection, { + ...requiredSendTransfer, + networkFeeAttribution: NetworkFeeAttribution.DEDUCT + }) + + expect(spy).toHaveBeenCalledWith( + expect.objectContaining({ + body: expect.objectContaining({ + deductFeeFromAmountIfSameType: true + }) + }) + ) + }) + + it('sends to an internal address', async () => { + const sendTransfer = { + ...requiredSendTransfer, + destination: { + address: address.address + } + } + + const internalTransfer = await anchorageTransferService.send(connection, sendTransfer) + const actualInternalTransfer = await transferRepository.findById(clientId, internalTransfer.transferId) + + expect(actualInternalTransfer).toMatchObject(internalTransfer) + }) + + it('sends to a known destination', async () => { + const sendTransfer = { + ...requiredSendTransfer, + destination: { + address: knownDestination.address + } + } + + const internalTransfer = await anchorageTransferService.send(connection, sendTransfer) + const actualInternalTransfer = await transferRepository.findById(clientId, internalTransfer.transferId) + + expect(actualInternalTransfer).toMatchObject(internalTransfer) + }) + }) +}) diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/handlers.ts b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/handlers.ts index a6a24abb4..4a68a2366 100644 --- a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/handlers.ts +++ b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/handlers.ts @@ -1,10 +1,12 @@ import { HttpResponse, http } from 'msw' +import getTransferOk from './response/get-transfer-200.json' +import getVaultsOk from './response/get-vaults-200.json' +import getVaultAddressesOk from './response/get-vaults-addresses-200.json' +import getWalletsOk from './response/get-wallets-200.json' +import postTransferCreated from './response/post-transfer-201.json' import trustedDestinationsFirst from './response/trusted-destinations-1.json' import trustedDestinationsSecond from './response/trusted-destinations-2.json' import trustedDestinationsThird from './response/trusted-destinations-3.json' -import vaultAddressesOk from './response/vaults-addresses-ok.json' -import vaultsOk from './response/vaults-ok.json' -import walletsOk from './response/wallets-ok.json' export const trustedDestinationsHandlers = (baseUrl: string) => { return { @@ -24,15 +26,23 @@ export const trustedDestinationsHandlers = (baseUrl: string) => { export const getHandlers = (baseUrl: string) => [ http.get(`${baseUrl}/v2/vaults/:vaultId/addresses`, () => { - return new HttpResponse(JSON.stringify(vaultAddressesOk)) + return new HttpResponse(JSON.stringify(getVaultAddressesOk)) }), http.get(`${baseUrl}/v2/vaults`, () => { - return new HttpResponse(JSON.stringify(vaultsOk)) + return new HttpResponse(JSON.stringify(getVaultsOk)) }), http.get(`${baseUrl}/v2/wallets`, () => { - return new HttpResponse(JSON.stringify(walletsOk)) + return new HttpResponse(JSON.stringify(getWalletsOk)) + }), + + http.get(`${baseUrl}/v2/transfers/:transferId`, () => { + return new HttpResponse(JSON.stringify(getTransferOk)) + }), + + http.post(`${baseUrl}/v2/transfers`, () => { + return new HttpResponse(JSON.stringify(postTransferCreated)) }), trustedDestinationsHandlers(baseUrl).findAll diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-transfer-200.json b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-transfer-200.json new file mode 100644 index 000000000..1ba192755 --- /dev/null +++ b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-transfer-200.json @@ -0,0 +1,28 @@ +{ + "data": { + "amount": { + "assetType": "BTC_S", + "currentPrice": "104576.34", + "currentUSDValue": "1.05", + "quantity": "0.00001" + }, + "assetType": "BTC_S", + "blockchainTxId": "71ffe98ce4f51b4d12c77626dc455c9223f68b215c631f45ff05958623761e23", + "createdAt": "2024-12-18T14:04:10.519Z", + "destination": { + "id": "afb308d207a76f029257ea6d9d7d58ab", + "type": "WALLET" + }, + "endedAt": "2024-12-18T14:08:13.618Z", + "fee": { + "assetType": "BTC_S", + "quantity": "0.00001771" + }, + "source": { + "id": "6a46a1977959e0529f567e8e927e3895", + "type": "WALLET" + }, + "status": "COMPLETED", + "transferId": "60a0676772fdbd7a041e9451c61c3cb6b28ee901186e40ac99433308604e2e20" + } +} diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/vaults-ok.json b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-vaults-200.json similarity index 100% rename from apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/vaults-ok.json rename to apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-vaults-200.json diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/vaults-addresses-ok.json b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-vaults-addresses-200.json similarity index 100% rename from apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/vaults-addresses-ok.json rename to apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-vaults-addresses-200.json diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/wallets-ok.json b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-wallets-200.json similarity index 100% rename from apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/wallets-ok.json rename to apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-wallets-200.json diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/post-transfer-201.json b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/post-transfer-201.json new file mode 100644 index 000000000..d99d733ea --- /dev/null +++ b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/post-transfer-201.json @@ -0,0 +1,6 @@ +{ + "data": { + "transferId": "008d3ec72558ce907571886df63ef51594b5bd8cf106a0b7fa8f12a30dfc867f", + "status": "IN_PROGRESS" + } +} diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/post-transfer-400.json b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/post-transfer-400.json new file mode 100644 index 000000000..56891b250 --- /dev/null +++ b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/post-transfer-400.json @@ -0,0 +1,4 @@ +{ + "errorType": "InternalError", + "message": "Missing required field 'amount'." +} diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/server.ts b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/server.ts index ab1381de6..567e4beba 100644 --- a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/server.ts +++ b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/server.ts @@ -1,4 +1,4 @@ -import { afterAll, afterEach, beforeAll } from '@jest/globals' +import { afterAll, afterEach, beforeAll, jest } from '@jest/globals' import { SetupServerApi, setupServer } from 'msw/node' import { disableNockProtection, restoreNockProtection } from '../../../../../../../../test/nock.util' import { getHandlers } from './handlers' @@ -7,6 +7,26 @@ export const ANCHORAGE_TEST_API_BASE_URL = 'https://test-mock-api.anchorage.com' export const getMockServer = () => setupServer(...getHandlers(ANCHORAGE_TEST_API_BASE_URL)) +export const useRequestSpy = (server: SetupServerApi): [jest.Mock, SetupServerApi] => { + const spy = jest.fn() + + server.events.on('request:start', async ({ request }) => { + // Clone the request to avoid draining any data stream on reads. + const clone = request.clone() + const body = await clone.json() + + spy({ + method: clone.method, + url: clone.url, + headers: Object.fromEntries(request.headers), + body + }) + }) + + // NOTE: Use `spy.mock.calls` to debug the calls recorded by the spy. + return [spy, server] +} + const attachToJestTestLifecycle = (server: SetupServerApi): SetupServerApi => { beforeAll(() => { // Disable nock net protection to allow requests to the mock server. diff --git a/apps/vault/src/broker/core/service/anchorage-transfer.service.ts b/apps/vault/src/broker/core/service/anchorage-transfer.service.ts new file mode 100644 index 000000000..c72066d46 --- /dev/null +++ b/apps/vault/src/broker/core/service/anchorage-transfer.service.ts @@ -0,0 +1,216 @@ +import { LoggerService } from '@narval/nestjs-shared' +import { HttpStatus, Injectable } from '@nestjs/common' +import { v4 as uuid } from 'uuid' +import { AnchorageClient } from '../../http/client/anchorage.client' +import { TransferRepository } from '../../persistence/repository/transfer.repository' +import { BrokerException } from '../exception/broker.exception' +import { ActiveConnectionWithCredentials, Provider } from '../type/connection.type' +import { + Destination, + InternalTransfer, + NetworkFeeAttribution, + SendTransfer, + Source, + Transfer, + TransferPartyType, + TransferStatus, + isAddressDestination, + isProviderSpecific +} from '../type/transfer.type' +import { TransferPartyService } from './transfer-party.service' + +@Injectable() +export class AnchorageTransferService { + constructor( + private readonly anchorageClient: AnchorageClient, + private readonly transferPartyService: TransferPartyService, + private readonly transferRepository: TransferRepository, + private readonly logger: LoggerService + ) {} + + async findById(connection: ActiveConnectionWithCredentials, transferId: string): Promise { + this.logger.log('Find Anchorage transfer by ID', { + clientId: connection.clientId, + connectionId: connection.connectionId, + transferId + }) + + const internalTransfer = await this.transferRepository.findById(connection.clientId, transferId) + + this.logger.log('Found internal transfer by ID', internalTransfer) + + const anchorageTransfer = await this.anchorageClient.getTransferById({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey, + transferId: internalTransfer.externalId + }) + + this.logger.log('Found remote transfer by external ID', anchorageTransfer) + + const transfer = { + assetId: internalTransfer.assetId, + clientId: internalTransfer.clientId, + createdAt: new Date(anchorageTransfer.createdAt), + customerRefId: internalTransfer.customerRefId, + destination: internalTransfer.destination, + externalId: internalTransfer.externalId, + grossAmount: anchorageTransfer.amount.quantity, + idempotenceId: internalTransfer.idempotenceId, + memo: anchorageTransfer.transferMemo || internalTransfer.memo || null, + networkFeeAttribution: internalTransfer.networkFeeAttribution, + provider: internalTransfer.provider, + source: internalTransfer.source, + status: this.mapStatus(anchorageTransfer.status), + transferId: internalTransfer.transferId, + fees: anchorageTransfer.fee + ? [ + { + type: 'network', + attribution: internalTransfer.networkFeeAttribution, + amount: anchorageTransfer.fee?.quantity, + assetId: anchorageTransfer.fee?.assetType + } + ] + : [] + } + + this.logger.log('Combined internal and remote transfer', transfer) + + return transfer + } + + private mapStatus(status: string): TransferStatus { + const upperCasedStatus = status.toUpperCase() + const statuses: Record = { + IN_PROGRESS: TransferStatus.PROCESSING, + QUEUED: TransferStatus.PROCESSING, + COMPLETED: TransferStatus.SUCCESS, + FAILED: TransferStatus.FAILED + } + + if (upperCasedStatus in statuses) { + return statuses[upperCasedStatus] + } + + throw new BrokerException({ + message: 'Cannot map Anchorage transfer status', + suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, + context: { status: upperCasedStatus } + }) + } + + async send(connection: ActiveConnectionWithCredentials, sendTransfer: SendTransfer): Promise { + this.logger.log('Send Anchorage transfer', { + clientId: connection.clientId, + connectionId: connection.connectionId, + sendTransfer + }) + + const source = await this.transferPartyService.resolve(connection.clientId, sendTransfer.source) + const destination = await this.transferPartyService.resolve(connection.clientId, sendTransfer.destination) + + this.logger.log('Resolved source and destination', { source, destination }) + + // NOTE: Because Anchorage defaults `deductFeeFromAmountIfSameType` to false, we + // default the fee attribution to ON_TOP to match their API's behaviour. + const networkFeeAttribution = sendTransfer.networkFeeAttribution || NetworkFeeAttribution.ON_TOP + const data = { + source: { + type: this.getResourceType(sendTransfer.source), + id: source.externalId + }, + destination: { + type: this.getResourceType(sendTransfer.destination), + id: destination.externalId + }, + assetType: sendTransfer.assetId, + amount: sendTransfer.amount, + customerRefId: sendTransfer.customerRefId || null, + transferMemo: sendTransfer.memo || null, + idempotenceId: sendTransfer.idempotenceId || null, + deductFeeFromAmountIfSameType: this.getDeductFeeFromAmountIfSameType(networkFeeAttribution), + ...(isProviderSpecific(sendTransfer.providerSpecific) ? { ...sendTransfer.providerSpecific } : {}) + } + + const anchorageTransfer = await this.anchorageClient.createTransfer({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey, + data + }) + + const internalTransfer: InternalTransfer = { + assetId: sendTransfer.assetId, + clientId: connection.clientId, + createdAt: new Date(), + customerRefId: sendTransfer.customerRefId || null, + destination: sendTransfer.destination, + externalId: anchorageTransfer.transferId, + grossAmount: sendTransfer.amount, + idempotenceId: sendTransfer.idempotenceId || null, + memo: sendTransfer.memo || null, + networkFeeAttribution, + provider: Provider.ANCHORAGE, + providerSpecific: sendTransfer.providerSpecific || null, + source: sendTransfer.source, + status: this.mapStatus(anchorageTransfer.status), + transferId: uuid() + } + + this.logger.log('Create internal transfer', internalTransfer) + + await this.transferRepository.bulkCreate([internalTransfer]) + + return internalTransfer + } + + /** + * Anchorage uses `deductFeeFromAmountIfSameType` that if set to true fees + * will be added to amount requested. + * + * Example: a request to transfer 5 BTC with + * `deductFeeFromAmountIfSameType=false` would result in 5 exactly BTC + * received to the destination vault and just over 5 BTC spent by the source + * vault. + * + * NOTE: Anchorage API defaults to `false`. + * + * @see https://docs.anchorage.com/reference/createtransfer + */ + private getDeductFeeFromAmountIfSameType(attribution: NetworkFeeAttribution): boolean { + if (attribution === NetworkFeeAttribution.DEDUCT) { + return true + } + + if (attribution === NetworkFeeAttribution.ON_TOP) { + return false + } + + return false + } + + private getResourceType(transferParty: Source | Destination) { + if (isAddressDestination(transferParty)) { + return 'ADDRESS' + } + + if (transferParty.type === TransferPartyType.WALLET) { + return 'VAULT' + } + + if (transferParty.type === TransferPartyType.ACCOUNT) { + return 'WALLET' + } + + if (transferParty.type === TransferPartyType.ADDRESS) { + return 'ADDRESS' + } + + throw new BrokerException({ + message: 'Cannot get Anchorage resource type from transfer party type', + suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, + context: { party: transferParty } + }) + } +} diff --git a/apps/vault/src/broker/core/service/transfer-party.service.ts b/apps/vault/src/broker/core/service/transfer-party.service.ts new file mode 100644 index 000000000..dd75706f5 --- /dev/null +++ b/apps/vault/src/broker/core/service/transfer-party.service.ts @@ -0,0 +1,89 @@ +import { HttpStatus, Injectable } from '@nestjs/common' +import { AccountRepository } from '../../persistence/repository/account.repository' +import { AddressRepository } from '../../persistence/repository/address.repository' +import { KnownDestinationRepository } from '../../persistence/repository/known-destination.repository' +import { WalletRepository } from '../../persistence/repository/wallet.repository' +import { BrokerException } from '../exception/broker.exception' +import { Account, Address, KnownDestination, Wallet } from '../type/indexed-resources.type' +import { Destination, Source, TransferPartyType, isAddressDestination } from '../type/transfer.type' + +@Injectable() +export class TransferPartyService { + constructor( + private readonly walletRepository: WalletRepository, + private readonly accountRepository: AccountRepository, + private readonly addressRepository: AddressRepository, + private readonly knownDestinationRepository: KnownDestinationRepository + ) {} + + async resolve( + clientId: string, + transferParty: Source | Destination + ): Promise { + if (isAddressDestination(transferParty)) { + const { data: addresses } = await this.addressRepository.findAll(clientId, { + filters: { + addresses: [transferParty.address] + } + }) + + if (addresses.length) { + if (addresses.length > 1) { + throw new BrokerException({ + message: 'Cannot resolve the right address due to ambiguity', + suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, + context: { + addresses: addresses.map(({ address, addressId }) => ({ addressId, address })) + } + }) + } + + return addresses[0] + } + + const { data: knownDestinations } = await this.knownDestinationRepository.findAll(clientId, { + filters: { + addresses: [transferParty.address] + } + }) + + if (knownDestinations.length) { + if (knownDestinations.length > 1) { + throw new BrokerException({ + message: 'Cannot resolve the known destination due to ambiguity', + suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, + context: { + addresses: knownDestinations.map(({ address, knownDestinationId }) => ({ knownDestinationId, address })) + } + }) + } + + return knownDestinations[0] + } + + throw new BrokerException({ + message: 'Cannot resolve destination address', + suggestedHttpStatusCode: HttpStatus.NOT_FOUND, + context: { transferParty } + }) + } + + if (transferParty.type === TransferPartyType.WALLET) { + return this.walletRepository.findById(clientId, transferParty.id) + } + + if (transferParty.type === TransferPartyType.ACCOUNT) { + return this.accountRepository.findById(clientId, transferParty.id) + } + + if (transferParty.type === TransferPartyType.ADDRESS) { + return this.addressRepository.findById(clientId, transferParty.id) + } + + throw new BrokerException({ + message: 'Cannot resolve transfer party type', + suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, + context: { transferParty } + }) + } +} diff --git a/apps/vault/src/broker/core/service/transfer.service.ts b/apps/vault/src/broker/core/service/transfer.service.ts new file mode 100644 index 000000000..5cb9a2129 --- /dev/null +++ b/apps/vault/src/broker/core/service/transfer.service.ts @@ -0,0 +1,53 @@ +import { HttpStatus, Injectable, NotImplementedException } from '@nestjs/common' +import { TransferRepository } from '../../persistence/repository/transfer.repository' +import { BrokerException } from '../exception/broker.exception' +import { ConnectionStatus, Provider, isActiveConnection } from '../type/connection.type' +import { InternalTransfer, SendTransfer } from '../type/transfer.type' +import { AnchorageTransferService } from './anchorage-transfer.service' +import { ConnectionService } from './connection.service' +import { TransferPartyService } from './transfer-party.service' + +@Injectable() +export class TransferService { + constructor( + private readonly transferRepository: TransferRepository, + private readonly connectionService: ConnectionService, + private readonly transferPartyService: TransferPartyService, + private readonly anchorageTransferService: AnchorageTransferService + ) {} + + async findById(clientId: string, transferId: string): Promise { + return this.transferRepository.findById(clientId, transferId) + } + + async bulkCreate(transfers: InternalTransfer[]): Promise { + return this.transferRepository.bulkCreate(transfers) + } + + async send(clientId: string, sendTransfer: SendTransfer): Promise { + const source = await this.transferPartyService.resolve(clientId, sendTransfer.source) + + if (source.provider === Provider.ANCHORAGE) { + const { data: connections } = await this.connectionService.findAll( + clientId, + { + filters: { + status: ConnectionStatus.ACTIVE + } + }, + true + ) + + if (connections.length && isActiveConnection(connections[0])) { + return this.anchorageTransferService.send(connections[0], sendTransfer) + } + + throw new BrokerException({ + message: 'Cannot find an active connection for Anchorage', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY + }) + } + + throw new NotImplementedException() + } +} diff --git a/apps/vault/src/broker/core/type/connection.type.ts b/apps/vault/src/broker/core/type/connection.type.ts index e773babbc..cf69eefb1 100644 --- a/apps/vault/src/broker/core/type/connection.type.ts +++ b/apps/vault/src/broker/core/type/connection.type.ts @@ -127,6 +127,7 @@ export const isActiveConnection = (connection: Connection): connection is Active export const isRevokedConnection = (connection: Connection): connection is RevokedConnection => { return connection.status === ConnectionStatus.REVOKED } + export const PublicConnection = BaseConnection.pick({ connectionId: true, status: true, label: true, provider: true }) export type PublicConnection = z.infer diff --git a/apps/vault/src/broker/core/type/indexed-resources.type.ts b/apps/vault/src/broker/core/type/indexed-resources.type.ts index 0b6801ea5..16f46e580 100644 --- a/apps/vault/src/broker/core/type/indexed-resources.type.ts +++ b/apps/vault/src/broker/core/type/indexed-resources.type.ts @@ -18,41 +18,41 @@ export const KnownDestination = z.object({ export type KnownDestination = z.infer export const Address = z.object({ - addressId: z.string(), - clientId: z.string(), - provider: z.nativeEnum(Provider), - externalId: z.string(), accountId: z.string(), address: z.string(), + addressId: z.string(), + clientId: z.string(), createdAt: z.date(), + externalId: z.string(), + provider: z.nativeEnum(Provider), updatedAt: z.date() }) export type Address = z.infer export const Account = z.object({ accountId: z.string(), - label: z.string().nullable().optional(), addresses: z.array(Address).optional(), clientId: z.string(), - provider: z.nativeEnum(Provider), + createdAt: z.date(), externalId: z.string(), - walletId: z.string(), + label: z.string().nullable().optional(), networkId: z.string(), - createdAt: z.date(), - updatedAt: z.date() + provider: z.nativeEnum(Provider), + updatedAt: z.date(), + walletId: z.string() }) export type Account = z.infer export const Wallet = z.object({ - walletId: z.string(), accounts: z.array(Account).optional(), + clientId: z.string(), connections: z.array(BaseConnection), + createdAt: z.date(), + externalId: z.string(), label: z.string().nullable().optional(), - clientId: z.string(), provider: z.nativeEnum(Provider), - externalId: z.string(), - createdAt: z.date(), - updatedAt: z.date() + updatedAt: z.date(), + walletId: z.string() }) export type Wallet = z.infer diff --git a/apps/vault/src/broker/core/type/transfer.type.ts b/apps/vault/src/broker/core/type/transfer.type.ts new file mode 100644 index 000000000..4e04afd8f --- /dev/null +++ b/apps/vault/src/broker/core/type/transfer.type.ts @@ -0,0 +1,110 @@ +import { z } from 'zod' +import { Provider } from './connection.type' + +export const NetworkFeeAttribution = { + ON_TOP: 'on_top', + DEDUCT: 'deduct' +} as const +export type NetworkFeeAttribution = (typeof NetworkFeeAttribution)[keyof typeof NetworkFeeAttribution] + +export const TransferPartyType = { + WALLET: 'wallet', + ACCOUNT: 'account', + ADDRESS: 'address' +} as const +export type TransferPartyType = (typeof TransferPartyType)[keyof typeof TransferPartyType] + +export const TransferParty = z.object({ + id: z.string(), + type: z.nativeEnum(TransferPartyType) +}) +export type TransferParty = z.infer + +export const Source = TransferParty +export type Source = z.infer + +export const AddressDestination = z.object({ + address: z.string() +}) +export type AddressDestination = z.infer + +export const Destination = z.union([TransferParty, AddressDestination]) +export type Destination = z.infer + +export const SendTransfer = z.object({ + source: Source, + destination: Destination, + amount: z.string(), + assetId: z.string(), + // This is optional on the base transfer and always default on the + // provider-specific transfer service. + networkFeeAttribution: z.nativeEnum(NetworkFeeAttribution).optional(), + customerRefId: z.string().optional(), + idempotenceId: z.string().optional(), + memo: z.string().optional(), + provider: z.nativeEnum(Provider).optional(), + // Requires `provider` to be set. + providerSpecific: z.unknown().optional() +}) +export type SendTransfer = z.infer + +export const Fee = z.object({ + type: z.string(), + attribution: z.string(), + amount: z.string(), + assetId: z.string() +}) +export type Fee = z.infer + +export const TransferStatus = { + PROCESSING: 'processing', + SUCCESS: 'success', + FAILED: 'failed' +} as const +export type TransferStatus = (typeof TransferStatus)[keyof typeof TransferStatus] + +export const InternalTransfer = z.object({ + assetId: z.string(), + clientId: z.string(), + createdAt: z.date(), + customerRefId: z.string().nullable(), + destination: Destination, + externalId: z.string(), + grossAmount: z.string(), + idempotenceId: z.string().nullable(), + memo: z.string().nullable(), + networkFeeAttribution: z.nativeEnum(NetworkFeeAttribution), + provider: z.nativeEnum(Provider), + providerSpecific: z.unknown().nullable(), + source: Source, + // The status is optional for an internal transfer because we query the + // provider to get the most recent status on reads. + // + // If we stored it, it would complicate our system by trying to keep + // distributed systems state in sync – an indexing problem. The Vault **is + // not an indexing solution**. + // + // NOTE: The status is not persisted in the database. + status: z.nativeEnum(TransferStatus).default(TransferStatus.PROCESSING).optional(), + transferId: z.string() +}) +export type InternalTransfer = z.infer + +export const Transfer = InternalTransfer.extend({ + // A transfer always has a status because we check with the provider to + // combine the information from the API and the database. + status: z.nativeEnum(TransferStatus), + fees: z.array(Fee) +}) +export type Transfer = z.infer + +export const isAddressDestination = (destination: Destination): destination is AddressDestination => { + return 'address' in destination +} + +/** + * Ensures the provider specific is an object. + */ +export const isProviderSpecific = (value?: unknown): value is Record => { + return typeof value === 'object' && value !== null +} diff --git a/apps/vault/src/broker/http/client/anchorage.client.ts b/apps/vault/src/broker/http/client/anchorage.client.ts index 54fe29f0c..b1ab3f0f9 100644 --- a/apps/vault/src/broker/http/client/anchorage.client.ts +++ b/apps/vault/src/broker/http/client/anchorage.client.ts @@ -3,13 +3,31 @@ import { Ed25519PrivateKey, privateKeyToHex } from '@narval/signature' import { HttpService } from '@nestjs/axios' import { HttpStatus, Injectable } from '@nestjs/common' import { sign } from '@noble/ed25519' -import axios, { AxiosRequestConfig, AxiosResponse } from 'axios' +import axios, { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios' import { isNil, omitBy } from 'lodash' -import { EMPTY, Observable, catchError, expand, from, lastValueFrom, map, reduce, switchMap, tap } from 'rxjs' +import { + EMPTY, + Observable, + OperatorFunction, + catchError, + expand, + from, + lastValueFrom, + map, + reduce, + switchMap, + tap +} from 'rxjs' import { ZodType, z } from 'zod' import { BrokerException } from '../../core/exception/broker.exception' +import { ProviderHttpException } from '../../core/exception/provider-http.exception' import { ProxyRequestException } from '../../core/exception/proxy-request.exception' import { UrlParserException } from '../../core/exception/url-parser.exception' +import { Provider } from '../../core/type/connection.type' + +// +// Response Schema +// const Amount = z.object({ quantity: z.string(), @@ -77,6 +95,79 @@ const Address = z.object({ }) type Address = z.infer +const TransferAmount = z.object({ + assetType: z.string(), + currentPrice: z.string().optional(), + currentUSDValue: z.string().optional(), + quantity: z.string() +}) + +const TransferFee = z.object({ + assetType: z.string(), + quantity: z.string() +}) + +const Resource = z.object({ + id: z.string(), + type: z.string() +}) + +const Transfer = z.object({ + amount: TransferAmount, + assetType: z.string(), + blockchainTxId: z.string().optional(), + createdAt: z.string(), + destination: Resource, + endedAt: z.string().optional(), + fee: TransferFee.optional(), + source: Resource, + status: z.string(), + transferId: z.string(), + transferMemo: z.string().optional() +}) +type Transfer = z.infer + +const CreateTransfer = z.object({ + amount: z.string(), + assetType: z.string(), + deductFeeFromAmountIfSameType: z.boolean(), + destination: Resource, + idempotenceId: z.string().max(128).nullable(), + source: Resource, + transferMemo: z.string().nullable() +}) +type CreateTransfer = z.infer + +const CreatedTransfer = z.object({ + transferId: z.string(), + status: z.string() +}) +type CreatedTransfer = z.infer + +const TrustedDestination = z.object({ + id: z.string(), + type: z.literal('crypto'), + crypto: z.object({ + address: z.string(), + networkId: z.string(), + // Asset type is optional. If it is not provided, then the destination will + // accept any network compatible transfer + // e.g: ETH network can accept only one specific token on ETH network + assetType: z.string().optional(), + memo: z.string().optional() + }) +}) +type TrustedDestination = z.infer + +// +// Response Type +// + +const CreateTransferResponse = z.object({ + data: CreatedTransfer +}) +type CreateTransferResponse = z.infer + const GetVaultsResponse = z.object({ data: z.array(Vault), page: z.object({ @@ -101,19 +192,10 @@ const GetVaultAddressesResponse = z.object({ }) type GetVaultAddressesResponse = z.infer -export const TrustedDestination = z.object({ - id: z.string(), - type: z.literal('crypto'), - crypto: z.object({ - address: z.string(), - networkId: z.string(), - // Asset type is optional. If it is not provided, then the destination will accept any network compatible transfer - // e.g: ETH network can accept only one specific token on ETH network - assetType: z.string().optional(), - memo: z.string().optional() - }) +const GetTransferResponse = z.object({ + data: Transfer }) -export type TrustedDestination = z.infer +type GetTransferResponse = z.infer const GetTrustedDestinationsResponse = z.object({ data: z.array(TrustedDestination), @@ -123,6 +205,10 @@ const GetTrustedDestinationsResponse = z.object({ }) type GetTrustedDestinationsResponse = z.infer +// +// Request Type +// + interface RequestOptions { url: string apiKey: string @@ -331,21 +417,15 @@ export class AnchorageClient { url: opts.url }) }), - catchError((error) => { - this.logger.error('Failed to get Anchorage vaults', { error }) - - throw error - }) + this.handleError('Failed to get Anchorage vaults') ) ) } async getWallets(opts: RequestOptions): Promise { - this.logger.log('Requesting Anchorage wallets page', { - url: opts.url, - limit: opts.limit - }) - const { apiKey, signKey, url } = opts + const { apiKey, signKey, url, limit } = opts + + this.logger.log('Requesting Anchorage wallets page', { url, limit }) return lastValueFrom( this.sendSignedRequest({ @@ -375,7 +455,7 @@ export class AnchorageClient { if (response.page.next) { this.logger.log('Requesting Anchorage wallets next page', { url: response.page.next, - limit: opts.limit + limit }) } else { this.logger.log('Reached Anchorage wallets last page') @@ -384,15 +464,11 @@ export class AnchorageClient { reduce((wallets: Wallet[], response) => [...wallets, ...response.data], []), tap((wallets) => { this.logger.log('Completed fetching all wallets', { - walletsCount: wallets.length, - url: opts.url + url, + walletsCount: wallets.length }) }), - catchError((error) => { - this.logger.error('Failed to get Anchorage wallets', { error }) - - throw error - }) + this.handleError('Failed to get Anchorage wallets') ) ) } @@ -454,12 +530,13 @@ export class AnchorageClient { } async getVaultAddresses(opts: RequestOptions & { vaultId: string; assetType: string }): Promise { + const { apiKey, signKey, url, vaultId, assetType } = opts + this.logger.log('Requesting Anchorage vault addresses page', { - url: opts.url, - vaultId: opts.vaultId, - assetType: opts.assetType + url, + vaultId, + assetType }) - const { apiKey, signKey, url, vaultId, assetType } = opts return lastValueFrom( this.sendSignedRequest({ @@ -508,12 +585,83 @@ export class AnchorageClient { url }) }), - catchError((error) => { - this.logger.error('Failed to get Anchorage vault addresses', { error }) + this.handleError('Failed to get Anchorage vault addresses') + ) + ) + } - throw error - }) + async getTransferById(opts: RequestOptions & { transferId: string }): Promise { + const { apiKey, signKey, url, transferId } = opts + + this.logger.log('Requesting Anchorage transfer', { url, transferId }) + + return lastValueFrom( + this.sendSignedRequest({ + schema: GetTransferResponse, + request: { + url: `${url}/v2/transfers/${transferId}`, + method: 'GET' + }, + apiKey, + signKey + }).pipe( + map((response) => response.data), + tap((transfer) => { + this.logger.log('Successfully fetched transfer', { + transferId, + url, + status: transfer.status + }) + }), + this.handleError('Failed to get Anchorage transfer') ) ) } + + async createTransfer(opts: RequestOptions & { data: CreateTransfer }): Promise { + const { apiKey, signKey, url, data } = opts + + this.logger.log('Sending create transfer in request to Anchorage', { data }) + + return lastValueFrom( + this.sendSignedRequest({ + schema: CreateTransferResponse, + request: { + url: `${url}/v2/transfers`, + method: 'POST', + data + }, + apiKey, + signKey + }).pipe( + map((response) => response.data), + tap((transfer) => { + this.logger.log('Successfully created transfer', { + transferId: transfer.transferId, + url + }) + }), + this.handleError('Failed to create Anchorage transfer') + ) + ) + } + + private handleError(logMessage: string): OperatorFunction { + return catchError((error: unknown): Observable => { + this.logger.error(logMessage, { error }) + + if (error instanceof AxiosError) { + throw new ProviderHttpException({ + provider: Provider.ANCHORAGE, + origin: error, + response: { + status: error.response?.status ?? HttpStatus.INTERNAL_SERVER_ERROR, + body: error.response?.data + } + }) + } + + throw error + }) + } } diff --git a/apps/vault/src/broker/http/rest/controller/transfer.controller.ts b/apps/vault/src/broker/http/rest/controller/transfer.controller.ts new file mode 100644 index 000000000..ff4e1518c --- /dev/null +++ b/apps/vault/src/broker/http/rest/controller/transfer.controller.ts @@ -0,0 +1,51 @@ +import { Body, Controller, Get, HttpStatus, Param, Post } from '@nestjs/common' +import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' +import { ClientId } from '../../../../shared/decorator/client-id.decorator' +import { PermissionGuard } from '../../../../shared/decorator/permission-guard.decorator' +import { VaultPermission } from '../../../../shared/type/domain.type' +import { TransferService } from '../../../core/service/transfer.service' +import { SendTransferDto } from '../dto/request/send-transfer.dto' +import { TransferDto } from '../dto/response/transfer.dto' + +@Controller({ + path: 'transfers', + version: '1' +}) +@ApiTags('Provider Transfer') +export class TransferController { + constructor(private readonly transferService: TransferService) {} + + @Post() + @PermissionGuard(VaultPermission.CONNECTION_WRITE) + @ApiOperation({ + summary: 'Send a transfer', + description: "This endpoint sends a transfer to the source's provider." + }) + @ApiResponse({ + status: HttpStatus.CREATED, + description: 'The transfer was successfully sent.', + type: TransferDto + }) + async send(@ClientId() clientId: string, @Body() body: SendTransferDto): Promise { + const internalTransfer = await this.transferService.send(clientId, body) + + return TransferDto.create({ data: internalTransfer }) + } + + @Get(':transferId') + @PermissionGuard(VaultPermission.CONNECTION_READ) + @ApiOperation({ + summary: 'Retrieve transfer details', + description: 'This endpoint retrieves the details of a specific transfer using its ID.' + }) + @ApiResponse({ + status: HttpStatus.OK, + description: 'The transfer details were successfully retrieved.', + type: TransferDto + }) + async getById(@ClientId() clientId: string, @Param('transferId') transferId: string) { + const internalTransfer = await this.transferService.findById(clientId, transferId) + + return TransferDto.create({ data: internalTransfer }) + } +} diff --git a/apps/vault/src/broker/http/rest/dto/request/send-transfer.dto.ts b/apps/vault/src/broker/http/rest/dto/request/send-transfer.dto.ts new file mode 100644 index 000000000..1fd8c8170 --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/request/send-transfer.dto.ts @@ -0,0 +1,4 @@ +import { createZodDto } from 'nestjs-zod' +import { SendTransfer } from '../../../../core/type/transfer.type' + +export class SendTransferDto extends createZodDto(SendTransfer) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/transfer.dto.ts b/apps/vault/src/broker/http/rest/dto/response/transfer.dto.ts new file mode 100644 index 000000000..b5ef1c656 --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/response/transfer.dto.ts @@ -0,0 +1,9 @@ +import { createZodDto } from 'nestjs-zod' +import { z } from 'zod' +import { InternalTransfer } from '../../../../core/type/transfer.type' + +export class TransferDto extends createZodDto( + z.object({ + data: InternalTransfer + }) +) {} diff --git a/apps/vault/src/broker/persistence/repository/address.repository.ts b/apps/vault/src/broker/persistence/repository/address.repository.ts index 71889a35d..5d2e1cc19 100644 --- a/apps/vault/src/broker/persistence/repository/address.repository.ts +++ b/apps/vault/src/broker/persistence/repository/address.repository.ts @@ -9,10 +9,9 @@ import { Address } from '../../core/type/indexed-resources.type' type FindAllFilters = { filters?: { - connectionId?: string - accountIds?: string[] - walletIds?: string[] externalIds?: string[] + addresses?: string[] + provider?: Provider } } @@ -64,6 +63,7 @@ export class AddressRepository { const address = await this.prismaService.providerAddress.findUnique({ where: { clientId, id: addressId } }) + if (!address) { throw new NotFoundException({ message: 'Address not found', @@ -80,6 +80,18 @@ export class AddressRepository { const models = await this.prismaService.providerAddress.findMany({ where: { clientId, + ...(opts?.filters?.provider + ? { + provider: opts.filters.provider + } + : {}), + ...(opts?.filters?.addresses + ? { + address: { + in: opts.filters.addresses + } + } + : {}), ...(opts?.filters?.externalIds ? { externalId: { diff --git a/apps/vault/src/broker/persistence/repository/known-destination.repository.ts b/apps/vault/src/broker/persistence/repository/known-destination.repository.ts index 117c8b227..6d3afa20e 100644 --- a/apps/vault/src/broker/persistence/repository/known-destination.repository.ts +++ b/apps/vault/src/broker/persistence/repository/known-destination.repository.ts @@ -11,6 +11,7 @@ import { ConnectionRepository, connectionSelectWithoutCredentials } from './conn type FindAllFilters = { filters?: { externalIds?: string[] + addresses?: string[] } } @@ -116,6 +117,13 @@ export class KnownDestinationRepository { const models = await this.prismaService.providerKnownDestination.findMany({ where: { clientId, + ...(opts?.filters?.addresses + ? { + address: { + in: opts.filters.addresses + } + } + : {}), ...(opts?.filters?.externalIds ? { externalId: { @@ -184,6 +192,7 @@ export class KnownDestinationRepository { // Use the same parsing logic as findAll return created.map(KnownDestinationRepository.parseModel) } + async bulkDelete(knownDestinations: KnownDestination[]): Promise { await this.prismaService.providerKnownDestinationConnection.deleteMany({ where: { diff --git a/apps/vault/src/broker/persistence/repository/transfer.repository.ts b/apps/vault/src/broker/persistence/repository/transfer.repository.ts new file mode 100644 index 000000000..76598cd0b --- /dev/null +++ b/apps/vault/src/broker/persistence/repository/transfer.repository.ts @@ -0,0 +1,173 @@ +import { Injectable, NotFoundException } from '@nestjs/common' +import { ProviderTransfer } from '@prisma/client/vault' +import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' +import { + InternalTransfer, + TransferPartyType, + TransferStatus, + isAddressDestination +} from '../../core/type/transfer.type' + +@Injectable() +export class TransferRepository { + constructor(private prismaService: PrismaService) {} + + static parseEntity(entity: InternalTransfer): ProviderTransfer { + return { + assetId: entity.assetId, + clientId: entity.clientId, + createdAt: entity.createdAt, + customerRefId: entity.customerRefId, + destinationAddressRaw: null, // TODO + externalId: entity.externalId, + id: entity.transferId, + idempotenceId: entity.idempotenceId, + memo: entity.memo, + grossAmount: entity.grossAmount, + networkFeeAttribution: entity.networkFeeAttribution, + provider: entity.provider, + providerSpecific: PrismaService.toStringJson(entity.providerSpecific), + ...(entity.source.type === TransferPartyType.WALLET + ? { + sourceWalletId: entity.source.id + } + : { + sourceWalletId: null + }), + ...(entity.source.type === TransferPartyType.ACCOUNT + ? { + sourceAccountId: entity.source.id + } + : { + sourceAccountId: null + }), + ...(entity.source.type === TransferPartyType.ADDRESS + ? { + sourceAddressId: entity.source.id + } + : { + sourceAddressId: null + }), + ...(!isAddressDestination(entity.destination) && entity.destination.type === TransferPartyType.WALLET + ? { + destinationWalletId: entity.destination.id + } + : { + destinationWalletId: null + }), + ...(!isAddressDestination(entity.destination) && entity.destination.type === TransferPartyType.ACCOUNT + ? { + destinationAccountId: entity.destination.id + } + : { + destinationAccountId: null + }), + ...(!isAddressDestination(entity.destination) && entity.destination.type === TransferPartyType.ADDRESS + ? { + destinationAddressId: entity.destination.id + } + : { + destinationAddressId: null + }), + ...(isAddressDestination(entity.destination) + ? { + destinationAddressRaw: entity.destination.address + } + : {}) + } + } + + static parseModel(model: ProviderTransfer): InternalTransfer { + return InternalTransfer.parse({ + assetId: model.assetId, + clientId: model.clientId, + createdAt: model.createdAt, + customerRefId: model.customerRefId, + externalId: model.externalId, + grossAmount: model.grossAmount, + idempotenceId: model.idempotenceId, + memo: model.memo, + networkFeeAttribution: model.networkFeeAttribution, + provider: model.provider, + providerSpecific: PrismaService.toJson(model.providerSpecific), + status: TransferStatus.PROCESSING, + transferId: model.id, + source: { + ...(model.sourceWalletId + ? { + type: TransferPartyType.WALLET, + id: model.sourceWalletId + } + : {}), + ...(model.sourceAccountId + ? { + type: TransferPartyType.ACCOUNT, + id: model.sourceAccountId + } + : {}), + ...(model.sourceAddressId + ? { + type: TransferPartyType.ADDRESS, + id: model.sourceAddressId + } + : {}) + }, + destination: { + ...(model.destinationWalletId + ? { + type: TransferPartyType.WALLET, + id: model.destinationWalletId + } + : {}), + ...(model.destinationAccountId + ? { + type: TransferPartyType.ACCOUNT, + id: model.destinationAccountId + } + : {}), + ...(model.destinationAddressId + ? { + type: TransferPartyType.ADDRESS, + id: model.destinationAddressId + } + : {}), + ...(model.destinationAddressRaw + ? { + address: model.destinationAddressRaw + } + : {}) + } + }) + } + + async bulkCreate(transfers: InternalTransfer[]): Promise { + await this.prismaService.providerTransfer.createMany({ + data: transfers.map((transfer) => { + return { + ...TransferRepository.parseEntity(transfer), + providerSpecific: PrismaService.toStringJson(transfer.providerSpecific) + } + }) + }) + + return transfers + } + + async findById(clientId: string, transferId: string): Promise { + const model = await this.prismaService.providerTransfer.findUnique({ + where: { + clientId, + id: transferId + } + }) + + if (model) { + return TransferRepository.parseModel(model) + } + + throw new NotFoundException({ + message: 'Transfer not found', + context: { transferId } + }) + } +} diff --git a/apps/vault/src/shared/filter/application-exception.filter.ts b/apps/vault/src/shared/filter/application-exception.filter.ts index d2e8922d0..647bf2b8c 100644 --- a/apps/vault/src/shared/filter/application-exception.filter.ts +++ b/apps/vault/src/shared/filter/application-exception.filter.ts @@ -1,9 +1,10 @@ import { ConfigService } from '@narval/config-module' import { LoggerService } from '@narval/nestjs-shared' -import { ArgumentsHost, Catch, ExceptionFilter, LogLevel } from '@nestjs/common' +import { ArgumentsHost, Catch, ExceptionFilter, HttpStatus, LogLevel } from '@nestjs/common' import { Response } from 'express' import { Config, Env } from '../../main.config' import { ApplicationException } from '../../shared/exception/application.exception' +import { HttpException } from '../type/http-exception.type' @Catch(ApplicationException) export class ApplicationExceptionFilter implements ExceptionFilter { @@ -20,33 +21,31 @@ export class ApplicationExceptionFilter implements ExceptionFilter { this.log(exception) - response.status(status).json( - isProduction - ? { - statusCode: status, - message: exception.message, - context: exception.context - } - : { - statusCode: status, - message: exception.message, - context: exception.context, - stack: exception.stack, - ...(exception.origin && { origin: exception.origin }) - } - ) + const body: HttpException = isProduction + ? { + statusCode: status, + message: exception.message, + context: exception.context + } + : { + statusCode: status, + message: exception.message, + context: exception.context, + stack: exception.stack, + ...(exception.origin && { origin: exception.origin }) + } + + response.status(status).json(body) } - // TODO (@wcalderipe, 16/01/24): Unit test the logging logic. For that, we - // must inject the logger in the constructor via dependency injection. private log(exception: ApplicationException) { - const level: LogLevel = exception.getStatus() >= 500 ? 'error' : 'warn' + const level: LogLevel = exception.getStatus() >= HttpStatus.INTERNAL_SERVER_ERROR ? 'error' : 'warn' if (this.logger[level]) { this.logger[level](exception.message, { status: exception.getStatus(), context: exception.context, - stacktrace: exception.stack, + stack: exception.stack, origin: exception.origin }) } diff --git a/apps/vault/src/shared/filter/provider-http-exception.filter.ts b/apps/vault/src/shared/filter/provider-http-exception.filter.ts new file mode 100644 index 000000000..d71c3cbf1 --- /dev/null +++ b/apps/vault/src/shared/filter/provider-http-exception.filter.ts @@ -0,0 +1,62 @@ +import { ConfigService } from '@narval/config-module' +import { LoggerService } from '@narval/nestjs-shared' +import { ArgumentsHost, Catch, ExceptionFilter, HttpStatus, LogLevel } from '@nestjs/common' +import { Response } from 'express' +import { ProviderHttpException } from '../../broker/core/exception/provider-http.exception' +import { Config, Env } from '../../main.config' +import { HttpException } from '../type/http-exception.type' + +@Catch(ProviderHttpException) +export class ProviderHttpExceptionFilter implements ExceptionFilter { + constructor( + private configService: ConfigService, + private logger: LoggerService + ) {} + + catch(exception: ProviderHttpException, host: ArgumentsHost) { + const ctx = host.switchToHttp() + const response = ctx.getResponse() + const isProduction = this.configService.get('env') === Env.PRODUCTION + const status = exception.response.status + + this.log(exception) + + const body: HttpException = isProduction + ? { + statusCode: status, + message: exception.message, + context: this.buildContext(exception) + } + : { + statusCode: status, + message: exception.message, + context: this.buildContext(exception), + stack: exception.stack, + ...(exception.origin && { origin: exception.origin }) + } + + response.status(status).json(body) + } + + private buildContext(exception: ProviderHttpException) { + return { + provider: exception.provider, + error: exception.response.body + } + } + + private log(exception: ProviderHttpException) { + const level: LogLevel = exception.response.status >= HttpStatus.INTERNAL_SERVER_ERROR ? 'error' : 'warn' + + if (this.logger[level]) { + this.logger[level]('Provider HTTP exception', { + context: exception.context, + errorMessage: exception.message, + origin: exception.origin, + provider: exception.provider, + response: exception.response, + stack: exception.stack + }) + } + } +} diff --git a/apps/vault/src/shared/filter/zod-exception.filter.ts b/apps/vault/src/shared/filter/zod-exception.filter.ts index 15d85a826..d4ac76e19 100644 --- a/apps/vault/src/shared/filter/zod-exception.filter.ts +++ b/apps/vault/src/shared/filter/zod-exception.filter.ts @@ -5,6 +5,7 @@ import { Response } from 'express' import { ZodValidationException } from 'nestjs-zod' import { ZodError } from 'zod' import { Config, Env } from '../../main.config' +import { HttpException } from '../type/http-exception.type' // Catch both types, because the zodToDto function will throw a wrapped // ZodValidationError that otherwise isn't picked up here. @@ -23,24 +24,23 @@ export class ZodExceptionFilter implements ExceptionFilter { const zodError = exception instanceof ZodValidationException ? exception.getZodError() : exception - // Log as error level because Zod issues should be handled by the caller. - this.logger.error('Uncaught ZodError', { + this.logger.error("Uncaught ZodError | IF YOU'RE READING THIS, HANDLE THE ERROR IN THE CALLER", { exception: zodError }) - response.status(status).json( - isProduction - ? { - statusCode: status, - message: 'Internal validation error', - context: zodError.flatten() - } - : { - statusCode: status, - message: 'Internal validation error', - context: zodError.flatten(), - stacktrace: zodError.stack - } - ) + const body: HttpException = isProduction + ? { + statusCode: status, + message: 'Validation error', + context: zodError.flatten() + } + : { + statusCode: status, + message: 'Validation error', + context: zodError.flatten(), + stack: zodError.stack + } + + response.status(status).json(body) } } diff --git a/apps/vault/src/shared/module/persistence/exception/parse.exception.ts b/apps/vault/src/shared/module/persistence/exception/parse.exception.ts new file mode 100644 index 000000000..2ff485b9f --- /dev/null +++ b/apps/vault/src/shared/module/persistence/exception/parse.exception.ts @@ -0,0 +1,11 @@ +import { PersistenceException } from './persistence.exception' + +export class ParseException extends PersistenceException { + readonly origin: Error + + constructor(origin: Error) { + super(origin.message) + + this.origin = origin + } +} diff --git a/apps/vault/src/shared/module/persistence/exception/persistence.exception.ts b/apps/vault/src/shared/module/persistence/exception/persistence.exception.ts new file mode 100644 index 000000000..b0faa3fc9 --- /dev/null +++ b/apps/vault/src/shared/module/persistence/exception/persistence.exception.ts @@ -0,0 +1 @@ +export class PersistenceException extends Error {} diff --git a/apps/vault/src/shared/module/persistence/schema/migrations/20241223121950_normalize_transfer_provider/migration.sql b/apps/vault/src/shared/module/persistence/schema/migrations/20241223121950_normalize_transfer_provider/migration.sql new file mode 100644 index 000000000..848f13c8f --- /dev/null +++ b/apps/vault/src/shared/module/persistence/schema/migrations/20241223121950_normalize_transfer_provider/migration.sql @@ -0,0 +1,41 @@ +/* + Warnings: + + - You are about to drop the column `request` on the `provider_transfer` table. All the data in the column will be lost. + - A unique constraint covering the columns `[client_id,idempotence_id]` on the table `provider_transfer` will be added. If there are existing duplicate values, this will fail. + - Added the required column `asset_id` to the `provider_transfer` table without a default value. This is not possible if the table is not empty. + - Added the required column `gross_amount` to the `provider_transfer` table without a default value. This is not possible if the table is not empty. + - Added the required column `network_fee_attribution` to the `provider_transfer` table without a default value. This is not possible if the table is not empty. + +*/ +-- DropForeignKey +ALTER TABLE "provider_known_destination_connection" DROP CONSTRAINT "provider_known_destination_connection_known_destination_id_fkey"; + +-- AlterTable +ALTER TABLE "provider_transfer" DROP COLUMN "request", +ADD COLUMN "asset_id" TEXT NOT NULL, +ADD COLUMN "customer_ref_id" TEXT, +ADD COLUMN "destination_account_id" TEXT, +ADD COLUMN "destination_address_id" TEXT, +ADD COLUMN "destination_address_raw" TEXT, +ADD COLUMN "destination_wallet_id" TEXT, +ADD COLUMN "gross_amount" TEXT NOT NULL, +ADD COLUMN "idempotence_id" TEXT, +ADD COLUMN "memo" TEXT, +ADD COLUMN "network_fee_attribution" TEXT NOT NULL, +ADD COLUMN "provider_specific" TEXT; + +-- CreateIndex +CREATE UNIQUE INDEX "provider_transfer_client_id_idempotence_id_key" ON "provider_transfer"("client_id", "idempotence_id"); + +-- AddForeignKey +ALTER TABLE "provider_known_destination_connection" ADD CONSTRAINT "provider_known_destination_connection_known_destination_id_fkey" FOREIGN KEY ("known_destination_id") REFERENCES "provider_known_destination"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "provider_transfer" ADD CONSTRAINT "provider_transfer_destination_wallet_id_fkey" FOREIGN KEY ("destination_wallet_id") REFERENCES "provider_wallet"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "provider_transfer" ADD CONSTRAINT "provider_transfer_destination_account_id_fkey" FOREIGN KEY ("destination_account_id") REFERENCES "provider_account"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "provider_transfer" ADD CONSTRAINT "provider_transfer_destination_address_id_fkey" FOREIGN KEY ("destination_address_id") REFERENCES "provider_address"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/apps/vault/src/shared/module/persistence/schema/schema.prisma b/apps/vault/src/shared/module/persistence/schema/schema.prisma index b9c844d57..ef7c7737e 100644 --- a/apps/vault/src/shared/module/persistence/schema/schema.prisma +++ b/apps/vault/src/shared/module/persistence/schema/schema.prisma @@ -106,9 +106,11 @@ model ProviderWallet { createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") - accounts ProviderAccount[] - connections ProviderWalletConnection[] - sourceTransfers ProviderTransfer[] @relation("SourceWallet") + accounts ProviderAccount[] + connections ProviderWalletConnection[] + + sourceTransfers ProviderTransfer[] @relation("SourceWallet") + destinationTransfers ProviderTransfer[] @relation("DestinationWallet") @@unique([clientId, externalId]) @@index([createdAt, clientId]) @@ -129,7 +131,8 @@ model ProviderAccount { wallet ProviderWallet @relation(fields: [walletId], references: [id]) addresses ProviderAddress[] - sourceTransfers ProviderTransfer[] @relation("SourceAccount") + sourceTransfers ProviderTransfer[] @relation("SourceAccount") + destinationTransfers ProviderTransfer[] @relation("DestinationAccount") @@unique([clientId, externalId]) @@index([createdAt, clientId]) @@ -148,7 +151,8 @@ model ProviderAddress { account ProviderAccount @relation(fields: [accountId], references: [id]) - sourceTransfers ProviderTransfer[] @relation("SourceAddress") + sourceTransfers ProviderTransfer[] @relation("SourceAddress") + destinationTransfers ProviderTransfer[] @relation("DestinationAddress") @@unique([clientId, externalId]) @@index([createdAt, clientId]) @@ -241,21 +245,36 @@ model ProviderSync { } model ProviderTransfer { - id String @id - clientId String @map("client_id") - sourceWalletId String? @map("source_wallet_id") - sourceAccountId String? @map("source_account_id") - sourceAddressId String? @map("source_address_id") - provider String - externalId String @map("external_id") - request Json - createdAt DateTime @default(now()) @map("created_at") + id String @id + assetId String @map("asset_id") + clientId String @map("client_id") + createdAt DateTime @default(now()) @map("created_at") + customerRefId String? @map("customer_ref_id") + destinationAccountId String? @map("destination_account_id") + destinationAddressId String? @map("destination_address_id") + destinationAddressRaw String? @map("destination_address_raw") + destinationWalletId String? @map("destination_wallet_id") + externalId String @map("external_id") + grossAmount String @map("gross_amount") + idempotenceId String? @map("idempotence_id") + memo String? + networkFeeAttribution String @map("network_fee_attribution") + provider String + providerSpecific String? @map("provider_specific") + sourceAccountId String? @map("source_account_id") + sourceAddressId String? @map("source_address_id") + sourceWalletId String? @map("source_wallet_id") sourceWallet ProviderWallet? @relation("SourceWallet", fields: [sourceWalletId], references: [id]) sourceAccount ProviderAccount? @relation("SourceAccount", fields: [sourceAccountId], references: [id]) sourceAddress ProviderAddress? @relation("SourceAddress", fields: [sourceAddressId], references: [id]) + destinationWallet ProviderWallet? @relation("DestinationWallet", fields: [destinationWalletId], references: [id]) + destinationAccount ProviderAccount? @relation("DestinationAccount", fields: [destinationAccountId], references: [id]) + destinationAddress ProviderAddress? @relation("DestinationAddress", fields: [destinationAddressId], references: [id]) + @@unique([clientId, externalId]) + @@unique([clientId, idempotenceId]) @@index([createdAt, clientId]) @@map("provider_transfer") } diff --git a/apps/vault/src/shared/module/persistence/service/prisma.service.ts b/apps/vault/src/shared/module/persistence/service/prisma.service.ts index a3defb6c4..9906f1423 100644 --- a/apps/vault/src/shared/module/persistence/service/prisma.service.ts +++ b/apps/vault/src/shared/module/persistence/service/prisma.service.ts @@ -8,6 +8,7 @@ import { bytesToHex } from '@noble/hashes/utils' import { Prisma, PrismaClient } from '@prisma/client/vault' import { canonicalize } from 'packages/signature/src/lib/json.util' import { Config } from '../../../../main.config' +import { ParseException } from '../exception/parse.exception' const ENCRYPTION_PREFIX = 'enc.v1.' // Version prefix helps with future encryption changes const INTEGRITY_PREFIX = 'hmac.v1.' // Version prefix helps with future integrity changes @@ -261,6 +262,52 @@ export class PrismaService extends PrismaClient implements OnModuleInit, OnModul } } + static toPrismaJson(value?: T | null): Prisma.InputJsonValue | Prisma.NullTypes.JsonNull { + if (value === null || value === undefined) { + return Prisma.JsonNull + } + + // Handle basic JSON-serializable types. + if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean' || Array.isArray(value)) { + return value as Prisma.InputJsonValue + } + + // For objects, ensure they're JSON-serializable. + if (typeof value === 'object') { + try { + return JSON.parse(JSON.stringify(value)) as Prisma.InputJsonValue + } catch (error) { + throw new ParseException(error) + } + } + + return Prisma.JsonNull + } + + static toStringJson(value?: T | null): string | null { + if (value) { + try { + return JSON.stringify(value) + } catch (error) { + throw new ParseException(error) + } + } + + return null + } + + static toJson(value?: string | null) { + if (value) { + try { + return JSON.parse(value) + } catch (error) { + throw new ParseException(error) + } + } + + return null + } + async onModuleInit() { this.logger.log('Connecting to Prisma on database module initialization') diff --git a/apps/vault/src/shared/type/http-exception.type.ts b/apps/vault/src/shared/type/http-exception.type.ts new file mode 100644 index 000000000..87163de6a --- /dev/null +++ b/apps/vault/src/shared/type/http-exception.type.ts @@ -0,0 +1,11 @@ +import { HttpStatus } from '@nestjs/common' +import { z } from 'zod' + +export const HttpException = z.object({ + statusCode: z.nativeEnum(HttpStatus), + message: z.string(), + context: z.unknown().optional(), + stack: z.string().optional().describe('In development mode, contains the exception stack trace'), + origin: z.instanceof(Error).optional().describe('In development mode, it may contain the error origin') +}) +export type HttpException = z.infer diff --git a/apps/vault/src/transit-encryption/core/service/encryption-key.service.ts b/apps/vault/src/transit-encryption/core/service/encryption-key.service.ts index a35b4d48d..0070a68f0 100644 --- a/apps/vault/src/transit-encryption/core/service/encryption-key.service.ts +++ b/apps/vault/src/transit-encryption/core/service/encryption-key.service.ts @@ -1,27 +1,46 @@ +import { ConfigService } from '@narval/config-module' +import { LoggerService } from '@narval/nestjs-shared' import { Alg, DEFAULT_RSA_MODULUS_LENGTH, RsaPrivateKey, + SMALLEST_RSA_MODULUS_LENGTH, generateJwk, rsaDecrypt, rsaPrivateKeyToPublicKey } from '@narval/signature' import { Injectable } from '@nestjs/common' import { decodeProtectedHeader } from 'jose' +import { Config, Env } from '../../../main.config' import { EncryptionKeyRepository } from '../../persistence/encryption-key.repository' import { InvalidJweHeaderException } from '../exception/invalid-jwe-header.exception' import { NotFoundException } from '../exception/not-found.exception' import { UnauthorizedException } from '../exception/unauthorized.exception' import { EncryptionKey } from '../type/encryption-key.type' +type GenerateOptions = { + modulusLength?: number +} + @Injectable() export class EncryptionKeyService { - constructor(private readonly encryptionKeyRepository: EncryptionKeyRepository) {} + constructor( + private readonly encryptionKeyRepository: EncryptionKeyRepository, + private readonly configService: ConfigService, + private readonly logger: LoggerService + ) {} - async generate(clientId: string, opts?: { modulusLength?: number }): Promise { - const modulusLength = opts?.modulusLength || DEFAULT_RSA_MODULUS_LENGTH + async generate(clientId: string, opts?: GenerateOptions): Promise { + const modulusLength = this.getRsaModulusLength(opts) const privateKey = await generateJwk(Alg.RS256, { use: 'enc', modulusLength }) const publicKey = rsaPrivateKeyToPublicKey(privateKey) + + this.logger.log('Generate RSA encryption key', { + clientId, + modulusLength, + keyId: publicKey.kid + }) + const encryptionKey = { clientId, privateKey, @@ -32,6 +51,20 @@ export class EncryptionKeyService { return this.encryptionKeyRepository.create(encryptionKey) } + private getRsaModulusLength(opts?: GenerateOptions): number { + if (opts?.modulusLength) { + return opts.modulusLength + } + + // Prevents flaky tests due to the high time it takes to generate an RSA + // key 4096. + if (this.configService.get('env') !== Env.PRODUCTION) { + return SMALLEST_RSA_MODULUS_LENGTH + } + + return DEFAULT_RSA_MODULUS_LENGTH + } + async decrypt(clientId: string, encryptedData: string): Promise { const header = decodeProtectedHeader(encryptedData) const kid = header.kid diff --git a/apps/vault/src/vault/__test__/e2e/sign.spec.ts b/apps/vault/src/vault/__test__/e2e/sign.spec.ts index cd3af8065..537cc8c62 100644 --- a/apps/vault/src/vault/__test__/e2e/sign.spec.ts +++ b/apps/vault/src/vault/__test__/e2e/sign.spec.ts @@ -229,13 +229,11 @@ describe('Sign', () => { .set('authorization', `GNAP ${accessToken}`) .send(payload) - expect(body).toEqual( - expect.objectContaining({ - context: expect.any(Object), - message: 'Internal validation error', - statusCode: HttpStatus.UNPROCESSABLE_ENTITY - }) - ) + expect(body).toMatchObject({ + context: expect.any(Object), + message: 'Validation error', + statusCode: HttpStatus.UNPROCESSABLE_ENTITY + }) expect(status).toEqual(HttpStatus.UNPROCESSABLE_ENTITY) }) From c674b40173ea8b395ffd28a3caafb2f3fa60ab66 Mon Sep 17 00:00:00 2001 From: Pierre Troger Date: Mon, 23 Dec 2024 16:02:32 +0100 Subject: [PATCH 056/120] naming convention over mock response files --- .../get-trusted-destinations-200-second.json | 35 +++++++++++++++ .../get-trusted-destinations-200-third.json | 16 +++++++ .../get-trusted-destinations-200.json | 44 +++++++++++++++++++ .../response/get-vaults-200-second.json | 34 ++++++++++++++ 4 files changed, 129 insertions(+) create mode 100644 apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200-second.json create mode 100644 apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200-third.json create mode 100644 apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200.json create mode 100644 apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-vaults-200-second.json diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200-second.json b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200-second.json new file mode 100644 index 000000000..cd627749f --- /dev/null +++ b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200-second.json @@ -0,0 +1,35 @@ +{ + "data": [ + { + "id": "toBeConnected", + "type": "crypto", + "crypto": { + "address": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", + "networkId": "ETH", + "assetType": "ETH" + } + }, + { + "id": "neverChanges", + "type": "crypto", + "crypto": { + "address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh", + "networkId": "BTC", + "assetType": "BTC" + } + }, + { + "id": "toBeUpdated", + "type": "crypto", + "crypto": { + "address": "0x8Bc2B8F33e5AeF847B8973Fa669B948A3028D6bd", + "networkId": "ETH", + "assetType": "USDC", + "memo": "new memo" + } + } + ], + "page": { + "next": null + } +} diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200-third.json b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200-third.json new file mode 100644 index 000000000..5985e2f1b --- /dev/null +++ b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200-third.json @@ -0,0 +1,16 @@ +{ + "data": [ + { + "id": "toBeConnected", + "type": "crypto", + "crypto": { + "address": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", + "networkId": "ETH", + "assetType": "ETH" + } + } + ], + "page": { + "next": null + } +} diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200.json b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200.json new file mode 100644 index 000000000..51dc594bd --- /dev/null +++ b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200.json @@ -0,0 +1,44 @@ +{ + "data": [ + { + "id": "toBeConnected", + "type": "crypto", + "crypto": { + "address": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", + "networkId": "ETH", + "assetType": "ETH" + } + }, + { + "id": "neverChanges", + "type": "crypto", + "crypto": { + "address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh", + "networkId": "BTC", + "assetType": "BTC" + } + }, + { + "id": "toBeUpdated", + "type": "crypto", + "crypto": { + "address": "0x8Bc2B8F33e5AeF847B8973Fa669B948A3028D6bd", + "networkId": "ETH", + "assetType": "USDC" + } + }, + { + "id": "toBeDeleted", + "type": "crypto", + "crypto": { + "address": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", + "networkId": "XRP", + "assetType": "XRP", + "memo": "123456" + } + } + ], + "page": { + "next": null + } +} diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-vaults-200-second.json b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-vaults-200-second.json new file mode 100644 index 000000000..c805f30c6 --- /dev/null +++ b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-vaults-200-second.json @@ -0,0 +1,34 @@ +{ + "data": [ + { + "accountName": "Narval Account 1", + "assets": [ + { + "assetType": "BTC_S", + "availableBalance": { + "assetType": "BTC_S", + "currentPrice": "100571.636951942", + "currentUSDValue": "502.86", + "quantity": "0.005" + }, + "totalBalance": { + "assetType": "BTC_S", + "currentPrice": "100571.636951942", + "currentUSDValue": "502.86", + "quantity": "0.005" + }, + "vaultId": "084ff57c0984420efac31723579c94fc", + "vaultName": "Vault 1 - renamed", + "walletId": "6a46a1977959e0529f567e8e927e3895" + } + ], + "description": "", + "name": "Vault 1 - renamed", + "type": "VAULT", + "vaultId": "084ff57c0984420efac31723579c94fc" + } + ], + "page": { + "next": null + } +} From f12ec3a189ba02e3b9f2441b0b19c13f9cf562b7 Mon Sep 17 00:00:00 2001 From: Pierre Troger Date: Mon, 23 Dec 2024 16:03:08 +0100 Subject: [PATCH 057/120] Revert "naming convention over mock response files" This reverts commit c674b40173ea8b395ffd28a3caafb2f3fa60ab66. --- .../get-trusted-destinations-200-second.json | 35 --------------- .../get-trusted-destinations-200-third.json | 16 ------- .../get-trusted-destinations-200.json | 44 ------------------- .../response/get-vaults-200-second.json | 34 -------------- 4 files changed, 129 deletions(-) delete mode 100644 apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200-second.json delete mode 100644 apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200-third.json delete mode 100644 apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200.json delete mode 100644 apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-vaults-200-second.json diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200-second.json b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200-second.json deleted file mode 100644 index cd627749f..000000000 --- a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200-second.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "data": [ - { - "id": "toBeConnected", - "type": "crypto", - "crypto": { - "address": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", - "networkId": "ETH", - "assetType": "ETH" - } - }, - { - "id": "neverChanges", - "type": "crypto", - "crypto": { - "address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh", - "networkId": "BTC", - "assetType": "BTC" - } - }, - { - "id": "toBeUpdated", - "type": "crypto", - "crypto": { - "address": "0x8Bc2B8F33e5AeF847B8973Fa669B948A3028D6bd", - "networkId": "ETH", - "assetType": "USDC", - "memo": "new memo" - } - } - ], - "page": { - "next": null - } -} diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200-third.json b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200-third.json deleted file mode 100644 index 5985e2f1b..000000000 --- a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200-third.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "data": [ - { - "id": "toBeConnected", - "type": "crypto", - "crypto": { - "address": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", - "networkId": "ETH", - "assetType": "ETH" - } - } - ], - "page": { - "next": null - } -} diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200.json b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200.json deleted file mode 100644 index 51dc594bd..000000000 --- a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "data": [ - { - "id": "toBeConnected", - "type": "crypto", - "crypto": { - "address": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", - "networkId": "ETH", - "assetType": "ETH" - } - }, - { - "id": "neverChanges", - "type": "crypto", - "crypto": { - "address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh", - "networkId": "BTC", - "assetType": "BTC" - } - }, - { - "id": "toBeUpdated", - "type": "crypto", - "crypto": { - "address": "0x8Bc2B8F33e5AeF847B8973Fa669B948A3028D6bd", - "networkId": "ETH", - "assetType": "USDC" - } - }, - { - "id": "toBeDeleted", - "type": "crypto", - "crypto": { - "address": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", - "networkId": "XRP", - "assetType": "XRP", - "memo": "123456" - } - } - ], - "page": { - "next": null - } -} diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-vaults-200-second.json b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-vaults-200-second.json deleted file mode 100644 index c805f30c6..000000000 --- a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-vaults-200-second.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "data": [ - { - "accountName": "Narval Account 1", - "assets": [ - { - "assetType": "BTC_S", - "availableBalance": { - "assetType": "BTC_S", - "currentPrice": "100571.636951942", - "currentUSDValue": "502.86", - "quantity": "0.005" - }, - "totalBalance": { - "assetType": "BTC_S", - "currentPrice": "100571.636951942", - "currentUSDValue": "502.86", - "quantity": "0.005" - }, - "vaultId": "084ff57c0984420efac31723579c94fc", - "vaultName": "Vault 1 - renamed", - "walletId": "6a46a1977959e0529f567e8e927e3895" - } - ], - "description": "", - "name": "Vault 1 - renamed", - "type": "VAULT", - "vaultId": "084ff57c0984420efac31723579c94fc" - } - ], - "page": { - "next": null - } -} From 627301502e682a9aa2fb275f571801b4430d8a24 Mon Sep 17 00:00:00 2001 From: Ptroger <44851272+Ptroger@users.noreply.github.com> Date: Mon, 23 Dec 2024 16:15:11 +0100 Subject: [PATCH 058/120] New connection finding an existing wallet creates join row (#51) * a new connection finding an existing wallet creates a join row conn<>wallet * expect created field from anchorageSyncService return * removing trailing space * join tables createdAt comes from wallet/knownAddress updatedAt * remove validation from repositories * naming convention over mock response files --- .../src/broker/__test__/util/mock-data.ts | 1 + .../core/exception/proxy-request.exception.ts | 10 +- .../anchorage-sync.service.spec.ts | 59 +++++++++-- .../integration/mocks/anchorage/handlers.ts | 24 +++-- ... get-trusted-destinations-200-second.json} | 0 ...> get-trusted-destinations-200-third.json} | 0 ...json => get-trusted-destinations-200.json} | 0 .../response/get-vaults-200-second.json | 34 +++++++ .../core/service/anchorage-sync.service.ts | 99 +++++++++++-------- .../core/service/know-destination.service.ts | 8 +- .../src/broker/core/service/wallet.service.ts | 10 +- .../core/type/indexed-resources.type.ts | 9 ++ .../known-destination.repository.ts | 93 ++++------------- .../repository/wallet.repository.ts | 42 +++++++- 14 files changed, 246 insertions(+), 143 deletions(-) rename apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/{trusted-destinations-2.json => get-trusted-destinations-200-second.json} (100%) rename apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/{trusted-destinations-3.json => get-trusted-destinations-200-third.json} (100%) rename apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/{trusted-destinations-1.json => get-trusted-destinations-200.json} (100%) create mode 100644 apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-vaults-200-second.json diff --git a/apps/vault/src/broker/__test__/util/mock-data.ts b/apps/vault/src/broker/__test__/util/mock-data.ts index beed2b76b..3357b6142 100644 --- a/apps/vault/src/broker/__test__/util/mock-data.ts +++ b/apps/vault/src/broker/__test__/util/mock-data.ts @@ -19,6 +19,7 @@ const privateKey = { d: 'nq2eDJPp9NAqCdTT_dNerIJFJxegTKmFgDAsFkhbJIA' } +// eslint-disable-next-line @typescript-eslint/no-unused-vars const { d: _d, ...publicKey } = privateKey export const TEST_CLIENT_ID = 'test-client-id' diff --git a/apps/vault/src/broker/core/exception/proxy-request.exception.ts b/apps/vault/src/broker/core/exception/proxy-request.exception.ts index bef47c9c1..a296bd160 100644 --- a/apps/vault/src/broker/core/exception/proxy-request.exception.ts +++ b/apps/vault/src/broker/core/exception/proxy-request.exception.ts @@ -1,9 +1,9 @@ import { BrokerException } from './broker.exception' export class ProxyRequestException extends BrokerException { - public data: any + public data: unknown public code: number - public headers: Record + public headers: Record constructor({ data, @@ -12,11 +12,11 @@ export class ProxyRequestException extends BrokerException { headers, context }: { - data: any + data: unknown status: number message: string - headers: Record - context: Record + headers: Record + context: Record }) { super({ message: message ? message : 'Provider request failed', diff --git a/apps/vault/src/broker/core/service/__test__/integration/anchorage-sync.service.spec.ts b/apps/vault/src/broker/core/service/__test__/integration/anchorage-sync.service.spec.ts index 1dcb3152b..625b826b8 100644 --- a/apps/vault/src/broker/core/service/__test__/integration/anchorage-sync.service.spec.ts +++ b/apps/vault/src/broker/core/service/__test__/integration/anchorage-sync.service.spec.ts @@ -23,7 +23,7 @@ import { AnchorageSyncService } from '../../anchorage-sync.service' import { ConnectionService } from '../../connection.service' import { KnownDestinationService } from '../../know-destination.service' import { WalletService } from '../../wallet.service' -import { trustedDestinationsHandlers } from './mocks/anchorage/handlers' +import { trustedDestinationsHandlers, vaultHandlers } from './mocks/anchorage/handlers' import { ANCHORAGE_TEST_API_BASE_URL, setupMockServer } from './mocks/anchorage/server' describe(AnchorageSyncService.name, () => { @@ -104,10 +104,10 @@ describe(AnchorageSyncService.name, () => { describe('syncWallets', () => { it('fetches anchorage vaults and persist them as wallets', async () => { - const syncedWallets = await anchorageSyncService.syncWallets(connection) + const { created } = await anchorageSyncService.syncWallets(connection) const { data: wallets } = await walletService.findAll(connection.clientId) - expect(syncedWallets).toEqual(expect.arrayContaining(wallets)) + expect(created).toEqual(expect.arrayContaining(wallets)) }) it('does not duplicate wallets', async () => { @@ -116,8 +116,47 @@ describe(AnchorageSyncService.name, () => { await anchorageSyncService.syncWallets(connection) ]) - expect(first.length).toEqual(2) - expect(second.length).toEqual(0) + expect(first.created.length).toEqual(2) + expect(second.created.length).toEqual(0) + }) + + it('connects wallet with the new connection', async () => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { credentials: firstCredentials, ...firstConnection } = connection + const secondConnectionWithCredentials = await connectionService.create(clientId, { + connectionId: uuid(), + provider: Provider.ANCHORAGE, + url: ANCHORAGE_TEST_API_BASE_URL, + credentials: { + apiKey: 'test-api-key', + privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) + } + }) + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { credentials: secondCredentials, ...secondConnection } = secondConnectionWithCredentials + + // First sync - should create all wallets + server.use(vaultHandlers(ANCHORAGE_TEST_API_BASE_URL).findAll) + await anchorageSyncService.syncWallets(connection) + + // Second sync with new connection that only finds one wallet and its label is changed + server.use(vaultHandlers(ANCHORAGE_TEST_API_BASE_URL).update) + const { updated } = await anchorageSyncService.syncWallets(secondConnectionWithCredentials) + + expect(updated).toHaveLength(1) + expect(updated[0]).toMatchObject({ + externalId: '084ff57c0984420efac31723579c94fc', + label: 'Vault 1 - renamed', + connections: [firstConnection, secondConnection] + }) + + // Verify other destinations weren't affected + const { data: allDestinations } = await walletService.findAll(connection.clientId) + const unchangedDestinations = allDestinations.filter((d) => d.externalId !== '084ff57c0984420efac31723579c94fc') + unchangedDestinations.forEach((dest) => { + expect(dest.connections).toEqual([firstConnection]) + }) }) }) @@ -186,6 +225,7 @@ describe(AnchorageSyncService.name, () => { }) it('updates anchorage knownDestination when it already exists', async () => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars const { credentials, ...expectedConnection } = connection // First sync - create initial destinations @@ -223,7 +263,8 @@ describe(AnchorageSyncService.name, () => { }) it('connects known-destination with the new connection', async () => { - const { credentials: firstCredentials, ...firstConnection } = connection + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { credentials, ...firstConnection } = connection const secondConnectionWithCredentials = await connectionService.create(clientId, { connectionId: uuid(), provider: Provider.ANCHORAGE, @@ -233,7 +274,7 @@ describe(AnchorageSyncService.name, () => { privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) } }) - + // eslint-disable-next-line @typescript-eslint/no-unused-vars const { credentials: secondCredentials, ...secondConnection } = secondConnectionWithCredentials // First sync - should create all destinations @@ -248,14 +289,14 @@ describe(AnchorageSyncService.name, () => { expect(updated).toHaveLength(1) expect(updated[0]).toMatchObject({ externalId: 'toBeConnected', - connections: expect.arrayContaining([firstConnection, secondConnection]) + connections: [firstConnection, secondConnection] }) // Verify other destinations weren't affected const { data: allDestinations } = await knownDestinationService.findAll(connection.clientId) const unchangedDestinations = allDestinations.filter((d) => d.externalId !== 'toBeConnected') unchangedDestinations.forEach((dest) => { - expect(dest.connections).toEqual(expect.arrayContaining([firstConnection])) + expect(dest.connections).toEqual([firstConnection]) }) }) }) diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/handlers.ts b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/handlers.ts index 4a68a2366..b403be023 100644 --- a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/handlers.ts +++ b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/handlers.ts @@ -1,12 +1,13 @@ import { HttpResponse, http } from 'msw' import getTransferOk from './response/get-transfer-200.json' +import trustedDestinationsSecond from './response/get-trusted-destinations-200-second.json' +import trustedDestinationsThird from './response/get-trusted-destinations-200-third.json' +import trustedDestinationsFirst from './response/get-trusted-destinations-200.json' +import getVaultsOkSecond from './response/get-vaults-200-second.json' import getVaultsOk from './response/get-vaults-200.json' import getVaultAddressesOk from './response/get-vaults-addresses-200.json' import getWalletsOk from './response/get-wallets-200.json' import postTransferCreated from './response/post-transfer-201.json' -import trustedDestinationsFirst from './response/trusted-destinations-1.json' -import trustedDestinationsSecond from './response/trusted-destinations-2.json' -import trustedDestinationsThird from './response/trusted-destinations-3.json' export const trustedDestinationsHandlers = (baseUrl: string) => { return { @@ -24,15 +25,22 @@ export const trustedDestinationsHandlers = (baseUrl: string) => { } } +export const vaultHandlers = (baseUrl: string) => { + return { + findAll: http.get(`${baseUrl}/v2/vaults`, () => { + return new HttpResponse(JSON.stringify(getVaultsOk)) + }), + update: http.get(`${baseUrl}/v2/vaults`, () => { + return new HttpResponse(JSON.stringify(getVaultsOkSecond)) + }) + } +} + export const getHandlers = (baseUrl: string) => [ http.get(`${baseUrl}/v2/vaults/:vaultId/addresses`, () => { return new HttpResponse(JSON.stringify(getVaultAddressesOk)) }), - http.get(`${baseUrl}/v2/vaults`, () => { - return new HttpResponse(JSON.stringify(getVaultsOk)) - }), - http.get(`${baseUrl}/v2/wallets`, () => { return new HttpResponse(JSON.stringify(getWalletsOk)) }), @@ -45,5 +53,7 @@ export const getHandlers = (baseUrl: string) => [ return new HttpResponse(JSON.stringify(postTransferCreated)) }), + vaultHandlers(baseUrl).findAll, + trustedDestinationsHandlers(baseUrl).findAll ] diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/trusted-destinations-2.json b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200-second.json similarity index 100% rename from apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/trusted-destinations-2.json rename to apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200-second.json diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/trusted-destinations-3.json b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200-third.json similarity index 100% rename from apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/trusted-destinations-3.json rename to apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200-third.json diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/trusted-destinations-1.json b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200.json similarity index 100% rename from apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/trusted-destinations-1.json rename to apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200.json diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-vaults-200-second.json b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-vaults-200-second.json new file mode 100644 index 000000000..c805f30c6 --- /dev/null +++ b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-vaults-200-second.json @@ -0,0 +1,34 @@ +{ + "data": [ + { + "accountName": "Narval Account 1", + "assets": [ + { + "assetType": "BTC_S", + "availableBalance": { + "assetType": "BTC_S", + "currentPrice": "100571.636951942", + "currentUSDValue": "502.86", + "quantity": "0.005" + }, + "totalBalance": { + "assetType": "BTC_S", + "currentPrice": "100571.636951942", + "currentUSDValue": "502.86", + "quantity": "0.005" + }, + "vaultId": "084ff57c0984420efac31723579c94fc", + "vaultName": "Vault 1 - renamed", + "walletId": "6a46a1977959e0529f567e8e927e3895" + } + ], + "description": "", + "name": "Vault 1 - renamed", + "type": "VAULT", + "vaultId": "084ff57c0984420efac31723579c94fc" + } + ], + "page": { + "next": null + } +} diff --git a/apps/vault/src/broker/core/service/anchorage-sync.service.ts b/apps/vault/src/broker/core/service/anchorage-sync.service.ts index c3965161b..5526458e3 100644 --- a/apps/vault/src/broker/core/service/anchorage-sync.service.ts +++ b/apps/vault/src/broker/core/service/anchorage-sync.service.ts @@ -52,37 +52,58 @@ export class AnchorageSyncService { } }) - const existingWalletByExternalId = new Map(existingWallets.map((wallet) => [wallet.externalId, wallet])) + const now = new Date() - const missingAnchorageVaults = anchorageVaults.filter( - (anchorageVault) => !existingWalletByExternalId.has(anchorageVault.vaultId) - ) + const existingMap = new Map(existingWallets.map((wallet) => [wallet.externalId, wallet])) - const now = new Date() + const toBeUpdated = anchorageVaults.reduce((acc, incoming) => { + const existing = existingMap.get(incoming.vaultId) + if (!existing) return acc - const wallets: Wallet[] = missingAnchorageVaults.map((vault) => ({ - accounts: [], - clientId: connection.clientId, - connections: [ActiveConnection.parse(connection)], - createdAt: now, - externalId: vault.vaultId, - label: vault.name, - provider: Provider.ANCHORAGE, - updatedAt: now, - walletId: uuid() - })) + const hasConnection = existing.connections.some((conn) => conn.connectionId === connection.connectionId) + const hasDataChanges = existing.label !== incoming.name + + if (hasDataChanges || !hasConnection) { + acc.push({ + ...existing, + label: incoming.name, + updatedAt: now, + connections: [...existing.connections, connection] + }) + } + + return acc + }, []) + + const toBeCreated: Wallet[] = anchorageVaults + .filter((vault) => !existingMap.has(vault.vaultId)) + .map((vault) => ({ + accounts: [], + clientId: connection.clientId, + connections: [ActiveConnection.parse(connection)], + createdAt: now, + externalId: vault.vaultId, + label: vault.name, + provider: Provider.ANCHORAGE, + updatedAt: now, + walletId: uuid() + })) try { - await this.walletService.bulkCreate(wallets) + const created = await this.walletService.bulkCreate(toBeCreated) + const updated = await this.walletService.bulkUpdate(toBeUpdated) + + return { + created, + updated + } } catch (error) { throw new SyncException({ - message: 'Fail to persist wallets', + message: 'Failed to persist wallets', suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, origin: error }) } - - return wallets } async syncAccounts(connection: ActiveConnectionWithCredentials) { @@ -289,33 +310,27 @@ export class AnchorageSyncService { const incomingMap = new Map(anchorageTrustedDestinations.map((dest) => [dest.id, dest])) const existingMap = new Map(existingKnownDestinations.map((dest) => [dest.externalId, dest])) - const toBeUpdated = anchorageTrustedDestinations - .filter((incoming) => { - // First check if we have an existing destination - const existing = existingMap.get(incoming.id) - if (!existing) return false - - // Check if the connection is already tied to this destination - const hasConnection = existing.connections.some((conn) => conn.connectionId === connection.connectionId) + const toBeUpdated = anchorageTrustedDestinations.reduce((acc, incoming) => { + const existing = existingMap.get(incoming.id) + if (!existing) return acc - // Check if any data has changed - const hasDataChanges = - (existing.label || undefined) !== incoming.crypto.memo || - (existing.assetId || undefined) !== incoming.crypto.assetType + const hasConnection = existing.connections.some((conn) => conn.connectionId === connection.connectionId) + const hasDataChanges = + (existing.label || undefined) !== incoming.crypto.memo || + (existing.assetId || undefined) !== incoming.crypto.assetType - // Only include if there are data changes or it needs the new connection - return hasDataChanges || !hasConnection - }) - .map((incoming) => { - const lookup = existingMap.get(incoming.id)! - return { - ...lookup, + if (hasDataChanges || !hasConnection) { + acc.push({ + ...existing, label: incoming.crypto.memo, assetId: incoming.crypto.assetType, updatedAt: now, - connections: [...lookup.connections, connection] - } - }) + connections: [...existing.connections, connection] + }) + } + + return acc + }, []) const toBeCreated: KnownDestination[] = anchorageTrustedDestinations .filter((anchorageDest) => !existingMap.has(anchorageDest.id)) diff --git a/apps/vault/src/broker/core/service/know-destination.service.ts b/apps/vault/src/broker/core/service/know-destination.service.ts index db1bdf7dd..251fb2d17 100644 --- a/apps/vault/src/broker/core/service/know-destination.service.ts +++ b/apps/vault/src/broker/core/service/know-destination.service.ts @@ -31,12 +31,10 @@ export class KnownDestinationService { } async bulkUpdate(knownDestinations: KnownDestination[]): Promise { - return Promise.all( - knownDestinations.map((knownDestination) => this.update(knownDestination.knownDestinationId, knownDestination)) - ) + return Promise.all(knownDestinations.map((knownDestination) => this.update(knownDestination))) } - async update(knownDestinationId: string, data: UpdateKnownDestination): Promise { - return this.knownDestinationRepository.update(knownDestinationId, data) + async update(knownDestination: UpdateKnownDestination): Promise { + return this.knownDestinationRepository.update(knownDestination) } async findAll(clientId: string, opts?: FindAllOptions): Promise> { diff --git a/apps/vault/src/broker/core/service/wallet.service.ts b/apps/vault/src/broker/core/service/wallet.service.ts index a8846412c..6e46dca9d 100644 --- a/apps/vault/src/broker/core/service/wallet.service.ts +++ b/apps/vault/src/broker/core/service/wallet.service.ts @@ -1,7 +1,7 @@ import { PaginatedResult, PaginationOptions } from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' import { FindAllOptions, WalletRepository } from '../../persistence/repository/wallet.repository' -import { Wallet } from '../type/indexed-resources.type' +import { UpdateWallet, Wallet } from '../type/indexed-resources.type' @Injectable() export class WalletService { @@ -19,6 +19,14 @@ export class WalletService { return this.walletRepository.bulkCreate(wallets) } + async bulkUpdate(wallets: Wallet[]): Promise { + return Promise.all(wallets.map((wallet) => this.update(wallet))) + } + + async update(wallet: UpdateWallet): Promise { + return this.walletRepository.update(wallet) + } + async findAll(clientId: string, options?: FindAllOptions): Promise> { return this.walletRepository.findAll(clientId, options) } diff --git a/apps/vault/src/broker/core/type/indexed-resources.type.ts b/apps/vault/src/broker/core/type/indexed-resources.type.ts index 16f46e580..a0fda7f1b 100644 --- a/apps/vault/src/broker/core/type/indexed-resources.type.ts +++ b/apps/vault/src/broker/core/type/indexed-resources.type.ts @@ -56,6 +56,15 @@ export const Wallet = z.object({ }) export type Wallet = z.infer +export const UpdateWallet = Wallet.pick({ + walletId: true, + clientId: true, + label: true, + connections: true, + updatedAt: true +}) +export type UpdateWallet = z.infer + export const PublicWallet = Wallet.extend({ connections: z.array(PublicConnection) }) diff --git a/apps/vault/src/broker/persistence/repository/known-destination.repository.ts b/apps/vault/src/broker/persistence/repository/known-destination.repository.ts index 6d3afa20e..e7aceeba1 100644 --- a/apps/vault/src/broker/persistence/repository/known-destination.repository.ts +++ b/apps/vault/src/broker/persistence/repository/known-destination.repository.ts @@ -22,10 +22,13 @@ type ProviderKnownDestinationAndRelations = ProviderKnownDestination & { export type FindAllOptions = FindAllFilters & { pagination?: PaginationOptions } const UpdateKnownDestination = KnownDestination.pick({ + knownDestinationId: true, label: true, connections: true, externalClassification: true, - assetId: true + updatedAt: true, + assetId: true, + clientId: true }) export type UpdateKnownDestination = z.infer @@ -212,87 +215,31 @@ export class KnownDestinationRepository { return count } - async connect(clientId: string, knownDestinationId: string, connectionId: string) { - const alreadyConnected = await this.prismaService.providerKnownDestinationConnection.findFirst({ - where: { - clientId, - knownDestinationId, - connectionId - } - }) - - if (alreadyConnected) { - return - } - - const connectionExists = await this.prismaService.providerConnection.findUnique({ - where: { clientId, id: connectionId } - }) - - if (!connectionExists) { - throw new NotFoundException({ - message: 'Connection not found', - context: { clientId, connectionId } - }) - } - - const knownDestinationExists = await this.prismaService.providerKnownDestination.findUnique({ - where: { clientId, id: knownDestinationId } - }) + async update(knownDestination: UpdateKnownDestination) { + const { clientId, connections, updatedAt, knownDestinationId, ...data } = knownDestination - if (!knownDestinationExists) { - throw new NotFoundException({ - message: 'Known destination not found', - context: { clientId, knownDestinationId } - }) - } - - await this.prismaService.providerKnownDestinationConnection.create({ - data: { - clientId, + const connectionPayload = connections.map((connection) => { + return { + clientId: clientId, knownDestinationId, - connectionId + connectionId: connection.connectionId, + createdAt: updatedAt } }) - } - async update(knownDestinationId: string, data: UpdateKnownDestination) { - const existingDest = await this.prismaService.providerKnownDestination.findUnique({ - where: { id: knownDestinationId }, - include: { - connections: { - include: { - connection: { - select: connectionSelectWithoutCredentials - } - } - } - } + await this.prismaService.providerKnownDestinationConnection.createMany({ + data: connectionPayload, + skipDuplicates: true }) - if (!existingDest) { - throw new NotFoundException({ - message: 'Destination not found', - context: { id: knownDestinationId } - }) - } - - const existingEntity = KnownDestinationRepository.parseModel(existingDest) - - await Promise.all( - data.connections - .filter((connection) => !existingEntity.connections.find((c) => c.connectionId === connection.connectionId)) - .map(async (connection) => { - await this.connect(existingEntity.clientId, knownDestinationId, connection.connectionId) - }) - ) - const updatedKnownDest = await this.prismaService.providerKnownDestination.update({ where: { id: knownDestinationId }, - data: KnownDestinationRepository.parseEntity({ - ...existingEntity, - ...data - }), + data: { + label: data.label, + externalClassification: data.externalClassification, + assetId: data.assetId, + updatedAt + }, include: { connections: { include: { diff --git a/apps/vault/src/broker/persistence/repository/wallet.repository.ts b/apps/vault/src/broker/persistence/repository/wallet.repository.ts index 145699fb9..925707274 100644 --- a/apps/vault/src/broker/persistence/repository/wallet.repository.ts +++ b/apps/vault/src/broker/persistence/repository/wallet.repository.ts @@ -9,7 +9,7 @@ import { } from '@prisma/client/vault' import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' import { NotFoundException } from '../../core/exception/not-found.exception' -import { Account, Wallet } from '../../core/type/indexed-resources.type' +import { Account, UpdateWallet, Wallet } from '../../core/type/indexed-resources.type' import { AccountRepository } from './account.repository' import { ConnectionRepository, connectionSelectWithoutCredentials } from './connection.repository' @@ -231,6 +231,46 @@ export class WalletRepository { return wallets } + async update(wallet: UpdateWallet) { + const providerWalletConnections = wallet.connections.map((connection) => { + return { + clientId: wallet.clientId, + walletId: wallet.walletId, + connectionId: connection.connectionId, + createdAt: wallet.updatedAt + } + }) + + await this.prismaService.providerWalletConnection.createMany({ + data: providerWalletConnections, + skipDuplicates: true + }) + + const updatedWallet = await this.prismaService.providerWallet.update({ + where: { id: wallet.walletId }, + data: { + updatedAt: wallet.updatedAt, + label: wallet.label + }, + include: { + connections: { + include: { + connection: { + select: connectionSelectWithoutCredentials + } + } + }, + accounts: { + include: { + addresses: true + } + } + } + }) + + return WalletRepository.parseModel(updatedWallet) + } + private getWalletConnectionModel(wallet: Wallet): ProviderWalletConnection[] { return wallet.connections.map((connection) => { return { From cd49b8fe97fea92d496be926159ea0c8945a6806 Mon Sep 17 00:00:00 2001 From: Matt Schoch Date: Tue, 24 Dec 2024 16:18:32 +0100 Subject: [PATCH 059/120] Updating OpenAPI annotations & codegen & cleaning up Vault sdk a bit (#52) * Updating OpenAPI annotations & codegen & cleaning up Vault sdk a bit * Example adding the Create Connection function as a new endpoint exposed in SDK * Constant fix in tests --- .prettierignore | 1 + apps/armory/src/armory.constant.ts | 21 - .../src/client/__test__/e2e/client.spec.ts | 19 +- apps/armory/src/main.ts | 12 +- .../decorator/api-admin-guard.decorator.ts | 6 +- .../api-client-id-guard.decorator.ts | 5 +- .../api-client-secret-guard.decorator.ts | 5 +- .../guard/__test__/unit/admin.guard.spec.ts | 11 +- .../src/shared/guard/admin-api-key.guard.ts | 7 +- .../src/engine/__test__/e2e/client.spec.ts | 18 +- apps/policy-engine/src/main.ts | 14 +- .../src/policy-engine.constant.ts | 16 - .../shared/decorator/admin-guard.decorator.ts | 6 +- .../decorator/client-guard.decorator.ts | 7 +- .../__test__/unit/admin-api-key.guard.spec.ts | 11 +- .../src/shared/guard/admin-api-key.guard.ts | 7 +- apps/vault/src/broker/broker.module.ts | 8 +- .../rest/controller/account.controller.ts | 5 +- .../rest/controller/address.controller.ts | 3 +- .../rest/controller/connection.controller.ts | 3 +- .../http/rest/controller/proxy.controller.ts | 2 + .../http/rest/controller/sync.controller.ts | 3 +- .../rest/controller/transfer.controller.ts | 2 + .../http/rest/controller/wallet.controller.ts | 5 +- .../src/client/__test__/e2e/client.spec.ts | 19 +- apps/vault/src/main.ts | 16 +- apps/vault/src/shared/constant.ts | 5 - .../shared/decorator/admin-guard.decorator.ts | 6 +- .../decorator/permission-guard.decorator.ts | 9 +- .../__test__/unit/admin-api-key.guard.spec.ts | 11 +- .../src/shared/guard/admin-api-key.guard.ts | 7 +- .../rest/encryption-key.controller.ts | 9 +- packages/armory-sdk/Makefile | 5 +- .../src/lib/http/client/vault/api.ts | 4459 ++++++++++++----- .../src/lib/http/client/vault/base.ts | 2 +- packages/armory-sdk/src/lib/shared/gnap.ts | 10 +- packages/armory-sdk/src/lib/vault/client.ts | 117 +- packages/armory-sdk/src/lib/vault/type.ts | 153 +- packages/nestjs-shared/src/lib/constant.ts | 3 + .../api-client-id-header.decorator.ts | 15 + .../api-detached-jws-security.decorator.ts | 14 + .../decorator/api-gnap-security.decorator.ts | 17 +- .../nestjs-shared/src/lib/decorator/index.ts | 2 + .../src/lib/util/with-swagger.util.ts | 82 +- 44 files changed, 3485 insertions(+), 1673 deletions(-) create mode 100644 packages/nestjs-shared/src/lib/decorator/api-client-id-header.decorator.ts create mode 100644 packages/nestjs-shared/src/lib/decorator/api-detached-jws-security.decorator.ts diff --git a/.prettierignore b/.prettierignore index 8ef09cc98..3399450d0 100644 --- a/.prettierignore +++ b/.prettierignore @@ -6,6 +6,7 @@ dist/* .nx/cache/* deploy/charts/* /.nx/workspace-data +.next/* # Generated code packages/armory-sdk/src/http/client diff --git a/apps/armory/src/armory.constant.ts b/apps/armory/src/armory.constant.ts index 5ce9a7fbe..a5b5c47bb 100644 --- a/apps/armory/src/armory.constant.ts +++ b/apps/armory/src/armory.constant.ts @@ -1,10 +1,3 @@ -import { - REQUEST_HEADER_CLIENT_ID, - REQUEST_HEADER_CLIENT_SECRET, - adminApiKeySecurity, - clientIdSecurity, - clientSecretSecurity -} from '@narval/nestjs-shared' import { AssetId } from '@narval/policy-engine-shared' import { ClassSerializerInterceptor, ValidationPipe } from '@nestjs/common' import { APP_FILTER, APP_INTERCEPTOR, APP_PIPE } from '@nestjs/core' @@ -51,20 +44,6 @@ export const DEFAULT_HTTP_MODULE_PROVIDERS = [ ...HTTP_VALIDATION_PIPES ] -// -// Headers -// - -export const REQUEST_HEADER_API_KEY = 'x-api-key' - -// -// API Security -// - -export const ADMIN_SECURITY = adminApiKeySecurity(REQUEST_HEADER_API_KEY) -export const CLIENT_ID_SECURITY = clientIdSecurity(REQUEST_HEADER_CLIENT_ID) -export const CLIENT_SECRET_SECURITY = clientSecretSecurity(REQUEST_HEADER_CLIENT_SECRET) - // // Queues // diff --git a/apps/armory/src/client/__test__/e2e/client.spec.ts b/apps/armory/src/client/__test__/e2e/client.spec.ts index a7054a3b0..75aa1d96b 100644 --- a/apps/armory/src/client/__test__/e2e/client.spec.ts +++ b/apps/armory/src/client/__test__/e2e/client.spec.ts @@ -1,5 +1,5 @@ import { ConfigModule, ConfigService } from '@narval/config-module' -import { LoggerModule, OpenTelemetryModule, secret } from '@narval/nestjs-shared' +import { LoggerModule, OpenTelemetryModule, REQUEST_HEADER_ADMIN_API_KEY, secret } from '@narval/nestjs-shared' import { DataStoreConfiguration, HttpSource, PublicClient, Source, SourceType } from '@narval/policy-engine-shared' import { getPublicKey, privateKeyToJwk } from '@narval/signature' import { HttpStatus, INestApplication } from '@nestjs/common' @@ -9,7 +9,6 @@ import request from 'supertest' import { generatePrivateKey } from 'viem/accounts' import { AppService } from '../../../app/core/service/app.service' import { Config, load } from '../../../armory.config' -import { REQUEST_HEADER_API_KEY } from '../../../armory.constant' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { ClientModule } from '../../client.module' import { ClientService } from '../../core/service/client.service' @@ -135,7 +134,7 @@ describe('Client', () => { const { status, body } = await request(app.getHttpServer()) .post('/clients') - .set(REQUEST_HEADER_API_KEY, adminApiKey) + .set(REQUEST_HEADER_ADMIN_API_KEY, adminApiKey) .send(createClientPayload) const actualClient = await clientService.findById(body.id) @@ -171,7 +170,7 @@ describe('Client', () => { const { body } = await request(app.getHttpServer()) .post('/clients') - .set(REQUEST_HEADER_API_KEY, adminApiKey) + .set(REQUEST_HEADER_ADMIN_API_KEY, adminApiKey) .send(createClientWithGivenPolicyEngine) const actualClient = await clientService.findById(body.id) @@ -187,7 +186,7 @@ describe('Client', () => { const { body } = await request(app.getHttpServer()) .post('/clients') - .set(REQUEST_HEADER_API_KEY, adminApiKey) + .set(REQUEST_HEADER_ADMIN_API_KEY, adminApiKey) .send({ ...createClientPayload, clientSecret }) const actualClient = await clientService.findById(body.id) @@ -201,7 +200,7 @@ describe('Client', () => { const { body } = await request(app.getHttpServer()) .post('/clients') - .set(REQUEST_HEADER_API_KEY, adminApiKey) + .set(REQUEST_HEADER_ADMIN_API_KEY, adminApiKey) .send(createClientPayload) const actualClient = await clientService.findById(body.id) @@ -215,7 +214,7 @@ describe('Client', () => { const { body } = await request(app.getHttpServer()) .post('/clients') - .set(REQUEST_HEADER_API_KEY, adminApiKey) + .set(REQUEST_HEADER_ADMIN_API_KEY, adminApiKey) .send({ ...createClientPayload, useManagedDataStore: true }) const actualClient = await clientService.findById(body.id) @@ -240,7 +239,7 @@ describe('Client', () => { const { status, body } = await request(app.getHttpServer()) .post('/clients') - .set(REQUEST_HEADER_API_KEY, adminApiKey) + .set(REQUEST_HEADER_ADMIN_API_KEY, adminApiKey) .send({ ...createClientPayload, useManagedDataStore: true, @@ -277,7 +276,7 @@ describe('Client', () => { it('responds with unprocessable entity when payload is invalid', async () => { const { status } = await request(app.getHttpServer()) .post('/clients') - .set(REQUEST_HEADER_API_KEY, adminApiKey) + .set(REQUEST_HEADER_ADMIN_API_KEY, adminApiKey) .send({}) expect(status).toEqual(HttpStatus.UNPROCESSABLE_ENTITY) @@ -286,7 +285,7 @@ describe('Client', () => { it('responds with forbidden when admin api key is invalid', async () => { const { status } = await request(app.getHttpServer()) .post('/clients') - .set(REQUEST_HEADER_API_KEY, 'invalid-admin-api-key') + .set(REQUEST_HEADER_ADMIN_API_KEY, 'invalid-admin-api-key') .send({}) expect(status).toEqual(HttpStatus.FORBIDDEN) diff --git a/apps/armory/src/main.ts b/apps/armory/src/main.ts index a7175923e..ffe992159 100644 --- a/apps/armory/src/main.ts +++ b/apps/armory/src/main.ts @@ -7,14 +7,20 @@ import { instrumentTelemetry } from '@narval/open-telemetry' instrumentTelemetry({ serviceName: 'armory' }) import { ConfigService } from '@narval/config-module' -import { LoggerService, withApiVersion, withCors, withLogger, withSwagger } from '@narval/nestjs-shared' +import { + LoggerService, + securityOptions, + withApiVersion, + withCors, + withLogger, + withSwagger +} from '@narval/nestjs-shared' import { ClassSerializerInterceptor, INestApplication, ValidationPipe } from '@nestjs/common' import { NestFactory, Reflector } from '@nestjs/core' import compression from 'compression' import { json } from 'express' import { lastValueFrom, map, of, switchMap } from 'rxjs' import { Config } from './armory.config' -import { ADMIN_SECURITY, CLIENT_ID_SECURITY, CLIENT_SECRET_SECURITY } from './armory.constant' import { ArmoryModule } from './armory.module' import { ApplicationExceptionFilter } from './shared/filter/application-exception.filter' import { HttpExceptionFilter } from './shared/filter/http-exception.filter' @@ -103,7 +109,7 @@ async function bootstrap(): Promise { title: 'Armory', description: 'Authentication and authorization system for web3.0', version: '1.0', - security: [ADMIN_SECURITY, CLIENT_ID_SECURITY, CLIENT_SECRET_SECURITY] + security: [securityOptions.clientId, securityOptions.clientSecret, securityOptions.adminApiKey] }) ), switchMap((app) => app.listen(port)) diff --git a/apps/armory/src/shared/decorator/api-admin-guard.decorator.ts b/apps/armory/src/shared/decorator/api-admin-guard.decorator.ts index a9c748a35..ef446c991 100644 --- a/apps/armory/src/shared/decorator/api-admin-guard.decorator.ts +++ b/apps/armory/src/shared/decorator/api-admin-guard.decorator.ts @@ -1,14 +1,14 @@ +import { REQUEST_HEADER_ADMIN_API_KEY, securityOptions } from '@narval/nestjs-shared' import { UseGuards, applyDecorators } from '@nestjs/common' import { ApiHeader, ApiSecurity } from '@nestjs/swagger' -import { ADMIN_SECURITY, REQUEST_HEADER_API_KEY } from '../../armory.constant' import { AdminApiKeyGuard } from '../guard/admin-api-key.guard' export function ApiAdminGuard() { return applyDecorators( UseGuards(AdminApiKeyGuard), - ApiSecurity(ADMIN_SECURITY.name), + ApiSecurity(securityOptions.adminApiKey.name), ApiHeader({ - name: REQUEST_HEADER_API_KEY, + name: REQUEST_HEADER_ADMIN_API_KEY, required: true }) ) diff --git a/apps/armory/src/shared/decorator/api-client-id-guard.decorator.ts b/apps/armory/src/shared/decorator/api-client-id-guard.decorator.ts index 04a03375a..1c43b5ff9 100644 --- a/apps/armory/src/shared/decorator/api-client-id-guard.decorator.ts +++ b/apps/armory/src/shared/decorator/api-client-id-guard.decorator.ts @@ -1,13 +1,12 @@ -import { REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' +import { REQUEST_HEADER_CLIENT_ID, securityOptions } from '@narval/nestjs-shared' import { UseGuards, applyDecorators } from '@nestjs/common' import { ApiHeader, ApiSecurity } from '@nestjs/swagger' -import { CLIENT_ID_SECURITY } from '../../armory.constant' import { ClientIdGuard } from '../guard/client-id.guard' export function ApiClientIdGuard() { return applyDecorators( UseGuards(ClientIdGuard), - ApiSecurity(CLIENT_ID_SECURITY.name), + ApiSecurity(securityOptions.clientId.name), ApiHeader({ name: REQUEST_HEADER_CLIENT_ID, required: true diff --git a/apps/armory/src/shared/decorator/api-client-secret-guard.decorator.ts b/apps/armory/src/shared/decorator/api-client-secret-guard.decorator.ts index 5a739a3bd..8bd8cd781 100644 --- a/apps/armory/src/shared/decorator/api-client-secret-guard.decorator.ts +++ b/apps/armory/src/shared/decorator/api-client-secret-guard.decorator.ts @@ -1,13 +1,12 @@ -import { REQUEST_HEADER_CLIENT_SECRET } from '@narval/nestjs-shared' +import { REQUEST_HEADER_CLIENT_SECRET, securityOptions } from '@narval/nestjs-shared' import { UseGuards, applyDecorators } from '@nestjs/common' import { ApiHeader, ApiSecurity } from '@nestjs/swagger' -import { CLIENT_SECRET_SECURITY } from '../../armory.constant' import { ClientSecretGuard } from '../guard/client-secret.guard' export function ApiClientSecretGuard() { return applyDecorators( UseGuards(ClientSecretGuard), - ApiSecurity(CLIENT_SECRET_SECURITY.name), + ApiSecurity(securityOptions.clientSecret.name), ApiHeader({ required: true, name: REQUEST_HEADER_CLIENT_SECRET diff --git a/apps/armory/src/shared/guard/__test__/unit/admin.guard.spec.ts b/apps/armory/src/shared/guard/__test__/unit/admin.guard.spec.ts index 63c077662..0febcd6a5 100644 --- a/apps/armory/src/shared/guard/__test__/unit/admin.guard.spec.ts +++ b/apps/armory/src/shared/guard/__test__/unit/admin.guard.spec.ts @@ -1,15 +1,14 @@ -import { secret } from '@narval/nestjs-shared' +import { REQUEST_HEADER_ADMIN_API_KEY, secret } from '@narval/nestjs-shared' import { ExecutionContext } from '@nestjs/common' import { mock } from 'jest-mock-extended' import { AppService } from '../../../../app/core/service/app.service' -import { REQUEST_HEADER_API_KEY } from '../../../../armory.constant' import { ApplicationException } from '../../../exception/application.exception' import { AdminApiKeyGuard } from '../../admin-api-key.guard' describe(AdminApiKeyGuard.name, () => { const mockExecutionContext = (apiKey?: string) => { const headers = { - [REQUEST_HEADER_API_KEY]: apiKey + [REQUEST_HEADER_ADMIN_API_KEY]: apiKey } const request = { headers } @@ -35,20 +34,20 @@ describe(AdminApiKeyGuard.name, () => { return serviceMock } - it(`throws an error when ${REQUEST_HEADER_API_KEY} header is missing`, async () => { + it(`throws an error when ${REQUEST_HEADER_ADMIN_API_KEY} header is missing`, async () => { const guard = new AdminApiKeyGuard(mockAppService()) await expect(guard.canActivate(mockExecutionContext())).rejects.toThrow(ApplicationException) }) - it(`returns true when ${REQUEST_HEADER_API_KEY} matches the app admin api key`, async () => { + it(`returns true when ${REQUEST_HEADER_ADMIN_API_KEY} matches the app admin api key`, async () => { const adminApiKey = 'test-admin-api-key' const guard = new AdminApiKeyGuard(mockAppService(adminApiKey)) expect(await guard.canActivate(mockExecutionContext(adminApiKey))).toEqual(true) }) - it(`returns false when ${REQUEST_HEADER_API_KEY} does not matches the app admin api key`, async () => { + it(`returns false when ${REQUEST_HEADER_ADMIN_API_KEY} does not matches the app admin api key`, async () => { const guard = new AdminApiKeyGuard(mockAppService('test-admin-api-key')) expect(await guard.canActivate(mockExecutionContext('another-api-key'))).toEqual(false) diff --git a/apps/armory/src/shared/guard/admin-api-key.guard.ts b/apps/armory/src/shared/guard/admin-api-key.guard.ts index 3a4385a95..c111186c2 100644 --- a/apps/armory/src/shared/guard/admin-api-key.guard.ts +++ b/apps/armory/src/shared/guard/admin-api-key.guard.ts @@ -1,7 +1,6 @@ -import { secret } from '@narval/nestjs-shared' +import { REQUEST_HEADER_ADMIN_API_KEY, secret } from '@narval/nestjs-shared' import { CanActivate, ExecutionContext, HttpStatus, Injectable } from '@nestjs/common' import { AppService } from '../../app/core/service/app.service' -import { REQUEST_HEADER_API_KEY } from '../../armory.constant' import { ApplicationException } from '../exception/application.exception' @Injectable() @@ -10,11 +9,11 @@ export class AdminApiKeyGuard implements CanActivate { async canActivate(context: ExecutionContext): Promise { const req = context.switchToHttp().getRequest() - const apiKey = req.headers[REQUEST_HEADER_API_KEY] + const apiKey = req.headers[REQUEST_HEADER_ADMIN_API_KEY] if (!apiKey) { throw new ApplicationException({ - message: `Missing or invalid ${REQUEST_HEADER_API_KEY} header`, + message: `Missing or invalid ${REQUEST_HEADER_ADMIN_API_KEY} header`, suggestedHttpStatusCode: HttpStatus.UNAUTHORIZED }) } diff --git a/apps/policy-engine/src/engine/__test__/e2e/client.spec.ts b/apps/policy-engine/src/engine/__test__/e2e/client.spec.ts index 801cfbc23..b2d3ada8e 100644 --- a/apps/policy-engine/src/engine/__test__/e2e/client.spec.ts +++ b/apps/policy-engine/src/engine/__test__/e2e/client.spec.ts @@ -3,6 +3,7 @@ import { EncryptionModuleOptionProvider } from '@narval/encryption-module' import { LoggerModule, OpenTelemetryModule, + REQUEST_HEADER_ADMIN_API_KEY, REQUEST_HEADER_CLIENT_ID, REQUEST_HEADER_CLIENT_SECRET, secret @@ -20,7 +21,6 @@ import request from 'supertest' import { v4 as uuid } from 'uuid' import { generatePrivateKey } from 'viem/accounts' import { Config, load } from '../../../policy-engine.config' -import { REQUEST_HEADER_API_KEY } from '../../../policy-engine.constant' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' import { Client } from '../../../shared/type/domain.type' @@ -115,7 +115,7 @@ describe('Client', () => { it('creates a new client', async () => { const { status, body } = await request(app.getHttpServer()) .post('/clients') - .set(REQUEST_HEADER_API_KEY, adminApiKey) + .set(REQUEST_HEADER_ADMIN_API_KEY, adminApiKey) .send(createClientPayload) const actualClient = await clientRepository.findById(clientId) @@ -137,7 +137,7 @@ describe('Client', () => { const { body } = await request(app.getHttpServer()) .post('/clients') - .set(REQUEST_HEADER_API_KEY, adminApiKey) + .set(REQUEST_HEADER_ADMIN_API_KEY, adminApiKey) .send({ ...createClientPayload, clientSecret }) expect(body.clientSecret).toEqual(clientSecret) @@ -146,7 +146,7 @@ describe('Client', () => { it('creates a new client with engine key in the entity and policy keys for self-signed data', async () => { const { status, body } = await request(app.getHttpServer()) .post('/clients') - .set(REQUEST_HEADER_API_KEY, adminApiKey) + .set(REQUEST_HEADER_ADMIN_API_KEY, adminApiKey) .send({ ...createClientPayload, allowSelfSignedData: true }) const actualClient = await clientRepository.findById(clientId) @@ -175,7 +175,7 @@ describe('Client', () => { it('does not expose the signer private key', async () => { const { body } = await request(app.getHttpServer()) .post('/clients') - .set(REQUEST_HEADER_API_KEY, adminApiKey) + .set(REQUEST_HEADER_ADMIN_API_KEY, adminApiKey) .send(createClientPayload) expect(body.signer.key).not.toBeDefined() @@ -188,12 +188,12 @@ describe('Client', () => { it('responds with an error when clientId already exist', async () => { await request(app.getHttpServer()) .post('/clients') - .set(REQUEST_HEADER_API_KEY, adminApiKey) + .set(REQUEST_HEADER_ADMIN_API_KEY, adminApiKey) .send(createClientPayload) const { status, body } = await request(app.getHttpServer()) .post('/clients') - .set(REQUEST_HEADER_API_KEY, adminApiKey) + .set(REQUEST_HEADER_ADMIN_API_KEY, adminApiKey) .send(createClientPayload) expect(body).toEqual({ @@ -206,7 +206,7 @@ describe('Client', () => { it('responds with forbidden when admin api key is invalid', async () => { const { status, body } = await request(app.getHttpServer()) .post('/clients') - .set(REQUEST_HEADER_API_KEY, 'invalid-api-key') + .set(REQUEST_HEADER_ADMIN_API_KEY, 'invalid-api-key') .send(createClientPayload) expect(body).toMatchObject({ @@ -225,7 +225,7 @@ describe('Client', () => { const { body } = await request(app.getHttpServer()) .post('/clients') - .set(REQUEST_HEADER_API_KEY, adminApiKey) + .set(REQUEST_HEADER_ADMIN_API_KEY, adminApiKey) .send({ ...createClientPayload, clientId: uuid() diff --git a/apps/policy-engine/src/main.ts b/apps/policy-engine/src/main.ts index 85b5ca9e0..2c9832412 100644 --- a/apps/policy-engine/src/main.ts +++ b/apps/policy-engine/src/main.ts @@ -7,13 +7,19 @@ import { instrumentTelemetry } from '@narval/open-telemetry' instrumentTelemetry({ serviceName: 'policy-engine' }) import { ConfigService } from '@narval/config-module' -import { LoggerService, withApiVersion, withCors, withLogger, withSwagger } from '@narval/nestjs-shared' +import { + LoggerService, + securityOptions, + withApiVersion, + withCors, + withLogger, + withSwagger +} from '@narval/nestjs-shared' import { INestApplication, ValidationPipe } from '@nestjs/common' import { NestFactory } from '@nestjs/core' import { json } from 'express' import { lastValueFrom, map, of, switchMap } from 'rxjs' import { Config } from './policy-engine.config' -import { ADMIN_SECURITY, CLIENT_ID_SECURITY, CLIENT_SECRET_SECURITY } from './policy-engine.constant' import { PolicyEngineModule, ProvisionModule } from './policy-engine.module' import { ApplicationExceptionFilter } from './shared/filter/application-exception.filter' import { HttpExceptionFilter } from './shared/filter/http-exception.filter' @@ -67,7 +73,7 @@ async function bootstrap() { // Increase the POST JSON payload size to support bigger data stores. application.use(json({ limit: '50mb' })) - // NOTE: Enable application shutdown lifecyle hooks to ensure connections are + // NOTE: Enable application shutdown lifecycle hooks to ensure connections are // close on exit. application.enableShutdownHooks() @@ -83,7 +89,7 @@ async function bootstrap() { title: 'Policy Engine', description: 'Policy decision point for fine-grained authorization in web3.0', version: '1.0', - security: [ADMIN_SECURITY, CLIENT_ID_SECURITY, CLIENT_SECRET_SECURITY] + security: [securityOptions.adminApiKey, securityOptions.clientId, securityOptions.clientSecret] }) ), switchMap((app) => app.listen(port)) diff --git a/apps/policy-engine/src/policy-engine.constant.ts b/apps/policy-engine/src/policy-engine.constant.ts index f6e742923..2366ea3db 100644 --- a/apps/policy-engine/src/policy-engine.constant.ts +++ b/apps/policy-engine/src/policy-engine.constant.ts @@ -1,17 +1,9 @@ import { RawAesWrappingSuiteIdentifier } from '@aws-crypto/client-node' -import { - REQUEST_HEADER_CLIENT_ID, - REQUEST_HEADER_CLIENT_SECRET, - adminApiKeySecurity, - clientIdSecurity, - clientSecretSecurity -} from '@narval/nestjs-shared' // // Headers // -export const REQUEST_HEADER_API_KEY = 'x-api-key' export const REQUEST_HEADER_SESSION_ID = 'x-session-id' // @@ -21,11 +13,3 @@ export const REQUEST_HEADER_SESSION_ID = 'x-session-id' export const ENCRYPTION_KEY_NAMESPACE = 'armory.policy-engine' export const ENCRYPTION_KEY_NAME = 'storage-encryption' export const ENCRYPTION_WRAPPING_SUITE = RawAesWrappingSuiteIdentifier.AES256_GCM_IV12_TAG16_NO_PADDING - -// -// API Security -// - -export const ADMIN_SECURITY = adminApiKeySecurity(REQUEST_HEADER_API_KEY) -export const CLIENT_ID_SECURITY = clientIdSecurity(REQUEST_HEADER_CLIENT_ID) -export const CLIENT_SECRET_SECURITY = clientSecretSecurity(REQUEST_HEADER_CLIENT_SECRET) diff --git a/apps/policy-engine/src/shared/decorator/admin-guard.decorator.ts b/apps/policy-engine/src/shared/decorator/admin-guard.decorator.ts index 206d460cf..c77c6caf2 100644 --- a/apps/policy-engine/src/shared/decorator/admin-guard.decorator.ts +++ b/apps/policy-engine/src/shared/decorator/admin-guard.decorator.ts @@ -1,15 +1,15 @@ +import { REQUEST_HEADER_ADMIN_API_KEY, securityOptions } from '@narval/nestjs-shared' import { UseGuards, applyDecorators } from '@nestjs/common' import { ApiHeader, ApiSecurity } from '@nestjs/swagger' -import { ADMIN_SECURITY, REQUEST_HEADER_API_KEY } from '../../policy-engine.constant' import { AdminApiKeyGuard } from '../guard/admin-api-key.guard' export function AdminGuard() { return applyDecorators( UseGuards(AdminApiKeyGuard), - ApiSecurity(ADMIN_SECURITY.name), + ApiSecurity(securityOptions.adminApiKey.name), ApiHeader({ required: true, - name: REQUEST_HEADER_API_KEY + name: REQUEST_HEADER_ADMIN_API_KEY }) ) } diff --git a/apps/policy-engine/src/shared/decorator/client-guard.decorator.ts b/apps/policy-engine/src/shared/decorator/client-guard.decorator.ts index 88215b619..15e1b37a8 100644 --- a/apps/policy-engine/src/shared/decorator/client-guard.decorator.ts +++ b/apps/policy-engine/src/shared/decorator/client-guard.decorator.ts @@ -1,14 +1,13 @@ -import { REQUEST_HEADER_CLIENT_ID, REQUEST_HEADER_CLIENT_SECRET } from '@narval/nestjs-shared' +import { REQUEST_HEADER_CLIENT_ID, REQUEST_HEADER_CLIENT_SECRET, securityOptions } from '@narval/nestjs-shared' import { UseGuards, applyDecorators } from '@nestjs/common' import { ApiHeader, ApiSecurity } from '@nestjs/swagger' -import { CLIENT_ID_SECURITY, CLIENT_SECRET_SECURITY } from '../../policy-engine.constant' import { ClientSecretGuard } from '../guard/client-secret.guard' export function ClientGuard() { return applyDecorators( UseGuards(ClientSecretGuard), - ApiSecurity(CLIENT_SECRET_SECURITY.name), - ApiSecurity(CLIENT_ID_SECURITY.name), + ApiSecurity(securityOptions.clientSecret.name), + ApiSecurity(securityOptions.clientId.name), // IMPORTANT: The order in which you define the headers also determines the // order of the function/method arguments in the generated HTTP client. ApiHeader({ diff --git a/apps/policy-engine/src/shared/guard/__test__/unit/admin-api-key.guard.spec.ts b/apps/policy-engine/src/shared/guard/__test__/unit/admin-api-key.guard.spec.ts index d6a792624..81f6cfb2c 100644 --- a/apps/policy-engine/src/shared/guard/__test__/unit/admin-api-key.guard.spec.ts +++ b/apps/policy-engine/src/shared/guard/__test__/unit/admin-api-key.guard.spec.ts @@ -1,15 +1,14 @@ -import { secret } from '@narval/nestjs-shared' +import { REQUEST_HEADER_ADMIN_API_KEY, secret } from '@narval/nestjs-shared' import { ExecutionContext } from '@nestjs/common' import { mock } from 'jest-mock-extended' import { EngineService } from '../../../../engine/core/service/engine.service' -import { REQUEST_HEADER_API_KEY } from '../../../../policy-engine.constant' import { ApplicationException } from '../../../exception/application.exception' import { AdminApiKeyGuard } from '../../admin-api-key.guard' describe(AdminApiKeyGuard.name, () => { const mockExecutionContext = (apiKey?: string) => { const headers = { - [REQUEST_HEADER_API_KEY]: apiKey + [REQUEST_HEADER_ADMIN_API_KEY]: apiKey } const request = { headers } @@ -35,20 +34,20 @@ describe(AdminApiKeyGuard.name, () => { return serviceMock } - it(`throws an error when ${REQUEST_HEADER_API_KEY} header is missing`, async () => { + it(`throws an error when ${REQUEST_HEADER_ADMIN_API_KEY} header is missing`, async () => { const guard = new AdminApiKeyGuard(mockEngineService()) await expect(guard.canActivate(mockExecutionContext())).rejects.toThrow(ApplicationException) }) - it(`returns true when ${REQUEST_HEADER_API_KEY} matches the engine admin api key`, async () => { + it(`returns true when ${REQUEST_HEADER_ADMIN_API_KEY} matches the engine admin api key`, async () => { const adminApiKey = 'test-admin-api-key' const guard = new AdminApiKeyGuard(mockEngineService(adminApiKey)) expect(await guard.canActivate(mockExecutionContext(adminApiKey))).toEqual(true) }) - it(`returns false when ${REQUEST_HEADER_API_KEY} does not match the engine admin api key`, async () => { + it(`returns false when ${REQUEST_HEADER_ADMIN_API_KEY} does not match the engine admin api key`, async () => { const guard = new AdminApiKeyGuard(mockEngineService('test-admin-api-key')) expect(await guard.canActivate(mockExecutionContext('another-api-key'))).toEqual(false) diff --git a/apps/policy-engine/src/shared/guard/admin-api-key.guard.ts b/apps/policy-engine/src/shared/guard/admin-api-key.guard.ts index a5e313564..c035fccc5 100644 --- a/apps/policy-engine/src/shared/guard/admin-api-key.guard.ts +++ b/apps/policy-engine/src/shared/guard/admin-api-key.guard.ts @@ -1,7 +1,6 @@ -import { secret } from '@narval/nestjs-shared' +import { REQUEST_HEADER_ADMIN_API_KEY, secret } from '@narval/nestjs-shared' import { CanActivate, ExecutionContext, HttpStatus, Injectable } from '@nestjs/common' import { EngineService } from '../../engine/core/service/engine.service' -import { REQUEST_HEADER_API_KEY } from '../../policy-engine.constant' import { ApplicationException } from '../exception/application.exception' @Injectable() @@ -10,11 +9,11 @@ export class AdminApiKeyGuard implements CanActivate { async canActivate(context: ExecutionContext): Promise { const req = context.switchToHttp().getRequest() - const apiKey = req.headers[REQUEST_HEADER_API_KEY] + const apiKey = req.headers[REQUEST_HEADER_ADMIN_API_KEY] if (!apiKey) { throw new ApplicationException({ - message: `Missing or invalid ${REQUEST_HEADER_API_KEY} header`, + message: `Missing or invalid ${REQUEST_HEADER_ADMIN_API_KEY} header`, suggestedHttpStatusCode: HttpStatus.UNAUTHORIZED }) } diff --git a/apps/vault/src/broker/broker.module.ts b/apps/vault/src/broker/broker.module.ts index a1d240b20..6d111506d 100644 --- a/apps/vault/src/broker/broker.module.ts +++ b/apps/vault/src/broker/broker.module.ts @@ -22,13 +22,13 @@ import { TransferService } from './core/service/transfer.service' import { WalletService } from './core/service/wallet.service' import { ConnectionSyncEventHandler } from './event/handler/connection-sync.event-handler' import { AnchorageClient } from './http/client/anchorage.client' -import { AccountController } from './http/rest/controller/account.controller' +import { ProviderAccountController } from './http/rest/controller/account.controller' import { AddressController } from './http/rest/controller/address.controller' import { ConnectionController } from './http/rest/controller/connection.controller' import { ProxyController } from './http/rest/controller/proxy.controller' import { SyncController } from './http/rest/controller/sync.controller' import { TransferController } from './http/rest/controller/transfer.controller' -import { WalletController } from './http/rest/controller/wallet.controller' +import { ProviderWalletController } from './http/rest/controller/wallet.controller' import { ConnectionSeedService } from './persistence/connection.seed' import { AccountRepository } from './persistence/repository/account.repository' import { AddressRepository } from './persistence/repository/address.repository' @@ -48,13 +48,13 @@ import { WalletRepository } from './persistence/repository/wallet.repository' TransitEncryptionModule ], controllers: [ - AccountController, + ProviderAccountController, AddressController, ConnectionController, ProxyController, SyncController, TransferController, - WalletController + ProviderWalletController ], providers: [ ...DEFAULT_HTTP_MODULE_PROVIDERS, diff --git a/apps/vault/src/broker/http/rest/controller/account.controller.ts b/apps/vault/src/broker/http/rest/controller/account.controller.ts index 41770a439..bf7a9bd93 100644 --- a/apps/vault/src/broker/http/rest/controller/account.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/account.controller.ts @@ -1,4 +1,4 @@ -import { Paginated, PaginationOptions, PaginationParam } from '@narval/nestjs-shared' +import { ApiClientIdHeader, Paginated, PaginationOptions, PaginationParam } from '@narval/nestjs-shared' import { Controller, Get, HttpStatus, Param } from '@nestjs/common' import { ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../shared/decorator/client-id.decorator' @@ -13,8 +13,9 @@ import { ProviderAccountDto } from '../dto/response/provider-account.dto' path: 'accounts', version: '1' }) +@ApiClientIdHeader() @ApiTags('Provider Account') -export class AccountController { +export class ProviderAccountController { constructor(private readonly accountService: AccountService) {} @Get() diff --git a/apps/vault/src/broker/http/rest/controller/address.controller.ts b/apps/vault/src/broker/http/rest/controller/address.controller.ts index 54924337e..e878e08dd 100644 --- a/apps/vault/src/broker/http/rest/controller/address.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/address.controller.ts @@ -1,4 +1,4 @@ -import { Paginated, PaginationOptions, PaginationParam } from '@narval/nestjs-shared' +import { ApiClientIdHeader, Paginated, PaginationOptions, PaginationParam } from '@narval/nestjs-shared' import { Controller, Get, HttpStatus, Param } from '@nestjs/common' import { ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../shared/decorator/client-id.decorator' @@ -12,6 +12,7 @@ import { ProviderAddressDto } from '../dto/response/provider-address.dto' path: 'addresses', version: '1' }) +@ApiClientIdHeader() @ApiTags('Provider Address') export class AddressController { constructor(private readonly addressService: AddressService) {} diff --git a/apps/vault/src/broker/http/rest/controller/connection.controller.ts b/apps/vault/src/broker/http/rest/controller/connection.controller.ts index bc438fc42..8e08fff90 100644 --- a/apps/vault/src/broker/http/rest/controller/connection.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/connection.controller.ts @@ -1,4 +1,4 @@ -import { Paginated, PaginationOptions, PaginationParam } from '@narval/nestjs-shared' +import { ApiClientIdHeader, Paginated, PaginationOptions, PaginationParam } from '@narval/nestjs-shared' import { publicKeyToHex, publicKeyToPem } from '@narval/signature' import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Patch, Post } from '@nestjs/common' import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' @@ -21,6 +21,7 @@ import { ProviderPendingConnectionDto } from '../dto/response/provider-pending-c path: 'connections', version: '1' }) +@ApiClientIdHeader() @ApiTags('Provider Connection') export class ConnectionController { constructor( diff --git a/apps/vault/src/broker/http/rest/controller/proxy.controller.ts b/apps/vault/src/broker/http/rest/controller/proxy.controller.ts index 876348ddb..fbf7bff1a 100644 --- a/apps/vault/src/broker/http/rest/controller/proxy.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/proxy.controller.ts @@ -1,3 +1,4 @@ +import { ApiClientIdHeader } from '@narval/nestjs-shared' import { Body, Controller, @@ -51,6 +52,7 @@ const INACTIVE_CONNECTION_RESPONSE = { path: 'proxy', version: '1' }) +@ApiClientIdHeader() @ApiTags('Provider Proxy') export class ProxyController { constructor(private readonly proxyService: ProxyService) {} diff --git a/apps/vault/src/broker/http/rest/controller/sync.controller.ts b/apps/vault/src/broker/http/rest/controller/sync.controller.ts index f0b7d80c6..6cb500937 100644 --- a/apps/vault/src/broker/http/rest/controller/sync.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/sync.controller.ts @@ -1,4 +1,4 @@ -import { Paginated, PaginationOptions, PaginationParam } from '@narval/nestjs-shared' +import { ApiClientIdHeader, Paginated, PaginationOptions, PaginationParam } from '@narval/nestjs-shared' import { Body, Controller, Get, HttpStatus, Param, Post, Query } from '@nestjs/common' import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../shared/decorator/client-id.decorator' @@ -16,6 +16,7 @@ import { SyncDto } from '../dto/response/sync.dto' path: 'syncs', version: '1' }) +@ApiClientIdHeader() @ApiTags('Provider Sync') export class SyncController { constructor( diff --git a/apps/vault/src/broker/http/rest/controller/transfer.controller.ts b/apps/vault/src/broker/http/rest/controller/transfer.controller.ts index ff4e1518c..f97eef2c0 100644 --- a/apps/vault/src/broker/http/rest/controller/transfer.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/transfer.controller.ts @@ -1,3 +1,4 @@ +import { ApiClientIdHeader } from '@narval/nestjs-shared' import { Body, Controller, Get, HttpStatus, Param, Post } from '@nestjs/common' import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../shared/decorator/client-id.decorator' @@ -11,6 +12,7 @@ import { TransferDto } from '../dto/response/transfer.dto' path: 'transfers', version: '1' }) +@ApiClientIdHeader() @ApiTags('Provider Transfer') export class TransferController { constructor(private readonly transferService: TransferService) {} diff --git a/apps/vault/src/broker/http/rest/controller/wallet.controller.ts b/apps/vault/src/broker/http/rest/controller/wallet.controller.ts index b1df5f236..53c185e69 100644 --- a/apps/vault/src/broker/http/rest/controller/wallet.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/wallet.controller.ts @@ -1,4 +1,4 @@ -import { Paginated, PaginationOptions, PaginationParam } from '@narval/nestjs-shared' +import { ApiClientIdHeader, Paginated, PaginationOptions, PaginationParam } from '@narval/nestjs-shared' import { Controller, Get, HttpStatus, Param } from '@nestjs/common' import { ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../shared/decorator/client-id.decorator' @@ -14,8 +14,9 @@ import { ProviderWalletDto } from '../dto/response/provider-wallet.dto' path: 'wallets', version: '1' }) +@ApiClientIdHeader() @ApiTags('Provider Wallet') -export class WalletController { +export class ProviderWalletController { constructor( private readonly walletService: WalletService, private readonly accountService: AccountService diff --git a/apps/vault/src/client/__test__/e2e/client.spec.ts b/apps/vault/src/client/__test__/e2e/client.spec.ts index 1e6fc44cb..e9cf03b00 100644 --- a/apps/vault/src/client/__test__/e2e/client.spec.ts +++ b/apps/vault/src/client/__test__/e2e/client.spec.ts @@ -1,5 +1,5 @@ import { EncryptionModuleOptionProvider } from '@narval/encryption-module' -import { LoggerModule } from '@narval/nestjs-shared' +import { LoggerModule, REQUEST_HEADER_ADMIN_API_KEY } from '@narval/nestjs-shared' import { Alg, PrivateKey, @@ -14,7 +14,6 @@ import request from 'supertest' import { v4 as uuid } from 'uuid' import { MainModule } from '../../../main.module' import { ProvisionService } from '../../../provision.service' -import { REQUEST_HEADER_API_KEY } from '../../../shared/constant' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' import { ClientRepository } from '../../persistence/repository/client.repository' @@ -72,7 +71,7 @@ describe('Client', () => { it('creates a new client', async () => { const { status, body } = await request(app.getHttpServer()) .post('/clients') - .set(REQUEST_HEADER_API_KEY, adminApiKey) + .set(REQUEST_HEADER_ADMIN_API_KEY, adminApiKey) .send(payload) const actualClient = await clientRepository.findById(clientId) @@ -99,7 +98,7 @@ describe('Client', () => { } const { status, body } = await request(app.getHttpServer()) .post('/clients') - .set(REQUEST_HEADER_API_KEY, adminApiKey) + .set(REQUEST_HEADER_ADMIN_API_KEY, adminApiKey) .send(newPayload) const actualClient = await clientRepository.findById('client-2') @@ -113,11 +112,11 @@ describe('Client', () => { }) it('responds with an error when clientId already exist', async () => { - await request(app.getHttpServer()).post('/clients').set(REQUEST_HEADER_API_KEY, adminApiKey).send(payload) + await request(app.getHttpServer()).post('/clients').set(REQUEST_HEADER_ADMIN_API_KEY, adminApiKey).send(payload) const { status, body } = await request(app.getHttpServer()) .post('/clients') - .set(REQUEST_HEADER_API_KEY, adminApiKey) + .set(REQUEST_HEADER_ADMIN_API_KEY, adminApiKey) .send(payload) expect(body.statusCode).toEqual(HttpStatus.BAD_REQUEST) @@ -128,7 +127,7 @@ describe('Client', () => { it('responds with forbidden when admin api key is invalid', async () => { const { status, body } = await request(app.getHttpServer()) .post('/clients') - .set(REQUEST_HEADER_API_KEY, 'invalid-api-key') + .set(REQUEST_HEADER_ADMIN_API_KEY, 'invalid-api-key') .send(payload) expect(body).toMatchObject({ @@ -154,7 +153,7 @@ describe('Client', () => { const { status: rightKeyStatus } = await request(app.getHttpServer()) .post('/clients') - .set(REQUEST_HEADER_API_KEY, adminApiKey) + .set(REQUEST_HEADER_ADMIN_API_KEY, adminApiKey) .send(validClientPayload) expect(rightKeyStatus).toEqual(HttpStatus.CREATED) @@ -173,7 +172,7 @@ describe('Client', () => { const { status: wrongKeyStatus } = await request(app.getHttpServer()) .post('/clients') - .set(REQUEST_HEADER_API_KEY, adminApiKey) + .set(REQUEST_HEADER_ADMIN_API_KEY, adminApiKey) .send(invalidClientPayload) expect(wrongKeyStatus).toEqual(HttpStatus.UNPROCESSABLE_ENTITY) @@ -206,7 +205,7 @@ describe('Client', () => { } const { status, body } = await request(app.getHttpServer()) .post('/clients') - .set(REQUEST_HEADER_API_KEY, adminApiKey) + .set(REQUEST_HEADER_ADMIN_API_KEY, adminApiKey) .send(newPayload) expect(status).toEqual(HttpStatus.CREATED) diff --git a/apps/vault/src/main.ts b/apps/vault/src/main.ts index 10f947bdb..db62856cf 100644 --- a/apps/vault/src/main.ts +++ b/apps/vault/src/main.ts @@ -7,13 +7,19 @@ import { instrumentTelemetry } from '@narval/open-telemetry' instrumentTelemetry({ serviceName: 'vault' }) import { ConfigService } from '@narval/config-module' -import { LoggerService, withApiVersion, withCors, withLogger, withSwagger } from '@narval/nestjs-shared' +import { + LoggerService, + securityOptions, + withApiVersion, + withCors, + withLogger, + withSwagger +} from '@narval/nestjs-shared' import { INestApplication, ValidationPipe } from '@nestjs/common' import { NestFactory } from '@nestjs/core' import { lastValueFrom, map, of, switchMap } from 'rxjs' import { Config } from './main.config' import { MainModule, ProvisionModule } from './main.module' -import { ADMIN_API_KEY_SECURITY, GNAP_SECURITY } from './shared/constant' /** * Adds global pipes to the application. @@ -59,7 +65,11 @@ async function bootstrap() { description: 'Secure storage for private keys and sensitive data, designed to protect your most critical assets in web3.0', version: '1.0', - security: [GNAP_SECURITY, ADMIN_API_KEY_SECURITY] + security: [securityOptions.gnap, securityOptions.adminApiKey, securityOptions.detachedJws], + server: { + url: configService.get('baseUrl'), + description: 'Narval Vault Base Url' + } }) ), switchMap((app) => app.listen(port)) diff --git a/apps/vault/src/shared/constant.ts b/apps/vault/src/shared/constant.ts index a6855b556..6c7077063 100644 --- a/apps/vault/src/shared/constant.ts +++ b/apps/vault/src/shared/constant.ts @@ -1,21 +1,16 @@ import { RawAesWrappingSuiteIdentifier } from '@aws-crypto/client-node' -import { adminApiKeySecurity, gnapSecurity } from '@narval/nestjs-shared' import { ClassSerializerInterceptor, ValidationPipe } from '@nestjs/common' import { APP_FILTER, APP_INTERCEPTOR, APP_PIPE } from '@nestjs/core' import { ZodValidationPipe } from 'nestjs-zod' import { ApplicationExceptionFilter } from './filter/application-exception.filter' import { ZodExceptionFilter } from './filter/zod-exception.filter' -export const REQUEST_HEADER_API_KEY = 'x-api-key' export const REQUEST_HEADER_AUTHORIZATION = 'Authorization' export const ENCRYPTION_KEY_NAMESPACE = 'armory.vault' export const ENCRYPTION_KEY_NAME = 'storage-encryption' export const ENCRYPTION_WRAPPING_SUITE = RawAesWrappingSuiteIdentifier.AES256_GCM_IV12_TAG16_NO_PADDING -export const GNAP_SECURITY = gnapSecurity() -export const ADMIN_API_KEY_SECURITY = adminApiKeySecurity(REQUEST_HEADER_API_KEY) - // // Providers // diff --git a/apps/vault/src/shared/decorator/admin-guard.decorator.ts b/apps/vault/src/shared/decorator/admin-guard.decorator.ts index 11671fc17..a02e26401 100644 --- a/apps/vault/src/shared/decorator/admin-guard.decorator.ts +++ b/apps/vault/src/shared/decorator/admin-guard.decorator.ts @@ -1,14 +1,14 @@ +import { REQUEST_HEADER_ADMIN_API_KEY, securityOptions } from '@narval/nestjs-shared' import { UseGuards, applyDecorators } from '@nestjs/common' import { ApiHeader, ApiSecurity } from '@nestjs/swagger' -import { ADMIN_API_KEY_SECURITY, REQUEST_HEADER_API_KEY } from '../constant' import { AdminApiKeyGuard } from '../guard/admin-api-key.guard' export function AdminGuard() { return applyDecorators( UseGuards(AdminApiKeyGuard), - ApiSecurity(ADMIN_API_KEY_SECURITY.name), + ApiSecurity(securityOptions.adminApiKey.name), ApiHeader({ - name: REQUEST_HEADER_API_KEY, + name: REQUEST_HEADER_ADMIN_API_KEY, required: true }) ) diff --git a/apps/vault/src/shared/decorator/permission-guard.decorator.ts b/apps/vault/src/shared/decorator/permission-guard.decorator.ts index 007900318..5c3234066 100644 --- a/apps/vault/src/shared/decorator/permission-guard.decorator.ts +++ b/apps/vault/src/shared/decorator/permission-guard.decorator.ts @@ -1,4 +1,4 @@ -import { ApiGnapSecurity } from '@narval/nestjs-shared' +import { ApiDetachedJwsSecurity, ApiGnapSecurity } from '@narval/nestjs-shared' import { UseGuards, applyDecorators } from '@nestjs/common' import { Reflector } from '@nestjs/core' import { AuthorizationGuard } from '../guard/authorization.guard' @@ -7,5 +7,10 @@ import { VaultPermission } from '../type/domain.type' const RequiredPermission = Reflector.createDecorator() export function PermissionGuard(...permissions: VaultPermission[]) { - return applyDecorators(RequiredPermission(permissions), UseGuards(AuthorizationGuard), ApiGnapSecurity(permissions)) + return applyDecorators( + RequiredPermission(permissions), + UseGuards(AuthorizationGuard), + ApiDetachedJwsSecurity(), + ApiGnapSecurity(permissions) + ) } diff --git a/apps/vault/src/shared/guard/__test__/unit/admin-api-key.guard.spec.ts b/apps/vault/src/shared/guard/__test__/unit/admin-api-key.guard.spec.ts index e79660d87..94f071a9b 100644 --- a/apps/vault/src/shared/guard/__test__/unit/admin-api-key.guard.spec.ts +++ b/apps/vault/src/shared/guard/__test__/unit/admin-api-key.guard.spec.ts @@ -1,15 +1,14 @@ -import { secret } from '@narval/nestjs-shared' +import { REQUEST_HEADER_ADMIN_API_KEY, secret } from '@narval/nestjs-shared' import { ExecutionContext } from '@nestjs/common' import { mock } from 'jest-mock-extended' import { AppService } from '../../../../app.service' -import { REQUEST_HEADER_API_KEY } from '../../../constant' import { ApplicationException } from '../../../exception/application.exception' import { AdminApiKeyGuard } from '../../admin-api-key.guard' describe(AdminApiKeyGuard.name, () => { const mockExecutionContext = (apiKey?: string) => { const headers = { - [REQUEST_HEADER_API_KEY]: apiKey + [REQUEST_HEADER_ADMIN_API_KEY]: apiKey } const request = { headers } @@ -36,20 +35,20 @@ describe(AdminApiKeyGuard.name, () => { return serviceMock } - it(`throws an error when ${REQUEST_HEADER_API_KEY} header is missing`, async () => { + it(`throws an error when ${REQUEST_HEADER_ADMIN_API_KEY} header is missing`, async () => { const guard = new AdminApiKeyGuard(mockAppService()) await expect(guard.canActivate(mockExecutionContext())).rejects.toThrow(ApplicationException) }) - it(`returns true when ${REQUEST_HEADER_API_KEY} matches the app admin api key`, async () => { + it(`returns true when ${REQUEST_HEADER_ADMIN_API_KEY} matches the app admin api key`, async () => { const adminApiKey = 'test-admin-api-key' const guard = new AdminApiKeyGuard(mockAppService(adminApiKey)) expect(await guard.canActivate(mockExecutionContext(adminApiKey))).toEqual(true) }) - it(`returns false when ${REQUEST_HEADER_API_KEY} does not matches the app admin api key`, async () => { + it(`returns false when ${REQUEST_HEADER_ADMIN_API_KEY} does not matches the app admin api key`, async () => { const guard = new AdminApiKeyGuard(mockAppService('test-admin-api-key')) expect(await guard.canActivate(mockExecutionContext('another-api-key'))).toEqual(false) diff --git a/apps/vault/src/shared/guard/admin-api-key.guard.ts b/apps/vault/src/shared/guard/admin-api-key.guard.ts index 812fd3e5d..26d1d79bf 100644 --- a/apps/vault/src/shared/guard/admin-api-key.guard.ts +++ b/apps/vault/src/shared/guard/admin-api-key.guard.ts @@ -1,7 +1,6 @@ -import { secret } from '@narval/nestjs-shared' +import { REQUEST_HEADER_ADMIN_API_KEY, secret } from '@narval/nestjs-shared' import { CanActivate, ExecutionContext, HttpStatus, Injectable } from '@nestjs/common' import { AppService } from '../../app.service' -import { REQUEST_HEADER_API_KEY } from '../constant' import { ApplicationException } from '../exception/application.exception' @Injectable() @@ -10,11 +9,11 @@ export class AdminApiKeyGuard implements CanActivate { async canActivate(context: ExecutionContext): Promise { const req = context.switchToHttp().getRequest() - const apiKey = req.headers[REQUEST_HEADER_API_KEY] + const apiKey = req.headers[REQUEST_HEADER_ADMIN_API_KEY] if (!apiKey) { throw new ApplicationException({ - message: `Missing or invalid ${REQUEST_HEADER_API_KEY} header`, + message: `Missing or invalid ${REQUEST_HEADER_ADMIN_API_KEY} header`, suggestedHttpStatusCode: HttpStatus.UNAUTHORIZED }) } diff --git a/apps/vault/src/transit-encryption/http/rest/controller/rest/encryption-key.controller.ts b/apps/vault/src/transit-encryption/http/rest/controller/rest/encryption-key.controller.ts index 70fc018d9..9aad573fa 100644 --- a/apps/vault/src/transit-encryption/http/rest/controller/rest/encryption-key.controller.ts +++ b/apps/vault/src/transit-encryption/http/rest/controller/rest/encryption-key.controller.ts @@ -1,8 +1,8 @@ import { Permission } from '@narval/armory-sdk' -import { REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' +import { ApiClientIdHeader } from '@narval/nestjs-shared' import { publicKeyToPem } from '@narval/signature' import { Controller, HttpStatus, Post } from '@nestjs/common' -import { ApiHeader, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' +import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../../shared/decorator/client-id.decorator' import { PermissionGuard } from '../../../../../shared/decorator/permission-guard.decorator' import { VaultPermission } from '../../../../../shared/type/domain.type' @@ -15,10 +15,7 @@ import { EncryptionKeyDto } from '../dto/response/encryption-key.dto' }) @PermissionGuard(Permission.WALLET_IMPORT, VaultPermission.CONNECTION_WRITE) @ApiTags('Encryption Key') -@ApiHeader({ - name: REQUEST_HEADER_CLIENT_ID, - required: true -}) +@ApiClientIdHeader() export class EncryptionKeyController { constructor(private readonly encryptionKeyService: EncryptionKeyService) {} diff --git a/packages/armory-sdk/Makefile b/packages/armory-sdk/Makefile index 0e9b75e4e..3bcc813d9 100644 --- a/packages/armory-sdk/Makefile +++ b/packages/armory-sdk/Makefile @@ -50,7 +50,8 @@ armory-sdk/generate/-http-client: --input-spec ${INPUT_SPEC} \ --output ${OUTPUT_DIR} \ --generator-name typescript-axios \ - --remove-operation-id-prefix + --remove-operation-id-prefix \ + --additional-properties=useSingleRequestParameter=${USE_SINGLE_REQUEST_PARAMETER} rm -rf ./${OUTPUT_DIR}/.openapi-generator \ ./${OUTPUT_DIR}/.gitignore \ @@ -61,9 +62,11 @@ armory-sdk/generate/-http-client: armory-sdk/generate/auth-client: INPUT_SPEC=http://localhost:3005/docs-yaml \ OUTPUT_DIR=packages/armory-sdk/src/lib/http/client/auth \ + USE_SINGLE_REQUEST_PARAMETER=false \ make armory-sdk/generate/-http-client armory-sdk/generate/vault-client: INPUT_SPEC=http://localhost:3011/docs-yaml \ OUTPUT_DIR=packages/armory-sdk/src/lib/http/client/vault \ + USE_SINGLE_REQUEST_PARAMETER=true \ make armory-sdk/generate/-http-client diff --git a/packages/armory-sdk/src/lib/http/client/vault/api.ts b/packages/armory-sdk/src/lib/http/client/vault/api.ts index c49867708..7638bb3d6 100644 --- a/packages/armory-sdk/src/lib/http/client/vault/api.ts +++ b/packages/armory-sdk/src/lib/http/client/vault/api.ts @@ -356,94 +356,6 @@ export type ClientDtoBackupPublicKeyUseEnum = typeof ClientDtoBackupPublicKeyUse */ export type ClientDtoConfigurationSource = string; -/** - * - * @export - * @interface ConnectionListDto - */ -export interface ConnectionListDto { - /** - * - * @type {Array} - * @memberof ConnectionListDto - */ - 'connections': Array; -} -/** - * - * @export - * @interface ConnectionListDtoConnectionsInner - */ -export interface ConnectionListDtoConnectionsInner { - /** - * - * @type {string} - * @memberof ConnectionListDtoConnectionsInner - */ - 'clientId': string; - /** - * - * @type {string} - * @memberof ConnectionListDtoConnectionsInner - */ - 'connectionId': string; - /** - * - * @type {any} - * @memberof ConnectionListDtoConnectionsInner - */ - 'createdAt': any; - /** - * - * @type {string} - * @memberof ConnectionListDtoConnectionsInner - */ - 'label'?: string; - /** - * - * @type {string} - * @memberof ConnectionListDtoConnectionsInner - */ - 'provider': ConnectionListDtoConnectionsInnerProviderEnum; - /** - * - * @type {any} - * @memberof ConnectionListDtoConnectionsInner - */ - 'revokedAt'?: any; - /** - * - * @type {string} - * @memberof ConnectionListDtoConnectionsInner - */ - 'status'?: ConnectionListDtoConnectionsInnerStatusEnum; - /** - * - * @type {any} - * @memberof ConnectionListDtoConnectionsInner - */ - 'updatedAt': any; - /** - * - * @type {string} - * @memberof ConnectionListDtoConnectionsInner - */ - 'url'?: string; -} - -export const ConnectionListDtoConnectionsInnerProviderEnum = { - Anchorage: 'anchorage' -} as const; - -export type ConnectionListDtoConnectionsInnerProviderEnum = typeof ConnectionListDtoConnectionsInnerProviderEnum[keyof typeof ConnectionListDtoConnectionsInnerProviderEnum]; -export const ConnectionListDtoConnectionsInnerStatusEnum = { - Pending: 'pending', - Active: 'active', - Revoked: 'revoked' -} as const; - -export type ConnectionListDtoConnectionsInnerStatusEnum = typeof ConnectionListDtoConnectionsInnerStatusEnum[keyof typeof ConnectionListDtoConnectionsInnerStatusEnum]; - /** * * @export @@ -470,10 +382,10 @@ export interface CreateClientDto { 'baseUrl'?: string; /** * - * @type {EncryptionKeyDtoPublicKey} + * @type {CreateClientDtoBackupPublicKey} * @memberof CreateClientDto */ - 'backupPublicKey'?: EncryptionKeyDtoPublicKey; + 'backupPublicKey'?: CreateClientDtoBackupPublicKey; /** * * @type {CreateClientDtoAuth} @@ -578,7 +490,7 @@ export interface CreateClientDtoAuthLocalAllowedUsersInner { * @type CreateClientDtoAuthLocalAllowedUsersInnerPublicKey * @export */ -export type CreateClientDtoAuthLocalAllowedUsersInnerPublicKey = CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf | CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1 | CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2 | CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3 | EncryptionKeyDtoPublicKey; +export type CreateClientDtoAuthLocalAllowedUsersInnerPublicKey = CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf | CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1 | CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2 | CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3 | CreateClientDtoBackupPublicKey; /** * @@ -928,7 +840,7 @@ export interface CreateClientDtoAuthTokenValidation { * @type CreateClientDtoAuthTokenValidationPinnedPublicKey * @export */ -export type CreateClientDtoAuthTokenValidationPinnedPublicKey = CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf | CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1 | CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2 | CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3 | EncryptionKeyDtoPublicKey; +export type CreateClientDtoAuthTokenValidationPinnedPublicKey = CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf | CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1 | CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2 | CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3 | CreateClientDtoBackupPublicKey; /** * @@ -973,6 +885,73 @@ export interface CreateClientDtoAuthTokenValidationVerification { */ 'allowWildcard'?: Array | null; } +/** + * + * @export + * @interface CreateClientDtoBackupPublicKey + */ +export interface CreateClientDtoBackupPublicKey { + /** + * + * @type {string} + * @memberof CreateClientDtoBackupPublicKey + */ + 'kty': CreateClientDtoBackupPublicKeyKtyEnum; + /** + * + * @type {string} + * @memberof CreateClientDtoBackupPublicKey + */ + 'alg': CreateClientDtoBackupPublicKeyAlgEnum; + /** + * + * @type {string} + * @memberof CreateClientDtoBackupPublicKey + */ + 'use'?: CreateClientDtoBackupPublicKeyUseEnum; + /** + * + * @type {string} + * @memberof CreateClientDtoBackupPublicKey + */ + 'kid': string; + /** + * + * @type {string} + * @memberof CreateClientDtoBackupPublicKey + */ + 'addr'?: string; + /** + * + * @type {string} + * @memberof CreateClientDtoBackupPublicKey + */ + 'n': string; + /** + * + * @type {string} + * @memberof CreateClientDtoBackupPublicKey + */ + 'e': string; +} + +export const CreateClientDtoBackupPublicKeyKtyEnum = { + Rsa: 'RSA' +} as const; + +export type CreateClientDtoBackupPublicKeyKtyEnum = typeof CreateClientDtoBackupPublicKeyKtyEnum[keyof typeof CreateClientDtoBackupPublicKeyKtyEnum]; +export const CreateClientDtoBackupPublicKeyAlgEnum = { + Rs256: 'RS256' +} as const; + +export type CreateClientDtoBackupPublicKeyAlgEnum = typeof CreateClientDtoBackupPublicKeyAlgEnum[keyof typeof CreateClientDtoBackupPublicKeyAlgEnum]; +export const CreateClientDtoBackupPublicKeyUseEnum = { + Sig: 'sig', + Enc: 'enc' +} as const; + +export type CreateClientDtoBackupPublicKeyUseEnum = typeof CreateClientDtoBackupPublicKeyUseEnum[keyof typeof CreateClientDtoBackupPublicKeyUseEnum]; + /** * * @export @@ -1098,10 +1077,48 @@ export interface EncryptionKeyDto { * @memberof EncryptionKeyDto */ 'publicKey': EncryptionKeyDtoPublicKey; + /** + * + * @type {EncryptionKeyDtoData} + * @memberof EncryptionKeyDto + */ + 'data': EncryptionKeyDtoData; } /** * * @export + * @interface EncryptionKeyDtoData + */ +export interface EncryptionKeyDtoData { + /** + * + * @type {string} + * @memberof EncryptionKeyDtoData + */ + 'keyId'?: string; + /** + * + * @type {EncryptionKeyDtoDataJwk} + * @memberof EncryptionKeyDtoData + */ + 'jwk'?: EncryptionKeyDtoDataJwk; + /** + * Base64url encoded PEM public key + * @type {string} + * @memberof EncryptionKeyDtoData + */ + 'pem'?: string; +} +/** + * @type EncryptionKeyDtoDataJwk + * JWK format of the public key + * @export + */ +export type EncryptionKeyDtoDataJwk = CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf | CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf1 | CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf2 | CreateClientDtoAuthLocalAllowedUsersInnerPublicKeyOneOf3 | CreateClientDtoBackupPublicKey; + +/** + * (DEPRECATED: use data.jwk instead) JWK format of the public key + * @export * @interface EncryptionKeyDtoPublicKey */ export interface EncryptionKeyDtoPublicKey { @@ -1275,555 +1292,708 @@ export type InitiateConnectionDtoProviderEnum = typeof InitiateConnectionDtoProv export interface PaginatedAccountsDto { /** * - * @type {Array} + * @type {Array} * @memberof PaginatedAccountsDto */ - 'accounts': Array; + 'data': Array; /** * - * @type {PaginatedWalletsDtoPage} + * @type {PaginatedAccountsDtoPage} * @memberof PaginatedAccountsDto */ - 'page'?: PaginatedWalletsDtoPage; -} -/** - * - * @export - * @interface PaginatedAddressesDto - */ -export interface PaginatedAddressesDto { - /** - * - * @type {Array} - * @memberof PaginatedAddressesDto - */ - 'addresses': Array; - /** - * - * @type {PaginatedWalletsDtoPage} - * @memberof PaginatedAddressesDto - */ - 'page'?: PaginatedWalletsDtoPage; -} -/** - * - * @export - * @interface PaginatedSyncsDto - */ -export interface PaginatedSyncsDto { - /** - * - * @type {PaginatedWalletsDtoPage} - * @memberof PaginatedSyncsDto - */ - 'page'?: PaginatedWalletsDtoPage; - /** - * - * @type {Array} - * @memberof PaginatedSyncsDto - */ - 'syncs': Array; -} -/** - * - * @export - * @interface PaginatedWalletsDto - */ -export interface PaginatedWalletsDto { - /** - * - * @type {Array} - * @memberof PaginatedWalletsDto - */ - 'wallets': Array; - /** - * - * @type {PaginatedWalletsDtoPage} - * @memberof PaginatedWalletsDto - */ - 'page'?: PaginatedWalletsDtoPage; + 'page'?: PaginatedAccountsDtoPage; } /** * * @export - * @interface PaginatedWalletsDtoPage + * @interface PaginatedAccountsDtoDataInner */ -export interface PaginatedWalletsDtoPage { +export interface PaginatedAccountsDtoDataInner { /** * * @type {string} - * @memberof PaginatedWalletsDtoPage + * @memberof PaginatedAccountsDtoDataInner */ - 'next': string | null; -} -/** - * - * @export - * @interface PaginatedWalletsDtoWalletsInner - */ -export interface PaginatedWalletsDtoWalletsInner { + 'accountId': string; /** * - * @type {string} - * @memberof PaginatedWalletsDtoWalletsInner + * @type {Array} + * @memberof PaginatedAccountsDtoDataInner */ - 'walletId': string; + 'addresses'?: Array; /** * - * @type {Array} - * @memberof PaginatedWalletsDtoWalletsInner + * @type {string} + * @memberof PaginatedAccountsDtoDataInner */ - 'accounts'?: Array; + 'clientId': string; /** * - * @type {Array} - * @memberof PaginatedWalletsDtoWalletsInner + * @type {any} + * @memberof PaginatedAccountsDtoDataInner */ - 'connections': Array; + 'createdAt': any; /** * * @type {string} - * @memberof PaginatedWalletsDtoWalletsInner + * @memberof PaginatedAccountsDtoDataInner */ - 'label'?: string | null; + 'externalId': string; /** * * @type {string} - * @memberof PaginatedWalletsDtoWalletsInner + * @memberof PaginatedAccountsDtoDataInner */ - 'clientId': string; + 'label'?: string | null; /** * * @type {string} - * @memberof PaginatedWalletsDtoWalletsInner + * @memberof PaginatedAccountsDtoDataInner */ - 'provider': PaginatedWalletsDtoWalletsInnerProviderEnum; + 'networkId': string; /** * * @type {string} - * @memberof PaginatedWalletsDtoWalletsInner + * @memberof PaginatedAccountsDtoDataInner */ - 'externalId': string; + 'provider': PaginatedAccountsDtoDataInnerProviderEnum; /** * * @type {any} - * @memberof PaginatedWalletsDtoWalletsInner + * @memberof PaginatedAccountsDtoDataInner */ - 'createdAt': any; + 'updatedAt': any; /** * - * @type {any} - * @memberof PaginatedWalletsDtoWalletsInner + * @type {string} + * @memberof PaginatedAccountsDtoDataInner */ - 'updatedAt': any; + 'walletId': string; } -export const PaginatedWalletsDtoWalletsInnerProviderEnum = { +export const PaginatedAccountsDtoDataInnerProviderEnum = { Anchorage: 'anchorage' } as const; -export type PaginatedWalletsDtoWalletsInnerProviderEnum = typeof PaginatedWalletsDtoWalletsInnerProviderEnum[keyof typeof PaginatedWalletsDtoWalletsInnerProviderEnum]; +export type PaginatedAccountsDtoDataInnerProviderEnum = typeof PaginatedAccountsDtoDataInnerProviderEnum[keyof typeof PaginatedAccountsDtoDataInnerProviderEnum]; /** * * @export - * @interface PaginatedWalletsDtoWalletsInnerAccountsInner + * @interface PaginatedAccountsDtoDataInnerAddressesInner */ -export interface PaginatedWalletsDtoWalletsInnerAccountsInner { +export interface PaginatedAccountsDtoDataInnerAddressesInner { /** * * @type {string} - * @memberof PaginatedWalletsDtoWalletsInnerAccountsInner + * @memberof PaginatedAccountsDtoDataInnerAddressesInner */ 'accountId': string; /** * * @type {string} - * @memberof PaginatedWalletsDtoWalletsInnerAccountsInner + * @memberof PaginatedAccountsDtoDataInnerAddressesInner */ - 'label'?: string | null; + 'address': string; /** * - * @type {Array} - * @memberof PaginatedWalletsDtoWalletsInnerAccountsInner + * @type {string} + * @memberof PaginatedAccountsDtoDataInnerAddressesInner */ - 'addresses'?: Array; + 'addressId': string; /** * * @type {string} - * @memberof PaginatedWalletsDtoWalletsInnerAccountsInner + * @memberof PaginatedAccountsDtoDataInnerAddressesInner */ 'clientId': string; /** * - * @type {string} - * @memberof PaginatedWalletsDtoWalletsInnerAccountsInner + * @type {any} + * @memberof PaginatedAccountsDtoDataInnerAddressesInner */ - 'provider': PaginatedWalletsDtoWalletsInnerAccountsInnerProviderEnum; + 'createdAt': any; /** * * @type {string} - * @memberof PaginatedWalletsDtoWalletsInnerAccountsInner + * @memberof PaginatedAccountsDtoDataInnerAddressesInner */ 'externalId': string; /** * * @type {string} - * @memberof PaginatedWalletsDtoWalletsInnerAccountsInner - */ - 'walletId': string; - /** - * - * @type {string} - * @memberof PaginatedWalletsDtoWalletsInnerAccountsInner - */ - 'networkId': string; - /** - * - * @type {any} - * @memberof PaginatedWalletsDtoWalletsInnerAccountsInner + * @memberof PaginatedAccountsDtoDataInnerAddressesInner */ - 'createdAt': any; + 'provider': PaginatedAccountsDtoDataInnerAddressesInnerProviderEnum; /** * * @type {any} - * @memberof PaginatedWalletsDtoWalletsInnerAccountsInner + * @memberof PaginatedAccountsDtoDataInnerAddressesInner */ 'updatedAt': any; } -export const PaginatedWalletsDtoWalletsInnerAccountsInnerProviderEnum = { +export const PaginatedAccountsDtoDataInnerAddressesInnerProviderEnum = { Anchorage: 'anchorage' } as const; -export type PaginatedWalletsDtoWalletsInnerAccountsInnerProviderEnum = typeof PaginatedWalletsDtoWalletsInnerAccountsInnerProviderEnum[keyof typeof PaginatedWalletsDtoWalletsInnerAccountsInnerProviderEnum]; +export type PaginatedAccountsDtoDataInnerAddressesInnerProviderEnum = typeof PaginatedAccountsDtoDataInnerAddressesInnerProviderEnum[keyof typeof PaginatedAccountsDtoDataInnerAddressesInnerProviderEnum]; /** * * @export - * @interface PaginatedWalletsDtoWalletsInnerAccountsInnerAddressesInner + * @interface PaginatedAccountsDtoPage */ -export interface PaginatedWalletsDtoWalletsInnerAccountsInnerAddressesInner { - /** - * - * @type {string} - * @memberof PaginatedWalletsDtoWalletsInnerAccountsInnerAddressesInner - */ - 'addressId': string; +export interface PaginatedAccountsDtoPage { /** * * @type {string} - * @memberof PaginatedWalletsDtoWalletsInnerAccountsInnerAddressesInner + * @memberof PaginatedAccountsDtoPage */ - 'clientId': string; + 'next': string | null; +} +/** + * + * @export + * @interface PaginatedAddressesDto + */ +export interface PaginatedAddressesDto { /** * - * @type {string} - * @memberof PaginatedWalletsDtoWalletsInnerAccountsInnerAddressesInner + * @type {Array} + * @memberof PaginatedAddressesDto */ - 'provider': PaginatedWalletsDtoWalletsInnerAccountsInnerAddressesInnerProviderEnum; + 'data': Array; /** * - * @type {string} - * @memberof PaginatedWalletsDtoWalletsInnerAccountsInnerAddressesInner + * @type {PaginatedAccountsDtoPage} + * @memberof PaginatedAddressesDto */ - 'externalId': string; + 'page'?: PaginatedAccountsDtoPage; +} +/** + * + * @export + * @interface PaginatedConnectionsDto + */ +export interface PaginatedConnectionsDto { /** * - * @type {string} - * @memberof PaginatedWalletsDtoWalletsInnerAccountsInnerAddressesInner + * @type {Array} + * @memberof PaginatedConnectionsDto */ - 'accountId': string; + 'data': Array; /** * - * @type {string} - * @memberof PaginatedWalletsDtoWalletsInnerAccountsInnerAddressesInner + * @type {PaginatedAccountsDtoPage} + * @memberof PaginatedConnectionsDto */ - 'address': string; - /** + 'page'?: PaginatedAccountsDtoPage; +} +/** + * + * @export + * @interface PaginatedSyncsDto + */ +export interface PaginatedSyncsDto { + /** + * + * @type {Array} + * @memberof PaginatedSyncsDto + */ + 'data': Array; + /** + * + * @type {PaginatedAccountsDtoPage} + * @memberof PaginatedSyncsDto + */ + 'page'?: PaginatedAccountsDtoPage; +} +/** + * + * @export + * @interface PaginatedWalletsDto + */ +export interface PaginatedWalletsDto { + /** + * + * @type {Array} + * @memberof PaginatedWalletsDto + */ + 'data': Array; + /** + * + * @type {PaginatedAccountsDtoPage} + * @memberof PaginatedWalletsDto + */ + 'page'?: PaginatedAccountsDtoPage; +} +/** + * + * @export + * @interface PaginatedWalletsDtoDataInner + */ +export interface PaginatedWalletsDtoDataInner { + /** + * + * @type {Array} + * @memberof PaginatedWalletsDtoDataInner + */ + 'accounts'?: Array; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoDataInner + */ + 'clientId': string; + /** + * + * @type {Array} + * @memberof PaginatedWalletsDtoDataInner + */ + 'connections': Array; + /** * * @type {any} - * @memberof PaginatedWalletsDtoWalletsInnerAccountsInnerAddressesInner + * @memberof PaginatedWalletsDtoDataInner */ 'createdAt': any; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoDataInner + */ + 'externalId': string; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoDataInner + */ + 'label'?: string | null; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoDataInner + */ + 'provider': PaginatedWalletsDtoDataInnerProviderEnum; /** * * @type {any} - * @memberof PaginatedWalletsDtoWalletsInnerAccountsInnerAddressesInner + * @memberof PaginatedWalletsDtoDataInner */ 'updatedAt': any; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoDataInner + */ + 'walletId': string; } -export const PaginatedWalletsDtoWalletsInnerAccountsInnerAddressesInnerProviderEnum = { +export const PaginatedWalletsDtoDataInnerProviderEnum = { Anchorage: 'anchorage' } as const; -export type PaginatedWalletsDtoWalletsInnerAccountsInnerAddressesInnerProviderEnum = typeof PaginatedWalletsDtoWalletsInnerAccountsInnerAddressesInnerProviderEnum[keyof typeof PaginatedWalletsDtoWalletsInnerAccountsInnerAddressesInnerProviderEnum]; +export type PaginatedWalletsDtoDataInnerProviderEnum = typeof PaginatedWalletsDtoDataInnerProviderEnum[keyof typeof PaginatedWalletsDtoDataInnerProviderEnum]; /** * * @export - * @interface PaginatedWalletsDtoWalletsInnerConnectionsInner + * @interface PaginatedWalletsDtoDataInnerConnectionsInner */ -export interface PaginatedWalletsDtoWalletsInnerConnectionsInner { +export interface PaginatedWalletsDtoDataInnerConnectionsInner { /** * * @type {string} - * @memberof PaginatedWalletsDtoWalletsInnerConnectionsInner + * @memberof PaginatedWalletsDtoDataInnerConnectionsInner */ 'connectionId': string; /** * * @type {string} - * @memberof PaginatedWalletsDtoWalletsInnerConnectionsInner + * @memberof PaginatedWalletsDtoDataInnerConnectionsInner */ - 'status'?: PaginatedWalletsDtoWalletsInnerConnectionsInnerStatusEnum; + 'status'?: PaginatedWalletsDtoDataInnerConnectionsInnerStatusEnum; /** * * @type {string} - * @memberof PaginatedWalletsDtoWalletsInnerConnectionsInner + * @memberof PaginatedWalletsDtoDataInnerConnectionsInner */ 'label'?: string; /** * * @type {string} - * @memberof PaginatedWalletsDtoWalletsInnerConnectionsInner + * @memberof PaginatedWalletsDtoDataInnerConnectionsInner */ - 'provider': PaginatedWalletsDtoWalletsInnerConnectionsInnerProviderEnum; + 'provider': PaginatedWalletsDtoDataInnerConnectionsInnerProviderEnum; } -export const PaginatedWalletsDtoWalletsInnerConnectionsInnerStatusEnum = { +export const PaginatedWalletsDtoDataInnerConnectionsInnerStatusEnum = { Pending: 'pending', Active: 'active', Revoked: 'revoked' } as const; -export type PaginatedWalletsDtoWalletsInnerConnectionsInnerStatusEnum = typeof PaginatedWalletsDtoWalletsInnerConnectionsInnerStatusEnum[keyof typeof PaginatedWalletsDtoWalletsInnerConnectionsInnerStatusEnum]; -export const PaginatedWalletsDtoWalletsInnerConnectionsInnerProviderEnum = { +export type PaginatedWalletsDtoDataInnerConnectionsInnerStatusEnum = typeof PaginatedWalletsDtoDataInnerConnectionsInnerStatusEnum[keyof typeof PaginatedWalletsDtoDataInnerConnectionsInnerStatusEnum]; +export const PaginatedWalletsDtoDataInnerConnectionsInnerProviderEnum = { Anchorage: 'anchorage' } as const; -export type PaginatedWalletsDtoWalletsInnerConnectionsInnerProviderEnum = typeof PaginatedWalletsDtoWalletsInnerConnectionsInnerProviderEnum[keyof typeof PaginatedWalletsDtoWalletsInnerConnectionsInnerProviderEnum]; +export type PaginatedWalletsDtoDataInnerConnectionsInnerProviderEnum = typeof PaginatedWalletsDtoDataInnerConnectionsInnerProviderEnum[keyof typeof PaginatedWalletsDtoDataInnerConnectionsInnerProviderEnum]; /** * * @export - * @interface PendingConnectionDto + * @interface PongDto + */ +export interface PongDto { + /** + * + * @type {boolean} + * @memberof PongDto + */ + 'pong': boolean; +} +/** + * + * @export + * @interface ProviderAccountDto + */ +export interface ProviderAccountDto { + /** + * + * @type {PaginatedAccountsDtoDataInner} + * @memberof ProviderAccountDto + */ + 'data': PaginatedAccountsDtoDataInner; +} +/** + * + * @export + * @interface ProviderConnectionDto + */ +export interface ProviderConnectionDto { + /** + * + * @type {ProviderConnectionDtoData} + * @memberof ProviderConnectionDto + */ + 'data': ProviderConnectionDtoData; +} +/** + * + * @export + * @interface ProviderConnectionDtoData */ -export interface PendingConnectionDto { +export interface ProviderConnectionDtoData { /** * * @type {string} - * @memberof PendingConnectionDto + * @memberof ProviderConnectionDtoData */ 'clientId': string; /** * * @type {string} - * @memberof PendingConnectionDto + * @memberof ProviderConnectionDtoData */ 'connectionId': string; + /** + * + * @type {any} + * @memberof ProviderConnectionDtoData + */ + 'createdAt': any; /** * * @type {string} - * @memberof PendingConnectionDto + * @memberof ProviderConnectionDtoData */ - 'provider': PendingConnectionDtoProviderEnum; + 'label'?: string; /** * * @type {string} - * @memberof PendingConnectionDto + * @memberof ProviderConnectionDtoData */ - 'status': PendingConnectionDtoStatusEnum; + 'provider': ProviderConnectionDtoDataProviderEnum; /** * * @type {any} - * @memberof PendingConnectionDto + * @memberof ProviderConnectionDtoData */ - 'createdAt': any; + 'revokedAt'?: any; + /** + * + * @type {string} + * @memberof ProviderConnectionDtoData + */ + 'status'?: ProviderConnectionDtoDataStatusEnum; /** * - * @type {PendingConnectionDtoPublicKey} - * @memberof PendingConnectionDto + * @type {any} + * @memberof ProviderConnectionDtoData */ - 'publicKey'?: PendingConnectionDtoPublicKey; + 'updatedAt': any; /** * - * @type {PendingConnectionDtoEncryptionPublicKey} - * @memberof PendingConnectionDto + * @type {string} + * @memberof ProviderConnectionDtoData */ - 'encryptionPublicKey': PendingConnectionDtoEncryptionPublicKey; + 'url'?: string; } -export const PendingConnectionDtoProviderEnum = { +export const ProviderConnectionDtoDataProviderEnum = { Anchorage: 'anchorage' } as const; -export type PendingConnectionDtoProviderEnum = typeof PendingConnectionDtoProviderEnum[keyof typeof PendingConnectionDtoProviderEnum]; -export const PendingConnectionDtoStatusEnum = { - Pending: 'pending' +export type ProviderConnectionDtoDataProviderEnum = typeof ProviderConnectionDtoDataProviderEnum[keyof typeof ProviderConnectionDtoDataProviderEnum]; +export const ProviderConnectionDtoDataStatusEnum = { + Pending: 'pending', + Active: 'active', + Revoked: 'revoked' } as const; -export type PendingConnectionDtoStatusEnum = typeof PendingConnectionDtoStatusEnum[keyof typeof PendingConnectionDtoStatusEnum]; +export type ProviderConnectionDtoDataStatusEnum = typeof ProviderConnectionDtoDataStatusEnum[keyof typeof ProviderConnectionDtoDataStatusEnum]; /** * * @export - * @interface PendingConnectionDtoEncryptionPublicKey + * @interface ProviderPendingConnectionDto + */ +export interface ProviderPendingConnectionDto { + /** + * + * @type {ProviderPendingConnectionDtoData} + * @memberof ProviderPendingConnectionDto + */ + 'data': ProviderPendingConnectionDtoData; +} +/** + * + * @export + * @interface ProviderPendingConnectionDtoData */ -export interface PendingConnectionDtoEncryptionPublicKey { +export interface ProviderPendingConnectionDtoData { /** * * @type {string} - * @memberof PendingConnectionDtoEncryptionPublicKey + * @memberof ProviderPendingConnectionDtoData */ - 'keyId'?: string; + 'clientId': string; /** * - * @type {CreateClientDtoAuthLocalAllowedUsersInnerPublicKey} - * @memberof PendingConnectionDtoEncryptionPublicKey + * @type {string} + * @memberof ProviderPendingConnectionDtoData */ - 'jwk'?: CreateClientDtoAuthLocalAllowedUsersInnerPublicKey; + 'connectionId': string; + /** + * + * @type {string} + * @memberof ProviderPendingConnectionDtoData + */ + 'provider': ProviderPendingConnectionDtoDataProviderEnum; + /** + * + * @type {string} + * @memberof ProviderPendingConnectionDtoData + */ + 'status': ProviderPendingConnectionDtoDataStatusEnum; + /** + * + * @type {any} + * @memberof ProviderPendingConnectionDtoData + */ + 'createdAt': any; + /** + * + * @type {ProviderPendingConnectionDtoDataPublicKey} + * @memberof ProviderPendingConnectionDtoData + */ + 'publicKey'?: ProviderPendingConnectionDtoDataPublicKey; + /** + * + * @type {EncryptionKeyDtoData} + * @memberof ProviderPendingConnectionDtoData + */ + 'encryptionPublicKey': EncryptionKeyDtoData; } + +export const ProviderPendingConnectionDtoDataProviderEnum = { + Anchorage: 'anchorage' +} as const; + +export type ProviderPendingConnectionDtoDataProviderEnum = typeof ProviderPendingConnectionDtoDataProviderEnum[keyof typeof ProviderPendingConnectionDtoDataProviderEnum]; +export const ProviderPendingConnectionDtoDataStatusEnum = { + Pending: 'pending' +} as const; + +export type ProviderPendingConnectionDtoDataStatusEnum = typeof ProviderPendingConnectionDtoDataStatusEnum[keyof typeof ProviderPendingConnectionDtoDataStatusEnum]; + /** * * @export - * @interface PendingConnectionDtoPublicKey + * @interface ProviderPendingConnectionDtoDataPublicKey */ -export interface PendingConnectionDtoPublicKey { +export interface ProviderPendingConnectionDtoDataPublicKey { /** * * @type {string} - * @memberof PendingConnectionDtoPublicKey + * @memberof ProviderPendingConnectionDtoDataPublicKey */ 'keyId'?: string; /** * * @type {CreateClientDtoAuthLocalAllowedUsersInnerPublicKey} - * @memberof PendingConnectionDtoPublicKey + * @memberof ProviderPendingConnectionDtoDataPublicKey */ 'jwk'?: CreateClientDtoAuthLocalAllowedUsersInnerPublicKey; /** * * @type {any} - * @memberof PendingConnectionDtoPublicKey + * @memberof ProviderPendingConnectionDtoDataPublicKey */ 'hex'?: any; } /** * * @export - * @interface PongDto + * @interface ProviderWalletDto */ -export interface PongDto { +export interface ProviderWalletDto { /** * - * @type {boolean} - * @memberof PongDto + * @type {PaginatedWalletsDtoDataInner} + * @memberof ProviderWalletDto */ - 'pong': boolean; + 'data': PaginatedWalletsDtoDataInner; } /** * * @export - * @interface ProviderAccountDto + * @interface SendTransferDto */ -export interface ProviderAccountDto { +export interface SendTransferDto { /** * - * @type {PaginatedWalletsDtoWalletsInnerAccountsInner} - * @memberof ProviderAccountDto + * @type {SendTransferDtoSource} + * @memberof SendTransferDto */ - 'account': PaginatedWalletsDtoWalletsInnerAccountsInner; -} -/** - * - * @export - * @interface ProviderConnectionDto - */ -export interface ProviderConnectionDto { + 'source': SendTransferDtoSource; /** * - * @type {string} - * @memberof ProviderConnectionDto + * @type {SendTransferDtoDestination} + * @memberof SendTransferDto */ - 'clientId': string; + 'destination': SendTransferDtoDestination; /** * * @type {string} - * @memberof ProviderConnectionDto + * @memberof SendTransferDto */ - 'connectionId': string; + 'amount': string; /** * - * @type {any} - * @memberof ProviderConnectionDto + * @type {string} + * @memberof SendTransferDto */ - 'createdAt': any; + 'assetId': string; /** * * @type {string} - * @memberof ProviderConnectionDto + * @memberof SendTransferDto */ - 'label'?: string; + 'networkFeeAttribution'?: SendTransferDtoNetworkFeeAttributionEnum; /** * * @type {string} - * @memberof ProviderConnectionDto + * @memberof SendTransferDto */ - 'provider': ProviderConnectionDtoProviderEnum; + 'customerRefId'?: string; /** * - * @type {any} - * @memberof ProviderConnectionDto + * @type {string} + * @memberof SendTransferDto */ - 'revokedAt'?: any; + 'idempotenceId'?: string; /** * * @type {string} - * @memberof ProviderConnectionDto + * @memberof SendTransferDto */ - 'status'?: ProviderConnectionDtoStatusEnum; + 'memo'?: string; /** * - * @type {any} - * @memberof ProviderConnectionDto + * @type {string} + * @memberof SendTransferDto */ - 'updatedAt': any; + 'provider'?: SendTransferDtoProviderEnum; /** * - * @type {string} - * @memberof ProviderConnectionDto + * @type {any} + * @memberof SendTransferDto */ - 'url'?: string; + 'providerSpecific'?: any; } -export const ProviderConnectionDtoProviderEnum = { - Anchorage: 'anchorage' +export const SendTransferDtoNetworkFeeAttributionEnum = { + OnTop: 'on_top', + Deduct: 'deduct' } as const; -export type ProviderConnectionDtoProviderEnum = typeof ProviderConnectionDtoProviderEnum[keyof typeof ProviderConnectionDtoProviderEnum]; -export const ProviderConnectionDtoStatusEnum = { - Pending: 'pending', - Active: 'active', - Revoked: 'revoked' +export type SendTransferDtoNetworkFeeAttributionEnum = typeof SendTransferDtoNetworkFeeAttributionEnum[keyof typeof SendTransferDtoNetworkFeeAttributionEnum]; +export const SendTransferDtoProviderEnum = { + Anchorage: 'anchorage' } as const; -export type ProviderConnectionDtoStatusEnum = typeof ProviderConnectionDtoStatusEnum[keyof typeof ProviderConnectionDtoStatusEnum]; +export type SendTransferDtoProviderEnum = typeof SendTransferDtoProviderEnum[keyof typeof SendTransferDtoProviderEnum]; + +/** + * @type SendTransferDtoDestination + * @export + */ +export type SendTransferDtoDestination = SendTransferDtoDestinationOneOf | SendTransferDtoSource; /** * * @export - * @interface ProviderWalletDto + * @interface SendTransferDtoDestinationOneOf */ -export interface ProviderWalletDto { +export interface SendTransferDtoDestinationOneOf { /** * - * @type {PaginatedWalletsDtoWalletsInner} - * @memberof ProviderWalletDto + * @type {string} + * @memberof SendTransferDtoDestinationOneOf + */ + 'address': string; +} +/** + * + * @export + * @interface SendTransferDtoSource + */ +export interface SendTransferDtoSource { + /** + * + * @type {string} + * @memberof SendTransferDtoSource + */ + 'id': string; + /** + * + * @type {string} + * @memberof SendTransferDtoSource */ - 'wallet': PaginatedWalletsDtoWalletsInner; + 'type': SendTransferDtoSourceTypeEnum; } + +export const SendTransferDtoSourceTypeEnum = { + Wallet: 'wallet', + Account: 'account', + Address: 'address' +} as const; + +export type SendTransferDtoSourceTypeEnum = typeof SendTransferDtoSourceTypeEnum[keyof typeof SendTransferDtoSourceTypeEnum]; + /** * * @export @@ -2437,158 +2607,256 @@ export interface StartSyncDto { export interface SyncDto { /** * - * @type {string} + * @type {SyncStartedDtoDataSyncsInner} * @memberof SyncDto */ - 'clientId': string; + 'data': SyncStartedDtoDataSyncsInner; +} +/** + * + * @export + * @interface SyncStartedDto + */ +export interface SyncStartedDto { /** * - * @type {any} - * @memberof SyncDto + * @type {SyncStartedDtoData} + * @memberof SyncStartedDto */ - 'completedAt'?: any; + 'data': SyncStartedDtoData; +} +/** + * + * @export + * @interface SyncStartedDtoData + */ +export interface SyncStartedDtoData { /** * - * @type {string} - * @memberof SyncDto + * @type {boolean} + * @memberof SyncStartedDtoData */ - 'connectionId': string; + 'started': boolean; + /** + * + * @type {Array} + * @memberof SyncStartedDtoData + */ + 'syncs': Array; +} +/** + * + * @export + * @interface SyncStartedDtoDataSyncsInner + */ +export interface SyncStartedDtoDataSyncsInner { + /** + * + * @type {string} + * @memberof SyncStartedDtoDataSyncsInner + */ + 'clientId': string; /** * * @type {any} - * @memberof SyncDto + * @memberof SyncStartedDtoDataSyncsInner + */ + 'completedAt'?: any; + /** + * + * @type {string} + * @memberof SyncStartedDtoDataSyncsInner + */ + 'connectionId': string; + /** + * + * @type {any} + * @memberof SyncStartedDtoDataSyncsInner */ 'createdAt': any; /** * - * @type {SyncStatusDtoSyncsInnerError} - * @memberof SyncDto + * @type {SyncStartedDtoDataSyncsInnerError} + * @memberof SyncStartedDtoDataSyncsInner */ - 'error'?: SyncStatusDtoSyncsInnerError; + 'error'?: SyncStartedDtoDataSyncsInnerError; /** * * @type {string} - * @memberof SyncDto + * @memberof SyncStartedDtoDataSyncsInner */ - 'status'?: SyncDtoStatusEnum; + 'status'?: SyncStartedDtoDataSyncsInnerStatusEnum; /** * * @type {string} - * @memberof SyncDto + * @memberof SyncStartedDtoDataSyncsInner */ 'syncId': string; } -export const SyncDtoStatusEnum = { +export const SyncStartedDtoDataSyncsInnerStatusEnum = { Processing: 'processing', Success: 'success', Failed: 'failed' } as const; -export type SyncDtoStatusEnum = typeof SyncDtoStatusEnum[keyof typeof SyncDtoStatusEnum]; +export type SyncStartedDtoDataSyncsInnerStatusEnum = typeof SyncStartedDtoDataSyncsInnerStatusEnum[keyof typeof SyncStartedDtoDataSyncsInnerStatusEnum]; /** * * @export - * @interface SyncStatusDto + * @interface SyncStartedDtoDataSyncsInnerError */ -export interface SyncStatusDto { +export interface SyncStartedDtoDataSyncsInnerError { /** * - * @type {boolean} - * @memberof SyncStatusDto + * @type {string} + * @memberof SyncStartedDtoDataSyncsInnerError */ - 'started': boolean; + 'name'?: string; /** * - * @type {Array} - * @memberof SyncStatusDto + * @type {string} + * @memberof SyncStartedDtoDataSyncsInnerError + */ + 'message'?: string; + /** + * + * @type {string} + * @memberof SyncStartedDtoDataSyncsInnerError + */ + 'traceId'?: string; +} +/** + * + * @export + * @interface TransferDto + */ +export interface TransferDto { + /** + * + * @type {TransferDtoData} + * @memberof TransferDto */ - 'syncs': Array; + 'data': TransferDtoData; } /** * * @export - * @interface SyncStatusDtoSyncsInner + * @interface TransferDtoData */ -export interface SyncStatusDtoSyncsInner { +export interface TransferDtoData { + /** + * + * @type {string} + * @memberof TransferDtoData + */ + 'assetId': string; /** * * @type {string} - * @memberof SyncStatusDtoSyncsInner + * @memberof TransferDtoData */ 'clientId': string; /** * * @type {any} - * @memberof SyncStatusDtoSyncsInner + * @memberof TransferDtoData */ - 'completedAt'?: any; + 'createdAt': any; /** * * @type {string} - * @memberof SyncStatusDtoSyncsInner + * @memberof TransferDtoData */ - 'connectionId': string; + 'customerRefId': string | null; /** * - * @type {any} - * @memberof SyncStatusDtoSyncsInner + * @type {SendTransferDtoDestination} + * @memberof TransferDtoData */ - 'createdAt': any; + 'destination': SendTransferDtoDestination; /** * - * @type {SyncStatusDtoSyncsInnerError} - * @memberof SyncStatusDtoSyncsInner + * @type {string} + * @memberof TransferDtoData */ - 'error'?: SyncStatusDtoSyncsInnerError; + 'externalId': string; /** * * @type {string} - * @memberof SyncStatusDtoSyncsInner + * @memberof TransferDtoData */ - 'status'?: SyncStatusDtoSyncsInnerStatusEnum; + 'grossAmount': string; /** * * @type {string} - * @memberof SyncStatusDtoSyncsInner + * @memberof TransferDtoData */ - 'syncId': string; -} - -export const SyncStatusDtoSyncsInnerStatusEnum = { - Processing: 'processing', - Success: 'success', - Failed: 'failed' -} as const; - -export type SyncStatusDtoSyncsInnerStatusEnum = typeof SyncStatusDtoSyncsInnerStatusEnum[keyof typeof SyncStatusDtoSyncsInnerStatusEnum]; - -/** - * - * @export - * @interface SyncStatusDtoSyncsInnerError - */ -export interface SyncStatusDtoSyncsInnerError { + 'idempotenceId': string | null; /** * * @type {string} - * @memberof SyncStatusDtoSyncsInnerError + * @memberof TransferDtoData */ - 'name'?: string; + 'memo': string | null; /** * * @type {string} - * @memberof SyncStatusDtoSyncsInnerError + * @memberof TransferDtoData */ - 'message'?: string; + 'networkFeeAttribution': TransferDtoDataNetworkFeeAttributionEnum; /** * * @type {string} - * @memberof SyncStatusDtoSyncsInnerError + * @memberof TransferDtoData */ - 'traceId'?: string; + 'provider': TransferDtoDataProviderEnum; + /** + * + * @type {any} + * @memberof TransferDtoData + */ + 'providerSpecific': any | null; + /** + * + * @type {SendTransferDtoSource} + * @memberof TransferDtoData + */ + 'source': SendTransferDtoSource; + /** + * + * @type {string} + * @memberof TransferDtoData + */ + 'status'?: TransferDtoDataStatusEnum; + /** + * + * @type {string} + * @memberof TransferDtoData + */ + 'transferId': string; } + +export const TransferDtoDataNetworkFeeAttributionEnum = { + OnTop: 'on_top', + Deduct: 'deduct' +} as const; + +export type TransferDtoDataNetworkFeeAttributionEnum = typeof TransferDtoDataNetworkFeeAttributionEnum[keyof typeof TransferDtoDataNetworkFeeAttributionEnum]; +export const TransferDtoDataProviderEnum = { + Anchorage: 'anchorage' +} as const; + +export type TransferDtoDataProviderEnum = typeof TransferDtoDataProviderEnum[keyof typeof TransferDtoDataProviderEnum]; +export const TransferDtoDataStatusEnum = { + Processing: 'processing', + Success: 'success', + Failed: 'failed' +} as const; + +export type TransferDtoDataStatusEnum = typeof TransferDtoDataStatusEnum[keyof typeof TransferDtoDataStatusEnum]; + /** * * @export @@ -2749,16 +3017,14 @@ export const AccountApiAxiosParamCreator = function (configuration?: Configurati * * @summary Add a new account to a wallet * @param {string} xClientId - * @param {string} authorization * @param {DeriveAccountDto} deriveAccountDto + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - derive: async (xClientId: string, authorization: string, deriveAccountDto: DeriveAccountDto, options: RawAxiosRequestConfig = {}): Promise => { + derive: async (xClientId: string, deriveAccountDto: DeriveAccountDto, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'xClientId' is not null or undefined assertParamExists('derive', 'xClientId', xClientId) - // verify required parameter 'authorization' is not null or undefined - assertParamExists('derive', 'authorization', authorization) // verify required parameter 'deriveAccountDto' is not null or undefined assertParamExists('derive', 'deriveAccountDto', deriveAccountDto) const localVarPath = `/v1/accounts`; @@ -2775,6 +3041,9 @@ export const AccountApiAxiosParamCreator = function (configuration?: Configurati // authentication GNAP required + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + if (xClientId != null) { localVarHeaderParameter['x-client-id'] = String(xClientId); } @@ -2801,16 +3070,14 @@ export const AccountApiAxiosParamCreator = function (configuration?: Configurati * * @summary Imports an account * @param {string} xClientId - * @param {string} authorization * @param {ImportPrivateKeyDto} importPrivateKeyDto + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - importPrivateKey: async (xClientId: string, authorization: string, importPrivateKeyDto: ImportPrivateKeyDto, options: RawAxiosRequestConfig = {}): Promise => { + importPrivateKey: async (xClientId: string, importPrivateKeyDto: ImportPrivateKeyDto, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'xClientId' is not null or undefined assertParamExists('importPrivateKey', 'xClientId', xClientId) - // verify required parameter 'authorization' is not null or undefined - assertParamExists('importPrivateKey', 'authorization', authorization) // verify required parameter 'importPrivateKeyDto' is not null or undefined assertParamExists('importPrivateKey', 'importPrivateKeyDto', importPrivateKeyDto) const localVarPath = `/v1/accounts/import`; @@ -2827,6 +3094,9 @@ export const AccountApiAxiosParamCreator = function (configuration?: Configurati // authentication GNAP required + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + if (xClientId != null) { localVarHeaderParameter['x-client-id'] = String(xClientId); } @@ -2853,15 +3123,13 @@ export const AccountApiAxiosParamCreator = function (configuration?: Configurati * * @summary Lists the client accounts * @param {string} xClientId - * @param {string} authorization + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - list: async (xClientId: string, authorization: string, options: RawAxiosRequestConfig = {}): Promise => { + list: async (xClientId: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'xClientId' is not null or undefined assertParamExists('list', 'xClientId', xClientId) - // verify required parameter 'authorization' is not null or undefined - assertParamExists('list', 'authorization', authorization) const localVarPath = `/v1/accounts`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -2876,6 +3144,9 @@ export const AccountApiAxiosParamCreator = function (configuration?: Configurati // authentication GNAP required + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + if (xClientId != null) { localVarHeaderParameter['x-client-id'] = String(xClientId); } @@ -2909,13 +3180,13 @@ export const AccountApiFp = function(configuration?: Configuration) { * * @summary Add a new account to a wallet * @param {string} xClientId - * @param {string} authorization * @param {DeriveAccountDto} deriveAccountDto + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async derive(xClientId: string, authorization: string, deriveAccountDto: DeriveAccountDto, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.derive(xClientId, authorization, deriveAccountDto, options); + async derive(xClientId: string, deriveAccountDto: DeriveAccountDto, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.derive(xClientId, deriveAccountDto, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['AccountApi.derive']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); @@ -2924,13 +3195,13 @@ export const AccountApiFp = function(configuration?: Configuration) { * * @summary Imports an account * @param {string} xClientId - * @param {string} authorization * @param {ImportPrivateKeyDto} importPrivateKeyDto + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async importPrivateKey(xClientId: string, authorization: string, importPrivateKeyDto: ImportPrivateKeyDto, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.importPrivateKey(xClientId, authorization, importPrivateKeyDto, options); + async importPrivateKey(xClientId: string, importPrivateKeyDto: ImportPrivateKeyDto, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.importPrivateKey(xClientId, importPrivateKeyDto, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['AccountApi.importPrivateKey']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); @@ -2939,11 +3210,11 @@ export const AccountApiFp = function(configuration?: Configuration) { * * @summary Lists the client accounts * @param {string} xClientId - * @param {string} authorization + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async list(xClientId: string, authorization: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async list(xClientId: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.list(xClientId, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['AccountApi.list']?.[localVarOperationServerIndex]?.url; @@ -2962,41 +3233,113 @@ export const AccountApiFactory = function (configuration?: Configuration, basePa /** * * @summary Add a new account to a wallet - * @param {string} xClientId - * @param {string} authorization - * @param {DeriveAccountDto} deriveAccountDto + * @param {AccountApiDeriveRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - derive(xClientId: string, authorization: string, deriveAccountDto: DeriveAccountDto, options?: any): AxiosPromise { - return localVarFp.derive(xClientId, authorization, deriveAccountDto, options).then((request) => request(axios, basePath)); + derive(requestParameters: AccountApiDeriveRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.derive(requestParameters.xClientId, requestParameters.deriveAccountDto, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, /** * * @summary Imports an account - * @param {string} xClientId - * @param {string} authorization - * @param {ImportPrivateKeyDto} importPrivateKeyDto + * @param {AccountApiImportPrivateKeyRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - importPrivateKey(xClientId: string, authorization: string, importPrivateKeyDto: ImportPrivateKeyDto, options?: any): AxiosPromise { - return localVarFp.importPrivateKey(xClientId, authorization, importPrivateKeyDto, options).then((request) => request(axios, basePath)); + importPrivateKey(requestParameters: AccountApiImportPrivateKeyRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.importPrivateKey(requestParameters.xClientId, requestParameters.importPrivateKeyDto, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, /** * * @summary Lists the client accounts - * @param {string} xClientId - * @param {string} authorization + * @param {AccountApiListRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - list(xClientId: string, authorization: string, options?: any): AxiosPromise { - return localVarFp.list(xClientId, authorization, options).then((request) => request(axios, basePath)); + list(requestParameters: AccountApiListRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.list(requestParameters.xClientId, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, }; }; +/** + * Request parameters for derive operation in AccountApi. + * @export + * @interface AccountApiDeriveRequest + */ +export interface AccountApiDeriveRequest { + /** + * + * @type {string} + * @memberof AccountApiDerive + */ + readonly xClientId: string + + /** + * + * @type {DeriveAccountDto} + * @memberof AccountApiDerive + */ + readonly deriveAccountDto: DeriveAccountDto + + /** + * + * @type {string} + * @memberof AccountApiDerive + */ + readonly authorization?: string +} + +/** + * Request parameters for importPrivateKey operation in AccountApi. + * @export + * @interface AccountApiImportPrivateKeyRequest + */ +export interface AccountApiImportPrivateKeyRequest { + /** + * + * @type {string} + * @memberof AccountApiImportPrivateKey + */ + readonly xClientId: string + + /** + * + * @type {ImportPrivateKeyDto} + * @memberof AccountApiImportPrivateKey + */ + readonly importPrivateKeyDto: ImportPrivateKeyDto + + /** + * + * @type {string} + * @memberof AccountApiImportPrivateKey + */ + readonly authorization?: string +} + +/** + * Request parameters for list operation in AccountApi. + * @export + * @interface AccountApiListRequest + */ +export interface AccountApiListRequest { + /** + * + * @type {string} + * @memberof AccountApiList + */ + readonly xClientId: string + + /** + * + * @type {string} + * @memberof AccountApiList + */ + readonly authorization?: string +} + /** * AccountApi - object-oriented interface * @export @@ -3007,42 +3350,37 @@ export class AccountApi extends BaseAPI { /** * * @summary Add a new account to a wallet - * @param {string} xClientId - * @param {string} authorization - * @param {DeriveAccountDto} deriveAccountDto + * @param {AccountApiDeriveRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof AccountApi */ - public derive(xClientId: string, authorization: string, deriveAccountDto: DeriveAccountDto, options?: RawAxiosRequestConfig) { - return AccountApiFp(this.configuration).derive(xClientId, authorization, deriveAccountDto, options).then((request) => request(this.axios, this.basePath)); + public derive(requestParameters: AccountApiDeriveRequest, options?: RawAxiosRequestConfig) { + return AccountApiFp(this.configuration).derive(requestParameters.xClientId, requestParameters.deriveAccountDto, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } /** * * @summary Imports an account - * @param {string} xClientId - * @param {string} authorization - * @param {ImportPrivateKeyDto} importPrivateKeyDto + * @param {AccountApiImportPrivateKeyRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof AccountApi */ - public importPrivateKey(xClientId: string, authorization: string, importPrivateKeyDto: ImportPrivateKeyDto, options?: RawAxiosRequestConfig) { - return AccountApiFp(this.configuration).importPrivateKey(xClientId, authorization, importPrivateKeyDto, options).then((request) => request(this.axios, this.basePath)); + public importPrivateKey(requestParameters: AccountApiImportPrivateKeyRequest, options?: RawAxiosRequestConfig) { + return AccountApiFp(this.configuration).importPrivateKey(requestParameters.xClientId, requestParameters.importPrivateKeyDto, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } /** * * @summary Lists the client accounts - * @param {string} xClientId - * @param {string} authorization + * @param {AccountApiListRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof AccountApi */ - public list(xClientId: string, authorization: string, options?: RawAxiosRequestConfig) { - return AccountApiFp(this.configuration).list(xClientId, authorization, options).then((request) => request(this.axios, this.basePath)); + public list(requestParameters: AccountApiListRequest, options?: RawAxiosRequestConfig) { + return AccountApiFp(this.configuration).list(requestParameters.xClientId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } } @@ -3119,7 +3457,7 @@ export const ApplicationApiFactory = function (configuration?: Configuration, ba * @param {*} [options] Override http request option. * @throws {RequiredError} */ - ping(options?: any): AxiosPromise { + ping(options?: RawAxiosRequestConfig): AxiosPromise { return localVarFp.ping(options).then((request) => request(axios, basePath)); }, }; @@ -3176,8 +3514,8 @@ export const ClientApiAxiosParamCreator = function (configuration?: Configuratio const localVarHeaderParameter = {} as any; const localVarQueryParameter = {} as any; - // authentication ADMIN_API_KEY required - await setApiKeyToObject(localVarHeaderParameter, "ADMIN_API_KEY", configuration) + // authentication Admin-API-Key required + await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration) if (xApiKey != null) { localVarHeaderParameter['x-api-key'] = String(xApiKey); @@ -3234,17 +3572,37 @@ export const ClientApiFactory = function (configuration?: Configuration, basePat /** * * @summary Creates a new client - * @param {string} xApiKey - * @param {CreateClientDto} createClientDto + * @param {ClientApiCreateRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - create(xApiKey: string, createClientDto: CreateClientDto, options?: any): AxiosPromise { - return localVarFp.create(xApiKey, createClientDto, options).then((request) => request(axios, basePath)); + create(requestParameters: ClientApiCreateRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.create(requestParameters.xApiKey, requestParameters.createClientDto, options).then((request) => request(axios, basePath)); }, }; }; +/** + * Request parameters for create operation in ClientApi. + * @export + * @interface ClientApiCreateRequest + */ +export interface ClientApiCreateRequest { + /** + * + * @type {string} + * @memberof ClientApiCreate + */ + readonly xApiKey: string + + /** + * + * @type {CreateClientDto} + * @memberof ClientApiCreate + */ + readonly createClientDto: CreateClientDto +} + /** * ClientApi - object-oriented interface * @export @@ -3255,14 +3613,13 @@ export class ClientApi extends BaseAPI { /** * * @summary Creates a new client - * @param {string} xApiKey - * @param {CreateClientDto} createClientDto + * @param {ClientApiCreateRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof ClientApi */ - public create(xApiKey: string, createClientDto: CreateClientDto, options?: RawAxiosRequestConfig) { - return ClientApiFp(this.configuration).create(xApiKey, createClientDto, options).then((request) => request(this.axios, this.basePath)); + public create(requestParameters: ClientApiCreateRequest, options?: RawAxiosRequestConfig) { + return ClientApiFp(this.configuration).create(requestParameters.xApiKey, requestParameters.createClientDto, options).then((request) => request(this.axios, this.basePath)); } } @@ -3278,15 +3635,13 @@ export const EncryptionKeyApiAxiosParamCreator = function (configuration?: Confi * * @summary Generates an encryption key pair used to secure end-to-end communication containing sensitive information * @param {string} xClientId - * @param {string} authorization + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - generate: async (xClientId: string, authorization: string, options: RawAxiosRequestConfig = {}): Promise => { + generate: async (xClientId: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'xClientId' is not null or undefined assertParamExists('generate', 'xClientId', xClientId) - // verify required parameter 'authorization' is not null or undefined - assertParamExists('generate', 'authorization', authorization) const localVarPath = `/v1/encryption-keys`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -3301,6 +3656,9 @@ export const EncryptionKeyApiAxiosParamCreator = function (configuration?: Confi // authentication GNAP required + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + if (xClientId != null) { localVarHeaderParameter['x-client-id'] = String(xClientId); } @@ -3334,11 +3692,11 @@ export const EncryptionKeyApiFp = function(configuration?: Configuration) { * * @summary Generates an encryption key pair used to secure end-to-end communication containing sensitive information * @param {string} xClientId - * @param {string} authorization + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async generate(xClientId: string, authorization: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async generate(xClientId: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.generate(xClientId, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['EncryptionKeyApi.generate']?.[localVarOperationServerIndex]?.url; @@ -3357,17 +3715,37 @@ export const EncryptionKeyApiFactory = function (configuration?: Configuration, /** * * @summary Generates an encryption key pair used to secure end-to-end communication containing sensitive information - * @param {string} xClientId - * @param {string} authorization + * @param {EncryptionKeyApiGenerateRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - generate(xClientId: string, authorization: string, options?: any): AxiosPromise { - return localVarFp.generate(xClientId, authorization, options).then((request) => request(axios, basePath)); + generate(requestParameters: EncryptionKeyApiGenerateRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.generate(requestParameters.xClientId, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, }; }; +/** + * Request parameters for generate operation in EncryptionKeyApi. + * @export + * @interface EncryptionKeyApiGenerateRequest + */ +export interface EncryptionKeyApiGenerateRequest { + /** + * + * @type {string} + * @memberof EncryptionKeyApiGenerate + */ + readonly xClientId: string + + /** + * + * @type {string} + * @memberof EncryptionKeyApiGenerate + */ + readonly authorization?: string +} + /** * EncryptionKeyApi - object-oriented interface * @export @@ -3378,14 +3756,13 @@ export class EncryptionKeyApi extends BaseAPI { /** * * @summary Generates an encryption key pair used to secure end-to-end communication containing sensitive information - * @param {string} xClientId - * @param {string} authorization + * @param {EncryptionKeyApiGenerateRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof EncryptionKeyApi */ - public generate(xClientId: string, authorization: string, options?: RawAxiosRequestConfig) { - return EncryptionKeyApiFp(this.configuration).generate(xClientId, authorization, options).then((request) => request(this.axios, this.basePath)); + public generate(requestParameters: EncryptionKeyApiGenerateRequest, options?: RawAxiosRequestConfig) { + return EncryptionKeyApiFp(this.configuration).generate(requestParameters.xClientId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } } @@ -3399,22 +3776,19 @@ export const ProviderAccountApiAxiosParamCreator = function (configuration?: Con return { /** * - * @summary List addresses for a specific account - * @param {string} accountId The ID of the account to retrieve addresses for - * @param {string} authorization - * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page - * @param {number} [limit] Number of records to return per page - * @param {string} [orderBy] Field to order results by - * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @summary Get a specific account by ID + * @param {string} xClientId + * @param {string} accountId The ID of the account to retrieve + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getAccountAddresses: async (accountId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options: RawAxiosRequestConfig = {}): Promise => { + getById: async (xClientId: string, accountId: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('getById', 'xClientId', xClientId) // verify required parameter 'accountId' is not null or undefined - assertParamExists('getAccountAddresses', 'accountId', accountId) - // verify required parameter 'authorization' is not null or undefined - assertParamExists('getAccountAddresses', 'authorization', authorization) - const localVarPath = `/v1/provider/accounts/{accountId}/addresses` + assertParamExists('getById', 'accountId', accountId) + const localVarPath = `/v1/provider/accounts/{accountId}` .replace(`{${"accountId"}}`, encodeURIComponent(String(accountId))); // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -3429,20 +3803,11 @@ export const ProviderAccountApiAxiosParamCreator = function (configuration?: Con // authentication GNAP required - if (cursor !== undefined) { - localVarQueryParameter['cursor'] = cursor; - } - - if (limit !== undefined) { - localVarQueryParameter['limit'] = limit; - } - - if (orderBy !== undefined) { - localVarQueryParameter['orderBy'] = orderBy; - } + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) - if (desc !== undefined) { - localVarQueryParameter['desc'] = desc; + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); } if (authorization != null) { @@ -3462,19 +3827,20 @@ export const ProviderAccountApiAxiosParamCreator = function (configuration?: Con }, /** * - * @summary Get a specific account by ID - * @param {string} accountId The ID of the account to retrieve - * @param {string} authorization + * @summary List the client accounts + * @param {string} xClientId + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getAccountById: async (accountId: string, authorization: string, options: RawAxiosRequestConfig = {}): Promise => { - // verify required parameter 'accountId' is not null or undefined - assertParamExists('getAccountById', 'accountId', accountId) - // verify required parameter 'authorization' is not null or undefined - assertParamExists('getAccountById', 'authorization', authorization) - const localVarPath = `/v1/provider/accounts/{accountId}` - .replace(`{${"accountId"}}`, encodeURIComponent(String(accountId))); + list: async (xClientId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('list', 'xClientId', xClientId) + const localVarPath = `/v1/provider/accounts`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); let baseOptions; @@ -3488,6 +3854,29 @@ export const ProviderAccountApiAxiosParamCreator = function (configuration?: Con // authentication GNAP required + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + + if (cursor !== undefined) { + localVarQueryParameter['cursor'] = cursor; + } + + if (limit !== undefined) { + localVarQueryParameter['limit'] = limit; + } + + if (orderBy !== undefined) { + localVarQueryParameter['orderBy'] = orderBy; + } + + if (desc !== undefined) { + localVarQueryParameter['desc'] = desc; + } + + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + if (authorization != null) { localVarHeaderParameter['Authorization'] = String(authorization); } @@ -3505,19 +3894,24 @@ export const ProviderAccountApiAxiosParamCreator = function (configuration?: Con }, /** * - * @summary List the client accounts - * @param {string} authorization + * @summary List addresses for a specific account + * @param {string} xClientId + * @param {string} accountId The ID of the account to retrieve addresses for * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page * @param {number} [limit] Number of records to return per page * @param {string} [orderBy] Field to order results by * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - listByClientId: async (authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options: RawAxiosRequestConfig = {}): Promise => { - // verify required parameter 'authorization' is not null or undefined - assertParamExists('listByClientId', 'authorization', authorization) - const localVarPath = `/v1/provider/accounts`; + listAddresses: async (xClientId: string, accountId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('listAddresses', 'xClientId', xClientId) + // verify required parameter 'accountId' is not null or undefined + assertParamExists('listAddresses', 'accountId', accountId) + const localVarPath = `/v1/provider/accounts/{accountId}/addresses` + .replace(`{${"accountId"}}`, encodeURIComponent(String(accountId))); // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); let baseOptions; @@ -3531,6 +3925,9 @@ export const ProviderAccountApiAxiosParamCreator = function (configuration?: Con // authentication GNAP required + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + if (cursor !== undefined) { localVarQueryParameter['cursor'] = cursor; } @@ -3547,6 +3944,10 @@ export const ProviderAccountApiAxiosParamCreator = function (configuration?: Con localVarQueryParameter['desc'] = desc; } + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + if (authorization != null) { localVarHeaderParameter['Authorization'] = String(authorization); } @@ -3574,51 +3975,54 @@ export const ProviderAccountApiFp = function(configuration?: Configuration) { return { /** * - * @summary List addresses for a specific account - * @param {string} accountId The ID of the account to retrieve addresses for - * @param {string} authorization - * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page - * @param {number} [limit] Number of records to return per page - * @param {string} [orderBy] Field to order results by - * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @summary Get a specific account by ID + * @param {string} xClientId + * @param {string} accountId The ID of the account to retrieve + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async getAccountAddresses(accountId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.getAccountAddresses(accountId, authorization, cursor, limit, orderBy, desc, options); + async getById(xClientId: string, accountId: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getById(xClientId, accountId, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = operationServerMap['ProviderAccountApi.getAccountAddresses']?.[localVarOperationServerIndex]?.url; + const localVarOperationServerBasePath = operationServerMap['ProviderAccountApi.getById']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** * - * @summary Get a specific account by ID - * @param {string} accountId The ID of the account to retrieve - * @param {string} authorization + * @summary List the client accounts + * @param {string} xClientId + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async getAccountById(accountId: string, authorization: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.getAccountById(accountId, authorization, options); + async list(xClientId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.list(xClientId, cursor, limit, orderBy, desc, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = operationServerMap['ProviderAccountApi.getAccountById']?.[localVarOperationServerIndex]?.url; + const localVarOperationServerBasePath = operationServerMap['ProviderAccountApi.list']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** * - * @summary List the client accounts - * @param {string} authorization + * @summary List addresses for a specific account + * @param {string} xClientId + * @param {string} accountId The ID of the account to retrieve addresses for * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page * @param {number} [limit] Number of records to return per page * @param {string} [orderBy] Field to order results by * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async listByClientId(authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.listByClientId(authorization, cursor, limit, orderBy, desc, options); + async listAddresses(xClientId: string, accountId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.listAddresses(xClientId, accountId, cursor, limit, orderBy, desc, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = operationServerMap['ProviderAccountApi.listByClientId']?.[localVarOperationServerIndex]?.url; + const localVarOperationServerBasePath = operationServerMap['ProviderAccountApi.listAddresses']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, } @@ -3633,47 +4037,170 @@ export const ProviderAccountApiFactory = function (configuration?: Configuration return { /** * - * @summary List addresses for a specific account - * @param {string} accountId The ID of the account to retrieve addresses for - * @param {string} authorization - * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page - * @param {number} [limit] Number of records to return per page - * @param {string} [orderBy] Field to order results by - * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @summary Get a specific account by ID + * @param {ProviderAccountApiGetByIdRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getAccountAddresses(accountId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: any): AxiosPromise { - return localVarFp.getAccountAddresses(accountId, authorization, cursor, limit, orderBy, desc, options).then((request) => request(axios, basePath)); + getById(requestParameters: ProviderAccountApiGetByIdRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.getById(requestParameters.xClientId, requestParameters.accountId, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, /** * - * @summary Get a specific account by ID - * @param {string} accountId The ID of the account to retrieve - * @param {string} authorization + * @summary List the client accounts + * @param {ProviderAccountApiListRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getAccountById(accountId: string, authorization: string, options?: any): AxiosPromise { - return localVarFp.getAccountById(accountId, authorization, options).then((request) => request(axios, basePath)); + list(requestParameters: ProviderAccountApiListRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.list(requestParameters.xClientId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, /** * - * @summary List the client accounts - * @param {string} authorization - * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page - * @param {number} [limit] Number of records to return per page - * @param {string} [orderBy] Field to order results by - * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @summary List addresses for a specific account + * @param {ProviderAccountApiListAddressesRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - listByClientId(authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: any): AxiosPromise { - return localVarFp.listByClientId(authorization, cursor, limit, orderBy, desc, options).then((request) => request(axios, basePath)); + listAddresses(requestParameters: ProviderAccountApiListAddressesRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.listAddresses(requestParameters.xClientId, requestParameters.accountId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, }; }; +/** + * Request parameters for getById operation in ProviderAccountApi. + * @export + * @interface ProviderAccountApiGetByIdRequest + */ +export interface ProviderAccountApiGetByIdRequest { + /** + * + * @type {string} + * @memberof ProviderAccountApiGetById + */ + readonly xClientId: string + + /** + * The ID of the account to retrieve + * @type {string} + * @memberof ProviderAccountApiGetById + */ + readonly accountId: string + + /** + * + * @type {string} + * @memberof ProviderAccountApiGetById + */ + readonly authorization?: string +} + +/** + * Request parameters for list operation in ProviderAccountApi. + * @export + * @interface ProviderAccountApiListRequest + */ +export interface ProviderAccountApiListRequest { + /** + * + * @type {string} + * @memberof ProviderAccountApiList + */ + readonly xClientId: string + + /** + * Cursor for pagination. Use the next cursor from previous response to get next page + * @type {string} + * @memberof ProviderAccountApiList + */ + readonly cursor?: string + + /** + * Number of records to return per page + * @type {number} + * @memberof ProviderAccountApiList + */ + readonly limit?: number + + /** + * Field to order results by + * @type {string} + * @memberof ProviderAccountApiList + */ + readonly orderBy?: string + + /** + * Set to \"true\" or \"1\" for descending order + * @type {string} + * @memberof ProviderAccountApiList + */ + readonly desc?: string + + /** + * + * @type {string} + * @memberof ProviderAccountApiList + */ + readonly authorization?: string +} + +/** + * Request parameters for listAddresses operation in ProviderAccountApi. + * @export + * @interface ProviderAccountApiListAddressesRequest + */ +export interface ProviderAccountApiListAddressesRequest { + /** + * + * @type {string} + * @memberof ProviderAccountApiListAddresses + */ + readonly xClientId: string + + /** + * The ID of the account to retrieve addresses for + * @type {string} + * @memberof ProviderAccountApiListAddresses + */ + readonly accountId: string + + /** + * Cursor for pagination. Use the next cursor from previous response to get next page + * @type {string} + * @memberof ProviderAccountApiListAddresses + */ + readonly cursor?: string + + /** + * Number of records to return per page + * @type {number} + * @memberof ProviderAccountApiListAddresses + */ + readonly limit?: number + + /** + * Field to order results by + * @type {string} + * @memberof ProviderAccountApiListAddresses + */ + readonly orderBy?: string + + /** + * Set to \"true\" or \"1\" for descending order + * @type {string} + * @memberof ProviderAccountApiListAddresses + */ + readonly desc?: string + + /** + * + * @type {string} + * @memberof ProviderAccountApiListAddresses + */ + readonly authorization?: string +} + /** * ProviderAccountApi - object-oriented interface * @export @@ -3683,48 +4210,38 @@ export const ProviderAccountApiFactory = function (configuration?: Configuration export class ProviderAccountApi extends BaseAPI { /** * - * @summary List addresses for a specific account - * @param {string} accountId The ID of the account to retrieve addresses for - * @param {string} authorization - * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page - * @param {number} [limit] Number of records to return per page - * @param {string} [orderBy] Field to order results by - * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @summary Get a specific account by ID + * @param {ProviderAccountApiGetByIdRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof ProviderAccountApi */ - public getAccountAddresses(accountId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig) { - return ProviderAccountApiFp(this.configuration).getAccountAddresses(accountId, authorization, cursor, limit, orderBy, desc, options).then((request) => request(this.axios, this.basePath)); + public getById(requestParameters: ProviderAccountApiGetByIdRequest, options?: RawAxiosRequestConfig) { + return ProviderAccountApiFp(this.configuration).getById(requestParameters.xClientId, requestParameters.accountId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } /** * - * @summary Get a specific account by ID - * @param {string} accountId The ID of the account to retrieve - * @param {string} authorization + * @summary List the client accounts + * @param {ProviderAccountApiListRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof ProviderAccountApi */ - public getAccountById(accountId: string, authorization: string, options?: RawAxiosRequestConfig) { - return ProviderAccountApiFp(this.configuration).getAccountById(accountId, authorization, options).then((request) => request(this.axios, this.basePath)); + public list(requestParameters: ProviderAccountApiListRequest, options?: RawAxiosRequestConfig) { + return ProviderAccountApiFp(this.configuration).list(requestParameters.xClientId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } /** * - * @summary List the client accounts - * @param {string} authorization - * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page - * @param {number} [limit] Number of records to return per page - * @param {string} [orderBy] Field to order results by - * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @summary List addresses for a specific account + * @param {ProviderAccountApiListAddressesRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof ProviderAccountApi */ - public listByClientId(authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig) { - return ProviderAccountApiFp(this.configuration).listByClientId(authorization, cursor, limit, orderBy, desc, options).then((request) => request(this.axios, this.basePath)); + public listAddresses(requestParameters: ProviderAccountApiListAddressesRequest, options?: RawAxiosRequestConfig) { + return ProviderAccountApiFp(this.configuration).listAddresses(requestParameters.xClientId, requestParameters.accountId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } } @@ -3739,16 +4256,17 @@ export const ProviderAddressApiAxiosParamCreator = function (configuration?: Con /** * * @summary Get a specific address by ID + * @param {string} xClientId * @param {string} addressId The ID of the address to retrieve - * @param {string} authorization + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getAddressById: async (addressId: string, authorization: string, options: RawAxiosRequestConfig = {}): Promise => { + getById: async (xClientId: string, addressId: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('getById', 'xClientId', xClientId) // verify required parameter 'addressId' is not null or undefined - assertParamExists('getAddressById', 'addressId', addressId) - // verify required parameter 'authorization' is not null or undefined - assertParamExists('getAddressById', 'authorization', authorization) + assertParamExists('getById', 'addressId', addressId) const localVarPath = `/v1/provider/addresses/{addressId}` .replace(`{${"addressId"}}`, encodeURIComponent(String(addressId))); // use dummy base URL string because the URL constructor only accepts absolute URLs. @@ -3764,6 +4282,13 @@ export const ProviderAddressApiAxiosParamCreator = function (configuration?: Con // authentication GNAP required + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + if (authorization != null) { localVarHeaderParameter['Authorization'] = String(authorization); } @@ -3782,17 +4307,18 @@ export const ProviderAddressApiAxiosParamCreator = function (configuration?: Con /** * * @summary List the client addresss - * @param {string} authorization + * @param {string} xClientId * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page * @param {number} [limit] Number of records to return per page * @param {string} [orderBy] Field to order results by * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - list: async (authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options: RawAxiosRequestConfig = {}): Promise => { - // verify required parameter 'authorization' is not null or undefined - assertParamExists('list', 'authorization', authorization) + list: async (xClientId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('list', 'xClientId', xClientId) const localVarPath = `/v1/provider/addresses`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -3807,6 +4333,9 @@ export const ProviderAddressApiAxiosParamCreator = function (configuration?: Con // authentication GNAP required + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + if (cursor !== undefined) { localVarQueryParameter['cursor'] = cursor; } @@ -3823,6 +4352,10 @@ export const ProviderAddressApiAxiosParamCreator = function (configuration?: Con localVarQueryParameter['desc'] = desc; } + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + if (authorization != null) { localVarHeaderParameter['Authorization'] = String(authorization); } @@ -3851,30 +4384,32 @@ export const ProviderAddressApiFp = function(configuration?: Configuration) { /** * * @summary Get a specific address by ID + * @param {string} xClientId * @param {string} addressId The ID of the address to retrieve - * @param {string} authorization + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async getAddressById(addressId: string, authorization: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.getAddressById(addressId, authorization, options); + async getById(xClientId: string, addressId: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getById(xClientId, addressId, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = operationServerMap['ProviderAddressApi.getAddressById']?.[localVarOperationServerIndex]?.url; + const localVarOperationServerBasePath = operationServerMap['ProviderAddressApi.getById']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** * * @summary List the client addresss - * @param {string} authorization + * @param {string} xClientId * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page * @param {number} [limit] Number of records to return per page * @param {string} [orderBy] Field to order results by * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async list(authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.list(authorization, cursor, limit, orderBy, desc, options); + async list(xClientId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.list(xClientId, cursor, limit, orderBy, desc, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['ProviderAddressApi.list']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); @@ -3892,31 +4427,103 @@ export const ProviderAddressApiFactory = function (configuration?: Configuration /** * * @summary Get a specific address by ID - * @param {string} addressId The ID of the address to retrieve - * @param {string} authorization + * @param {ProviderAddressApiGetByIdRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getAddressById(addressId: string, authorization: string, options?: any): AxiosPromise { - return localVarFp.getAddressById(addressId, authorization, options).then((request) => request(axios, basePath)); + getById(requestParameters: ProviderAddressApiGetByIdRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.getById(requestParameters.xClientId, requestParameters.addressId, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, /** * * @summary List the client addresss - * @param {string} authorization - * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page - * @param {number} [limit] Number of records to return per page - * @param {string} [orderBy] Field to order results by - * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {ProviderAddressApiListRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - list(authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: any): AxiosPromise { - return localVarFp.list(authorization, cursor, limit, orderBy, desc, options).then((request) => request(axios, basePath)); + list(requestParameters: ProviderAddressApiListRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.list(requestParameters.xClientId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, }; }; +/** + * Request parameters for getById operation in ProviderAddressApi. + * @export + * @interface ProviderAddressApiGetByIdRequest + */ +export interface ProviderAddressApiGetByIdRequest { + /** + * + * @type {string} + * @memberof ProviderAddressApiGetById + */ + readonly xClientId: string + + /** + * The ID of the address to retrieve + * @type {string} + * @memberof ProviderAddressApiGetById + */ + readonly addressId: string + + /** + * + * @type {string} + * @memberof ProviderAddressApiGetById + */ + readonly authorization?: string +} + +/** + * Request parameters for list operation in ProviderAddressApi. + * @export + * @interface ProviderAddressApiListRequest + */ +export interface ProviderAddressApiListRequest { + /** + * + * @type {string} + * @memberof ProviderAddressApiList + */ + readonly xClientId: string + + /** + * Cursor for pagination. Use the next cursor from previous response to get next page + * @type {string} + * @memberof ProviderAddressApiList + */ + readonly cursor?: string + + /** + * Number of records to return per page + * @type {number} + * @memberof ProviderAddressApiList + */ + readonly limit?: number + + /** + * Field to order results by + * @type {string} + * @memberof ProviderAddressApiList + */ + readonly orderBy?: string + + /** + * Set to \"true\" or \"1\" for descending order + * @type {string} + * @memberof ProviderAddressApiList + */ + readonly desc?: string + + /** + * + * @type {string} + * @memberof ProviderAddressApiList + */ + readonly authorization?: string +} + /** * ProviderAddressApi - object-oriented interface * @export @@ -3927,30 +4534,25 @@ export class ProviderAddressApi extends BaseAPI { /** * * @summary Get a specific address by ID - * @param {string} addressId The ID of the address to retrieve - * @param {string} authorization + * @param {ProviderAddressApiGetByIdRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof ProviderAddressApi */ - public getAddressById(addressId: string, authorization: string, options?: RawAxiosRequestConfig) { - return ProviderAddressApiFp(this.configuration).getAddressById(addressId, authorization, options).then((request) => request(this.axios, this.basePath)); + public getById(requestParameters: ProviderAddressApiGetByIdRequest, options?: RawAxiosRequestConfig) { + return ProviderAddressApiFp(this.configuration).getById(requestParameters.xClientId, requestParameters.addressId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } /** * * @summary List the client addresss - * @param {string} authorization - * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page - * @param {number} [limit] Number of records to return per page - * @param {string} [orderBy] Field to order results by - * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {ProviderAddressApiListRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof ProviderAddressApi */ - public list(authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig) { - return ProviderAddressApiFp(this.configuration).list(authorization, cursor, limit, orderBy, desc, options).then((request) => request(this.axios, this.basePath)); + public list(requestParameters: ProviderAddressApiListRequest, options?: RawAxiosRequestConfig) { + return ProviderAddressApiFp(this.configuration).list(requestParameters.xClientId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } } @@ -3965,14 +4567,15 @@ export const ProviderConnectionApiAxiosParamCreator = function (configuration?: /** * This endpoint securely stores the details of a provider connection, ensuring that all sensitive information is encrypted. * @summary Store a provider connection securely - * @param {string} authorization + * @param {string} xClientId * @param {CreateConnectionDto} createConnectionDto + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - create: async (authorization: string, createConnectionDto: CreateConnectionDto, options: RawAxiosRequestConfig = {}): Promise => { - // verify required parameter 'authorization' is not null or undefined - assertParamExists('create', 'authorization', authorization) + create: async (xClientId: string, createConnectionDto: CreateConnectionDto, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('create', 'xClientId', xClientId) // verify required parameter 'createConnectionDto' is not null or undefined assertParamExists('create', 'createConnectionDto', createConnectionDto) const localVarPath = `/v1/provider/connections`; @@ -3989,6 +4592,13 @@ export const ProviderConnectionApiAxiosParamCreator = function (configuration?: // authentication GNAP required + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + if (authorization != null) { localVarHeaderParameter['Authorization'] = String(authorization); } @@ -4008,23 +4618,20 @@ export const ProviderConnectionApiAxiosParamCreator = function (configuration?: }; }, /** - * This endpoint retrieves a list of accounts associated with a specific connection. - * @summary List accounts for a specific connection + * This endpoint retrieves the details of a specific connection associated with the client, identified by the ID. + * @summary Retrieve a specific connection by ID + * @param {string} xClientId * @param {string} connectionId - * @param {string} authorization - * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page - * @param {number} [limit] Number of records to return per page - * @param {string} [orderBy] Field to order results by - * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getAccounts: async (connectionId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options: RawAxiosRequestConfig = {}): Promise => { + getById: async (xClientId: string, connectionId: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('getById', 'xClientId', xClientId) // verify required parameter 'connectionId' is not null or undefined - assertParamExists('getAccounts', 'connectionId', connectionId) - // verify required parameter 'authorization' is not null or undefined - assertParamExists('getAccounts', 'authorization', authorization) - const localVarPath = `/v1/provider/connections/{connectionId}/accounts` + assertParamExists('getById', 'connectionId', connectionId) + const localVarPath = `/v1/provider/connections/{connectionId}` .replace(`{${"connectionId"}}`, encodeURIComponent(String(connectionId))); // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -4039,20 +4646,11 @@ export const ProviderConnectionApiAxiosParamCreator = function (configuration?: // authentication GNAP required - if (cursor !== undefined) { - localVarQueryParameter['cursor'] = cursor; - } - - if (limit !== undefined) { - localVarQueryParameter['limit'] = limit; - } - - if (orderBy !== undefined) { - localVarQueryParameter['orderBy'] = orderBy; - } + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) - if (desc !== undefined) { - localVarQueryParameter['desc'] = desc; + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); } if (authorization != null) { @@ -4071,20 +4669,20 @@ export const ProviderConnectionApiAxiosParamCreator = function (configuration?: }; }, /** - * This endpoint retrieves the details of a specific connection associated with the client, identified by the ID. - * @summary Retrieve a specific connection by ID - * @param {string} connectionId - * @param {string} authorization + * This endpoint initiates a new connection by generating a public key and an encryption key for secure communication. + * @summary Initiate a new provider connection + * @param {string} xClientId + * @param {InitiateConnectionDto} initiateConnectionDto + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getById: async (connectionId: string, authorization: string, options: RawAxiosRequestConfig = {}): Promise => { - // verify required parameter 'connectionId' is not null or undefined - assertParamExists('getById', 'connectionId', connectionId) - // verify required parameter 'authorization' is not null or undefined - assertParamExists('getById', 'authorization', authorization) - const localVarPath = `/v1/provider/connections/{connectionId}` - .replace(`{${"connectionId"}}`, encodeURIComponent(String(connectionId))); + initiate: async (xClientId: string, initiateConnectionDto: InitiateConnectionDto, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('initiate', 'xClientId', xClientId) + // verify required parameter 'initiateConnectionDto' is not null or undefined + assertParamExists('initiate', 'initiateConnectionDto', initiateConnectionDto) + const localVarPath = `/v1/provider/connections/initiate`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); let baseOptions; @@ -4092,21 +4690,31 @@ export const ProviderConnectionApiAxiosParamCreator = function (configuration?: baseOptions = configuration.baseOptions; } - const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; const localVarHeaderParameter = {} as any; const localVarQueryParameter = {} as any; // authentication GNAP required + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + if (authorization != null) { localVarHeaderParameter['Authorization'] = String(authorization); } + localVarHeaderParameter['Content-Type'] = 'application/json'; + setSearchParams(localVarUrlObj, localVarQueryParameter); let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(initiateConnectionDto, localVarRequestOptions, configuration) return { url: toPathString(localVarUrlObj), @@ -4114,24 +4722,21 @@ export const ProviderConnectionApiAxiosParamCreator = function (configuration?: }; }, /** - * This endpoint retrieves a list of wallets associated with a specific connection. - * @summary List wallets for a specific connection - * @param {string} connectionId - * @param {string} authorization + * This endpoint retrieves a list of all connections associated with the client. + * @summary List all connections + * @param {string} xClientId * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page * @param {number} [limit] Number of records to return per page * @param {string} [orderBy] Field to order results by * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getWallets: async (connectionId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options: RawAxiosRequestConfig = {}): Promise => { - // verify required parameter 'connectionId' is not null or undefined - assertParamExists('getWallets', 'connectionId', connectionId) - // verify required parameter 'authorization' is not null or undefined - assertParamExists('getWallets', 'authorization', authorization) - const localVarPath = `/v1/provider/connections/{connectionId}/wallets` - .replace(`{${"connectionId"}}`, encodeURIComponent(String(connectionId))); + list: async (xClientId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('list', 'xClientId', xClientId) + const localVarPath = `/v1/provider/connections`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); let baseOptions; @@ -4145,6 +4750,9 @@ export const ProviderConnectionApiAxiosParamCreator = function (configuration?: // authentication GNAP required + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + if (cursor !== undefined) { localVarQueryParameter['cursor'] = cursor; } @@ -4161,6 +4769,10 @@ export const ProviderConnectionApiAxiosParamCreator = function (configuration?: localVarQueryParameter['desc'] = desc; } + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + if (authorization != null) { localVarHeaderParameter['Authorization'] = String(authorization); } @@ -4177,19 +4789,25 @@ export const ProviderConnectionApiAxiosParamCreator = function (configuration?: }; }, /** - * This endpoint initiates a new connection by generating a public key and an encryption key for secure communication. - * @summary Initiate a new provider connection - * @param {string} authorization - * @param {InitiateConnectionDto} initiateConnectionDto + * This endpoint retrieves a list of accounts associated with a specific connection. + * @summary List accounts for a specific connection + * @param {string} xClientId + * @param {string} connectionId + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - initiate: async (authorization: string, initiateConnectionDto: InitiateConnectionDto, options: RawAxiosRequestConfig = {}): Promise => { - // verify required parameter 'authorization' is not null or undefined - assertParamExists('initiate', 'authorization', authorization) - // verify required parameter 'initiateConnectionDto' is not null or undefined - assertParamExists('initiate', 'initiateConnectionDto', initiateConnectionDto) - const localVarPath = `/v1/provider/connections/initiate`; + listAccounts: async (xClientId: string, connectionId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('listAccounts', 'xClientId', xClientId) + // verify required parameter 'connectionId' is not null or undefined + assertParamExists('listAccounts', 'connectionId', connectionId) + const localVarPath = `/v1/provider/connections/{connectionId}/accounts` + .replace(`{${"connectionId"}}`, encodeURIComponent(String(connectionId))); // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); let baseOptions; @@ -4197,24 +4815,44 @@ export const ProviderConnectionApiAxiosParamCreator = function (configuration?: baseOptions = configuration.baseOptions; } - const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; const localVarHeaderParameter = {} as any; const localVarQueryParameter = {} as any; // authentication GNAP required + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + + if (cursor !== undefined) { + localVarQueryParameter['cursor'] = cursor; + } + + if (limit !== undefined) { + localVarQueryParameter['limit'] = limit; + } + + if (orderBy !== undefined) { + localVarQueryParameter['orderBy'] = orderBy; + } + + if (desc !== undefined) { + localVarQueryParameter['desc'] = desc; + } + + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + if (authorization != null) { localVarHeaderParameter['Authorization'] = String(authorization); } - localVarHeaderParameter['Content-Type'] = 'application/json'; - setSearchParams(localVarUrlObj, localVarQueryParameter); let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - localVarRequestOptions.data = serializeDataIfNeeded(initiateConnectionDto, localVarRequestOptions, configuration) return { url: toPathString(localVarUrlObj), @@ -4222,20 +4860,25 @@ export const ProviderConnectionApiAxiosParamCreator = function (configuration?: }; }, /** - * This endpoint retrieves a list of all connections associated with the client. - * @summary List all connections - * @param {string} authorization + * This endpoint retrieves a list of wallets associated with a specific connection. + * @summary List wallets for a specific connection + * @param {string} xClientId + * @param {string} connectionId * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page * @param {number} [limit] Number of records to return per page * @param {string} [orderBy] Field to order results by * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - list: async (authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options: RawAxiosRequestConfig = {}): Promise => { - // verify required parameter 'authorization' is not null or undefined - assertParamExists('list', 'authorization', authorization) - const localVarPath = `/v1/provider/connections`; + listWallets: async (xClientId: string, connectionId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('listWallets', 'xClientId', xClientId) + // verify required parameter 'connectionId' is not null or undefined + assertParamExists('listWallets', 'connectionId', connectionId) + const localVarPath = `/v1/provider/connections/{connectionId}/wallets` + .replace(`{${"connectionId"}}`, encodeURIComponent(String(connectionId))); // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); let baseOptions; @@ -4249,6 +4892,9 @@ export const ProviderConnectionApiAxiosParamCreator = function (configuration?: // authentication GNAP required + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + if (cursor !== undefined) { localVarQueryParameter['cursor'] = cursor; } @@ -4265,6 +4911,10 @@ export const ProviderConnectionApiAxiosParamCreator = function (configuration?: localVarQueryParameter['desc'] = desc; } + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + if (authorization != null) { localVarHeaderParameter['Authorization'] = String(authorization); } @@ -4283,16 +4933,17 @@ export const ProviderConnectionApiAxiosParamCreator = function (configuration?: /** * This endpoint revokes an existing connection, effectively terminating any ongoing communication and invalidating the connection credentials. * @summary Revoke an existing connection + * @param {string} xClientId * @param {string} connectionId - * @param {string} authorization + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - revoke: async (connectionId: string, authorization: string, options: RawAxiosRequestConfig = {}): Promise => { + revoke: async (xClientId: string, connectionId: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('revoke', 'xClientId', xClientId) // verify required parameter 'connectionId' is not null or undefined assertParamExists('revoke', 'connectionId', connectionId) - // verify required parameter 'authorization' is not null or undefined - assertParamExists('revoke', 'authorization', authorization) const localVarPath = `/v1/provider/connections/{connectionId}` .replace(`{${"connectionId"}}`, encodeURIComponent(String(connectionId))); // use dummy base URL string because the URL constructor only accepts absolute URLs. @@ -4308,6 +4959,13 @@ export const ProviderConnectionApiAxiosParamCreator = function (configuration?: // authentication GNAP required + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + if (authorization != null) { localVarHeaderParameter['Authorization'] = String(authorization); } @@ -4326,17 +4984,18 @@ export const ProviderConnectionApiAxiosParamCreator = function (configuration?: /** * This endpoint updates the details of a specific connection associated with the client, identified by the connection ID. * @summary Update a specific connection by ID + * @param {string} xClientId * @param {string} connectionId - * @param {string} authorization * @param {UpdateConnectionDto} updateConnectionDto + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - update: async (connectionId: string, authorization: string, updateConnectionDto: UpdateConnectionDto, options: RawAxiosRequestConfig = {}): Promise => { + update: async (xClientId: string, connectionId: string, updateConnectionDto: UpdateConnectionDto, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('update', 'xClientId', xClientId) // verify required parameter 'connectionId' is not null or undefined assertParamExists('update', 'connectionId', connectionId) - // verify required parameter 'authorization' is not null or undefined - assertParamExists('update', 'authorization', authorization) // verify required parameter 'updateConnectionDto' is not null or undefined assertParamExists('update', 'updateConnectionDto', updateConnectionDto) const localVarPath = `/v1/provider/connections/{connectionId}` @@ -4354,6 +5013,13 @@ export const ProviderConnectionApiAxiosParamCreator = function (configuration?: // authentication GNAP required + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + if (authorization != null) { localVarHeaderParameter['Authorization'] = String(authorization); } @@ -4385,108 +5051,115 @@ export const ProviderConnectionApiFp = function(configuration?: Configuration) { /** * This endpoint securely stores the details of a provider connection, ensuring that all sensitive information is encrypted. * @summary Store a provider connection securely - * @param {string} authorization + * @param {string} xClientId * @param {CreateConnectionDto} createConnectionDto + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async create(authorization: string, createConnectionDto: CreateConnectionDto, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.create(authorization, createConnectionDto, options); + async create(xClientId: string, createConnectionDto: CreateConnectionDto, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.create(xClientId, createConnectionDto, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['ProviderConnectionApi.create']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** - * This endpoint retrieves a list of accounts associated with a specific connection. - * @summary List accounts for a specific connection + * This endpoint retrieves the details of a specific connection associated with the client, identified by the ID. + * @summary Retrieve a specific connection by ID + * @param {string} xClientId * @param {string} connectionId - * @param {string} authorization - * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page - * @param {number} [limit] Number of records to return per page - * @param {string} [orderBy] Field to order results by - * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async getAccounts(connectionId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.getAccounts(connectionId, authorization, cursor, limit, orderBy, desc, options); + async getById(xClientId: string, connectionId: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getById(xClientId, connectionId, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = operationServerMap['ProviderConnectionApi.getAccounts']?.[localVarOperationServerIndex]?.url; + const localVarOperationServerBasePath = operationServerMap['ProviderConnectionApi.getById']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** - * This endpoint retrieves the details of a specific connection associated with the client, identified by the ID. - * @summary Retrieve a specific connection by ID - * @param {string} connectionId - * @param {string} authorization + * This endpoint initiates a new connection by generating a public key and an encryption key for secure communication. + * @summary Initiate a new provider connection + * @param {string} xClientId + * @param {InitiateConnectionDto} initiateConnectionDto + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async getById(connectionId: string, authorization: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.getById(connectionId, authorization, options); + async initiate(xClientId: string, initiateConnectionDto: InitiateConnectionDto, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.initiate(xClientId, initiateConnectionDto, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = operationServerMap['ProviderConnectionApi.getById']?.[localVarOperationServerIndex]?.url; + const localVarOperationServerBasePath = operationServerMap['ProviderConnectionApi.initiate']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** - * This endpoint retrieves a list of wallets associated with a specific connection. - * @summary List wallets for a specific connection - * @param {string} connectionId - * @param {string} authorization + * This endpoint retrieves a list of all connections associated with the client. + * @summary List all connections + * @param {string} xClientId * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page * @param {number} [limit] Number of records to return per page * @param {string} [orderBy] Field to order results by * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async getWallets(connectionId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.getWallets(connectionId, authorization, cursor, limit, orderBy, desc, options); + async list(xClientId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.list(xClientId, cursor, limit, orderBy, desc, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = operationServerMap['ProviderConnectionApi.getWallets']?.[localVarOperationServerIndex]?.url; + const localVarOperationServerBasePath = operationServerMap['ProviderConnectionApi.list']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** - * This endpoint initiates a new connection by generating a public key and an encryption key for secure communication. - * @summary Initiate a new provider connection - * @param {string} authorization - * @param {InitiateConnectionDto} initiateConnectionDto + * This endpoint retrieves a list of accounts associated with a specific connection. + * @summary List accounts for a specific connection + * @param {string} xClientId + * @param {string} connectionId + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async initiate(authorization: string, initiateConnectionDto: InitiateConnectionDto, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.initiate(authorization, initiateConnectionDto, options); + async listAccounts(xClientId: string, connectionId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.listAccounts(xClientId, connectionId, cursor, limit, orderBy, desc, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = operationServerMap['ProviderConnectionApi.initiate']?.[localVarOperationServerIndex]?.url; + const localVarOperationServerBasePath = operationServerMap['ProviderConnectionApi.listAccounts']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** - * This endpoint retrieves a list of all connections associated with the client. - * @summary List all connections - * @param {string} authorization + * This endpoint retrieves a list of wallets associated with a specific connection. + * @summary List wallets for a specific connection + * @param {string} xClientId + * @param {string} connectionId * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page * @param {number} [limit] Number of records to return per page * @param {string} [orderBy] Field to order results by * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async list(authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.list(authorization, cursor, limit, orderBy, desc, options); + async listWallets(xClientId: string, connectionId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.listWallets(xClientId, connectionId, cursor, limit, orderBy, desc, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = operationServerMap['ProviderConnectionApi.list']?.[localVarOperationServerIndex]?.url; + const localVarOperationServerBasePath = operationServerMap['ProviderConnectionApi.listWallets']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** * This endpoint revokes an existing connection, effectively terminating any ongoing communication and invalidating the connection credentials. * @summary Revoke an existing connection + * @param {string} xClientId * @param {string} connectionId - * @param {string} authorization + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async revoke(connectionId: string, authorization: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.revoke(connectionId, authorization, options); + async revoke(xClientId: string, connectionId: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.revoke(xClientId, connectionId, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['ProviderConnectionApi.revoke']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); @@ -4494,14 +5167,15 @@ export const ProviderConnectionApiFp = function(configuration?: Configuration) { /** * This endpoint updates the details of a specific connection associated with the client, identified by the connection ID. * @summary Update a specific connection by ID + * @param {string} xClientId * @param {string} connectionId - * @param {string} authorization * @param {UpdateConnectionDto} updateConnectionDto + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async update(connectionId: string, authorization: string, updateConnectionDto: UpdateConnectionDto, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.update(connectionId, authorization, updateConnectionDto, options); + async update(xClientId: string, connectionId: string, updateConnectionDto: UpdateConnectionDto, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.update(xClientId, connectionId, updateConnectionDto, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['ProviderConnectionApi.update']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); @@ -4519,227 +5193,495 @@ export const ProviderConnectionApiFactory = function (configuration?: Configurat /** * This endpoint securely stores the details of a provider connection, ensuring that all sensitive information is encrypted. * @summary Store a provider connection securely - * @param {string} authorization - * @param {CreateConnectionDto} createConnectionDto + * @param {ProviderConnectionApiCreateRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - create(authorization: string, createConnectionDto: CreateConnectionDto, options?: any): AxiosPromise { - return localVarFp.create(authorization, createConnectionDto, options).then((request) => request(axios, basePath)); + create(requestParameters: ProviderConnectionApiCreateRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.create(requestParameters.xClientId, requestParameters.createConnectionDto, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, /** - * This endpoint retrieves a list of accounts associated with a specific connection. - * @summary List accounts for a specific connection - * @param {string} connectionId - * @param {string} authorization - * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page - * @param {number} [limit] Number of records to return per page - * @param {string} [orderBy] Field to order results by - * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * This endpoint retrieves the details of a specific connection associated with the client, identified by the ID. + * @summary Retrieve a specific connection by ID + * @param {ProviderConnectionApiGetByIdRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getAccounts(connectionId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: any): AxiosPromise { - return localVarFp.getAccounts(connectionId, authorization, cursor, limit, orderBy, desc, options).then((request) => request(axios, basePath)); + getById(requestParameters: ProviderConnectionApiGetByIdRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.getById(requestParameters.xClientId, requestParameters.connectionId, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, /** - * This endpoint retrieves the details of a specific connection associated with the client, identified by the ID. - * @summary Retrieve a specific connection by ID - * @param {string} connectionId - * @param {string} authorization + * This endpoint initiates a new connection by generating a public key and an encryption key for secure communication. + * @summary Initiate a new provider connection + * @param {ProviderConnectionApiInitiateRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getById(connectionId: string, authorization: string, options?: any): AxiosPromise { - return localVarFp.getById(connectionId, authorization, options).then((request) => request(axios, basePath)); + initiate(requestParameters: ProviderConnectionApiInitiateRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.initiate(requestParameters.xClientId, requestParameters.initiateConnectionDto, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, /** - * This endpoint retrieves a list of wallets associated with a specific connection. - * @summary List wallets for a specific connection - * @param {string} connectionId - * @param {string} authorization - * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page - * @param {number} [limit] Number of records to return per page - * @param {string} [orderBy] Field to order results by - * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * This endpoint retrieves a list of all connections associated with the client. + * @summary List all connections + * @param {ProviderConnectionApiListRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getWallets(connectionId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: any): AxiosPromise { - return localVarFp.getWallets(connectionId, authorization, cursor, limit, orderBy, desc, options).then((request) => request(axios, basePath)); + list(requestParameters: ProviderConnectionApiListRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.list(requestParameters.xClientId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, /** - * This endpoint initiates a new connection by generating a public key and an encryption key for secure communication. - * @summary Initiate a new provider connection - * @param {string} authorization - * @param {InitiateConnectionDto} initiateConnectionDto + * This endpoint retrieves a list of accounts associated with a specific connection. + * @summary List accounts for a specific connection + * @param {ProviderConnectionApiListAccountsRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - initiate(authorization: string, initiateConnectionDto: InitiateConnectionDto, options?: any): AxiosPromise { - return localVarFp.initiate(authorization, initiateConnectionDto, options).then((request) => request(axios, basePath)); + listAccounts(requestParameters: ProviderConnectionApiListAccountsRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.listAccounts(requestParameters.xClientId, requestParameters.connectionId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, /** - * This endpoint retrieves a list of all connections associated with the client. - * @summary List all connections - * @param {string} authorization - * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page - * @param {number} [limit] Number of records to return per page - * @param {string} [orderBy] Field to order results by - * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * This endpoint retrieves a list of wallets associated with a specific connection. + * @summary List wallets for a specific connection + * @param {ProviderConnectionApiListWalletsRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - list(authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: any): AxiosPromise { - return localVarFp.list(authorization, cursor, limit, orderBy, desc, options).then((request) => request(axios, basePath)); + listWallets(requestParameters: ProviderConnectionApiListWalletsRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.listWallets(requestParameters.xClientId, requestParameters.connectionId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, /** * This endpoint revokes an existing connection, effectively terminating any ongoing communication and invalidating the connection credentials. * @summary Revoke an existing connection - * @param {string} connectionId - * @param {string} authorization + * @param {ProviderConnectionApiRevokeRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - revoke(connectionId: string, authorization: string, options?: any): AxiosPromise { - return localVarFp.revoke(connectionId, authorization, options).then((request) => request(axios, basePath)); + revoke(requestParameters: ProviderConnectionApiRevokeRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.revoke(requestParameters.xClientId, requestParameters.connectionId, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, /** * This endpoint updates the details of a specific connection associated with the client, identified by the connection ID. * @summary Update a specific connection by ID - * @param {string} connectionId - * @param {string} authorization - * @param {UpdateConnectionDto} updateConnectionDto + * @param {ProviderConnectionApiUpdateRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - update(connectionId: string, authorization: string, updateConnectionDto: UpdateConnectionDto, options?: any): AxiosPromise { - return localVarFp.update(connectionId, authorization, updateConnectionDto, options).then((request) => request(axios, basePath)); + update(requestParameters: ProviderConnectionApiUpdateRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.update(requestParameters.xClientId, requestParameters.connectionId, requestParameters.updateConnectionDto, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, }; }; /** - * ProviderConnectionApi - object-oriented interface + * Request parameters for create operation in ProviderConnectionApi. * @export - * @class ProviderConnectionApi - * @extends {BaseAPI} + * @interface ProviderConnectionApiCreateRequest */ -export class ProviderConnectionApi extends BaseAPI { +export interface ProviderConnectionApiCreateRequest { /** - * This endpoint securely stores the details of a provider connection, ensuring that all sensitive information is encrypted. - * @summary Store a provider connection securely - * @param {string} authorization - * @param {CreateConnectionDto} createConnectionDto - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof ProviderConnectionApi + * + * @type {string} + * @memberof ProviderConnectionApiCreate */ - public create(authorization: string, createConnectionDto: CreateConnectionDto, options?: RawAxiosRequestConfig) { - return ProviderConnectionApiFp(this.configuration).create(authorization, createConnectionDto, options).then((request) => request(this.axios, this.basePath)); - } + readonly xClientId: string /** - * This endpoint retrieves a list of accounts associated with a specific connection. - * @summary List accounts for a specific connection - * @param {string} connectionId - * @param {string} authorization - * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page - * @param {number} [limit] Number of records to return per page - * @param {string} [orderBy] Field to order results by - * @param {string} [desc] Set to \"true\" or \"1\" for descending order - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof ProviderConnectionApi + * + * @type {CreateConnectionDto} + * @memberof ProviderConnectionApiCreate */ - public getAccounts(connectionId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig) { - return ProviderConnectionApiFp(this.configuration).getAccounts(connectionId, authorization, cursor, limit, orderBy, desc, options).then((request) => request(this.axios, this.basePath)); - } + readonly createConnectionDto: CreateConnectionDto /** - * This endpoint retrieves the details of a specific connection associated with the client, identified by the ID. - * @summary Retrieve a specific connection by ID - * @param {string} connectionId - * @param {string} authorization - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof ProviderConnectionApi + * + * @type {string} + * @memberof ProviderConnectionApiCreate */ - public getById(connectionId: string, authorization: string, options?: RawAxiosRequestConfig) { - return ProviderConnectionApiFp(this.configuration).getById(connectionId, authorization, options).then((request) => request(this.axios, this.basePath)); - } + readonly authorization?: string +} +/** + * Request parameters for getById operation in ProviderConnectionApi. + * @export + * @interface ProviderConnectionApiGetByIdRequest + */ +export interface ProviderConnectionApiGetByIdRequest { /** - * This endpoint retrieves a list of wallets associated with a specific connection. - * @summary List wallets for a specific connection - * @param {string} connectionId - * @param {string} authorization - * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page - * @param {number} [limit] Number of records to return per page - * @param {string} [orderBy] Field to order results by - * @param {string} [desc] Set to \"true\" or \"1\" for descending order - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof ProviderConnectionApi + * + * @type {string} + * @memberof ProviderConnectionApiGetById */ - public getWallets(connectionId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig) { - return ProviderConnectionApiFp(this.configuration).getWallets(connectionId, authorization, cursor, limit, orderBy, desc, options).then((request) => request(this.axios, this.basePath)); - } + readonly xClientId: string /** - * This endpoint initiates a new connection by generating a public key and an encryption key for secure communication. - * @summary Initiate a new provider connection - * @param {string} authorization - * @param {InitiateConnectionDto} initiateConnectionDto - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof ProviderConnectionApi + * + * @type {string} + * @memberof ProviderConnectionApiGetById */ - public initiate(authorization: string, initiateConnectionDto: InitiateConnectionDto, options?: RawAxiosRequestConfig) { - return ProviderConnectionApiFp(this.configuration).initiate(authorization, initiateConnectionDto, options).then((request) => request(this.axios, this.basePath)); - } + readonly connectionId: string /** - * This endpoint retrieves a list of all connections associated with the client. - * @summary List all connections - * @param {string} authorization - * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page - * @param {number} [limit] Number of records to return per page - * @param {string} [orderBy] Field to order results by - * @param {string} [desc] Set to \"true\" or \"1\" for descending order - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof ProviderConnectionApi + * + * @type {string} + * @memberof ProviderConnectionApiGetById */ - public list(authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig) { - return ProviderConnectionApiFp(this.configuration).list(authorization, cursor, limit, orderBy, desc, options).then((request) => request(this.axios, this.basePath)); - } + readonly authorization?: string +} +/** + * Request parameters for initiate operation in ProviderConnectionApi. + * @export + * @interface ProviderConnectionApiInitiateRequest + */ +export interface ProviderConnectionApiInitiateRequest { /** - * This endpoint revokes an existing connection, effectively terminating any ongoing communication and invalidating the connection credentials. - * @summary Revoke an existing connection - * @param {string} connectionId - * @param {string} authorization - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof ProviderConnectionApi + * + * @type {string} + * @memberof ProviderConnectionApiInitiate */ - public revoke(connectionId: string, authorization: string, options?: RawAxiosRequestConfig) { - return ProviderConnectionApiFp(this.configuration).revoke(connectionId, authorization, options).then((request) => request(this.axios, this.basePath)); - } + readonly xClientId: string /** - * This endpoint updates the details of a specific connection associated with the client, identified by the connection ID. + * + * @type {InitiateConnectionDto} + * @memberof ProviderConnectionApiInitiate + */ + readonly initiateConnectionDto: InitiateConnectionDto + + /** + * + * @type {string} + * @memberof ProviderConnectionApiInitiate + */ + readonly authorization?: string +} + +/** + * Request parameters for list operation in ProviderConnectionApi. + * @export + * @interface ProviderConnectionApiListRequest + */ +export interface ProviderConnectionApiListRequest { + /** + * + * @type {string} + * @memberof ProviderConnectionApiList + */ + readonly xClientId: string + + /** + * Cursor for pagination. Use the next cursor from previous response to get next page + * @type {string} + * @memberof ProviderConnectionApiList + */ + readonly cursor?: string + + /** + * Number of records to return per page + * @type {number} + * @memberof ProviderConnectionApiList + */ + readonly limit?: number + + /** + * Field to order results by + * @type {string} + * @memberof ProviderConnectionApiList + */ + readonly orderBy?: string + + /** + * Set to \"true\" or \"1\" for descending order + * @type {string} + * @memberof ProviderConnectionApiList + */ + readonly desc?: string + + /** + * + * @type {string} + * @memberof ProviderConnectionApiList + */ + readonly authorization?: string +} + +/** + * Request parameters for listAccounts operation in ProviderConnectionApi. + * @export + * @interface ProviderConnectionApiListAccountsRequest + */ +export interface ProviderConnectionApiListAccountsRequest { + /** + * + * @type {string} + * @memberof ProviderConnectionApiListAccounts + */ + readonly xClientId: string + + /** + * + * @type {string} + * @memberof ProviderConnectionApiListAccounts + */ + readonly connectionId: string + + /** + * Cursor for pagination. Use the next cursor from previous response to get next page + * @type {string} + * @memberof ProviderConnectionApiListAccounts + */ + readonly cursor?: string + + /** + * Number of records to return per page + * @type {number} + * @memberof ProviderConnectionApiListAccounts + */ + readonly limit?: number + + /** + * Field to order results by + * @type {string} + * @memberof ProviderConnectionApiListAccounts + */ + readonly orderBy?: string + + /** + * Set to \"true\" or \"1\" for descending order + * @type {string} + * @memberof ProviderConnectionApiListAccounts + */ + readonly desc?: string + + /** + * + * @type {string} + * @memberof ProviderConnectionApiListAccounts + */ + readonly authorization?: string +} + +/** + * Request parameters for listWallets operation in ProviderConnectionApi. + * @export + * @interface ProviderConnectionApiListWalletsRequest + */ +export interface ProviderConnectionApiListWalletsRequest { + /** + * + * @type {string} + * @memberof ProviderConnectionApiListWallets + */ + readonly xClientId: string + + /** + * + * @type {string} + * @memberof ProviderConnectionApiListWallets + */ + readonly connectionId: string + + /** + * Cursor for pagination. Use the next cursor from previous response to get next page + * @type {string} + * @memberof ProviderConnectionApiListWallets + */ + readonly cursor?: string + + /** + * Number of records to return per page + * @type {number} + * @memberof ProviderConnectionApiListWallets + */ + readonly limit?: number + + /** + * Field to order results by + * @type {string} + * @memberof ProviderConnectionApiListWallets + */ + readonly orderBy?: string + + /** + * Set to \"true\" or \"1\" for descending order + * @type {string} + * @memberof ProviderConnectionApiListWallets + */ + readonly desc?: string + + /** + * + * @type {string} + * @memberof ProviderConnectionApiListWallets + */ + readonly authorization?: string +} + +/** + * Request parameters for revoke operation in ProviderConnectionApi. + * @export + * @interface ProviderConnectionApiRevokeRequest + */ +export interface ProviderConnectionApiRevokeRequest { + /** + * + * @type {string} + * @memberof ProviderConnectionApiRevoke + */ + readonly xClientId: string + + /** + * + * @type {string} + * @memberof ProviderConnectionApiRevoke + */ + readonly connectionId: string + + /** + * + * @type {string} + * @memberof ProviderConnectionApiRevoke + */ + readonly authorization?: string +} + +/** + * Request parameters for update operation in ProviderConnectionApi. + * @export + * @interface ProviderConnectionApiUpdateRequest + */ +export interface ProviderConnectionApiUpdateRequest { + /** + * + * @type {string} + * @memberof ProviderConnectionApiUpdate + */ + readonly xClientId: string + + /** + * + * @type {string} + * @memberof ProviderConnectionApiUpdate + */ + readonly connectionId: string + + /** + * + * @type {UpdateConnectionDto} + * @memberof ProviderConnectionApiUpdate + */ + readonly updateConnectionDto: UpdateConnectionDto + + /** + * + * @type {string} + * @memberof ProviderConnectionApiUpdate + */ + readonly authorization?: string +} + +/** + * ProviderConnectionApi - object-oriented interface + * @export + * @class ProviderConnectionApi + * @extends {BaseAPI} + */ +export class ProviderConnectionApi extends BaseAPI { + /** + * This endpoint securely stores the details of a provider connection, ensuring that all sensitive information is encrypted. + * @summary Store a provider connection securely + * @param {ProviderConnectionApiCreateRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderConnectionApi + */ + public create(requestParameters: ProviderConnectionApiCreateRequest, options?: RawAxiosRequestConfig) { + return ProviderConnectionApiFp(this.configuration).create(requestParameters.xClientId, requestParameters.createConnectionDto, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * This endpoint retrieves the details of a specific connection associated with the client, identified by the ID. + * @summary Retrieve a specific connection by ID + * @param {ProviderConnectionApiGetByIdRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderConnectionApi + */ + public getById(requestParameters: ProviderConnectionApiGetByIdRequest, options?: RawAxiosRequestConfig) { + return ProviderConnectionApiFp(this.configuration).getById(requestParameters.xClientId, requestParameters.connectionId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * This endpoint initiates a new connection by generating a public key and an encryption key for secure communication. + * @summary Initiate a new provider connection + * @param {ProviderConnectionApiInitiateRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderConnectionApi + */ + public initiate(requestParameters: ProviderConnectionApiInitiateRequest, options?: RawAxiosRequestConfig) { + return ProviderConnectionApiFp(this.configuration).initiate(requestParameters.xClientId, requestParameters.initiateConnectionDto, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * This endpoint retrieves a list of all connections associated with the client. + * @summary List all connections + * @param {ProviderConnectionApiListRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderConnectionApi + */ + public list(requestParameters: ProviderConnectionApiListRequest, options?: RawAxiosRequestConfig) { + return ProviderConnectionApiFp(this.configuration).list(requestParameters.xClientId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * This endpoint retrieves a list of accounts associated with a specific connection. + * @summary List accounts for a specific connection + * @param {ProviderConnectionApiListAccountsRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderConnectionApi + */ + public listAccounts(requestParameters: ProviderConnectionApiListAccountsRequest, options?: RawAxiosRequestConfig) { + return ProviderConnectionApiFp(this.configuration).listAccounts(requestParameters.xClientId, requestParameters.connectionId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * This endpoint retrieves a list of wallets associated with a specific connection. + * @summary List wallets for a specific connection + * @param {ProviderConnectionApiListWalletsRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderConnectionApi + */ + public listWallets(requestParameters: ProviderConnectionApiListWalletsRequest, options?: RawAxiosRequestConfig) { + return ProviderConnectionApiFp(this.configuration).listWallets(requestParameters.xClientId, requestParameters.connectionId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * This endpoint revokes an existing connection, effectively terminating any ongoing communication and invalidating the connection credentials. + * @summary Revoke an existing connection + * @param {ProviderConnectionApiRevokeRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderConnectionApi + */ + public revoke(requestParameters: ProviderConnectionApiRevokeRequest, options?: RawAxiosRequestConfig) { + return ProviderConnectionApiFp(this.configuration).revoke(requestParameters.xClientId, requestParameters.connectionId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * This endpoint updates the details of a specific connection associated with the client, identified by the connection ID. * @summary Update a specific connection by ID - * @param {string} connectionId - * @param {string} authorization - * @param {UpdateConnectionDto} updateConnectionDto + * @param {ProviderConnectionApiUpdateRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof ProviderConnectionApi */ - public update(connectionId: string, authorization: string, updateConnectionDto: UpdateConnectionDto, options?: RawAxiosRequestConfig) { - return ProviderConnectionApiFp(this.configuration).update(connectionId, authorization, updateConnectionDto, options).then((request) => request(this.axios, this.basePath)); + public update(requestParameters: ProviderConnectionApiUpdateRequest, options?: RawAxiosRequestConfig) { + return ProviderConnectionApiFp(this.configuration).update(requestParameters.xClientId, requestParameters.connectionId, requestParameters.updateConnectionDto, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } } @@ -4754,19 +5696,20 @@ export const ProviderProxyApiAxiosParamCreator = function (configuration?: Confi /** * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. * @summary Authorizes and forwards the request to the provider + * @param {string} xClientId * @param {string} endpoint The raw endpoint path in the provider * @param {string} xConnectionId The connection ID used to forward request to provider - * @param {string} authorization + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - _delete: async (endpoint: string, xConnectionId: string, authorization: string, options: RawAxiosRequestConfig = {}): Promise => { + _delete: async (xClientId: string, endpoint: string, xConnectionId: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('_delete', 'xClientId', xClientId) // verify required parameter 'endpoint' is not null or undefined assertParamExists('_delete', 'endpoint', endpoint) // verify required parameter 'xConnectionId' is not null or undefined assertParamExists('_delete', 'xConnectionId', xConnectionId) - // verify required parameter 'authorization' is not null or undefined - assertParamExists('_delete', 'authorization', authorization) const localVarPath = `/v1/provider/proxy/{endpoint}` .replace(`{${"endpoint"}}`, encodeURIComponent(String(endpoint))); // use dummy base URL string because the URL constructor only accepts absolute URLs. @@ -4782,6 +5725,13 @@ export const ProviderProxyApiAxiosParamCreator = function (configuration?: Confi // authentication GNAP required + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + if (xConnectionId != null) { localVarHeaderParameter['x-connection-id'] = String(xConnectionId); } @@ -4804,19 +5754,20 @@ export const ProviderProxyApiAxiosParamCreator = function (configuration?: Confi /** * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. * @summary Authorizes and forwards the request to the provider + * @param {string} xClientId * @param {string} endpoint The raw endpoint path in the provider * @param {string} xConnectionId The connection ID used to forward request to provider - * @param {string} authorization + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - _options: async (endpoint: string, xConnectionId: string, authorization: string, options: RawAxiosRequestConfig = {}): Promise => { + _options: async (xClientId: string, endpoint: string, xConnectionId: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('_options', 'xClientId', xClientId) // verify required parameter 'endpoint' is not null or undefined assertParamExists('_options', 'endpoint', endpoint) // verify required parameter 'xConnectionId' is not null or undefined assertParamExists('_options', 'xConnectionId', xConnectionId) - // verify required parameter 'authorization' is not null or undefined - assertParamExists('_options', 'authorization', authorization) const localVarPath = `/v1/provider/proxy/{endpoint}` .replace(`{${"endpoint"}}`, encodeURIComponent(String(endpoint))); // use dummy base URL string because the URL constructor only accepts absolute URLs. @@ -4832,6 +5783,13 @@ export const ProviderProxyApiAxiosParamCreator = function (configuration?: Confi // authentication GNAP required + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + if (xConnectionId != null) { localVarHeaderParameter['x-connection-id'] = String(xConnectionId); } @@ -4854,19 +5812,20 @@ export const ProviderProxyApiAxiosParamCreator = function (configuration?: Confi /** * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. * @summary Authorizes and forwards the request to the provider + * @param {string} xClientId * @param {string} endpoint The raw endpoint path in the provider * @param {string} xConnectionId The connection ID used to forward request to provider - * @param {string} authorization + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - get: async (endpoint: string, xConnectionId: string, authorization: string, options: RawAxiosRequestConfig = {}): Promise => { + get: async (xClientId: string, endpoint: string, xConnectionId: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('get', 'xClientId', xClientId) // verify required parameter 'endpoint' is not null or undefined assertParamExists('get', 'endpoint', endpoint) // verify required parameter 'xConnectionId' is not null or undefined assertParamExists('get', 'xConnectionId', xConnectionId) - // verify required parameter 'authorization' is not null or undefined - assertParamExists('get', 'authorization', authorization) const localVarPath = `/v1/provider/proxy/{endpoint}` .replace(`{${"endpoint"}}`, encodeURIComponent(String(endpoint))); // use dummy base URL string because the URL constructor only accepts absolute URLs. @@ -4882,6 +5841,13 @@ export const ProviderProxyApiAxiosParamCreator = function (configuration?: Confi // authentication GNAP required + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + if (xConnectionId != null) { localVarHeaderParameter['x-connection-id'] = String(xConnectionId); } @@ -4904,19 +5870,20 @@ export const ProviderProxyApiAxiosParamCreator = function (configuration?: Confi /** * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. * @summary Authorizes and forwards the request to the provider + * @param {string} xClientId * @param {string} endpoint The raw endpoint path in the provider * @param {string} xConnectionId The connection ID used to forward request to provider - * @param {string} authorization + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - head: async (endpoint: string, xConnectionId: string, authorization: string, options: RawAxiosRequestConfig = {}): Promise => { + head: async (xClientId: string, endpoint: string, xConnectionId: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('head', 'xClientId', xClientId) // verify required parameter 'endpoint' is not null or undefined assertParamExists('head', 'endpoint', endpoint) // verify required parameter 'xConnectionId' is not null or undefined assertParamExists('head', 'xConnectionId', xConnectionId) - // verify required parameter 'authorization' is not null or undefined - assertParamExists('head', 'authorization', authorization) const localVarPath = `/v1/provider/proxy/{endpoint}` .replace(`{${"endpoint"}}`, encodeURIComponent(String(endpoint))); // use dummy base URL string because the URL constructor only accepts absolute URLs. @@ -4932,6 +5899,13 @@ export const ProviderProxyApiAxiosParamCreator = function (configuration?: Confi // authentication GNAP required + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + if (xConnectionId != null) { localVarHeaderParameter['x-connection-id'] = String(xConnectionId); } @@ -4954,19 +5928,20 @@ export const ProviderProxyApiAxiosParamCreator = function (configuration?: Confi /** * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. * @summary Authorizes and forwards the request to the provider + * @param {string} xClientId * @param {string} endpoint The raw endpoint path in the provider * @param {string} xConnectionId The connection ID used to forward request to provider - * @param {string} authorization + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - patch: async (endpoint: string, xConnectionId: string, authorization: string, options: RawAxiosRequestConfig = {}): Promise => { + patch: async (xClientId: string, endpoint: string, xConnectionId: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('patch', 'xClientId', xClientId) // verify required parameter 'endpoint' is not null or undefined assertParamExists('patch', 'endpoint', endpoint) // verify required parameter 'xConnectionId' is not null or undefined assertParamExists('patch', 'xConnectionId', xConnectionId) - // verify required parameter 'authorization' is not null or undefined - assertParamExists('patch', 'authorization', authorization) const localVarPath = `/v1/provider/proxy/{endpoint}` .replace(`{${"endpoint"}}`, encodeURIComponent(String(endpoint))); // use dummy base URL string because the URL constructor only accepts absolute URLs. @@ -4982,9 +5957,16 @@ export const ProviderProxyApiAxiosParamCreator = function (configuration?: Confi // authentication GNAP required - if (xConnectionId != null) { - localVarHeaderParameter['x-connection-id'] = String(xConnectionId); - } + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + + if (xConnectionId != null) { + localVarHeaderParameter['x-connection-id'] = String(xConnectionId); + } if (authorization != null) { localVarHeaderParameter['Authorization'] = String(authorization); @@ -5004,19 +5986,20 @@ export const ProviderProxyApiAxiosParamCreator = function (configuration?: Confi /** * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. * @summary Authorizes and forwards the request to the provider + * @param {string} xClientId * @param {string} endpoint The raw endpoint path in the provider * @param {string} xConnectionId The connection ID used to forward request to provider - * @param {string} authorization + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - post: async (endpoint: string, xConnectionId: string, authorization: string, options: RawAxiosRequestConfig = {}): Promise => { + post: async (xClientId: string, endpoint: string, xConnectionId: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('post', 'xClientId', xClientId) // verify required parameter 'endpoint' is not null or undefined assertParamExists('post', 'endpoint', endpoint) // verify required parameter 'xConnectionId' is not null or undefined assertParamExists('post', 'xConnectionId', xConnectionId) - // verify required parameter 'authorization' is not null or undefined - assertParamExists('post', 'authorization', authorization) const localVarPath = `/v1/provider/proxy/{endpoint}` .replace(`{${"endpoint"}}`, encodeURIComponent(String(endpoint))); // use dummy base URL string because the URL constructor only accepts absolute URLs. @@ -5032,6 +6015,13 @@ export const ProviderProxyApiAxiosParamCreator = function (configuration?: Confi // authentication GNAP required + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + if (xConnectionId != null) { localVarHeaderParameter['x-connection-id'] = String(xConnectionId); } @@ -5054,19 +6044,20 @@ export const ProviderProxyApiAxiosParamCreator = function (configuration?: Confi /** * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. * @summary Authorizes and forwards the request to the provider + * @param {string} xClientId * @param {string} endpoint The raw endpoint path in the provider * @param {string} xConnectionId The connection ID used to forward request to provider - * @param {string} authorization + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - put: async (endpoint: string, xConnectionId: string, authorization: string, options: RawAxiosRequestConfig = {}): Promise => { + put: async (xClientId: string, endpoint: string, xConnectionId: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('put', 'xClientId', xClientId) // verify required parameter 'endpoint' is not null or undefined assertParamExists('put', 'endpoint', endpoint) // verify required parameter 'xConnectionId' is not null or undefined assertParamExists('put', 'xConnectionId', xConnectionId) - // verify required parameter 'authorization' is not null or undefined - assertParamExists('put', 'authorization', authorization) const localVarPath = `/v1/provider/proxy/{endpoint}` .replace(`{${"endpoint"}}`, encodeURIComponent(String(endpoint))); // use dummy base URL string because the URL constructor only accepts absolute URLs. @@ -5082,6 +6073,13 @@ export const ProviderProxyApiAxiosParamCreator = function (configuration?: Confi // authentication GNAP required + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + if (xConnectionId != null) { localVarHeaderParameter['x-connection-id'] = String(xConnectionId); } @@ -5114,14 +6112,15 @@ export const ProviderProxyApiFp = function(configuration?: Configuration) { /** * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. * @summary Authorizes and forwards the request to the provider + * @param {string} xClientId * @param {string} endpoint The raw endpoint path in the provider * @param {string} xConnectionId The connection ID used to forward request to provider - * @param {string} authorization + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async _delete(endpoint: string, xConnectionId: string, authorization: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator._delete(endpoint, xConnectionId, authorization, options); + async _delete(xClientId: string, endpoint: string, xConnectionId: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator._delete(xClientId, endpoint, xConnectionId, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['ProviderProxyApi._delete']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); @@ -5129,14 +6128,15 @@ export const ProviderProxyApiFp = function(configuration?: Configuration) { /** * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. * @summary Authorizes and forwards the request to the provider + * @param {string} xClientId * @param {string} endpoint The raw endpoint path in the provider * @param {string} xConnectionId The connection ID used to forward request to provider - * @param {string} authorization + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async _options(endpoint: string, xConnectionId: string, authorization: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator._options(endpoint, xConnectionId, authorization, options); + async _options(xClientId: string, endpoint: string, xConnectionId: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator._options(xClientId, endpoint, xConnectionId, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['ProviderProxyApi._options']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); @@ -5144,14 +6144,15 @@ export const ProviderProxyApiFp = function(configuration?: Configuration) { /** * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. * @summary Authorizes and forwards the request to the provider + * @param {string} xClientId * @param {string} endpoint The raw endpoint path in the provider * @param {string} xConnectionId The connection ID used to forward request to provider - * @param {string} authorization + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async get(endpoint: string, xConnectionId: string, authorization: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.get(endpoint, xConnectionId, authorization, options); + async get(xClientId: string, endpoint: string, xConnectionId: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.get(xClientId, endpoint, xConnectionId, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['ProviderProxyApi.get']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); @@ -5159,14 +6160,15 @@ export const ProviderProxyApiFp = function(configuration?: Configuration) { /** * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. * @summary Authorizes and forwards the request to the provider + * @param {string} xClientId * @param {string} endpoint The raw endpoint path in the provider * @param {string} xConnectionId The connection ID used to forward request to provider - * @param {string} authorization + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async head(endpoint: string, xConnectionId: string, authorization: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.head(endpoint, xConnectionId, authorization, options); + async head(xClientId: string, endpoint: string, xConnectionId: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.head(xClientId, endpoint, xConnectionId, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['ProviderProxyApi.head']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); @@ -5174,14 +6176,15 @@ export const ProviderProxyApiFp = function(configuration?: Configuration) { /** * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. * @summary Authorizes and forwards the request to the provider + * @param {string} xClientId * @param {string} endpoint The raw endpoint path in the provider * @param {string} xConnectionId The connection ID used to forward request to provider - * @param {string} authorization + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async patch(endpoint: string, xConnectionId: string, authorization: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.patch(endpoint, xConnectionId, authorization, options); + async patch(xClientId: string, endpoint: string, xConnectionId: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.patch(xClientId, endpoint, xConnectionId, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['ProviderProxyApi.patch']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); @@ -5189,14 +6192,15 @@ export const ProviderProxyApiFp = function(configuration?: Configuration) { /** * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. * @summary Authorizes and forwards the request to the provider + * @param {string} xClientId * @param {string} endpoint The raw endpoint path in the provider * @param {string} xConnectionId The connection ID used to forward request to provider - * @param {string} authorization + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async post(endpoint: string, xConnectionId: string, authorization: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.post(endpoint, xConnectionId, authorization, options); + async post(xClientId: string, endpoint: string, xConnectionId: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.post(xClientId, endpoint, xConnectionId, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['ProviderProxyApi.post']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); @@ -5204,14 +6208,15 @@ export const ProviderProxyApiFp = function(configuration?: Configuration) { /** * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. * @summary Authorizes and forwards the request to the provider + * @param {string} xClientId * @param {string} endpoint The raw endpoint path in the provider * @param {string} xConnectionId The connection ID used to forward request to provider - * @param {string} authorization + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async put(endpoint: string, xConnectionId: string, authorization: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.put(endpoint, xConnectionId, authorization, options); + async put(xClientId: string, endpoint: string, xConnectionId: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.put(xClientId, endpoint, xConnectionId, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['ProviderProxyApi.put']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); @@ -5229,90 +6234,321 @@ export const ProviderProxyApiFactory = function (configuration?: Configuration, /** * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. * @summary Authorizes and forwards the request to the provider - * @param {string} endpoint The raw endpoint path in the provider - * @param {string} xConnectionId The connection ID used to forward request to provider - * @param {string} authorization + * @param {ProviderProxyApiDeleteRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - _delete(endpoint: string, xConnectionId: string, authorization: string, options?: any): AxiosPromise { - return localVarFp._delete(endpoint, xConnectionId, authorization, options).then((request) => request(axios, basePath)); + _delete(requestParameters: ProviderProxyApiDeleteRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp._delete(requestParameters.xClientId, requestParameters.endpoint, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, /** * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. * @summary Authorizes and forwards the request to the provider - * @param {string} endpoint The raw endpoint path in the provider - * @param {string} xConnectionId The connection ID used to forward request to provider - * @param {string} authorization + * @param {ProviderProxyApiOptionsRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - _options(endpoint: string, xConnectionId: string, authorization: string, options?: any): AxiosPromise { - return localVarFp._options(endpoint, xConnectionId, authorization, options).then((request) => request(axios, basePath)); + _options(requestParameters: ProviderProxyApiOptionsRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp._options(requestParameters.xClientId, requestParameters.endpoint, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, /** * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. * @summary Authorizes and forwards the request to the provider - * @param {string} endpoint The raw endpoint path in the provider - * @param {string} xConnectionId The connection ID used to forward request to provider - * @param {string} authorization + * @param {ProviderProxyApiGetRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - get(endpoint: string, xConnectionId: string, authorization: string, options?: any): AxiosPromise { - return localVarFp.get(endpoint, xConnectionId, authorization, options).then((request) => request(axios, basePath)); + get(requestParameters: ProviderProxyApiGetRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.get(requestParameters.xClientId, requestParameters.endpoint, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, /** * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. * @summary Authorizes and forwards the request to the provider - * @param {string} endpoint The raw endpoint path in the provider - * @param {string} xConnectionId The connection ID used to forward request to provider - * @param {string} authorization + * @param {ProviderProxyApiHeadRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - head(endpoint: string, xConnectionId: string, authorization: string, options?: any): AxiosPromise { - return localVarFp.head(endpoint, xConnectionId, authorization, options).then((request) => request(axios, basePath)); + head(requestParameters: ProviderProxyApiHeadRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.head(requestParameters.xClientId, requestParameters.endpoint, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, /** * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. * @summary Authorizes and forwards the request to the provider - * @param {string} endpoint The raw endpoint path in the provider - * @param {string} xConnectionId The connection ID used to forward request to provider - * @param {string} authorization + * @param {ProviderProxyApiPatchRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - patch(endpoint: string, xConnectionId: string, authorization: string, options?: any): AxiosPromise { - return localVarFp.patch(endpoint, xConnectionId, authorization, options).then((request) => request(axios, basePath)); + patch(requestParameters: ProviderProxyApiPatchRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.patch(requestParameters.xClientId, requestParameters.endpoint, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, /** * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. * @summary Authorizes and forwards the request to the provider - * @param {string} endpoint The raw endpoint path in the provider - * @param {string} xConnectionId The connection ID used to forward request to provider - * @param {string} authorization + * @param {ProviderProxyApiPostRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - post(endpoint: string, xConnectionId: string, authorization: string, options?: any): AxiosPromise { - return localVarFp.post(endpoint, xConnectionId, authorization, options).then((request) => request(axios, basePath)); + post(requestParameters: ProviderProxyApiPostRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.post(requestParameters.xClientId, requestParameters.endpoint, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, /** * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. * @summary Authorizes and forwards the request to the provider - * @param {string} endpoint The raw endpoint path in the provider - * @param {string} xConnectionId The connection ID used to forward request to provider - * @param {string} authorization + * @param {ProviderProxyApiPutRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - put(endpoint: string, xConnectionId: string, authorization: string, options?: any): AxiosPromise { - return localVarFp.put(endpoint, xConnectionId, authorization, options).then((request) => request(axios, basePath)); + put(requestParameters: ProviderProxyApiPutRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.put(requestParameters.xClientId, requestParameters.endpoint, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, }; }; +/** + * Request parameters for _delete operation in ProviderProxyApi. + * @export + * @interface ProviderProxyApiDeleteRequest + */ +export interface ProviderProxyApiDeleteRequest { + /** + * + * @type {string} + * @memberof ProviderProxyApiDelete + */ + readonly xClientId: string + + /** + * The raw endpoint path in the provider + * @type {string} + * @memberof ProviderProxyApiDelete + */ + readonly endpoint: string + + /** + * The connection ID used to forward request to provider + * @type {string} + * @memberof ProviderProxyApiDelete + */ + readonly xConnectionId: string + + /** + * + * @type {string} + * @memberof ProviderProxyApiDelete + */ + readonly authorization?: string +} + +/** + * Request parameters for _options operation in ProviderProxyApi. + * @export + * @interface ProviderProxyApiOptionsRequest + */ +export interface ProviderProxyApiOptionsRequest { + /** + * + * @type {string} + * @memberof ProviderProxyApiOptions + */ + readonly xClientId: string + + /** + * The raw endpoint path in the provider + * @type {string} + * @memberof ProviderProxyApiOptions + */ + readonly endpoint: string + + /** + * The connection ID used to forward request to provider + * @type {string} + * @memberof ProviderProxyApiOptions + */ + readonly xConnectionId: string + + /** + * + * @type {string} + * @memberof ProviderProxyApiOptions + */ + readonly authorization?: string +} + +/** + * Request parameters for get operation in ProviderProxyApi. + * @export + * @interface ProviderProxyApiGetRequest + */ +export interface ProviderProxyApiGetRequest { + /** + * + * @type {string} + * @memberof ProviderProxyApiGet + */ + readonly xClientId: string + + /** + * The raw endpoint path in the provider + * @type {string} + * @memberof ProviderProxyApiGet + */ + readonly endpoint: string + + /** + * The connection ID used to forward request to provider + * @type {string} + * @memberof ProviderProxyApiGet + */ + readonly xConnectionId: string + + /** + * + * @type {string} + * @memberof ProviderProxyApiGet + */ + readonly authorization?: string +} + +/** + * Request parameters for head operation in ProviderProxyApi. + * @export + * @interface ProviderProxyApiHeadRequest + */ +export interface ProviderProxyApiHeadRequest { + /** + * + * @type {string} + * @memberof ProviderProxyApiHead + */ + readonly xClientId: string + + /** + * The raw endpoint path in the provider + * @type {string} + * @memberof ProviderProxyApiHead + */ + readonly endpoint: string + + /** + * The connection ID used to forward request to provider + * @type {string} + * @memberof ProviderProxyApiHead + */ + readonly xConnectionId: string + + /** + * + * @type {string} + * @memberof ProviderProxyApiHead + */ + readonly authorization?: string +} + +/** + * Request parameters for patch operation in ProviderProxyApi. + * @export + * @interface ProviderProxyApiPatchRequest + */ +export interface ProviderProxyApiPatchRequest { + /** + * + * @type {string} + * @memberof ProviderProxyApiPatch + */ + readonly xClientId: string + + /** + * The raw endpoint path in the provider + * @type {string} + * @memberof ProviderProxyApiPatch + */ + readonly endpoint: string + + /** + * The connection ID used to forward request to provider + * @type {string} + * @memberof ProviderProxyApiPatch + */ + readonly xConnectionId: string + + /** + * + * @type {string} + * @memberof ProviderProxyApiPatch + */ + readonly authorization?: string +} + +/** + * Request parameters for post operation in ProviderProxyApi. + * @export + * @interface ProviderProxyApiPostRequest + */ +export interface ProviderProxyApiPostRequest { + /** + * + * @type {string} + * @memberof ProviderProxyApiPost + */ + readonly xClientId: string + + /** + * The raw endpoint path in the provider + * @type {string} + * @memberof ProviderProxyApiPost + */ + readonly endpoint: string + + /** + * The connection ID used to forward request to provider + * @type {string} + * @memberof ProviderProxyApiPost + */ + readonly xConnectionId: string + + /** + * + * @type {string} + * @memberof ProviderProxyApiPost + */ + readonly authorization?: string +} + +/** + * Request parameters for put operation in ProviderProxyApi. + * @export + * @interface ProviderProxyApiPutRequest + */ +export interface ProviderProxyApiPutRequest { + /** + * + * @type {string} + * @memberof ProviderProxyApiPut + */ + readonly xClientId: string + + /** + * The raw endpoint path in the provider + * @type {string} + * @memberof ProviderProxyApiPut + */ + readonly endpoint: string + + /** + * The connection ID used to forward request to provider + * @type {string} + * @memberof ProviderProxyApiPut + */ + readonly xConnectionId: string + + /** + * + * @type {string} + * @memberof ProviderProxyApiPut + */ + readonly authorization?: string +} + /** * ProviderProxyApi - object-oriented interface * @export @@ -5323,99 +6559,85 @@ export class ProviderProxyApi extends BaseAPI { /** * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. * @summary Authorizes and forwards the request to the provider - * @param {string} endpoint The raw endpoint path in the provider - * @param {string} xConnectionId The connection ID used to forward request to provider - * @param {string} authorization + * @param {ProviderProxyApiDeleteRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof ProviderProxyApi */ - public _delete(endpoint: string, xConnectionId: string, authorization: string, options?: RawAxiosRequestConfig) { - return ProviderProxyApiFp(this.configuration)._delete(endpoint, xConnectionId, authorization, options).then((request) => request(this.axios, this.basePath)); + public _delete(requestParameters: ProviderProxyApiDeleteRequest, options?: RawAxiosRequestConfig) { + return ProviderProxyApiFp(this.configuration)._delete(requestParameters.xClientId, requestParameters.endpoint, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } /** * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. * @summary Authorizes and forwards the request to the provider - * @param {string} endpoint The raw endpoint path in the provider - * @param {string} xConnectionId The connection ID used to forward request to provider - * @param {string} authorization + * @param {ProviderProxyApiOptionsRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof ProviderProxyApi */ - public _options(endpoint: string, xConnectionId: string, authorization: string, options?: RawAxiosRequestConfig) { - return ProviderProxyApiFp(this.configuration)._options(endpoint, xConnectionId, authorization, options).then((request) => request(this.axios, this.basePath)); + public _options(requestParameters: ProviderProxyApiOptionsRequest, options?: RawAxiosRequestConfig) { + return ProviderProxyApiFp(this.configuration)._options(requestParameters.xClientId, requestParameters.endpoint, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } /** * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. * @summary Authorizes and forwards the request to the provider - * @param {string} endpoint The raw endpoint path in the provider - * @param {string} xConnectionId The connection ID used to forward request to provider - * @param {string} authorization + * @param {ProviderProxyApiGetRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof ProviderProxyApi */ - public get(endpoint: string, xConnectionId: string, authorization: string, options?: RawAxiosRequestConfig) { - return ProviderProxyApiFp(this.configuration).get(endpoint, xConnectionId, authorization, options).then((request) => request(this.axios, this.basePath)); + public get(requestParameters: ProviderProxyApiGetRequest, options?: RawAxiosRequestConfig) { + return ProviderProxyApiFp(this.configuration).get(requestParameters.xClientId, requestParameters.endpoint, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } /** * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. * @summary Authorizes and forwards the request to the provider - * @param {string} endpoint The raw endpoint path in the provider - * @param {string} xConnectionId The connection ID used to forward request to provider - * @param {string} authorization + * @param {ProviderProxyApiHeadRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof ProviderProxyApi */ - public head(endpoint: string, xConnectionId: string, authorization: string, options?: RawAxiosRequestConfig) { - return ProviderProxyApiFp(this.configuration).head(endpoint, xConnectionId, authorization, options).then((request) => request(this.axios, this.basePath)); + public head(requestParameters: ProviderProxyApiHeadRequest, options?: RawAxiosRequestConfig) { + return ProviderProxyApiFp(this.configuration).head(requestParameters.xClientId, requestParameters.endpoint, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } /** * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. * @summary Authorizes and forwards the request to the provider - * @param {string} endpoint The raw endpoint path in the provider - * @param {string} xConnectionId The connection ID used to forward request to provider - * @param {string} authorization + * @param {ProviderProxyApiPatchRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof ProviderProxyApi */ - public patch(endpoint: string, xConnectionId: string, authorization: string, options?: RawAxiosRequestConfig) { - return ProviderProxyApiFp(this.configuration).patch(endpoint, xConnectionId, authorization, options).then((request) => request(this.axios, this.basePath)); + public patch(requestParameters: ProviderProxyApiPatchRequest, options?: RawAxiosRequestConfig) { + return ProviderProxyApiFp(this.configuration).patch(requestParameters.xClientId, requestParameters.endpoint, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } /** * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. * @summary Authorizes and forwards the request to the provider - * @param {string} endpoint The raw endpoint path in the provider - * @param {string} xConnectionId The connection ID used to forward request to provider - * @param {string} authorization + * @param {ProviderProxyApiPostRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof ProviderProxyApi */ - public post(endpoint: string, xConnectionId: string, authorization: string, options?: RawAxiosRequestConfig) { - return ProviderProxyApiFp(this.configuration).post(endpoint, xConnectionId, authorization, options).then((request) => request(this.axios, this.basePath)); + public post(requestParameters: ProviderProxyApiPostRequest, options?: RawAxiosRequestConfig) { + return ProviderProxyApiFp(this.configuration).post(requestParameters.xClientId, requestParameters.endpoint, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } /** * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. * @summary Authorizes and forwards the request to the provider - * @param {string} endpoint The raw endpoint path in the provider - * @param {string} xConnectionId The connection ID used to forward request to provider - * @param {string} authorization + * @param {ProviderProxyApiPutRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof ProviderProxyApi */ - public put(endpoint: string, xConnectionId: string, authorization: string, options?: RawAxiosRequestConfig) { - return ProviderProxyApiFp(this.configuration).put(endpoint, xConnectionId, authorization, options).then((request) => request(this.axios, this.basePath)); + public put(requestParameters: ProviderProxyApiPutRequest, options?: RawAxiosRequestConfig) { + return ProviderProxyApiFp(this.configuration).put(requestParameters.xClientId, requestParameters.endpoint, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } } @@ -5427,23 +6649,75 @@ export class ProviderProxyApi extends BaseAPI { */ export const ProviderSyncApiAxiosParamCreator = function (configuration?: Configuration) { return { + /** + * This endpoint retrieves the details of a specific synchronization process associated with the client, identified by the sync ID. + * @summary Retrieve a specific synchronization process by ID + * @param {string} xClientId + * @param {string} syncId + * @param {string} [authorization] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getById: async (xClientId: string, syncId: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('getById', 'xClientId', xClientId) + // verify required parameter 'syncId' is not null or undefined + assertParamExists('getById', 'syncId', syncId) + const localVarPath = `/v1/provider/syncs/{syncId}` + .replace(`{${"syncId"}}`, encodeURIComponent(String(syncId))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, /** * This endpoint retrieves a list of synchronization processes associated with the client. Optionally, it can filter the processes by a specific connection ID. * @summary Retrieve a list of synchronization processes + * @param {string} xClientId * @param {string} connectionId - * @param {string} authorization * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page * @param {number} [limit] Number of records to return per page * @param {string} [orderBy] Field to order results by * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - findAll: async (connectionId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options: RawAxiosRequestConfig = {}): Promise => { + list: async (xClientId: string, connectionId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('list', 'xClientId', xClientId) // verify required parameter 'connectionId' is not null or undefined - assertParamExists('findAll', 'connectionId', connectionId) - // verify required parameter 'authorization' is not null or undefined - assertParamExists('findAll', 'authorization', authorization) + assertParamExists('list', 'connectionId', connectionId) const localVarPath = `/v1/provider/syncs`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -5458,6 +6732,9 @@ export const ProviderSyncApiAxiosParamCreator = function (configuration?: Config // authentication GNAP required + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + if (connectionId !== undefined) { localVarQueryParameter['connectionId'] = connectionId; } @@ -5478,55 +6755,16 @@ export const ProviderSyncApiAxiosParamCreator = function (configuration?: Config localVarQueryParameter['desc'] = desc; } + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + if (authorization != null) { localVarHeaderParameter['Authorization'] = String(authorization); } - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * This endpoint retrieves the details of a specific synchronization process associated with the client, identified by the sync ID. - * @summary Retrieve a specific synchronization process by ID - * @param {string} syncId - * @param {string} authorization - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - findById: async (syncId: string, authorization: string, options: RawAxiosRequestConfig = {}): Promise => { - // verify required parameter 'syncId' is not null or undefined - assertParamExists('findById', 'syncId', syncId) - // verify required parameter 'authorization' is not null or undefined - assertParamExists('findById', 'authorization', authorization) - const localVarPath = `/v1/provider/syncs/{syncId}` - .replace(`{${"syncId"}}`, encodeURIComponent(String(syncId))); - // use dummy base URL string because the URL constructor only accepts absolute URLs. - const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); - let baseOptions; - if (configuration) { - baseOptions = configuration.baseOptions; - } - - const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; - const localVarHeaderParameter = {} as any; - const localVarQueryParameter = {} as any; - - // authentication GNAP required - - if (authorization != null) { - localVarHeaderParameter['Authorization'] = String(authorization); - } - - - setSearchParams(localVarUrlObj, localVarQueryParameter); let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; @@ -5539,14 +6777,15 @@ export const ProviderSyncApiAxiosParamCreator = function (configuration?: Config /** * This endpoint starts synchronization process for the client. * @summary Start a synchronization process - * @param {string} authorization + * @param {string} xClientId * @param {StartSyncDto} startSyncDto + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - start: async (authorization: string, startSyncDto: StartSyncDto, options: RawAxiosRequestConfig = {}): Promise => { - // verify required parameter 'authorization' is not null or undefined - assertParamExists('start', 'authorization', authorization) + start: async (xClientId: string, startSyncDto: StartSyncDto, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('start', 'xClientId', xClientId) // verify required parameter 'startSyncDto' is not null or undefined assertParamExists('start', 'startSyncDto', startSyncDto) const localVarPath = `/v1/provider/syncs`; @@ -5563,6 +6802,13 @@ export const ProviderSyncApiAxiosParamCreator = function (configuration?: Config // authentication GNAP required + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + if (authorization != null) { localVarHeaderParameter['Authorization'] = String(authorization); } @@ -5592,47 +6838,50 @@ export const ProviderSyncApiFp = function(configuration?: Configuration) { const localVarAxiosParamCreator = ProviderSyncApiAxiosParamCreator(configuration) return { /** - * This endpoint retrieves a list of synchronization processes associated with the client. Optionally, it can filter the processes by a specific connection ID. - * @summary Retrieve a list of synchronization processes - * @param {string} connectionId - * @param {string} authorization - * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page - * @param {number} [limit] Number of records to return per page - * @param {string} [orderBy] Field to order results by - * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * This endpoint retrieves the details of a specific synchronization process associated with the client, identified by the sync ID. + * @summary Retrieve a specific synchronization process by ID + * @param {string} xClientId + * @param {string} syncId + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async findAll(connectionId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.findAll(connectionId, authorization, cursor, limit, orderBy, desc, options); + async getById(xClientId: string, syncId: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getById(xClientId, syncId, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = operationServerMap['ProviderSyncApi.findAll']?.[localVarOperationServerIndex]?.url; + const localVarOperationServerBasePath = operationServerMap['ProviderSyncApi.getById']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** - * This endpoint retrieves the details of a specific synchronization process associated with the client, identified by the sync ID. - * @summary Retrieve a specific synchronization process by ID - * @param {string} syncId - * @param {string} authorization + * This endpoint retrieves a list of synchronization processes associated with the client. Optionally, it can filter the processes by a specific connection ID. + * @summary Retrieve a list of synchronization processes + * @param {string} xClientId + * @param {string} connectionId + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async findById(syncId: string, authorization: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.findById(syncId, authorization, options); + async list(xClientId: string, connectionId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.list(xClientId, connectionId, cursor, limit, orderBy, desc, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = operationServerMap['ProviderSyncApi.findById']?.[localVarOperationServerIndex]?.url; + const localVarOperationServerBasePath = operationServerMap['ProviderSyncApi.list']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** * This endpoint starts synchronization process for the client. * @summary Start a synchronization process - * @param {string} authorization + * @param {string} xClientId * @param {StartSyncDto} startSyncDto + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async start(authorization: string, startSyncDto: StartSyncDto, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.start(authorization, startSyncDto, options); + async start(xClientId: string, startSyncDto: StartSyncDto, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.start(xClientId, startSyncDto, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['ProviderSyncApi.start']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); @@ -5648,45 +6897,150 @@ export const ProviderSyncApiFactory = function (configuration?: Configuration, b const localVarFp = ProviderSyncApiFp(configuration) return { /** - * This endpoint retrieves a list of synchronization processes associated with the client. Optionally, it can filter the processes by a specific connection ID. - * @summary Retrieve a list of synchronization processes - * @param {string} connectionId - * @param {string} authorization - * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page - * @param {number} [limit] Number of records to return per page - * @param {string} [orderBy] Field to order results by - * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * This endpoint retrieves the details of a specific synchronization process associated with the client, identified by the sync ID. + * @summary Retrieve a specific synchronization process by ID + * @param {ProviderSyncApiGetByIdRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - findAll(connectionId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: any): AxiosPromise { - return localVarFp.findAll(connectionId, authorization, cursor, limit, orderBy, desc, options).then((request) => request(axios, basePath)); + getById(requestParameters: ProviderSyncApiGetByIdRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.getById(requestParameters.xClientId, requestParameters.syncId, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, /** - * This endpoint retrieves the details of a specific synchronization process associated with the client, identified by the sync ID. - * @summary Retrieve a specific synchronization process by ID - * @param {string} syncId - * @param {string} authorization + * This endpoint retrieves a list of synchronization processes associated with the client. Optionally, it can filter the processes by a specific connection ID. + * @summary Retrieve a list of synchronization processes + * @param {ProviderSyncApiListRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - findById(syncId: string, authorization: string, options?: any): AxiosPromise { - return localVarFp.findById(syncId, authorization, options).then((request) => request(axios, basePath)); + list(requestParameters: ProviderSyncApiListRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.list(requestParameters.xClientId, requestParameters.connectionId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, /** * This endpoint starts synchronization process for the client. * @summary Start a synchronization process - * @param {string} authorization - * @param {StartSyncDto} startSyncDto + * @param {ProviderSyncApiStartRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - start(authorization: string, startSyncDto: StartSyncDto, options?: any): AxiosPromise { - return localVarFp.start(authorization, startSyncDto, options).then((request) => request(axios, basePath)); + start(requestParameters: ProviderSyncApiStartRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.start(requestParameters.xClientId, requestParameters.startSyncDto, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, }; }; +/** + * Request parameters for getById operation in ProviderSyncApi. + * @export + * @interface ProviderSyncApiGetByIdRequest + */ +export interface ProviderSyncApiGetByIdRequest { + /** + * + * @type {string} + * @memberof ProviderSyncApiGetById + */ + readonly xClientId: string + + /** + * + * @type {string} + * @memberof ProviderSyncApiGetById + */ + readonly syncId: string + + /** + * + * @type {string} + * @memberof ProviderSyncApiGetById + */ + readonly authorization?: string +} + +/** + * Request parameters for list operation in ProviderSyncApi. + * @export + * @interface ProviderSyncApiListRequest + */ +export interface ProviderSyncApiListRequest { + /** + * + * @type {string} + * @memberof ProviderSyncApiList + */ + readonly xClientId: string + + /** + * + * @type {string} + * @memberof ProviderSyncApiList + */ + readonly connectionId: string + + /** + * Cursor for pagination. Use the next cursor from previous response to get next page + * @type {string} + * @memberof ProviderSyncApiList + */ + readonly cursor?: string + + /** + * Number of records to return per page + * @type {number} + * @memberof ProviderSyncApiList + */ + readonly limit?: number + + /** + * Field to order results by + * @type {string} + * @memberof ProviderSyncApiList + */ + readonly orderBy?: string + + /** + * Set to \"true\" or \"1\" for descending order + * @type {string} + * @memberof ProviderSyncApiList + */ + readonly desc?: string + + /** + * + * @type {string} + * @memberof ProviderSyncApiList + */ + readonly authorization?: string +} + +/** + * Request parameters for start operation in ProviderSyncApi. + * @export + * @interface ProviderSyncApiStartRequest + */ +export interface ProviderSyncApiStartRequest { + /** + * + * @type {string} + * @memberof ProviderSyncApiStart + */ + readonly xClientId: string + + /** + * + * @type {StartSyncDto} + * @memberof ProviderSyncApiStart + */ + readonly startSyncDto: StartSyncDto + + /** + * + * @type {string} + * @memberof ProviderSyncApiStart + */ + readonly authorization?: string +} + /** * ProviderSyncApi - object-oriented interface * @export @@ -5695,76 +7049,66 @@ export const ProviderSyncApiFactory = function (configuration?: Configuration, b */ export class ProviderSyncApi extends BaseAPI { /** - * This endpoint retrieves a list of synchronization processes associated with the client. Optionally, it can filter the processes by a specific connection ID. - * @summary Retrieve a list of synchronization processes - * @param {string} connectionId - * @param {string} authorization - * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page - * @param {number} [limit] Number of records to return per page - * @param {string} [orderBy] Field to order results by - * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * This endpoint retrieves the details of a specific synchronization process associated with the client, identified by the sync ID. + * @summary Retrieve a specific synchronization process by ID + * @param {ProviderSyncApiGetByIdRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof ProviderSyncApi */ - public findAll(connectionId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig) { - return ProviderSyncApiFp(this.configuration).findAll(connectionId, authorization, cursor, limit, orderBy, desc, options).then((request) => request(this.axios, this.basePath)); + public getById(requestParameters: ProviderSyncApiGetByIdRequest, options?: RawAxiosRequestConfig) { + return ProviderSyncApiFp(this.configuration).getById(requestParameters.xClientId, requestParameters.syncId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } /** - * This endpoint retrieves the details of a specific synchronization process associated with the client, identified by the sync ID. - * @summary Retrieve a specific synchronization process by ID - * @param {string} syncId - * @param {string} authorization + * This endpoint retrieves a list of synchronization processes associated with the client. Optionally, it can filter the processes by a specific connection ID. + * @summary Retrieve a list of synchronization processes + * @param {ProviderSyncApiListRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof ProviderSyncApi */ - public findById(syncId: string, authorization: string, options?: RawAxiosRequestConfig) { - return ProviderSyncApiFp(this.configuration).findById(syncId, authorization, options).then((request) => request(this.axios, this.basePath)); + public list(requestParameters: ProviderSyncApiListRequest, options?: RawAxiosRequestConfig) { + return ProviderSyncApiFp(this.configuration).list(requestParameters.xClientId, requestParameters.connectionId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } /** * This endpoint starts synchronization process for the client. * @summary Start a synchronization process - * @param {string} authorization - * @param {StartSyncDto} startSyncDto + * @param {ProviderSyncApiStartRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof ProviderSyncApi */ - public start(authorization: string, startSyncDto: StartSyncDto, options?: RawAxiosRequestConfig) { - return ProviderSyncApiFp(this.configuration).start(authorization, startSyncDto, options).then((request) => request(this.axios, this.basePath)); + public start(requestParameters: ProviderSyncApiStartRequest, options?: RawAxiosRequestConfig) { + return ProviderSyncApiFp(this.configuration).start(requestParameters.xClientId, requestParameters.startSyncDto, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } } /** - * ProviderWalletApi - axios parameter creator + * ProviderTransferApi - axios parameter creator * @export */ -export const ProviderWalletApiAxiosParamCreator = function (configuration?: Configuration) { +export const ProviderTransferApiAxiosParamCreator = function (configuration?: Configuration) { return { /** - * - * @summary List accounts for a specific wallet - * @param {string} walletId The ID of the wallet to retrieve accounts for - * @param {string} authorization - * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page - * @param {number} [limit] Number of records to return per page - * @param {string} [orderBy] Field to order results by - * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * This endpoint retrieves the details of a specific transfer using its ID. + * @summary Retrieve transfer details + * @param {string} xClientId + * @param {string} transferId + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getWalletAccounts: async (walletId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options: RawAxiosRequestConfig = {}): Promise => { - // verify required parameter 'walletId' is not null or undefined - assertParamExists('getWalletAccounts', 'walletId', walletId) - // verify required parameter 'authorization' is not null or undefined - assertParamExists('getWalletAccounts', 'authorization', authorization) - const localVarPath = `/v1/provider/wallets/{walletId}/accounts` - .replace(`{${"walletId"}}`, encodeURIComponent(String(walletId))); + getById: async (xClientId: string, transferId: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('getById', 'xClientId', xClientId) + // verify required parameter 'transferId' is not null or undefined + assertParamExists('getById', 'transferId', transferId) + const localVarPath = `/v1/provider/transfers/{transferId}` + .replace(`{${"transferId"}}`, encodeURIComponent(String(transferId))); // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); let baseOptions; @@ -5778,20 +7122,284 @@ export const ProviderWalletApiAxiosParamCreator = function (configuration?: Conf // authentication GNAP required - if (cursor !== undefined) { - localVarQueryParameter['cursor'] = cursor; + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); } - if (limit !== undefined) { - localVarQueryParameter['limit'] = limit; + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); } - if (orderBy !== undefined) { - localVarQueryParameter['orderBy'] = orderBy; + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * This endpoint sends a transfer to the source\'s provider. + * @summary Send a transfer + * @param {string} xClientId + * @param {SendTransferDto} sendTransferDto + * @param {string} [authorization] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + send: async (xClientId: string, sendTransferDto: SendTransferDto, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('send', 'xClientId', xClientId) + // verify required parameter 'sendTransferDto' is not null or undefined + assertParamExists('send', 'sendTransferDto', sendTransferDto) + const localVarPath = `/v1/provider/transfers`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; } - if (desc !== undefined) { - localVarQueryParameter['desc'] = desc; + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(sendTransferDto, localVarRequestOptions, configuration) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + } +}; + +/** + * ProviderTransferApi - functional programming interface + * @export + */ +export const ProviderTransferApiFp = function(configuration?: Configuration) { + const localVarAxiosParamCreator = ProviderTransferApiAxiosParamCreator(configuration) + return { + /** + * This endpoint retrieves the details of a specific transfer using its ID. + * @summary Retrieve transfer details + * @param {string} xClientId + * @param {string} transferId + * @param {string} [authorization] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getById(xClientId: string, transferId: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getById(xClientId, transferId, authorization, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderTransferApi.getById']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + /** + * This endpoint sends a transfer to the source\'s provider. + * @summary Send a transfer + * @param {string} xClientId + * @param {SendTransferDto} sendTransferDto + * @param {string} [authorization] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async send(xClientId: string, sendTransferDto: SendTransferDto, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.send(xClientId, sendTransferDto, authorization, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderTransferApi.send']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + } +}; + +/** + * ProviderTransferApi - factory interface + * @export + */ +export const ProviderTransferApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { + const localVarFp = ProviderTransferApiFp(configuration) + return { + /** + * This endpoint retrieves the details of a specific transfer using its ID. + * @summary Retrieve transfer details + * @param {ProviderTransferApiGetByIdRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getById(requestParameters: ProviderTransferApiGetByIdRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.getById(requestParameters.xClientId, requestParameters.transferId, requestParameters.authorization, options).then((request) => request(axios, basePath)); + }, + /** + * This endpoint sends a transfer to the source\'s provider. + * @summary Send a transfer + * @param {ProviderTransferApiSendRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + send(requestParameters: ProviderTransferApiSendRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.send(requestParameters.xClientId, requestParameters.sendTransferDto, requestParameters.authorization, options).then((request) => request(axios, basePath)); + }, + }; +}; + +/** + * Request parameters for getById operation in ProviderTransferApi. + * @export + * @interface ProviderTransferApiGetByIdRequest + */ +export interface ProviderTransferApiGetByIdRequest { + /** + * + * @type {string} + * @memberof ProviderTransferApiGetById + */ + readonly xClientId: string + + /** + * + * @type {string} + * @memberof ProviderTransferApiGetById + */ + readonly transferId: string + + /** + * + * @type {string} + * @memberof ProviderTransferApiGetById + */ + readonly authorization?: string +} + +/** + * Request parameters for send operation in ProviderTransferApi. + * @export + * @interface ProviderTransferApiSendRequest + */ +export interface ProviderTransferApiSendRequest { + /** + * + * @type {string} + * @memberof ProviderTransferApiSend + */ + readonly xClientId: string + + /** + * + * @type {SendTransferDto} + * @memberof ProviderTransferApiSend + */ + readonly sendTransferDto: SendTransferDto + + /** + * + * @type {string} + * @memberof ProviderTransferApiSend + */ + readonly authorization?: string +} + +/** + * ProviderTransferApi - object-oriented interface + * @export + * @class ProviderTransferApi + * @extends {BaseAPI} + */ +export class ProviderTransferApi extends BaseAPI { + /** + * This endpoint retrieves the details of a specific transfer using its ID. + * @summary Retrieve transfer details + * @param {ProviderTransferApiGetByIdRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderTransferApi + */ + public getById(requestParameters: ProviderTransferApiGetByIdRequest, options?: RawAxiosRequestConfig) { + return ProviderTransferApiFp(this.configuration).getById(requestParameters.xClientId, requestParameters.transferId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * This endpoint sends a transfer to the source\'s provider. + * @summary Send a transfer + * @param {ProviderTransferApiSendRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderTransferApi + */ + public send(requestParameters: ProviderTransferApiSendRequest, options?: RawAxiosRequestConfig) { + return ProviderTransferApiFp(this.configuration).send(requestParameters.xClientId, requestParameters.sendTransferDto, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + } +} + + + +/** + * ProviderWalletApi - axios parameter creator + * @export + */ +export const ProviderWalletApiAxiosParamCreator = function (configuration?: Configuration) { + return { + /** + * + * @summary Get a specific wallet by ID + * @param {string} xClientId + * @param {string} walletId The ID of the wallet to retrieve + * @param {string} [authorization] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getById: async (xClientId: string, walletId: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('getById', 'xClientId', xClientId) + // verify required parameter 'walletId' is not null or undefined + assertParamExists('getById', 'walletId', walletId) + const localVarPath = `/v1/provider/wallets/{walletId}` + .replace(`{${"walletId"}}`, encodeURIComponent(String(walletId))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); } if (authorization != null) { @@ -5811,19 +7419,20 @@ export const ProviderWalletApiAxiosParamCreator = function (configuration?: Conf }, /** * - * @summary Get a specific wallet by ID - * @param {string} walletId The ID of the wallet to retrieve - * @param {string} authorization + * @summary List the client wallets + * @param {string} xClientId + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getWalletById: async (walletId: string, authorization: string, options: RawAxiosRequestConfig = {}): Promise => { - // verify required parameter 'walletId' is not null or undefined - assertParamExists('getWalletById', 'walletId', walletId) - // verify required parameter 'authorization' is not null or undefined - assertParamExists('getWalletById', 'authorization', authorization) - const localVarPath = `/v1/provider/wallets/{walletId}` - .replace(`{${"walletId"}}`, encodeURIComponent(String(walletId))); + list: async (xClientId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('list', 'xClientId', xClientId) + const localVarPath = `/v1/provider/wallets`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); let baseOptions; @@ -5837,6 +7446,29 @@ export const ProviderWalletApiAxiosParamCreator = function (configuration?: Conf // authentication GNAP required + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + + if (cursor !== undefined) { + localVarQueryParameter['cursor'] = cursor; + } + + if (limit !== undefined) { + localVarQueryParameter['limit'] = limit; + } + + if (orderBy !== undefined) { + localVarQueryParameter['orderBy'] = orderBy; + } + + if (desc !== undefined) { + localVarQueryParameter['desc'] = desc; + } + + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + if (authorization != null) { localVarHeaderParameter['Authorization'] = String(authorization); } @@ -5854,19 +7486,24 @@ export const ProviderWalletApiAxiosParamCreator = function (configuration?: Conf }, /** * - * @summary List the client wallets - * @param {string} authorization + * @summary List accounts for a specific wallet + * @param {string} xClientId + * @param {string} walletId The ID of the wallet to retrieve accounts for * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page * @param {number} [limit] Number of records to return per page * @param {string} [orderBy] Field to order results by * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - listByClientId: async (authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options: RawAxiosRequestConfig = {}): Promise => { - // verify required parameter 'authorization' is not null or undefined - assertParamExists('listByClientId', 'authorization', authorization) - const localVarPath = `/v1/provider/wallets`; + listAccounts: async (xClientId: string, walletId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('listAccounts', 'xClientId', xClientId) + // verify required parameter 'walletId' is not null or undefined + assertParamExists('listAccounts', 'walletId', walletId) + const localVarPath = `/v1/provider/wallets/{walletId}/accounts` + .replace(`{${"walletId"}}`, encodeURIComponent(String(walletId))); // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); let baseOptions; @@ -5880,6 +7517,9 @@ export const ProviderWalletApiAxiosParamCreator = function (configuration?: Conf // authentication GNAP required + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + if (cursor !== undefined) { localVarQueryParameter['cursor'] = cursor; } @@ -5896,6 +7536,10 @@ export const ProviderWalletApiAxiosParamCreator = function (configuration?: Conf localVarQueryParameter['desc'] = desc; } + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + if (authorization != null) { localVarHeaderParameter['Authorization'] = String(authorization); } @@ -5923,51 +7567,54 @@ export const ProviderWalletApiFp = function(configuration?: Configuration) { return { /** * - * @summary List accounts for a specific wallet - * @param {string} walletId The ID of the wallet to retrieve accounts for - * @param {string} authorization - * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page - * @param {number} [limit] Number of records to return per page - * @param {string} [orderBy] Field to order results by - * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @summary Get a specific wallet by ID + * @param {string} xClientId + * @param {string} walletId The ID of the wallet to retrieve + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async getWalletAccounts(walletId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.getWalletAccounts(walletId, authorization, cursor, limit, orderBy, desc, options); + async getById(xClientId: string, walletId: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getById(xClientId, walletId, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = operationServerMap['ProviderWalletApi.getWalletAccounts']?.[localVarOperationServerIndex]?.url; + const localVarOperationServerBasePath = operationServerMap['ProviderWalletApi.getById']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** * - * @summary Get a specific wallet by ID - * @param {string} walletId The ID of the wallet to retrieve - * @param {string} authorization + * @summary List the client wallets + * @param {string} xClientId + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async getWalletById(walletId: string, authorization: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.getWalletById(walletId, authorization, options); + async list(xClientId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.list(xClientId, cursor, limit, orderBy, desc, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = operationServerMap['ProviderWalletApi.getWalletById']?.[localVarOperationServerIndex]?.url; + const localVarOperationServerBasePath = operationServerMap['ProviderWalletApi.list']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** * - * @summary List the client wallets - * @param {string} authorization + * @summary List accounts for a specific wallet + * @param {string} xClientId + * @param {string} walletId The ID of the wallet to retrieve accounts for * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page * @param {number} [limit] Number of records to return per page * @param {string} [orderBy] Field to order results by * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async listByClientId(authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.listByClientId(authorization, cursor, limit, orderBy, desc, options); + async listAccounts(xClientId: string, walletId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.listAccounts(xClientId, walletId, cursor, limit, orderBy, desc, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = operationServerMap['ProviderWalletApi.listByClientId']?.[localVarOperationServerIndex]?.url; + const localVarOperationServerBasePath = operationServerMap['ProviderWalletApi.listAccounts']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, } @@ -5982,47 +7629,170 @@ export const ProviderWalletApiFactory = function (configuration?: Configuration, return { /** * - * @summary List accounts for a specific wallet - * @param {string} walletId The ID of the wallet to retrieve accounts for - * @param {string} authorization - * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page - * @param {number} [limit] Number of records to return per page - * @param {string} [orderBy] Field to order results by - * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @summary Get a specific wallet by ID + * @param {ProviderWalletApiGetByIdRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getWalletAccounts(walletId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: any): AxiosPromise { - return localVarFp.getWalletAccounts(walletId, authorization, cursor, limit, orderBy, desc, options).then((request) => request(axios, basePath)); + getById(requestParameters: ProviderWalletApiGetByIdRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.getById(requestParameters.xClientId, requestParameters.walletId, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, /** * - * @summary Get a specific wallet by ID - * @param {string} walletId The ID of the wallet to retrieve - * @param {string} authorization + * @summary List the client wallets + * @param {ProviderWalletApiListRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getWalletById(walletId: string, authorization: string, options?: any): AxiosPromise { - return localVarFp.getWalletById(walletId, authorization, options).then((request) => request(axios, basePath)); + list(requestParameters: ProviderWalletApiListRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.list(requestParameters.xClientId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, /** * - * @summary List the client wallets - * @param {string} authorization - * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page - * @param {number} [limit] Number of records to return per page - * @param {string} [orderBy] Field to order results by - * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @summary List accounts for a specific wallet + * @param {ProviderWalletApiListAccountsRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - listByClientId(authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: any): AxiosPromise { - return localVarFp.listByClientId(authorization, cursor, limit, orderBy, desc, options).then((request) => request(axios, basePath)); + listAccounts(requestParameters: ProviderWalletApiListAccountsRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.listAccounts(requestParameters.xClientId, requestParameters.walletId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, }; }; +/** + * Request parameters for getById operation in ProviderWalletApi. + * @export + * @interface ProviderWalletApiGetByIdRequest + */ +export interface ProviderWalletApiGetByIdRequest { + /** + * + * @type {string} + * @memberof ProviderWalletApiGetById + */ + readonly xClientId: string + + /** + * The ID of the wallet to retrieve + * @type {string} + * @memberof ProviderWalletApiGetById + */ + readonly walletId: string + + /** + * + * @type {string} + * @memberof ProviderWalletApiGetById + */ + readonly authorization?: string +} + +/** + * Request parameters for list operation in ProviderWalletApi. + * @export + * @interface ProviderWalletApiListRequest + */ +export interface ProviderWalletApiListRequest { + /** + * + * @type {string} + * @memberof ProviderWalletApiList + */ + readonly xClientId: string + + /** + * Cursor for pagination. Use the next cursor from previous response to get next page + * @type {string} + * @memberof ProviderWalletApiList + */ + readonly cursor?: string + + /** + * Number of records to return per page + * @type {number} + * @memberof ProviderWalletApiList + */ + readonly limit?: number + + /** + * Field to order results by + * @type {string} + * @memberof ProviderWalletApiList + */ + readonly orderBy?: string + + /** + * Set to \"true\" or \"1\" for descending order + * @type {string} + * @memberof ProviderWalletApiList + */ + readonly desc?: string + + /** + * + * @type {string} + * @memberof ProviderWalletApiList + */ + readonly authorization?: string +} + +/** + * Request parameters for listAccounts operation in ProviderWalletApi. + * @export + * @interface ProviderWalletApiListAccountsRequest + */ +export interface ProviderWalletApiListAccountsRequest { + /** + * + * @type {string} + * @memberof ProviderWalletApiListAccounts + */ + readonly xClientId: string + + /** + * The ID of the wallet to retrieve accounts for + * @type {string} + * @memberof ProviderWalletApiListAccounts + */ + readonly walletId: string + + /** + * Cursor for pagination. Use the next cursor from previous response to get next page + * @type {string} + * @memberof ProviderWalletApiListAccounts + */ + readonly cursor?: string + + /** + * Number of records to return per page + * @type {number} + * @memberof ProviderWalletApiListAccounts + */ + readonly limit?: number + + /** + * Field to order results by + * @type {string} + * @memberof ProviderWalletApiListAccounts + */ + readonly orderBy?: string + + /** + * Set to \"true\" or \"1\" for descending order + * @type {string} + * @memberof ProviderWalletApiListAccounts + */ + readonly desc?: string + + /** + * + * @type {string} + * @memberof ProviderWalletApiListAccounts + */ + readonly authorization?: string +} + /** * ProviderWalletApi - object-oriented interface * @export @@ -6032,48 +7802,38 @@ export const ProviderWalletApiFactory = function (configuration?: Configuration, export class ProviderWalletApi extends BaseAPI { /** * - * @summary List accounts for a specific wallet - * @param {string} walletId The ID of the wallet to retrieve accounts for - * @param {string} authorization - * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page - * @param {number} [limit] Number of records to return per page - * @param {string} [orderBy] Field to order results by - * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @summary Get a specific wallet by ID + * @param {ProviderWalletApiGetByIdRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof ProviderWalletApi */ - public getWalletAccounts(walletId: string, authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig) { - return ProviderWalletApiFp(this.configuration).getWalletAccounts(walletId, authorization, cursor, limit, orderBy, desc, options).then((request) => request(this.axios, this.basePath)); + public getById(requestParameters: ProviderWalletApiGetByIdRequest, options?: RawAxiosRequestConfig) { + return ProviderWalletApiFp(this.configuration).getById(requestParameters.xClientId, requestParameters.walletId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } /** * - * @summary Get a specific wallet by ID - * @param {string} walletId The ID of the wallet to retrieve - * @param {string} authorization + * @summary List the client wallets + * @param {ProviderWalletApiListRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof ProviderWalletApi */ - public getWalletById(walletId: string, authorization: string, options?: RawAxiosRequestConfig) { - return ProviderWalletApiFp(this.configuration).getWalletById(walletId, authorization, options).then((request) => request(this.axios, this.basePath)); + public list(requestParameters: ProviderWalletApiListRequest, options?: RawAxiosRequestConfig) { + return ProviderWalletApiFp(this.configuration).list(requestParameters.xClientId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } /** * - * @summary List the client wallets - * @param {string} authorization - * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page - * @param {number} [limit] Number of records to return per page - * @param {string} [orderBy] Field to order results by - * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @summary List accounts for a specific wallet + * @param {ProviderWalletApiListAccountsRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof ProviderWalletApi */ - public listByClientId(authorization: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, options?: RawAxiosRequestConfig) { - return ProviderWalletApiFp(this.configuration).listByClientId(authorization, cursor, limit, orderBy, desc, options).then((request) => request(this.axios, this.basePath)); + public listAccounts(requestParameters: ProviderWalletApiListAccountsRequest, options?: RawAxiosRequestConfig) { + return ProviderWalletApiFp(this.configuration).listAccounts(requestParameters.xClientId, requestParameters.walletId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } } @@ -6089,16 +7849,14 @@ export const SignApiAxiosParamCreator = function (configuration?: Configuration) * * @summary Signs the given request * @param {string} xClientId - * @param {string} authorization * @param {SignRequestDto} signRequestDto + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - sign: async (xClientId: string, authorization: string, signRequestDto: SignRequestDto, options: RawAxiosRequestConfig = {}): Promise => { + sign: async (xClientId: string, signRequestDto: SignRequestDto, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'xClientId' is not null or undefined assertParamExists('sign', 'xClientId', xClientId) - // verify required parameter 'authorization' is not null or undefined - assertParamExists('sign', 'authorization', authorization) // verify required parameter 'signRequestDto' is not null or undefined assertParamExists('sign', 'signRequestDto', signRequestDto) const localVarPath = `/v1/sign`; @@ -6115,6 +7873,9 @@ export const SignApiAxiosParamCreator = function (configuration?: Configuration) // authentication GNAP required + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + if (xClientId != null) { localVarHeaderParameter['x-client-id'] = String(xClientId); } @@ -6151,13 +7912,13 @@ export const SignApiFp = function(configuration?: Configuration) { * * @summary Signs the given request * @param {string} xClientId - * @param {string} authorization * @param {SignRequestDto} signRequestDto + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async sign(xClientId: string, authorization: string, signRequestDto: SignRequestDto, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.sign(xClientId, authorization, signRequestDto, options); + async sign(xClientId: string, signRequestDto: SignRequestDto, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.sign(xClientId, signRequestDto, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['SignApi.sign']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); @@ -6175,18 +7936,44 @@ export const SignApiFactory = function (configuration?: Configuration, basePath? /** * * @summary Signs the given request - * @param {string} xClientId - * @param {string} authorization - * @param {SignRequestDto} signRequestDto + * @param {SignApiSignRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - sign(xClientId: string, authorization: string, signRequestDto: SignRequestDto, options?: any): AxiosPromise { - return localVarFp.sign(xClientId, authorization, signRequestDto, options).then((request) => request(axios, basePath)); + sign(requestParameters: SignApiSignRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.sign(requestParameters.xClientId, requestParameters.signRequestDto, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, }; }; +/** + * Request parameters for sign operation in SignApi. + * @export + * @interface SignApiSignRequest + */ +export interface SignApiSignRequest { + /** + * + * @type {string} + * @memberof SignApiSign + */ + readonly xClientId: string + + /** + * + * @type {SignRequestDto} + * @memberof SignApiSign + */ + readonly signRequestDto: SignRequestDto + + /** + * + * @type {string} + * @memberof SignApiSign + */ + readonly authorization?: string +} + /** * SignApi - object-oriented interface * @export @@ -6197,15 +7984,13 @@ export class SignApi extends BaseAPI { /** * * @summary Signs the given request - * @param {string} xClientId - * @param {string} authorization - * @param {SignRequestDto} signRequestDto + * @param {SignApiSignRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof SignApi */ - public sign(xClientId: string, authorization: string, signRequestDto: SignRequestDto, options?: RawAxiosRequestConfig) { - return SignApiFp(this.configuration).sign(xClientId, authorization, signRequestDto, options).then((request) => request(this.axios, this.basePath)); + public sign(requestParameters: SignApiSignRequest, options?: RawAxiosRequestConfig) { + return SignApiFp(this.configuration).sign(requestParameters.xClientId, requestParameters.signRequestDto, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } } @@ -6221,16 +8006,14 @@ export const WalletApiAxiosParamCreator = function (configuration?: Configuratio * * @summary Generates a new wallet * @param {string} xClientId - * @param {string} authorization * @param {GenerateWalletDto} generateWalletDto + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - generate: async (xClientId: string, authorization: string, generateWalletDto: GenerateWalletDto, options: RawAxiosRequestConfig = {}): Promise => { + generate: async (xClientId: string, generateWalletDto: GenerateWalletDto, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'xClientId' is not null or undefined assertParamExists('generate', 'xClientId', xClientId) - // verify required parameter 'authorization' is not null or undefined - assertParamExists('generate', 'authorization', authorization) // verify required parameter 'generateWalletDto' is not null or undefined assertParamExists('generate', 'generateWalletDto', generateWalletDto) const localVarPath = `/v1/wallets`; @@ -6247,6 +8030,9 @@ export const WalletApiAxiosParamCreator = function (configuration?: Configuratio // authentication GNAP required + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + if (xClientId != null) { localVarHeaderParameter['x-client-id'] = String(xClientId); } @@ -6273,16 +8059,14 @@ export const WalletApiAxiosParamCreator = function (configuration?: Configuratio * * @summary Imports a wallet * @param {string} xClientId - * @param {string} authorization * @param {ImportWalletDto} importWalletDto + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - importSeed: async (xClientId: string, authorization: string, importWalletDto: ImportWalletDto, options: RawAxiosRequestConfig = {}): Promise => { + importSeed: async (xClientId: string, importWalletDto: ImportWalletDto, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'xClientId' is not null or undefined assertParamExists('importSeed', 'xClientId', xClientId) - // verify required parameter 'authorization' is not null or undefined - assertParamExists('importSeed', 'authorization', authorization) // verify required parameter 'importWalletDto' is not null or undefined assertParamExists('importSeed', 'importWalletDto', importWalletDto) const localVarPath = `/v1/wallets/import`; @@ -6299,6 +8083,9 @@ export const WalletApiAxiosParamCreator = function (configuration?: Configuratio // authentication GNAP required + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + if (xClientId != null) { localVarHeaderParameter['x-client-id'] = String(xClientId); } @@ -6325,15 +8112,13 @@ export const WalletApiAxiosParamCreator = function (configuration?: Configuratio * * @summary List the client wallets * @param {string} xClientId - * @param {string} authorization + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - list: async (xClientId: string, authorization: string, options: RawAxiosRequestConfig = {}): Promise => { + list: async (xClientId: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'xClientId' is not null or undefined assertParamExists('list', 'xClientId', xClientId) - // verify required parameter 'authorization' is not null or undefined - assertParamExists('list', 'authorization', authorization) const localVarPath = `/v1/wallets`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -6348,6 +8133,9 @@ export const WalletApiAxiosParamCreator = function (configuration?: Configuratio // authentication GNAP required + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + if (xClientId != null) { localVarHeaderParameter['x-client-id'] = String(xClientId); } @@ -6381,13 +8169,13 @@ export const WalletApiFp = function(configuration?: Configuration) { * * @summary Generates a new wallet * @param {string} xClientId - * @param {string} authorization * @param {GenerateWalletDto} generateWalletDto + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async generate(xClientId: string, authorization: string, generateWalletDto: GenerateWalletDto, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.generate(xClientId, authorization, generateWalletDto, options); + async generate(xClientId: string, generateWalletDto: GenerateWalletDto, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.generate(xClientId, generateWalletDto, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['WalletApi.generate']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); @@ -6396,13 +8184,13 @@ export const WalletApiFp = function(configuration?: Configuration) { * * @summary Imports a wallet * @param {string} xClientId - * @param {string} authorization * @param {ImportWalletDto} importWalletDto + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async importSeed(xClientId: string, authorization: string, importWalletDto: ImportWalletDto, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.importSeed(xClientId, authorization, importWalletDto, options); + async importSeed(xClientId: string, importWalletDto: ImportWalletDto, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.importSeed(xClientId, importWalletDto, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['WalletApi.importSeed']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); @@ -6411,11 +8199,11 @@ export const WalletApiFp = function(configuration?: Configuration) { * * @summary List the client wallets * @param {string} xClientId - * @param {string} authorization + * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async list(xClientId: string, authorization: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async list(xClientId: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.list(xClientId, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['WalletApi.list']?.[localVarOperationServerIndex]?.url; @@ -6434,41 +8222,113 @@ export const WalletApiFactory = function (configuration?: Configuration, basePat /** * * @summary Generates a new wallet - * @param {string} xClientId - * @param {string} authorization - * @param {GenerateWalletDto} generateWalletDto + * @param {WalletApiGenerateRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - generate(xClientId: string, authorization: string, generateWalletDto: GenerateWalletDto, options?: any): AxiosPromise { - return localVarFp.generate(xClientId, authorization, generateWalletDto, options).then((request) => request(axios, basePath)); + generate(requestParameters: WalletApiGenerateRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.generate(requestParameters.xClientId, requestParameters.generateWalletDto, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, /** * * @summary Imports a wallet - * @param {string} xClientId - * @param {string} authorization - * @param {ImportWalletDto} importWalletDto + * @param {WalletApiImportSeedRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - importSeed(xClientId: string, authorization: string, importWalletDto: ImportWalletDto, options?: any): AxiosPromise { - return localVarFp.importSeed(xClientId, authorization, importWalletDto, options).then((request) => request(axios, basePath)); + importSeed(requestParameters: WalletApiImportSeedRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.importSeed(requestParameters.xClientId, requestParameters.importWalletDto, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, /** * * @summary List the client wallets - * @param {string} xClientId - * @param {string} authorization + * @param {WalletApiListRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - list(xClientId: string, authorization: string, options?: any): AxiosPromise { - return localVarFp.list(xClientId, authorization, options).then((request) => request(axios, basePath)); + list(requestParameters: WalletApiListRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.list(requestParameters.xClientId, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, }; }; +/** + * Request parameters for generate operation in WalletApi. + * @export + * @interface WalletApiGenerateRequest + */ +export interface WalletApiGenerateRequest { + /** + * + * @type {string} + * @memberof WalletApiGenerate + */ + readonly xClientId: string + + /** + * + * @type {GenerateWalletDto} + * @memberof WalletApiGenerate + */ + readonly generateWalletDto: GenerateWalletDto + + /** + * + * @type {string} + * @memberof WalletApiGenerate + */ + readonly authorization?: string +} + +/** + * Request parameters for importSeed operation in WalletApi. + * @export + * @interface WalletApiImportSeedRequest + */ +export interface WalletApiImportSeedRequest { + /** + * + * @type {string} + * @memberof WalletApiImportSeed + */ + readonly xClientId: string + + /** + * + * @type {ImportWalletDto} + * @memberof WalletApiImportSeed + */ + readonly importWalletDto: ImportWalletDto + + /** + * + * @type {string} + * @memberof WalletApiImportSeed + */ + readonly authorization?: string +} + +/** + * Request parameters for list operation in WalletApi. + * @export + * @interface WalletApiListRequest + */ +export interface WalletApiListRequest { + /** + * + * @type {string} + * @memberof WalletApiList + */ + readonly xClientId: string + + /** + * + * @type {string} + * @memberof WalletApiList + */ + readonly authorization?: string +} + /** * WalletApi - object-oriented interface * @export @@ -6479,42 +8339,37 @@ export class WalletApi extends BaseAPI { /** * * @summary Generates a new wallet - * @param {string} xClientId - * @param {string} authorization - * @param {GenerateWalletDto} generateWalletDto + * @param {WalletApiGenerateRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof WalletApi */ - public generate(xClientId: string, authorization: string, generateWalletDto: GenerateWalletDto, options?: RawAxiosRequestConfig) { - return WalletApiFp(this.configuration).generate(xClientId, authorization, generateWalletDto, options).then((request) => request(this.axios, this.basePath)); + public generate(requestParameters: WalletApiGenerateRequest, options?: RawAxiosRequestConfig) { + return WalletApiFp(this.configuration).generate(requestParameters.xClientId, requestParameters.generateWalletDto, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } /** * * @summary Imports a wallet - * @param {string} xClientId - * @param {string} authorization - * @param {ImportWalletDto} importWalletDto + * @param {WalletApiImportSeedRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof WalletApi */ - public importSeed(xClientId: string, authorization: string, importWalletDto: ImportWalletDto, options?: RawAxiosRequestConfig) { - return WalletApiFp(this.configuration).importSeed(xClientId, authorization, importWalletDto, options).then((request) => request(this.axios, this.basePath)); + public importSeed(requestParameters: WalletApiImportSeedRequest, options?: RawAxiosRequestConfig) { + return WalletApiFp(this.configuration).importSeed(requestParameters.xClientId, requestParameters.importWalletDto, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } /** * * @summary List the client wallets - * @param {string} xClientId - * @param {string} authorization + * @param {WalletApiListRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof WalletApi */ - public list(xClientId: string, authorization: string, options?: RawAxiosRequestConfig) { - return WalletApiFp(this.configuration).list(xClientId, authorization, options).then((request) => request(this.axios, this.basePath)); + public list(requestParameters: WalletApiListRequest, options?: RawAxiosRequestConfig) { + return WalletApiFp(this.configuration).list(requestParameters.xClientId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } } diff --git a/packages/armory-sdk/src/lib/http/client/vault/base.ts b/packages/armory-sdk/src/lib/http/client/vault/base.ts index ee423a9ba..b617443dc 100644 --- a/packages/armory-sdk/src/lib/http/client/vault/base.ts +++ b/packages/armory-sdk/src/lib/http/client/vault/base.ts @@ -19,7 +19,7 @@ import type { Configuration } from './configuration'; import type { AxiosPromise, AxiosInstance, RawAxiosRequestConfig } from 'axios'; import globalAxios from 'axios'; -export const BASE_PATH = "http://localhost".replace(/\/+$/, ""); +export const BASE_PATH = "http://localhost:3011".replace(/\/+$/, ""); /** * diff --git a/packages/armory-sdk/src/lib/shared/gnap.ts b/packages/armory-sdk/src/lib/shared/gnap.ts index 3e9bb7fa4..80429d707 100644 --- a/packages/armory-sdk/src/lib/shared/gnap.ts +++ b/packages/armory-sdk/src/lib/shared/gnap.ts @@ -67,9 +67,9 @@ export const getJwsdProof = async (args: GetJwsdProof): Promise => { return parts.join('.') } -export const getBearerToken = ({ value }: AccessToken): string => `GNAP ${value}` +export const prefixGnapToken = ({ value }: AccessToken): string => `GNAP ${value}` -export const parseToken = (value: string): string => value.replace('GNAP ', '') +export const parseToken = (value: string): string => value.trim().replace(/^(GNAP|bearer)\s+/i, '') const getHtm = (method: string): Htm => { switch (method.toLowerCase()) { @@ -90,10 +90,10 @@ export const interceptRequestAddDetachedJwsHeader = assert(config.url !== undefined, 'Missing request URL') assert(config.method !== undefined, 'Missing request method') - const bearerToken = config.headers['Authorization'] || config.headers['authorization'] + const authorizationHeader = config.headers['Authorization'] || config.headers['authorization'] - if (bearerToken) { - const token = parseToken(bearerToken) + if (authorizationHeader) { + const token = parseToken(authorizationHeader) const htm = getHtm(config.method) const payload = config.data ? JSON.parse(config.data) : {} diff --git a/packages/armory-sdk/src/lib/vault/client.ts b/packages/armory-sdk/src/lib/vault/client.ts index 27316df33..274daeedb 100644 --- a/packages/armory-sdk/src/lib/vault/client.ts +++ b/packages/armory-sdk/src/lib/vault/client.ts @@ -10,6 +10,7 @@ import { ClientDto, Configuration, CreateClientDto, + CreateConnectionDto, DeriveAccountDto, DeriveAccountResponseDto, EncryptionKeyApiFactory, @@ -17,27 +18,21 @@ import { ImportPrivateKeyDto, ImportWalletDto, PongDto, + ProviderConnectionApiFactory, + ProviderConnectionDto, SignApiFactory, SignatureDto, WalletApiFactory, WalletDto, WalletsDto } from '../http/client/vault' -import { getBearerToken, interceptRequestAddDetachedJwsHeader } from '../shared/gnap' -import { - AccountHttp, - EncryptionKeyHttp, - SignHttp, - VaultAdminConfig, - VaultClientHttp, - VaultConfig, - WalletHttp -} from './type' +import { interceptRequestAddDetachedJwsHeader, prefixGnapToken } from '../shared/gnap' +import { VaultAdminConfig, VaultConfig } from './type' export class VaultAdminClient { private config: VaultAdminConfig - private clientHttp: VaultClientHttp + private clientHttp constructor(config: VaultAdminConfig) { const httpConfig = new Configuration({ @@ -51,7 +46,10 @@ export class VaultAdminClient { } async createClient(input: CreateClientDto): Promise { - const { data } = await this.clientHttp.create(this.config.adminApiKey, input) + const { data } = await this.clientHttp.create({ + xApiKey: this.config.adminApiKey, + createClientDto: input + }) return data } @@ -60,15 +58,17 @@ export class VaultAdminClient { export class VaultClient { private config: VaultConfig - private encryptionKeyHttp: EncryptionKeyHttp + private encryptionKeyHttp + + private walletHttp - private walletHttp: WalletHttp + private accountHttp - private accountHttp: AccountHttp + private signHttp - private signHttp: SignHttp + private connectionHttp - private applicationApi: ApplicationApi + private applicationApi constructor(config: VaultConfig) { const httpConfig = new Configuration({ @@ -85,7 +85,7 @@ export class VaultClient { this.encryptionKeyHttp = EncryptionKeyApiFactory(httpConfig, config.host, axiosInstance) this.accountHttp = AccountApiFactory(httpConfig, config.host, axiosInstance) this.signHttp = SignApiFactory(httpConfig, config.host, axiosInstance) - + this.connectionHttp = ProviderConnectionApiFactory(httpConfig, config.host, axiosInstance) this.applicationApi = new ApplicationApi(httpConfig, config.host, axiosInstance) } @@ -96,9 +96,12 @@ export class VaultClient { } async generateEncryptionKey({ accessToken }: { accessToken: AccessToken }): Promise { - const token = getBearerToken(accessToken) + const token = prefixGnapToken(accessToken) - const { data: encryptionKey } = await this.encryptionKeyHttp.generate(this.config.clientId, token) + const { data: encryptionKey } = await this.encryptionKeyHttp.generate({ + xClientId: this.config.clientId, + authorization: token + }) return encryptionKey.publicKey } @@ -111,9 +114,13 @@ export class VaultClient { accessToken: AccessToken }): Promise { const payload = data || {} - const token = getBearerToken(accessToken) + const token = prefixGnapToken(accessToken) - const { data: wallet } = await this.walletHttp.generate(this.config.clientId, token, payload) + const { data: wallet } = await this.walletHttp.generate({ + xClientId: this.config.clientId, + authorization: token, + generateWalletDto: payload + }) return wallet } @@ -127,20 +134,27 @@ export class VaultClient { encryptionKey: RsaPublicKey accessToken: AccessToken }): Promise { - const token = getBearerToken(accessToken) + const token = prefixGnapToken(accessToken) const { seed, ...options } = data const encryptedSeed = await rsaEncrypt(seed, encryptionKey) const payload = { ...options, encryptedSeed } - const { data: wallet } = await this.walletHttp.importSeed(this.config.clientId, token, payload) + const { data: wallet } = await this.walletHttp.importSeed({ + xClientId: this.config.clientId, + authorization: token, + importWalletDto: payload + }) return wallet } async listWallets({ accessToken }: { accessToken: AccessToken }): Promise { - const token = getBearerToken(accessToken) + const token = prefixGnapToken(accessToken) - const { data: wallets } = await this.walletHttp.list(this.config.clientId, token) + const { data: wallets } = await this.walletHttp.list({ + xClientId: this.config.clientId, + authorization: token + }) return wallets } @@ -152,9 +166,13 @@ export class VaultClient { data: DeriveAccountDto accessToken: AccessToken }): Promise { - const token = getBearerToken(accessToken) + const token = prefixGnapToken(accessToken) - const { data: account } = await this.accountHttp.derive(this.config.clientId, token, data) + const { data: account } = await this.accountHttp.derive({ + xClientId: this.config.clientId, + authorization: token, + deriveAccountDto: data + }) return account } @@ -170,30 +188,59 @@ export class VaultClient { }): Promise { const { privateKey, ...options } = data const encryptedPrivateKey = await rsaEncrypt(privateKey, encryptionKey) - const token = getBearerToken(accessToken) + const token = prefixGnapToken(accessToken) const payload = { ...options, encryptedPrivateKey } - const { data: account } = await this.accountHttp.importPrivateKey(this.config.clientId, token, payload) + const { data: account } = await this.accountHttp.importPrivateKey({ + xClientId: this.config.clientId, + authorization: token, + importPrivateKeyDto: payload + }) return account } async listAccounts({ accessToken }: { accessToken: AccessToken }): Promise { - const token = getBearerToken(accessToken) + const token = prefixGnapToken(accessToken) - const { data: accounts } = await this.accountHttp.list(this.config.clientId, token) + const { data: accounts } = await this.accountHttp.list({ + xClientId: this.config.clientId, + authorization: token + }) return accounts } async sign({ data, accessToken }: { data: Request; accessToken: AccessToken }): Promise { - const token = getBearerToken(accessToken) + const token = prefixGnapToken(accessToken) const parsedRequest = Request.parse(data) - const { data: signature } = await this.signHttp.sign(this.config.clientId, token, { - request: SerializedSignableRequest.parse(parsedRequest) + const { data: signature } = await this.signHttp.sign({ + xClientId: this.config.clientId, + authorization: token, + signRequestDto: { + request: SerializedSignableRequest.parse(parsedRequest) + } }) return signature } + + async createConnection({ + data, + accessToken + }: { + data: CreateConnectionDto + accessToken?: AccessToken + }): Promise { + const token = accessToken ? prefixGnapToken(accessToken) : undefined + + const { data: connection } = await this.connectionHttp.create({ + xClientId: this.config.clientId, + authorization: token, + createConnectionDto: data + }) + + return connection + } } diff --git a/packages/armory-sdk/src/lib/vault/type.ts b/packages/armory-sdk/src/lib/vault/type.ts index 053b7df1f..0e673733c 100644 --- a/packages/armory-sdk/src/lib/vault/type.ts +++ b/packages/armory-sdk/src/lib/vault/type.ts @@ -1,22 +1,5 @@ -import { AxiosPromise, RawAxiosRequestConfig } from 'axios' import { z } from 'zod' -import { - AccountDto, - AccountsDto, - CreateClientDto, - ClientDto as CreateVaultClientResponse, - DeriveAccountDto, - DeriveAccountResponseDto, - EncryptionKeyDto, - GenerateWalletDto, - ImportPrivateKeyDto, - ImportWalletDto, - SignRequestDto, - SignatureDto, - WalletDto, - WalletsDto -} from '../http/client/vault' -import { RequiredError } from '../http/client/vault/base' +import { ClientDto as CreateVaultClientResponse } from '../http/client/vault' import { Signer } from '../shared/type' export type { CreateVaultClientResponse } @@ -33,137 +16,3 @@ export const VaultConfig = z.object({ clientId: z.string().describe('The client ID') }) export type VaultConfig = z.infer - -export type VaultClientHttp = { - /** - * Creates a new client - * - * @param {string} apiKey - * @param {CreateClientDto} data - * @param {RawAxiosRequestConfig} [options] Override http request option. - * @throws {RequiredError} - */ - create( - apiKey: string, - data: CreateClientDto, - options?: RawAxiosRequestConfig - ): AxiosPromise -} - -export type EncryptionKeyHttp = { - /** - * Generates an encryption key pair used to secure end-to-end - * communication containing sensitive information. - * - * @param {string} clientId - * @param {string} accessToken - * @param {RawAxiosRequestConfig} [options] Override http request option. - * @throws {RequiredError} - */ - generate(clientId: string, accessToken: string, options?: RawAxiosRequestConfig): AxiosPromise -} - -export type WalletHttp = { - /** - * Generates a new wallet. - * - * @param {string} clientId - * @param {string} accessToken - * @param {GenerateWalletDto} data - * @param {RawAxiosRequestConfig} [options] Override http request option. - * @throws {RequiredError} - */ - generate( - clientId: string, - accessToken: string, - data: GenerateWalletDto, - options?: RawAxiosRequestConfig - ): AxiosPromise - - /** - * Imports a wallet. - * - * @param {string} clientId - * @param {string} accessToken - * @param {ImportWalletDto} data - * @param {RawAxiosRequestConfig} [options] Override http request option. - * @throws {RequiredError} - */ - importSeed( - clientId: string, - accessToken: string, - data: ImportWalletDto, - options?: RawAxiosRequestConfig - ): AxiosPromise - - /** - * List the client wallets. - * - * @param {string} clientId - * @param {string} accessToken - * @param {RawAxiosRequestConfig} [options] Override http request option. - * @throws {RequiredError} - */ - list(clientId: string, accessToken: string, options?: RawAxiosRequestConfig): AxiosPromise -} - -export type AccountHttp = { - /** - * Add a new account to a wallet - * - * @param {string} clientId - * @param {string} accessToken - * @param {DeriveAccountDto} data - * @param {RawAxiosRequestConfig} [options] Override http request option. - * @throws {RequiredError} - */ - derive( - clientId: string, - accessToken: string, - data: DeriveAccountDto, - options?: RawAxiosRequestConfig - ): AxiosPromise - - /** - * Imports an account - * - * @param {string} clientId - * @param {string} accessToken - * @param {ImportPrivateKeyDto} data - * @param {RawAxiosRequestConfig} [options] Override http request option. - * @throws {RequiredError} - */ - importPrivateKey( - clientId: string, - accessToken: string, - data: ImportPrivateKeyDto, - options?: RawAxiosRequestConfig - ): AxiosPromise - - /** - * Lists the client accounts - * - * @param {string} clientId - * @param {RawAxiosRequestConfig} [options] Override http request option. - * @throws {RequiredError} - */ - list(clientId: string, accessToken: string, options?: RawAxiosRequestConfig): AxiosPromise -} - -export type SignHttp = { - /** - * Signs the given request. - * - * @param {string} clientId - * @param {string} accessToken - * @param {SignRequestDto} data - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - sign( - clientId: string, - accessToken: string, - data: SignRequestDto, - options?: RawAxiosRequestConfig - ): AxiosPromise -} diff --git a/packages/nestjs-shared/src/lib/constant.ts b/packages/nestjs-shared/src/lib/constant.ts index 1f5b47c6c..ecfafb444 100644 --- a/packages/nestjs-shared/src/lib/constant.ts +++ b/packages/nestjs-shared/src/lib/constant.ts @@ -4,6 +4,9 @@ export const REQUEST_HEADER_CLIENT_ID = 'x-client-id' export const REQUEST_HEADER_CLIENT_SECRET = 'x-client-secret' +export const REQUEST_HEADER_ADMIN_API_KEY = 'x-api-key' +export const REQUEST_HEADER_DETACHED_JWS = 'detached-jws' +export const REQUEST_HEADER_AUTHORIZATION = 'Authorization' // can be GNAP, Bearer, etc // // OpenTelemetry diff --git a/packages/nestjs-shared/src/lib/decorator/api-client-id-header.decorator.ts b/packages/nestjs-shared/src/lib/decorator/api-client-id-header.decorator.ts new file mode 100644 index 000000000..774539d06 --- /dev/null +++ b/packages/nestjs-shared/src/lib/decorator/api-client-id-header.decorator.ts @@ -0,0 +1,15 @@ +import { applyDecorators } from '@nestjs/common' +import { ApiHeader } from '@nestjs/swagger' +import { REQUEST_HEADER_CLIENT_ID } from '../constant' + +// We support Authentication through a jwsd that does NOT require an access token as well. +// This decorator is simply to flag that a signature is required. If using combined with GNAP, use the api-gnap-security decorator. + +export function ApiClientIdHeader() { + return applyDecorators( + ApiHeader({ + name: REQUEST_HEADER_CLIENT_ID, + required: true + }) + ) +} diff --git a/packages/nestjs-shared/src/lib/decorator/api-detached-jws-security.decorator.ts b/packages/nestjs-shared/src/lib/decorator/api-detached-jws-security.decorator.ts new file mode 100644 index 000000000..0b7e036c4 --- /dev/null +++ b/packages/nestjs-shared/src/lib/decorator/api-detached-jws-security.decorator.ts @@ -0,0 +1,14 @@ +import { applyDecorators } from '@nestjs/common' +import { ApiSecurity } from '@nestjs/swagger' +import { securityOptions } from '../util/with-swagger.util' + +// We support Authentication through a jwsd that does NOT require an access token as well. +// This decorator is simply to flag that a signature is required. If using combined with GNAP, use the api-gnap-security decorator. + +export function ApiDetachedJwsSecurity() { + return applyDecorators( + ApiSecurity({ + [securityOptions.detachedJws.name]: [] + }) + ) +} diff --git a/packages/nestjs-shared/src/lib/decorator/api-gnap-security.decorator.ts b/packages/nestjs-shared/src/lib/decorator/api-gnap-security.decorator.ts index c385f3c9a..94dabe38a 100644 --- a/packages/nestjs-shared/src/lib/decorator/api-gnap-security.decorator.ts +++ b/packages/nestjs-shared/src/lib/decorator/api-gnap-security.decorator.ts @@ -1,13 +1,22 @@ import { applyDecorators } from '@nestjs/common' import { ApiHeader, ApiSecurity } from '@nestjs/swagger' -import { gnapSecurity } from '../util/with-swagger.util' +import { REQUEST_HEADER_AUTHORIZATION } from '../constant' +import { securityOptions } from '../util/with-swagger.util' + +// GNAP tokens are bound, so they require both the Authorization header and a signature +// We currently only support detached JWS, for key proofs, so we add the `detached-jws` header as well. +// In the future, this can also support httpsig & other key proofing options, making the detached-jws header optional. export function ApiGnapSecurity(permissions?: string[]) { return applyDecorators( - ApiSecurity(gnapSecurity().name, permissions), + ApiSecurity({ + [securityOptions.gnap.name]: permissions || [], + [securityOptions.detachedJws.name]: [] + }), + // We have to say the Authorization header is required, because the GNAP scheme isn't known by OpenAPI Generator fully, so it won't generate the code to add it. ApiHeader({ - name: 'Authorization', - required: true + name: REQUEST_HEADER_AUTHORIZATION, + required: false }) ) } diff --git a/packages/nestjs-shared/src/lib/decorator/index.ts b/packages/nestjs-shared/src/lib/decorator/index.ts index 2b7af26b8..27fd442c0 100644 --- a/packages/nestjs-shared/src/lib/decorator/index.ts +++ b/packages/nestjs-shared/src/lib/decorator/index.ts @@ -1,3 +1,5 @@ +export * from './api-client-id-header.decorator' +export * from './api-detached-jws-security.decorator' export * from './api-gnap-security.decorator' export * from './is-hex-string.decorator' export * from './is-not-empty-array-enum.decorator' diff --git a/packages/nestjs-shared/src/lib/util/with-swagger.util.ts b/packages/nestjs-shared/src/lib/util/with-swagger.util.ts index 7211d0fdd..a512e7b9e 100644 --- a/packages/nestjs-shared/src/lib/util/with-swagger.util.ts +++ b/packages/nestjs-shared/src/lib/util/with-swagger.util.ts @@ -2,43 +2,70 @@ import { INestApplication } from '@nestjs/common' import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger' import { SecuritySchemeObject } from '@nestjs/swagger/dist/interfaces/open-api-spec.interface' import { patchNestJsSwagger } from 'nestjs-zod' -import { SetRequired } from 'type-fest' - -type Security = SetRequired +import { + REQUEST_HEADER_ADMIN_API_KEY, + REQUEST_HEADER_CLIENT_ID, + REQUEST_HEADER_CLIENT_SECRET, + REQUEST_HEADER_DETACHED_JWS +} from '../constant' // NOTE: See https://swagger.io/docs/specification/authentication to understand // Swagger auth schema. -export const gnapSecurity = (): Security => ({ - name: 'GNAP', +const gnapSecurity: SecuritySchemeObject = { type: 'http', - in: 'header', // A scheme is what sits in front of the token `Authorization: // `. // See https://swagger.io/docs/specification/authentication/ scheme: 'GNAP' -}) +} + +const detachedJwsSecurity: SecuritySchemeObject = { + name: REQUEST_HEADER_DETACHED_JWS, + type: 'apiKey', + in: 'header' +} -export const adminApiKeySecurity = (header: string): Security => ({ - name: 'ADMIN_API_KEY', +const adminApiKeySecurity: SecuritySchemeObject = { + name: REQUEST_HEADER_ADMIN_API_KEY, type: 'apiKey', - in: 'header', - 'x-tokenName': header -}) + in: 'header' +} -export const clientIdSecurity = (header: string): Security => ({ - name: 'CLIENT_ID', +const clientIdSecurity: SecuritySchemeObject = { + name: REQUEST_HEADER_CLIENT_ID, type: 'apiKey', - in: 'header', - 'x-tokenName': header -}) + in: 'header' +} -export const clientSecretSecurity = (header: string): Security => ({ - name: 'CLIENT_SECRET', +const clientSecretSecurity: SecuritySchemeObject = { + name: REQUEST_HEADER_CLIENT_SECRET, type: 'apiKey', - in: 'header', - 'x-tokenName': header -}) + in: 'header' +} + +export const securityOptions = { + gnap: { + name: 'GNAP', + securityScheme: gnapSecurity + }, + detachedJws: { + name: 'Detached-JWS-Signature', + securityScheme: detachedJwsSecurity + }, + adminApiKey: { + name: 'Admin-API-Key', + securityScheme: adminApiKeySecurity + }, + clientId: { + name: 'Client-ID', + securityScheme: clientIdSecurity + }, + clientSecret: { + name: 'Client-Secret', + securityScheme: clientSecretSecurity + } +} /** * Adds Swagger documentation to the application. @@ -47,7 +74,13 @@ export const clientSecretSecurity = (header: string): Security => ({ * @returns The modified INestApplication instance. */ export const withSwagger = - (params: { title: string; description: string; version: string; security?: Security[] }) => + (params: { + title: string + description: string + version: string + security?: { name: string; securityScheme: SecuritySchemeObject }[] + server?: { url: string; description: string } + }) => (app: INestApplication): INestApplication => { // IMPORTANT: This modifies the Nest Swagger module to be compatible with // DTOs created by Zod schemas. The patch MUST be done before the @@ -59,8 +92,9 @@ export const withSwagger = .setTitle(params.title) .setDescription(params.description) .setVersion(params.version) + .addServer(params.server?.url || 'http://localhost:3005', params.server?.description || 'Armory Server') for (const s of security) { - documentBuilder.addSecurity(s.name, s) + documentBuilder.addSecurity(s.name, s.securityScheme) } const document = SwaggerModule.createDocument(app, documentBuilder.build()) From f63b6f36e41531992025f1b78b8879be54690270 Mon Sep 17 00:00:00 2001 From: Ptroger <44851272+Ptroger@users.noreply.github.com> Date: Thu, 26 Dec 2024 09:26:58 +0100 Subject: [PATCH 060/120] Feature/nar 2017 assettype networkid mapping (#54) * export a constant with supported chains * first list of networks * corrected cointypes * added name --- packages/policy-engine-shared/src/index.ts | 2 + .../src/lib/resource/networks.ts | 324 ++++++++++++++++++ 2 files changed, 326 insertions(+) create mode 100644 packages/policy-engine-shared/src/lib/resource/networks.ts diff --git a/packages/policy-engine-shared/src/index.ts b/packages/policy-engine-shared/src/index.ts index b64777d9b..b9c27e8fb 100644 --- a/packages/policy-engine-shared/src/index.ts +++ b/packages/policy-engine-shared/src/index.ts @@ -22,4 +22,6 @@ export * from './lib/util/json.util' export * from './lib/util/transaction.util' export * from './lib/util/typeguards' +export * from './lib/resource/networks' + export * as FIXTURE from './lib/dev.fixture' diff --git a/packages/policy-engine-shared/src/lib/resource/networks.ts b/packages/policy-engine-shared/src/lib/resource/networks.ts new file mode 100644 index 000000000..4569e1094 --- /dev/null +++ b/packages/policy-engine-shared/src/lib/resource/networks.ts @@ -0,0 +1,324 @@ +export const NETWORK_INFO = [ + { + networkId: 'AGORIC_MAINNET', + anchorageId: 'BLD', + coinType: 564, + name: 'Agoric', + addressValidationRegex: '^agoric(valoper)?1[ac-hj-np-z02-9]{7,88}$|^AGORIC(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' + }, + { + networkId: 'ALLORA_MAINNET', + anchorageId: 'ALLO', + coinType: null, + name: 'Allora', + addressValidationRegex: '^allo(valoper)?1[ac-hj-np-z02-9]{7,88}$|^ALLO(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' + }, + { + networkId: 'ALLORA_TESTNET', + anchorageId: 'ALLO_T', + coinType: 1, + name: 'Allora Testnet', + addressValidationRegex: '^allo(valoper)?1[ac-hj-np-z02-9]{7,88}$|^ALLO(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' + }, + { + networkId: 'APTOS_MAINNET', + anchorageId: 'APT', + coinType: 637, + name: 'Aptos', + addressValidationRegex: '^(0x)?[0-9a-fA-F]{1,64}$' + }, + { + networkId: 'APTOS_TESTNET', + anchorageId: 'APT_T', + coinType: 1, + name: 'Aptos Testnet', + addressValidationRegex: '^(0x)?[0-9a-fA-F]{1,64}$' + }, + { + networkId: 'AXELAR_MAINNET', + anchorageId: 'AXL', + coinType: null, + name: 'Axelar', + addressValidationRegex: '^axelar(valoper)?1[ac-hj-np-z02-9]{7,88}$|^AXELAR(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' + }, + { + networkId: 'AXELAR_TESTNET', + anchorageId: 'AXL_T', + coinType: 1, + name: 'Axelar Testnet', + addressValidationRegex: '^axelar(valoper)?1[ac-hj-np-z02-9]{7,88}$|^AXELAR(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' + }, + { + networkId: 'BABYLON_MAINNET', + anchorageId: 'BBN', + coinType: null, + name: 'Babylon', + addressValidationRegex: '^bbn(valoper)?1[ac-hj-np-z02-9]{7,88}$|^BBN(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' + }, + { + networkId: 'BITCOIN_MAINNET', + anchorageId: 'BTC', + coinType: 0, + name: 'Bitcoin', + addressValidationRegex: '^[13][a-km-zA-HJ-NP-Z1-9]{25,40}$|^bc1q[ac-hj-np-z02-9]{38,38}$|^BC1Q[AC-HJ-NP-Z02-9]{38,38}$|^bc1q[ac-hj-np-z02-9]{58,58}$|^BC1Q[AC-HJ-NP-Z02-9]{58,58}$|^bc1p[ac-hj-np-z02-9]{58,58}$|^BC1P[AC-HJ-NP-Z02-9]{58,58}$' + }, + { + networkId: 'BITCOIN_CASH_MAINNET', + anchorageId: 'BCH', + coinType: 145, + name: 'Bitcoin Cash', + addressValidationRegex: '^[13][a-km-zA-HJ-NP-Z1-9]{25,40}$|^(bitcoincash:)?[ac-hj-np-z02-9]{11,78}$|^(BITCOINCASH:)?[AC-HJ-NP-Z02-9]{11,78}$' + }, + { + networkId: 'BITCOIN_SIGNET', + anchorageId: 'BTC_S', + coinType: null, + name: 'Bitcoin Signet', + addressValidationRegex: '^[2nm][a-km-zA-HJ-NP-Z1-9]{25,40}$|^tb1q[ac-hj-np-z02-9]{38,38}$|^TB1Q[AC-HJ-NP-Z02-9]{38,38}$|^tb1q[ac-hj-np-z02-9]{58,58}$|^TB1Q[AC-HJ-NP-Z02-9]{58,58}$|^tb1p[ac-hj-np-z02-9]{58,58}$|^TB1P[AC-HJ-NP-Z02-9]{58,58}$' + }, + { + networkId: 'CELESTIA_MAINNET', + anchorageId: 'TIA', + coinType: null, + name: 'Celestia', + addressValidationRegex: '^celestia(valoper)?1[ac-hj-np-z02-9]{7,88}$|^CELESTIA(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' + }, + { + networkId: 'CELO_BAKLAVA', + anchorageId: 'CGLD_TB', + coinType: 1, + name: 'Celo Baklava', + addressValidationRegex: '^(0x)?[0-9a-fA-F]{40}$' + }, + { + networkId: 'COSMOS_MAINNET', + anchorageId: 'ATOM', + coinType: 118, + name: 'Cosmos', + addressValidationRegex: '^cosmos(valoper)?1[ac-hj-np-z02-9]{7,88}$|^COSMOS(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' + }, + { + networkId: 'DOGECOIN_MAINNET', + anchorageId: 'DOGE', + coinType: 3, + name: 'Dogecoin', + addressValidationRegex: '^[AD9][a-km-zA-HJ-NP-Z1-9]{25,40}$' + }, + { + networkId: 'DYDX_CHAIN_MAINNET', + anchorageId: 'DYDX_CHAIN', + coinType: null, + name: 'Dydx Chain', + addressValidationRegex: '^dydx(valoper)?1[ac-hj-np-z02-9]{7,88}$|^DYDX(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' + }, + { + networkId: 'DYDX_CHAIN_TESTNET', + anchorageId: 'DYDX_CHAIN_T', + coinType: 1, + name: 'Dydx Testnet', + addressValidationRegex: '^dydx(valoper)?1[ac-hj-np-z02-9]{7,88}$|^DYDX(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' + }, + { + networkId: 'ETHEREUM_MAINNET', + anchorageId: 'ETH', + coinType: 60, + name: 'Ethereum', + addressValidationRegex: '^(0x)?[0-9a-fA-F]{40}$' + }, + { + networkId: 'ETHEREUM_HOLESKY', + anchorageId: 'ETHHOL', + coinType: 1, + name: 'Ethereum Holešky', + addressValidationRegex: '^(0x)?[0-9a-fA-F]{40}$' + }, + { + networkId: 'ETHEREUM_SEPOLIA', + anchorageId: 'ETHSEP', + coinType: 1, + name: 'Ethereum Sepolia', + addressValidationRegex: '^(0x)?[0-9a-fA-F]{40}$' + }, + { + networkId: 'ARBITRUM_SEPOLIA', + anchorageId: 'ETH_ARBITRUM_T', + coinType: 1, + name: 'Arbitrum Sepolia Testnet', + addressValidationRegex: '^(0x)?[0-9a-fA-F]{40}$' + }, + { + networkId: 'PLUME_SEPOLIA', + anchorageId: 'ETH_PLUME_T', + coinType: 1, + name: 'Plume Sepolia Testnet', + addressValidationRegex: '^(0x)?[0-9a-fA-F]{40}$' + }, + { + networkId: 'ZKSYNC_SEPOLIA', + anchorageId: 'ETH_ZKSYNC_T', + coinType: 1, + name: 'ZKsync Sepolia Testnet', + addressValidationRegex: '^(0x)?[0-9a-fA-F]{40}$' + }, + { + networkId: 'EVMOS_MAINNET', + anchorageId: 'EVMOS', + coinType: null, + name: 'Evmos', + addressValidationRegex: '^evmos(valoper)?1[ac-hj-np-z02-9]{7,88}$|^EVMOS(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' + }, + { + networkId: 'EVMOS_TESTNET', + anchorageId: 'EVMOS_T', + coinType: 1, + name: 'Evmos Testnet', + addressValidationRegex: '^evmos(valoper)?1[ac-hj-np-z02-9]{7,88}$|^EVMOS(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' + }, + { + networkId: 'FILECOIN_MAINNET', + anchorageId: 'FIL', + coinType: 461, + name: 'Filecoin', + addressValidationRegex: '^[ft](0[0-9]{1,20}|[12][a-z2-7]{39}|3[a-z2-7]{84})$' + }, + { + networkId: 'FLOW_TESTNET', + anchorageId: 'FLOW_T', + coinType: 1, + name: 'Flow Testnet', + addressValidationRegex: '^(0x)?[0-9a-fA-F]{16}$' + }, + { + networkId: 'LITECOIN_MAINNET', + anchorageId: 'LTC', + coinType: 2, + name: 'Litecoin', + addressValidationRegex: '^[LM][a-km-zA-HJ-NP-Z1-9]{25,40}$|^ltc1q[ac-hj-np-z02-9]{38,38}$|^LTC1Q[AC-HJ-NP-Z02-9]{38,38}$|^ltc1q[ac-hj-np-z02-9]{58,58}$|^LTC1Q[AC-HJ-NP-Z02-9]{58,58}$' + }, + { + networkId: 'NEUTRON_MAINNET', + anchorageId: 'NTRN', + coinType: null, + name: 'Neutron', + addressValidationRegex: '^neutron(valoper)?1[ac-hj-np-z02-9]{7,88}$|^NEUTRON(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' + }, + { + networkId: 'OM_MANTRA_MAINNET', + anchorageId: 'OM_MANTRA', + coinType: null, + name: 'OM Mantra', + addressValidationRegex: '^mantra(valoper)?1[ac-hj-np-z02-9]{7,88}$|^MANTRA(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' + }, + { + networkId: 'OM_MANTRA_TESTNET', + anchorageId: 'OM_MANTRA_T', + coinType: 1, + name: 'OM Mantra Testnet', + addressValidationRegex: '^mantra(valoper)?1[ac-hj-np-z02-9]{7,88}$|^MANTRA(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' + }, + { + networkId: 'OASIS_MAINNET', + anchorageId: 'ROSE', + coinType: 474, + name: 'Oasis', + addressValidationRegex: '^oasis1[ac-hj-np-z02-9]{39,59}$|^OASIS1[AC-HJ-NP-Z02-9]{39,59}$' + }, + { + networkId: 'OSMOSIS_MAINNET', + anchorageId: 'OSMO', + coinType: 10000118, + name: 'Osmosis', + addressValidationRegex: '^osmo(valoper)?1[ac-hj-np-z02-9]{7,88}$|^OSMO(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' + }, + { + networkId: 'POLYGON_MAINNET', + anchorageId: 'MATIC_POLYGON', + coinType: 966, + name: 'Polygon', + addressValidationRegex: '^(0x)?[0-9a-fA-F]{40}$' + }, + { + networkId: 'PROVENANCE_MAINNET', + anchorageId: 'HASH', + coinType: 505, + name: 'Provenance', + addressValidationRegex: '^pb(valoper)?1[ac-hj-np-z02-9]{7,88}$|^PB(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' + }, + { + networkId: 'RARIMO_MAINNET', + anchorageId: 'RMO', + coinType: null, + name: 'Rarimo', + addressValidationRegex: '^rarimo(valoper)?1[ac-hj-np-z02-9]{7,88}$|^RARIMO(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' + }, + { + networkId: 'RIPPLE_MAINNET', + anchorageId: 'XRP', + coinType: 144, + name: 'Ripple', + addressValidationRegex: '^r[a-km-zA-HJ-NP-Z1-9]{24,34}$' + }, + { + networkId: 'SEI_MAINNET', + anchorageId: 'SEI', + coinType: 19000118, + name: 'Sei', + addressValidationRegex: '^sei(valoper)?1[ac-hj-np-z02-9]{7,88}$|^SEI(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' + }, + { + networkId: 'SEI_TESTNET', + anchorageId: 'SEI_T', + coinType: 1, + name: 'Sei Testnet', + addressValidationRegex: '^sei(valoper)?1[ac-hj-np-z02-9]{7,88}$|^SEI(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' + }, + { + networkId: 'SOLANA_DEVNET', + anchorageId: 'SOL_TD', + coinType: 1, + name: 'Solana Devnet', + addressValidationRegex: '^[a-km-zA-HJ-NP-Z1-9]{32,44}$' + }, + { + networkId: 'STARKNET_MAINNET', + anchorageId: 'STRK_STARKNET', + coinType: 9004, + name: 'Starknet', + addressValidationRegex: '^(0x)?[0-9a-fA-F]{1,64}$' + }, + { + networkId: 'STARKNET_TESTNET', + anchorageId: 'STRK_STARKNET_T', + coinType: 1, + name: 'Starknet Testnet', + addressValidationRegex: '^(0x)?[0-9a-fA-F]{1,64}$' + }, + { + networkId: 'STRIDE_MAINNET', + anchorageId: 'STRD', + coinType: null, + name: 'Stride', + addressValidationRegex: '^stride(valoper)?1[ac-hj-np-z02-9]{7,88}$|^STRIDE(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' + }, + { + networkId: 'SUI_TESTNET', + anchorageId: 'SUI_T', + coinType: 1, + name: 'Sui Testnet', + addressValidationRegex: '^0x[a-fA-F0-9]{64}$' + }, + { + networkId: 'VANA_MOKSHA_TESTNET', + anchorageId: 'VANA_VANA_MOKSHA_T', + coinType: 1, + name: 'Vana Moksha Testnet', + addressValidationRegex: '^(0x)?[0-9a-fA-F]{40}$' + }, + { + networkId: 'VANA_MAINNET', + anchorageId: 'VANA_VANA', + coinType: null, + name: 'Vana', + addressValidationRegex: '^(0x)?[0-9a-fA-F]{40}$' + } +] \ No newline at end of file From 1b769ed633146cdc51c801c6d2c338a825278e01 Mon Sep 17 00:00:00 2001 From: Ptroger <44851272+Ptroger@users.noreply.github.com> Date: Thu, 26 Dec 2024 13:37:48 +0100 Subject: [PATCH 061/120] minor version bump with eddsa signing support (#56) --- package-lock.json | 2 +- packages/armory-sdk/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index bbe5b414b..f29160f06 100644 --- a/package-lock.json +++ b/package-lock.json @@ -46204,7 +46204,7 @@ }, "packages/armory-sdk": { "name": "@narval-xyz/armory-sdk", - "version": "0.11.0", + "version": "0.12.0", "license": "MPL-2.0", "dependencies": { "@noble/curves": "1.6.0", diff --git a/packages/armory-sdk/package.json b/packages/armory-sdk/package.json index 220593d1d..7e2af812f 100644 --- a/packages/armory-sdk/package.json +++ b/packages/armory-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@narval-xyz/armory-sdk", - "version": "0.11.0", + "version": "0.12.0", "license": "MPL-2.0", "publishConfig": { "access": "public" From 51184fa1a10b797ecf228ecae03251fccabaadbf Mon Sep 17 00:00:00 2001 From: Ptroger <44851272+Ptroger@users.noreply.github.com> Date: Thu, 26 Dec 2024 17:28:33 +0100 Subject: [PATCH 062/120] read endpoints for known-destinations (#55) * read endpoints for known-destinations * mock event emitter * fixed typo on anchorage endpoint * fixed same typo in tests * removed obligation for provider query, ask for connection-id header * connection filter is a query parameter, use kebab case for endpoints, assert over full body --- .../__test__/e2e/known-destinations.spec.ts | 341 ++++++++++++++++++ apps/vault/src/broker/broker.module.ts | 4 +- .../invalid-query-string.exception.ts | 13 + .../anchorage-sync.service.spec.ts | 4 +- .../integration/mocks/anchorage/handlers.ts | 6 +- .../core/service/anchorage-sync.service.ts | 2 +- ...ervice.ts => known-destination.service.ts} | 0 .../broker/http/client/anchorage.client.ts | 2 +- .../known-destination.controller.ts | 62 ++++ .../paginated-known-destinations.dto.ts | 11 + .../provider-known-destination.dto.ts | 9 + .../known-destination.repository.ts | 20 + 12 files changed, 466 insertions(+), 8 deletions(-) create mode 100644 apps/vault/src/broker/__test__/e2e/known-destinations.spec.ts create mode 100644 apps/vault/src/broker/core/exception/invalid-query-string.exception.ts rename apps/vault/src/broker/core/service/{know-destination.service.ts => known-destination.service.ts} (100%) create mode 100644 apps/vault/src/broker/http/rest/controller/known-destination.controller.ts create mode 100644 apps/vault/src/broker/http/rest/dto/response/paginated-known-destinations.dto.ts create mode 100644 apps/vault/src/broker/http/rest/dto/response/provider-known-destination.dto.ts diff --git a/apps/vault/src/broker/__test__/e2e/known-destinations.spec.ts b/apps/vault/src/broker/__test__/e2e/known-destinations.spec.ts new file mode 100644 index 000000000..015739d8c --- /dev/null +++ b/apps/vault/src/broker/__test__/e2e/known-destinations.spec.ts @@ -0,0 +1,341 @@ +import { EncryptionModuleOptionProvider } from '@narval/encryption-module' +import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' +import { Alg, generateJwk, privateKeyToHex } from '@narval/signature' +import { HttpStatus, INestApplication } from '@nestjs/common' +import { EventEmitter2 } from '@nestjs/event-emitter' +import { Test, TestingModule } from '@nestjs/testing' +import { mock } from 'jest-mock-extended' +import request from 'supertest' +import { v4 } from 'uuid' +import { ClientService } from '../../../client/core/service/client.service' +import { MainModule } from '../../../main.module' +import { ProvisionService } from '../../../provision.service' +import { KeyValueRepository } from '../../../shared/module/key-value/core/repository/key-value.repository' +import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' +import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' +import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' +import { ANCHORAGE_TEST_API_BASE_URL } from '../../core/service/__test__/integration/mocks/anchorage/server' +import { ConnectionService } from '../../core/service/connection.service' +import { KnownDestinationService } from '../../core/service/known-destination.service' +import { Provider } from '../../core/type/connection.type' +import { KnownDestination } from '../../core/type/indexed-resources.type' +import { getJwsd, testClient, testUserPrivateJwk } from '../util/mock-data' + +describe('KnownDestination', () => { + let app: INestApplication + let module: TestingModule + let testPrismaService: TestPrismaService + let provisionService: ProvisionService + let clientService: ClientService + let knownDestinationService: KnownDestinationService + let connectionService: ConnectionService + + let connection1Id: string + let connection2Id: string + + const now = new Date('2025-01-01T00:00:00Z') + + beforeAll(async () => { + module = await Test.createTestingModule({ + imports: [MainModule] + }) + .overrideModule(LoggerModule) + .useModule(LoggerModule.forTest()) + .overrideProvider(KeyValueRepository) + .useValue(new InMemoryKeyValueRepository()) + .overrideProvider(EncryptionModuleOptionProvider) + .useValue({ + keyring: getTestRawAesKeyring() + }) + .overrideProvider(EventEmitter2) + .useValue(mock()) + .compile() + + app = module.createNestApplication() + testPrismaService = module.get(TestPrismaService) + provisionService = module.get(ProvisionService) + clientService = module.get(ClientService) + connectionService = module.get(ConnectionService) + + knownDestinationService = module.get(KnownDestinationService) + await testPrismaService.truncateAll() + }) + + afterAll(async () => { + await testPrismaService.truncateAll() + await module.close() + await app.close() + }) + + let knownDestinations: KnownDestination[] + + beforeEach(async () => { + await testPrismaService.truncateAll() + await provisionService.provision() + + await clientService.save(testClient) + + await app.init() + + const connection1 = await connectionService.create(testClient.clientId, { + connectionId: v4(), + provider: Provider.ANCHORAGE, + url: ANCHORAGE_TEST_API_BASE_URL, + createdAt: now, + credentials: { + apiKey: 'test-api-key', + privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) + } + }) + + const connection2 = await connectionService.create(testClient.clientId, { + connectionId: v4(), + provider: Provider.ANCHORAGE, + url: ANCHORAGE_TEST_API_BASE_URL, + createdAt: now, + credentials: { + apiKey: 'test-api-key', + privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) + } + }) + + connection1Id = connection1.connectionId + connection2Id = connection2.connectionId + + knownDestinations = [ + { + clientId: 'test-client-id', + provider: 'anchorage', + externalId: 'neverChanges', + externalClassification: null, + address: 'bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh', + label: null, + assetId: 'BTC', + networkId: 'BTC', + createdAt: now, + updatedAt: now, + connections: [connection1], + knownDestinationId: 'c2f7d2f1-e0b5-4966-a55f-7257420df81f' + }, + { + clientId: 'test-client-id', + provider: 'anchorage', + externalId: 'toBeDeleted', + externalClassification: null, + address: 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', + label: '123456', + assetId: 'XRP', + networkId: 'XRP', + createdAt: now, + updatedAt: now, + connections: [connection1], + knownDestinationId: '9ba64a60-0684-4b7c-9d2d-78bf0a1c6de8' + }, + { + clientId: 'test-client-id', + provider: 'anchorage', + externalId: 'toBeUpdated', + externalClassification: null, + address: '0x8Bc2B8F33e5AeF847B8973Fa669B948A3028D6bd', + label: null, + assetId: 'USDC', + networkId: 'ETH', + createdAt: now, + updatedAt: now, + connections: [connection2], + knownDestinationId: '8d5e8d6f-2836-4d47-821d-80906e1a1448' + }, + { + clientId: 'test-client-id', + provider: 'anchorage', + externalId: 'toBeConnected', + externalClassification: null, + address: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e', + label: null, + assetId: 'ETH', + networkId: 'ETH', + createdAt: now, + updatedAt: now, + connections: [connection2], + knownDestinationId: '04817a66-039d-43e7-ab0a-023997597054' + } + ] + await knownDestinationService.bulkCreate(knownDestinations) + }) + + describe('GET /provider/known-destinations', () => { + it('returns known destinations for a connection', async () => { + const { status, body } = await request(app.getHttpServer()) + .get('/provider/known-destinations') + .set(REQUEST_HEADER_CLIENT_ID, testClient.clientId) + .query({ connectionId: connection1Id }) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: `/provider/known-destinations?connectionId=${connection1Id}`, + payload: {}, + htm: 'GET' + }) + ) + + const expectedDestinations = [knownDestinations[0], knownDestinations[1]] + + expect(body).toEqual({ + data: expectedDestinations.map((knownDestination) => ({ + ...knownDestination, + createdAt: now.toISOString(), + updatedAt: now.toISOString(), + connections: knownDestination.connections.map((connection) => ({ + updatedAt: expect.any(String), + createdAt: expect.any(String), + status: connection.status, + provider: connection.provider, + url: connection.url, + connectionId: connection.connectionId, + clientId: connection.clientId + })) + })), + page: { next: null } + }) + expect(status).toBe(HttpStatus.OK) + }) + + it('returns known destinations for another connection', async () => { + const { status, body } = await request(app.getHttpServer()) + .get('/provider/known-destinations') + .set(REQUEST_HEADER_CLIENT_ID, testClient.clientId) + .query({ connectionId: connection2Id }) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: `/provider/known-destinations?connectionId=${connection2Id}`, + payload: {}, + htm: 'GET' + }) + ) + + const expectedDestinations = [knownDestinations[2], knownDestinations[3]] + expect(body).toEqual({ + data: expectedDestinations.map((knownDestination) => ({ + ...knownDestination, + createdAt: now.toISOString(), + updatedAt: now.toISOString(), + connections: knownDestination.connections.map((connection) => ({ + updatedAt: expect.any(String), + createdAt: expect.any(String), + status: connection.status, + provider: connection.provider, + url: connection.url, + connectionId: connection.connectionId, + clientId: connection.clientId + })) + })), + page: { next: null } + }) + expect(status).toBe(HttpStatus.OK) + }) + + it('returns empty if connection is not in the system', async () => { + const { status, body } = await request(app.getHttpServer()) + .get('/provider/known-destinations') + .set(REQUEST_HEADER_CLIENT_ID, testClient.clientId) + .query({ connectionId: 'unknown' }) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/known-destinations?connectionId=unknown', + payload: {}, + htm: 'GET' + }) + ) + + expect(body).toEqual({ data: [], page: { next: null } }) + expect(status).toBe(HttpStatus.OK) + }) + + it('returns all known destinations if connection is not specified', async () => { + const { status, body } = await request(app.getHttpServer()) + .get('/provider/known-destinations') + .set(REQUEST_HEADER_CLIENT_ID, testClient.clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/known-destinations', + payload: {}, + htm: 'GET' + }) + ) + + expect(body).toEqual({ + data: knownDestinations.map((knownDestination) => ({ + ...knownDestination, + createdAt: now.toISOString(), + updatedAt: now.toISOString(), + connections: knownDestination.connections.map((connection) => ({ + updatedAt: expect.any(String), + createdAt: expect.any(String), + status: connection.status, + provider: connection.provider, + url: connection.url, + connectionId: connection.connectionId, + clientId: connection.clientId + })) + })), + page: { next: null } + }) + expect(status).toBe(HttpStatus.OK) + }) + }) + + describe('GET /provider/known-destinations/:knownDestinationId', () => { + it('returns known destination', async () => { + const { status, body } = await request(app.getHttpServer()) + .get('/provider/known-destinations/c2f7d2f1-e0b5-4966-a55f-7257420df81f') + .set(REQUEST_HEADER_CLIENT_ID, testClient.clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: `/provider/known-destinations/c2f7d2f1-e0b5-4966-a55f-7257420df81f`, + payload: {}, + htm: 'GET' + }) + ) + expect(body.data).toEqual({ + ...knownDestinations[0], + createdAt: now.toISOString(), + updatedAt: now.toISOString(), + connections: knownDestinations[0].connections.map((connection) => ({ + updatedAt: expect.any(String), + createdAt: expect.any(String), + status: connection.status, + provider: connection.provider, + url: connection.url, + connectionId: connection.connectionId, + clientId: connection.clientId + })) + }) + expect(status).toBe(HttpStatus.OK) + }) + + it('returns 404 for unknown known destination', async () => { + const { status, body } = await request(app.getHttpServer()) + .get('/provider/known-destinations/unknown') + .set(REQUEST_HEADER_CLIENT_ID, testClient.clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: `/provider/known-destinations/unknown`, + payload: {}, + htm: 'GET' + }) + ) + expect(status).toBe(HttpStatus.NOT_FOUND) + }) + }) +}) diff --git a/apps/vault/src/broker/broker.module.ts b/apps/vault/src/broker/broker.module.ts index 6d111506d..6879cc9d5 100644 --- a/apps/vault/src/broker/broker.module.ts +++ b/apps/vault/src/broker/broker.module.ts @@ -14,7 +14,7 @@ import { AddressService } from './core/service/address.service' import { AnchorageSyncService } from './core/service/anchorage-sync.service' import { AnchorageTransferService } from './core/service/anchorage-transfer.service' import { ConnectionService } from './core/service/connection.service' -import { KnownDestinationService } from './core/service/know-destination.service' +import { KnownDestinationService } from './core/service/known-destination.service' import { ProxyService } from './core/service/proxy.service' import { SyncService } from './core/service/sync.service' import { TransferPartyService } from './core/service/transfer-party.service' @@ -25,6 +25,7 @@ import { AnchorageClient } from './http/client/anchorage.client' import { ProviderAccountController } from './http/rest/controller/account.controller' import { AddressController } from './http/rest/controller/address.controller' import { ConnectionController } from './http/rest/controller/connection.controller' +import { KnownDestinationController } from './http/rest/controller/known-destination.controller' import { ProxyController } from './http/rest/controller/proxy.controller' import { SyncController } from './http/rest/controller/sync.controller' import { TransferController } from './http/rest/controller/transfer.controller' @@ -51,6 +52,7 @@ import { WalletRepository } from './persistence/repository/wallet.repository' ProviderAccountController, AddressController, ConnectionController, + KnownDestinationController, ProxyController, SyncController, TransferController, diff --git a/apps/vault/src/broker/core/exception/invalid-query-string.exception.ts b/apps/vault/src/broker/core/exception/invalid-query-string.exception.ts new file mode 100644 index 000000000..42d969071 --- /dev/null +++ b/apps/vault/src/broker/core/exception/invalid-query-string.exception.ts @@ -0,0 +1,13 @@ +import { HttpStatus } from '@nestjs/common' +import { ApplicationExceptionParams } from '../../../shared/exception/application.exception' +import { BrokerException } from './broker.exception' + +export class InvalidQueryStringException extends BrokerException { + constructor(query: string, params?: Partial) { + super({ + message: params?.message || `Query string "${query}" is required`, + suggestedHttpStatusCode: params?.suggestedHttpStatusCode || HttpStatus.BAD_REQUEST, + ...params + }) + } +} diff --git a/apps/vault/src/broker/core/service/__test__/integration/anchorage-sync.service.spec.ts b/apps/vault/src/broker/core/service/__test__/integration/anchorage-sync.service.spec.ts index 625b826b8..ddf8cf774 100644 --- a/apps/vault/src/broker/core/service/__test__/integration/anchorage-sync.service.spec.ts +++ b/apps/vault/src/broker/core/service/__test__/integration/anchorage-sync.service.spec.ts @@ -21,7 +21,7 @@ import { AccountService } from '../../account.service' import { AddressService } from '../../address.service' import { AnchorageSyncService } from '../../anchorage-sync.service' import { ConnectionService } from '../../connection.service' -import { KnownDestinationService } from '../../know-destination.service' +import { KnownDestinationService } from '../../known-destination.service' import { WalletService } from '../../wallet.service' import { trustedDestinationsHandlers, vaultHandlers } from './mocks/anchorage/handlers' import { ANCHORAGE_TEST_API_BASE_URL, setupMockServer } from './mocks/anchorage/server' @@ -217,7 +217,7 @@ describe(AnchorageSyncService.name, () => { }) describe('syncKnownDestinations', () => { - it('fetches anchorage addresses and persist them as known-addresses', async () => { + it('fetches anchorage addresses and persist them as knownDestinations', async () => { const { created } = await anchorageSyncService.syncKnownDestinations(connection) const { data: knownDestinations } = await knownDestinationService.findAll(connection.clientId) diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/handlers.ts b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/handlers.ts index b403be023..c48ae796e 100644 --- a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/handlers.ts +++ b/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/handlers.ts @@ -11,15 +11,15 @@ import postTransferCreated from './response/post-transfer-201.json' export const trustedDestinationsHandlers = (baseUrl: string) => { return { - findAll: http.get(`${baseUrl}/v2/trusted-destinations`, () => { + findAll: http.get(`${baseUrl}/v2/trusted_destinations`, () => { return new HttpResponse(JSON.stringify(trustedDestinationsFirst)) }), - deleteAndUpdate: http.get(`${baseUrl}/v2/trusted-destinations`, () => { + deleteAndUpdate: http.get(`${baseUrl}/v2/trusted_destinations`, () => { return new HttpResponse(JSON.stringify(trustedDestinationsSecond)) }), - connect: http.get(`${baseUrl}/v2/trusted-destinations`, () => { + connect: http.get(`${baseUrl}/v2/trusted_destinations`, () => { return new HttpResponse(JSON.stringify(trustedDestinationsThird)) }) } diff --git a/apps/vault/src/broker/core/service/anchorage-sync.service.ts b/apps/vault/src/broker/core/service/anchorage-sync.service.ts index 5526458e3..4bf9e1d3b 100644 --- a/apps/vault/src/broker/core/service/anchorage-sync.service.ts +++ b/apps/vault/src/broker/core/service/anchorage-sync.service.ts @@ -10,7 +10,7 @@ import { ActiveConnection, ActiveConnectionWithCredentials, Provider } from '../ import { Account, Address, KnownDestination, Wallet } from '../type/indexed-resources.type' import { AccountService } from './account.service' import { AddressService } from './address.service' -import { KnownDestinationService } from './know-destination.service' +import { KnownDestinationService } from './known-destination.service' import { WalletService } from './wallet.service' @Injectable() diff --git a/apps/vault/src/broker/core/service/know-destination.service.ts b/apps/vault/src/broker/core/service/known-destination.service.ts similarity index 100% rename from apps/vault/src/broker/core/service/know-destination.service.ts rename to apps/vault/src/broker/core/service/known-destination.service.ts diff --git a/apps/vault/src/broker/http/client/anchorage.client.ts b/apps/vault/src/broker/http/client/anchorage.client.ts index b1ab3f0f9..c61fcc87f 100644 --- a/apps/vault/src/broker/http/client/anchorage.client.ts +++ b/apps/vault/src/broker/http/client/anchorage.client.ts @@ -484,7 +484,7 @@ export class AnchorageClient { this.sendSignedRequest({ schema: GetTrustedDestinationsResponse, request: { - url: `${url}/v2/trusted-destinations`, + url: `${url}/v2/trusted_destinations`, method: 'GET' }, apiKey, diff --git a/apps/vault/src/broker/http/rest/controller/known-destination.controller.ts b/apps/vault/src/broker/http/rest/controller/known-destination.controller.ts new file mode 100644 index 000000000..fc20c4f50 --- /dev/null +++ b/apps/vault/src/broker/http/rest/controller/known-destination.controller.ts @@ -0,0 +1,62 @@ +import { ApiClientIdHeader, PaginationOptions, PaginationParam } from '@narval/nestjs-shared' +import { Controller, Get, HttpStatus, Param, Query } from '@nestjs/common' +import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' +import { ClientId } from '../../../../shared/decorator/client-id.decorator' +import { PermissionGuard } from '../../../../shared/decorator/permission-guard.decorator' +import { VaultPermission } from '../../../../shared/type/domain.type' +import { KnownDestinationService } from '../../../core/service/known-destination.service' +import { PaginatedKnownDestinationsDto } from '../dto/response/paginated-known-destinations.dto' +import { KnownDestinationDto } from '../dto/response/provider-known-destination.dto' + +@Controller({ + path: 'known-destinations', + version: '1' +}) +@ApiTags('Provider Known Destination') +@ApiClientIdHeader() +export class KnownDestinationController { + constructor(private readonly knownDestinationService: KnownDestinationService) {} + + @Get() + @PermissionGuard(VaultPermission.CONNECTION_READ) + @ApiOperation({ summary: 'Get known destinations across providers' }) + @ApiResponse({ + status: HttpStatus.OK, + description: 'Returns paginated known destinations', + type: PaginatedKnownDestinationsDto + }) + async list( + @ClientId() clientId: string, + @PaginationParam() paginationOptions: PaginationOptions, + @Query('connectionId') connectionId?: string + ): Promise { + const filters = connectionId ? { connections: [connectionId] } : {} + + const { data, page } = await this.knownDestinationService.findAll(clientId, { + ...paginationOptions, + filters + }) + + return PaginatedKnownDestinationsDto.create({ data, page }) + } + + @Get(':knownDestinationId') + @PermissionGuard(VaultPermission.CONNECTION_READ) + @ApiOperation({ summary: 'Get known destination by ID' }) + @ApiResponse({ + status: HttpStatus.OK, + description: 'Returns known destination', + type: KnownDestinationDto + }) + @ApiResponse({ + status: HttpStatus.NOT_FOUND, + description: 'Known destination not found' + }) + async getById( + @ClientId() clientId: string, + @Param('knownDestinationId') knownDestinationId: string + ): Promise { + const data = await this.knownDestinationService.getKnownDestination(clientId, knownDestinationId) + return KnownDestinationDto.create({ data }) + } +} diff --git a/apps/vault/src/broker/http/rest/dto/response/paginated-known-destinations.dto.ts b/apps/vault/src/broker/http/rest/dto/response/paginated-known-destinations.dto.ts new file mode 100644 index 000000000..1737982e4 --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/response/paginated-known-destinations.dto.ts @@ -0,0 +1,11 @@ +import { Page } from '@narval/nestjs-shared' +import { createZodDto } from 'nestjs-zod' +import { z } from 'zod' +import { KnownDestination } from '../../../../core/type/indexed-resources.type' + +export class PaginatedKnownDestinationsDto extends createZodDto( + z.object({ + data: z.array(KnownDestination), + page: Page + }) +) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/provider-known-destination.dto.ts b/apps/vault/src/broker/http/rest/dto/response/provider-known-destination.dto.ts new file mode 100644 index 000000000..a83af23a7 --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/response/provider-known-destination.dto.ts @@ -0,0 +1,9 @@ +import { createZodDto } from 'nestjs-zod' +import { z } from 'zod' +import { KnownDestination } from '../../../../core/type/indexed-resources.type' + +export class KnownDestinationDto extends createZodDto( + z.object({ + data: KnownDestination + }) +) {} diff --git a/apps/vault/src/broker/persistence/repository/known-destination.repository.ts b/apps/vault/src/broker/persistence/repository/known-destination.repository.ts index e7aceeba1..02711ea0e 100644 --- a/apps/vault/src/broker/persistence/repository/known-destination.repository.ts +++ b/apps/vault/src/broker/persistence/repository/known-destination.repository.ts @@ -12,6 +12,8 @@ type FindAllFilters = { filters?: { externalIds?: string[] addresses?: string[] + providers?: Provider[] + connections?: string[] } } @@ -133,6 +135,24 @@ export class KnownDestinationRepository { in: opts.filters.externalIds } } + : {}), + ...(opts?.filters?.providers + ? { + provider: { + in: opts.filters.providers + } + } + : {}), + ...(opts?.filters?.connections + ? { + connections: { + some: { + connectionId: { + in: opts.filters.connections + } + } + } + } : {}) }, include: { From 8173cc025174b1883ac84779abbcc4fdd06ce7ee Mon Sep 17 00:00:00 2001 From: Ptroger <44851272+Ptroger@users.noreply.github.com> Date: Mon, 30 Dec 2024 09:35:44 +0100 Subject: [PATCH 063/120] removing exception and piping success and errors from anchorage (#57) --- .../src/broker/__test__/e2e/proxy.spec.ts | 28 +++++++++++++++++ .../core/exception/proxy-request.exception.ts | 30 ------------------- .../broker/http/client/anchorage.client.ts | 25 +++++----------- .../http/rest/controller/proxy.controller.ts | 26 ++++++---------- 4 files changed, 44 insertions(+), 65 deletions(-) delete mode 100644 apps/vault/src/broker/core/exception/proxy-request.exception.ts diff --git a/apps/vault/src/broker/__test__/e2e/proxy.spec.ts b/apps/vault/src/broker/__test__/e2e/proxy.spec.ts index 7a41a9033..07749c2d0 100644 --- a/apps/vault/src/broker/__test__/e2e/proxy.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/proxy.spec.ts @@ -328,4 +328,32 @@ describe('Proxy', () => { }) expect(response.status).toBe(HttpStatus.UNPROCESSABLE_ENTITY) }) + + it('correctly forwards response headers without conflicts', async () => { + nock(MOCK_API_URL).get('/v2/vaults').reply( + 200, + { data: 'mock response' }, + { + 'transfer-encoding': 'chunked' + } + ) + + const response = await request(app.getHttpServer()) + .get('/provider/proxy/v2/vaults') + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set(REQUEST_HEADER_CONNECTION_ID, TEST_CONNECTION_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/proxy/v2/vaults', + payload: {}, + htm: 'GET' + }) + ) + + // If there's a header conflict, nock will throw before we get here + expect(response.body).toEqual({ data: 'mock response' }) + expect(response.status).toBe(HttpStatus.OK) + }) }) diff --git a/apps/vault/src/broker/core/exception/proxy-request.exception.ts b/apps/vault/src/broker/core/exception/proxy-request.exception.ts deleted file mode 100644 index a296bd160..000000000 --- a/apps/vault/src/broker/core/exception/proxy-request.exception.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { BrokerException } from './broker.exception' - -export class ProxyRequestException extends BrokerException { - public data: unknown - public code: number - public headers: Record - - constructor({ - data, - status, - message, - headers, - context - }: { - data: unknown - status: number - message: string - headers: Record - context: Record - }) { - super({ - message: message ? message : 'Provider request failed', - suggestedHttpStatusCode: status, - context - }) - this.data = data - this.code = status - this.headers = headers - } -} diff --git a/apps/vault/src/broker/http/client/anchorage.client.ts b/apps/vault/src/broker/http/client/anchorage.client.ts index c61fcc87f..e7ec54b08 100644 --- a/apps/vault/src/broker/http/client/anchorage.client.ts +++ b/apps/vault/src/broker/http/client/anchorage.client.ts @@ -21,7 +21,6 @@ import { import { ZodType, z } from 'zod' import { BrokerException } from '../../core/exception/broker.exception' import { ProviderHttpException } from '../../core/exception/provider-http.exception' -import { ProxyRequestException } from '../../core/exception/proxy-request.exception' import { UrlParserException } from '../../core/exception/url-parser.exception' import { Provider } from '../../core/type/connection.type' @@ -236,28 +235,18 @@ export class AnchorageClient { request: { url, method, - data + data, + responseType: 'stream', + // Don't reject on error status codes. Needed to re-throw our exception + validateStatus: null }, apiKey, signKey }) - try { - const response = await axios(signedRequest) - - return response - } catch (error) { - throw new ProxyRequestException({ - message: 'Anchorage proxy request failed', - status: error.response?.status, - data: error.response?.data, - headers: error.response?.headers, - context: { - url, - method - } - }) - } + const response = await axios(signedRequest) + + return response } async authorize(opts: { diff --git a/apps/vault/src/broker/http/rest/controller/proxy.controller.ts b/apps/vault/src/broker/http/rest/controller/proxy.controller.ts index fbf7bff1a..bd54edaaa 100644 --- a/apps/vault/src/broker/http/rest/controller/proxy.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/proxy.controller.ts @@ -20,7 +20,6 @@ import { ClientId } from '../../../../shared/decorator/client-id.decorator' import { ConnectionId } from '../../../../shared/decorator/connection-id.decorator' import { PermissionGuard } from '../../../../shared/decorator/permission-guard.decorator' import { VaultPermission } from '../../../../shared/type/domain.type' -import { ProxyRequestException } from '../../../core/exception/proxy-request.exception' import { ProxyService } from '../../../core/service/proxy.service' const API_PARAM = ':endpoint(*)' @@ -68,22 +67,15 @@ export class ProxyController { const queryString = new URLSearchParams(request.query as Record).toString() const sanitizedEndpoint = queryString ? `/${endpoint}?${queryString}` : `/${endpoint}` - try { - const response = await this.proxyService.forward(clientId, { - connectionId, - endpoint: sanitizedEndpoint, - method: request.method, - data: body - }) - - res.status(response.code).set(response.headers).send(response.data) - } catch (error) { - if (error instanceof ProxyRequestException) { - res.status(error.code).set(error.headers).send(error.data) - } else { - throw error - } - } + const response = await this.proxyService.forward(clientId, { + connectionId, + endpoint: sanitizedEndpoint, + method: request.method, + data: body + }) + + res.status(response.code).set(response.headers) + response.data.pipe(res) } // IMPORTANT: The `@All` decorator from NestJS cannot be used here because it From ba208464966413f3c9ef4611924775fa5bb6c271 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Mon, 30 Dec 2024 11:06:50 +0100 Subject: [PATCH 064/120] Introduce provider mandatory interfaces (#58) * Add provider specific interface and refactor Anchorage sync * Test sync method * Copy Anchorage transfer service * Refactor sync to write operations * Move provider specific code to its own directory * Remove files after merge * Fix wrong import names * Fix idempotentId wrong map for Anchorage * Add back wallet update * Fix wrong import * Update accounts and fix wrong imports * Reorganize mock server --- .../broker/__test__/e2e/connection.spec.ts | 9 +- .../__test__/e2e/known-destinations.spec.ts | 2 +- .../src/broker/__test__/e2e/sync.spec.ts | 56 +- .../src/broker/__test__/e2e/transfer.spec.ts | 10 +- apps/vault/src/broker/broker.module.ts | 4 +- .../anchorage-sync.service.spec.ts | 525 ++++++++++++++++++ .../anchorage-transfer.service.spec.ts | 54 +- .../response/get-transfer-200.json | 0 .../get-trusted-destinations-200-second.json | 0 .../get-trusted-destinations-200-third.json | 0 .../get-trusted-destinations-200.json | 0 .../response/get-vaults-200-second.json | 0 .../server-mock}/response/get-vaults-200.json | 0 .../response/get-vaults-addresses-200.json | 0 .../response/get-wallets-200.json | 0 .../response/post-transfer-201.json | 0 .../response/post-transfer-400.json | 0 .../anchorage/__test__/server-mock/server.ts} | 12 +- .../anchorage/anchorage-sync.service.ts | 445 +++++++++++++++ .../anchorage}/anchorage-transfer.service.ts | 17 +- .../anchorage-sync.service.spec.ts | 303 ---------- .../__test__/integration/sync.service.spec.ts | 449 +++++++++++++++ .../broker/core/service/account.service.ts | 22 +- .../core/service/anchorage-sync.service.ts | 427 -------------- .../core/service/known-destination.service.ts | 9 +- .../src/broker/core/service/sync.service.ts | 191 ++++++- .../broker/core/service/transfer.service.ts | 56 +- .../src/broker/core/service/wallet.service.ts | 14 +- .../src/broker/core/type/provider.type.ts | 247 ++++++++ .../broker/core/util/provider-sync.util.ts | 18 + .../handler/connection-sync.event-handler.ts | 13 +- .../broker/http/client/anchorage.client.ts | 2 +- .../rest/controller/account.controller.ts | 6 +- .../http/rest/controller/wallet.controller.ts | 6 +- .../repository/account.repository.ts | 51 +- .../known-destination.repository.ts | 15 +- .../__test__/mock-server.ts} | 12 +- .../broker/shared/event/sync-started.event.ts | 11 + 38 files changed, 2090 insertions(+), 896 deletions(-) create mode 100644 apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-sync.service.spec.ts rename apps/vault/src/broker/core/{service => provider/anchorage}/__test__/integration/anchorage-transfer.service.spec.ts (86%) rename apps/vault/src/broker/core/{service/__test__/integration/mocks/anchorage => provider/anchorage/__test__/server-mock}/response/get-transfer-200.json (100%) rename apps/vault/src/broker/core/{service/__test__/integration/mocks/anchorage => provider/anchorage/__test__/server-mock}/response/get-trusted-destinations-200-second.json (100%) rename apps/vault/src/broker/core/{service/__test__/integration/mocks/anchorage => provider/anchorage/__test__/server-mock}/response/get-trusted-destinations-200-third.json (100%) rename apps/vault/src/broker/core/{service/__test__/integration/mocks/anchorage => provider/anchorage/__test__/server-mock}/response/get-trusted-destinations-200.json (100%) rename apps/vault/src/broker/core/{service/__test__/integration/mocks/anchorage => provider/anchorage/__test__/server-mock}/response/get-vaults-200-second.json (100%) rename apps/vault/src/broker/core/{service/__test__/integration/mocks/anchorage => provider/anchorage/__test__/server-mock}/response/get-vaults-200.json (100%) rename apps/vault/src/broker/core/{service/__test__/integration/mocks/anchorage => provider/anchorage/__test__/server-mock}/response/get-vaults-addresses-200.json (100%) rename apps/vault/src/broker/core/{service/__test__/integration/mocks/anchorage => provider/anchorage/__test__/server-mock}/response/get-wallets-200.json (100%) rename apps/vault/src/broker/core/{service/__test__/integration/mocks/anchorage => provider/anchorage/__test__/server-mock}/response/post-transfer-201.json (100%) rename apps/vault/src/broker/core/{service/__test__/integration/mocks/anchorage => provider/anchorage/__test__/server-mock}/response/post-transfer-400.json (100%) rename apps/vault/src/broker/core/{service/__test__/integration/mocks/anchorage/handlers.ts => provider/anchorage/__test__/server-mock/server.ts} (82%) create mode 100644 apps/vault/src/broker/core/provider/anchorage/anchorage-sync.service.ts rename apps/vault/src/broker/core/{service => provider/anchorage}/anchorage-transfer.service.ts (91%) delete mode 100644 apps/vault/src/broker/core/service/__test__/integration/anchorage-sync.service.spec.ts create mode 100644 apps/vault/src/broker/core/service/__test__/integration/sync.service.spec.ts delete mode 100644 apps/vault/src/broker/core/service/anchorage-sync.service.ts create mode 100644 apps/vault/src/broker/core/type/provider.type.ts create mode 100644 apps/vault/src/broker/core/util/provider-sync.util.ts rename apps/vault/src/broker/{core/service/__test__/integration/mocks/anchorage/server.ts => shared/__test__/mock-server.ts} (83%) create mode 100644 apps/vault/src/broker/shared/event/sync-started.event.ts diff --git a/apps/vault/src/broker/__test__/e2e/connection.spec.ts b/apps/vault/src/broker/__test__/e2e/connection.spec.ts index 5002e3f0e..d5149b463 100644 --- a/apps/vault/src/broker/__test__/e2e/connection.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/connection.spec.ts @@ -69,12 +69,13 @@ const toMatchZodSchema = (received: unknown, schema: ZodSchema): void => { describe('Connection', () => { let app: INestApplication let module: TestingModule - let connectionService: ConnectionService - let encryptionKeyService: EncryptionKeyService let testPrismaService: TestPrismaService - let provisionService: ProvisionService + let clientService: ClientService + let connectionService: ConnectionService + let encryptionKeyService: EncryptionKeyService let eventEmitterMock: MockProxy + let provisionService: ProvisionService const url = 'http://provider.narval.xyz' @@ -216,7 +217,7 @@ describe('Connection', () => { const createdConnection = await connectionService.findById(clientId, connection.connectionId, true) expect(eventEmitterMock.emit).toHaveBeenCalledWith( - 'connection.activated', + ConnectionActivatedEvent.EVENT_NAME, new ConnectionActivatedEvent(createdConnection as ActiveConnectionWithCredentials) ) }) diff --git a/apps/vault/src/broker/__test__/e2e/known-destinations.spec.ts b/apps/vault/src/broker/__test__/e2e/known-destinations.spec.ts index 015739d8c..2cdff5264 100644 --- a/apps/vault/src/broker/__test__/e2e/known-destinations.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/known-destinations.spec.ts @@ -14,7 +14,7 @@ import { KeyValueRepository } from '../../../shared/module/key-value/core/reposi import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' -import { ANCHORAGE_TEST_API_BASE_URL } from '../../core/service/__test__/integration/mocks/anchorage/server' +import { ANCHORAGE_TEST_API_BASE_URL } from '../../core/provider/anchorage/__test__/server-mock/server' import { ConnectionService } from '../../core/service/connection.service' import { KnownDestinationService } from '../../core/service/known-destination.service' import { Provider } from '../../core/type/connection.type' diff --git a/apps/vault/src/broker/__test__/e2e/sync.spec.ts b/apps/vault/src/broker/__test__/e2e/sync.spec.ts index 55ed0a905..b35a4c5ce 100644 --- a/apps/vault/src/broker/__test__/e2e/sync.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/sync.spec.ts @@ -14,30 +14,28 @@ import { KeyValueRepository } from '../../../shared/module/key-value/core/reposi import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' -import { - ANCHORAGE_TEST_API_BASE_URL, - setupMockServer -} from '../../core/service/__test__/integration/mocks/anchorage/server' -import { AnchorageSyncService } from '../../core/service/anchorage-sync.service' +import { ANCHORAGE_TEST_API_BASE_URL, getHandlers } from '../../core/provider/anchorage/__test__/server-mock/server' +import { AnchorageSyncService } from '../../core/provider/anchorage/anchorage-sync.service' import { ConnectionService } from '../../core/service/connection.service' import { SyncService } from '../../core/service/sync.service' -import { ActiveConnectionWithCredentials, PendingConnection, Provider } from '../../core/type/connection.type' +import { ActiveConnectionWithCredentials, Provider } from '../../core/type/connection.type' import { SyncStatus } from '../../core/type/sync.type' +import { setupMockServer } from '../../shared/__test__/mock-server' +import { SyncStartedEvent } from '../../shared/event/sync-started.event' import { getJwsd, testClient, testUserPrivateJwk } from '../util/mock-data' describe('Sync', () => { let app: INestApplication let module: TestingModule + + let eventEmitterMock: MockProxy let syncService: SyncService let connectionService: ConnectionService let testPrismaService: TestPrismaService let anchorageSyncServiceMock: MockProxy let provisionService: ProvisionService let clientService: ClientService - let activeConnection: ActiveConnectionWithCredentials - // eslint-disable-next-line @typescript-eslint/no-unused-vars - let pendingConnection: PendingConnection const url = ANCHORAGE_TEST_API_BASE_URL @@ -45,17 +43,14 @@ describe('Sync', () => { const clientId = testClient.clientId - setupMockServer() + setupMockServer(getHandlers()) beforeAll(async () => { - // We mock the provider's sync service here to prevent race conditions - // during the tests. This is because the SyncService sends a promise to - // start the sync but does not wait for it to complete. - // - // NOTE: The sync logic is tested in the provider's sync service - // integration tests. - anchorageSyncServiceMock = mock() - anchorageSyncServiceMock.sync.mockResolvedValue() + // NOTE: The sync logic is tested in the provider's sync service and the + // sync service integration tests. + + eventEmitterMock = mock() + eventEmitterMock.emit.mockReturnValue(true) module = await Test.createTestingModule({ imports: [MainModule] @@ -70,10 +65,8 @@ describe('Sync', () => { }) .overrideProvider(AnchorageSyncService) .useValue(anchorageSyncServiceMock) - // Mock the event emitter because we don't want to send a - // connection.activated event after the creation. .overrideProvider(EventEmitter2) - .useValue(mock()) + .useValue(eventEmitterMock) .compile() app = module.createNestApplication() @@ -109,7 +102,7 @@ describe('Sync', () => { } }) - pendingConnection = await connectionService.initiate(clientId, { + await connectionService.initiate(clientId, { connectionId: uuid(), provider: Provider.ANCHORAGE }) @@ -123,7 +116,7 @@ describe('Sync', () => { // single state throughout the entire test lifecycle. Therefore, changing // the order of this test will affect how many times the `sync` function is // called. - it('dispatches the sync to the provider specific service', async () => { + it('emits sync.started event on syncs start', async () => { await request(app.getHttpServer()) .post('/provider/syncs') .set(REQUEST_HEADER_CLIENT_ID, clientId) @@ -138,7 +131,12 @@ describe('Sync', () => { ) .send() - expect(anchorageSyncServiceMock.sync).toHaveBeenCalledTimes(1) + const { data: syncs } = await syncService.findAll(clientId) + + expect(eventEmitterMock.emit).toHaveBeenCalledWith( + SyncStartedEvent.EVENT_NAME, + new SyncStartedEvent(syncs[0], activeConnection) + ) }) it('starts a sync on every active connection', async () => { @@ -238,9 +236,7 @@ describe('Sync', () => { connectionId: sync.connectionId, createdAt: sync.createdAt.toISOString(), syncId: sync.syncId, - // In between the calling `start` and sending the request, the sync - // status changed from `processing` to `success`. - status: SyncStatus.SUCCESS + status: SyncStatus.PROCESSING }) expect(status).toEqual(HttpStatus.OK) @@ -273,9 +269,7 @@ describe('Sync', () => { connectionId: sync.connectionId, createdAt: sync.createdAt.toISOString(), syncId: sync.syncId, - // In between the calling `start` and sending the request, the sync - // status changed from `processing` to `success`. - status: SyncStatus.SUCCESS + status: SyncStatus.PROCESSING } ] }) @@ -311,7 +305,7 @@ describe('Sync', () => { connectionId: sync.connectionId, createdAt: sync.createdAt.toISOString(), syncId: sync.syncId, - status: SyncStatus.SUCCESS + status: SyncStatus.PROCESSING } ] }) diff --git a/apps/vault/src/broker/__test__/e2e/transfer.spec.ts b/apps/vault/src/broker/__test__/e2e/transfer.spec.ts index f5e782925..39927904e 100644 --- a/apps/vault/src/broker/__test__/e2e/transfer.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/transfer.spec.ts @@ -15,11 +15,8 @@ import { KeyValueRepository } from '../../../shared/module/key-value/core/reposi import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' -import postAnchorageTransferBadRequest from '../../core/service/__test__/integration/mocks/anchorage/response/post-transfer-400.json' -import { - ANCHORAGE_TEST_API_BASE_URL, - setupMockServer -} from '../../core/service/__test__/integration/mocks/anchorage/server' +import postAnchorageTransferBadRequest from '../../core/provider/anchorage/__test__/server-mock/response/post-transfer-400.json' +import { ANCHORAGE_TEST_API_BASE_URL, getHandlers } from '../../core/provider/anchorage/__test__/server-mock/server' import { ActiveConnectionWithCredentials, ConnectionStatus, Provider } from '../../core/type/connection.type' import { Account, Wallet } from '../../core/type/indexed-resources.type' import { @@ -32,6 +29,7 @@ import { AccountRepository } from '../../persistence/repository/account.reposito import { ConnectionRepository } from '../../persistence/repository/connection.repository' import { TransferRepository } from '../../persistence/repository/transfer.repository' import { WalletRepository } from '../../persistence/repository/wallet.repository' +import { setupMockServer } from '../../shared/__test__/mock-server' import { getJwsd, testClient, testUserPrivateJwk } from '../util/mock-data' const ENDPOINT = '/provider/transfers' @@ -138,7 +136,7 @@ describe('Transfer', () => { transferId: uuid() } - const mockServer = setupMockServer() + const mockServer = setupMockServer(getHandlers()) beforeAll(async () => { module = await Test.createTestingModule({ diff --git a/apps/vault/src/broker/broker.module.ts b/apps/vault/src/broker/broker.module.ts index 6879cc9d5..450c79f78 100644 --- a/apps/vault/src/broker/broker.module.ts +++ b/apps/vault/src/broker/broker.module.ts @@ -9,10 +9,10 @@ import { PersistenceModule } from '../shared/module/persistence/persistence.modu import { EncryptionKeyService } from '../transit-encryption/core/service/encryption-key.service' import { EncryptionKeyRepository } from '../transit-encryption/persistence/encryption-key.repository' import { TransitEncryptionModule } from '../transit-encryption/transit-encryption.module' +import { AnchorageSyncService } from './core/provider/anchorage/anchorage-sync.service' +import { AnchorageTransferService } from './core/provider/anchorage/anchorage-transfer.service' import { AccountService } from './core/service/account.service' import { AddressService } from './core/service/address.service' -import { AnchorageSyncService } from './core/service/anchorage-sync.service' -import { AnchorageTransferService } from './core/service/anchorage-transfer.service' import { ConnectionService } from './core/service/connection.service' import { KnownDestinationService } from './core/service/known-destination.service' import { ProxyService } from './core/service/proxy.service' diff --git a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-sync.service.spec.ts b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-sync.service.spec.ts new file mode 100644 index 000000000..02f1b08be --- /dev/null +++ b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-sync.service.spec.ts @@ -0,0 +1,525 @@ +import { EncryptionModuleOptionProvider } from '@narval/encryption-module' +import { LoggerModule } from '@narval/nestjs-shared' +import { Alg, generateJwk, privateKeyToHex } from '@narval/signature' +import { INestApplication } from '@nestjs/common' +import { EventEmitter2 } from '@nestjs/event-emitter' +import { Test, TestingModule } from '@nestjs/testing' +import { mock } from 'jest-mock-extended' +import { v4 as uuid } from 'uuid' +import { ClientService } from '../../../../../../client/core/service/client.service' +import { MainModule } from '../../../../../../main.module' +import { ProvisionService } from '../../../../../../provision.service' +import { KeyValueRepository } from '../../../../../../shared/module/key-value/core/repository/key-value.repository' +import { InMemoryKeyValueRepository } from '../../../../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' +import { TestPrismaService } from '../../../../../../shared/module/persistence/service/test-prisma.service' +import { getTestRawAesKeyring } from '../../../../../../shared/testing/encryption.testing' +import { testClient } from '../../../../../__test__/util/mock-data' +import { WalletRepository } from '../../../../../persistence/repository/wallet.repository' +import { setupMockServer } from '../../../../../shared/__test__/mock-server' +import { AccountService } from '../../../../service/account.service' +import { AddressService } from '../../../../service/address.service' +import { ConnectionService } from '../../../../service/connection.service' +import { KnownDestinationService } from '../../../../service/known-destination.service' +import { WalletService } from '../../../../service/wallet.service' +import { ActiveConnectionWithCredentials, Provider } from '../../../../type/connection.type' +import { + SyncContext, + SyncOperationType, + isCreateOperation, + isDeleteOperation, + isFailedOperation, + isUpdateOperation +} from '../../../../type/provider.type' +import { buildEmptyContext } from '../../../../util/provider-sync.util' +import { AnchorageSyncService } from '../../../anchorage/anchorage-sync.service' +import { + ANCHORAGE_TEST_API_BASE_URL, + getHandlers, + getTrustedDestinationHandlers, + getVaultHandlers +} from '../server-mock/server' + +const toConnectionAssociation = (connection: ActiveConnectionWithCredentials) => ({ + clientId: connection.clientId, + connectionId: connection.connectionId, + createdAt: connection.createdAt, + label: connection.label, + provider: connection.provider, + revokedAt: connection.revokedAt, + status: connection.status, + updatedAt: connection.updatedAt, + url: connection.url +}) + +describe(AnchorageSyncService.name, () => { + let app: INestApplication + let module: TestingModule + let testPrismaService: TestPrismaService + let anchorageSyncService: AnchorageSyncService + let connectionService: ConnectionService + let connection: ActiveConnectionWithCredentials + let knownDestinationService: KnownDestinationService + let addressService: AddressService + let provisionService: ProvisionService + let clientService: ClientService + let walletService: WalletRepository + let accountService: AccountService + + const mockServer = setupMockServer(getHandlers()) + + const clientId = 'test-client-id' + + const now = new Date() + + beforeAll(async () => { + module = await Test.createTestingModule({ + imports: [MainModule] + }) + .overrideModule(LoggerModule) + .useModule(LoggerModule.forTest()) + .overrideProvider(KeyValueRepository) + .useValue(new InMemoryKeyValueRepository()) + .overrideProvider(EncryptionModuleOptionProvider) + .useValue({ + keyring: getTestRawAesKeyring() + }) + // Mock the event emitter because we don't want to send a + // connection.activated event after the creation. + .overrideProvider(EventEmitter2) + .useValue(mock()) + .compile() + + app = module.createNestApplication() + + testPrismaService = module.get(TestPrismaService) + anchorageSyncService = module.get(AnchorageSyncService) + connectionService = module.get(ConnectionService) + walletService = module.get(WalletService) + accountService = module.get(AccountService) + addressService = module.get(AddressService) + knownDestinationService = module.get(KnownDestinationService) + provisionService = module.get(ProvisionService) + clientService = module.get(ClientService) + + await testPrismaService.truncateAll() + }) + + afterAll(async () => { + await testPrismaService.truncateAll() + await module.close() + await app.close() + }) + + beforeEach(async () => { + await testPrismaService.truncateAll() + + await provisionService.provision() + await clientService.save(testClient) + + connection = await connectionService.create(clientId, { + connectionId: uuid(), + provider: Provider.ANCHORAGE, + url: ANCHORAGE_TEST_API_BASE_URL, + label: 'test active connection', + credentials: { + apiKey: 'test-api-key', + privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) + } + }) + + await app.init() + }) + + describe('sync', () => { + it('returns sync operations for wallets, accounts, addresses and known destinations', async () => { + const sync = await anchorageSyncService.sync(connection) + + expect(sync.wallets.length).toBeGreaterThan(0) + expect(sync.accounts.length).toBeGreaterThan(0) + expect(sync.addresses.length).toBeGreaterThan(0) + expect(sync.knownDestinations.length).toBeGreaterThan(0) + }) + }) + + describe('syncWallets', () => { + it('adds create operations into the context', async () => { + const result = await anchorageSyncService.syncWallets(buildEmptyContext({ connection, now })) + + expect(result.wallets).toEqual([ + { + type: SyncOperationType.CREATE, + create: { + accounts: [], + clientId: connection.clientId, + connections: [toConnectionAssociation(connection)], + createdAt: now, + externalId: '084ff57c0984420efac31723579c94fc', + label: 'Vault 1', + provider: connection.provider, + updatedAt: now, + walletId: expect.any(String) + } + }, + { + type: SyncOperationType.CREATE, + create: { + accounts: [], + clientId: connection.clientId, + connections: [toConnectionAssociation(connection)], + createdAt: now, + externalId: '62547351cea99e827bcd43a513c40e7c', + label: 'Vault 2', + provider: connection.provider, + updatedAt: now, + walletId: expect.any(String) + } + } + ]) + }) + + it('skips duplicate wallets', async () => { + const context = buildEmptyContext({ connection, now }) + + const firstSync = await anchorageSyncService.syncWallets(context) + await walletService.bulkCreate(firstSync.wallets.filter(isCreateOperation).map(({ create }) => create)) + + const secondSync = await anchorageSyncService.syncWallets(context) + + expect(secondSync.wallets).toHaveLength(0) + }) + + it('adds update operations to associate wallet with a new connection', async () => { + const secondConnectionWithCredentials = await connectionService.create(clientId, { + connectionId: 'connection-two-id', + provider: Provider.ANCHORAGE, + url: ANCHORAGE_TEST_API_BASE_URL, + credentials: { + apiKey: 'test-api-key', + privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) + } + }) + + // First sync - should create all wallets + mockServer.use(getVaultHandlers(ANCHORAGE_TEST_API_BASE_URL).findAll) + const firstSync = await anchorageSyncService.syncWallets(buildEmptyContext({ connection, now })) + await walletService.bulkCreate(firstSync.wallets.filter(isCreateOperation).map(({ create }) => create)) + + // Second sync with new connection that only finds one wallet and its + // label is changed. + mockServer.use(getVaultHandlers(ANCHORAGE_TEST_API_BASE_URL).update) + const secondSync = await anchorageSyncService.syncWallets( + buildEmptyContext({ + connection: secondConnectionWithCredentials, + now + }) + ) + + expect(secondSync.wallets.filter(isCreateOperation)).toHaveLength(0) + expect(secondSync.wallets.filter(isUpdateOperation)).toHaveLength(1) + expect(secondSync.wallets.filter(isDeleteOperation)).toHaveLength(0) + expect(secondSync.wallets.filter(isFailedOperation)).toHaveLength(0) + + expect(secondSync.wallets.filter(isUpdateOperation)[0]).toEqual({ + type: SyncOperationType.UPDATE, + update: expect.objectContaining({ + externalId: '084ff57c0984420efac31723579c94fc', + label: 'Vault 1 - renamed', + connections: [toConnectionAssociation(connection), toConnectionAssociation(secondConnectionWithCredentials)] + }) + }) + }) + }) + + describe('syncAccounts', () => { + it('adds create operations into the context', async () => { + const walletOne = { + accounts: [], + clientId: connection.clientId, + connections: [], + createdAt: now, + externalId: '084ff57c0984420efac31723579c94fc', + label: 'Vault 1', + provider: connection.provider, + updatedAt: now, + walletId: '96e7bdc0-d090-42fe-8aaf-f25c2a752e79' + } + const walletTwo = { + accounts: [], + clientId: connection.clientId, + connections: [], + createdAt: now, + externalId: '62547351cea99e827bcd43a513c40e7c', + label: 'Vault 2', + provider: connection.provider, + updatedAt: now, + walletId: 'f22cd7b3-f1af-4312-8c05-25acb7dbb76f' + } + const context = buildEmptyContext({ + connection, + now, + wallets: [ + { type: SyncOperationType.CREATE, create: walletOne }, + { type: SyncOperationType.CREATE, create: walletTwo } + ] + }) + + const result = await anchorageSyncService.syncAccounts(context) + + expect(result.accounts.filter(isCreateOperation)).toHaveLength(18) + expect(result.accounts.filter(isUpdateOperation)).toHaveLength(0) + expect(result.accounts.filter(isDeleteOperation)).toHaveLength(0) + expect(result.accounts.filter(isFailedOperation)).toHaveLength(0) + + expect(result.accounts.filter(isCreateOperation)[0]).toEqual({ + type: SyncOperationType.CREATE, + create: { + accountId: expect.any(String), + walletId: walletOne.walletId, + label: 'secondWalletThroughApi!', + clientId: connection.clientId, + provider: Provider.ANCHORAGE, + addresses: [], + externalId: '145ff5b10e0e208b9c3adab0a9531f0c', + createdAt: now, + updatedAt: now, + networkId: 'BTC' + } + }) + }) + + it('skips duplicate accounts', async () => { + const walletOne = { + accounts: [], + clientId: connection.clientId, + connections: [], + createdAt: now, + externalId: '084ff57c0984420efac31723579c94fc', + label: 'Vault 1', + provider: connection.provider, + updatedAt: now, + walletId: '96e7bdc0-d090-42fe-8aaf-f25c2a752e79' + } + const walletTwo = { + accounts: [], + clientId: connection.clientId, + connections: [], + createdAt: now, + externalId: '62547351cea99e827bcd43a513c40e7c', + label: 'Vault 2', + provider: connection.provider, + updatedAt: now, + walletId: 'f22cd7b3-f1af-4312-8c05-25acb7dbb76f' + } + const context = buildEmptyContext({ + connection, + now, + wallets: [ + { type: SyncOperationType.CREATE, create: walletOne }, + { type: SyncOperationType.CREATE, create: walletTwo } + ] + }) + + const firstSync = await anchorageSyncService.syncAccounts(context) + + await walletService.bulkCreate(firstSync.wallets.filter(isCreateOperation).map(({ create }) => create)) + await accountService.bulkCreate(firstSync.accounts.filter(isCreateOperation).map(({ create }) => create)) + + const secondSync = await anchorageSyncService.syncAccounts(context) + + expect(secondSync.accounts).toHaveLength(0) + }) + + it.todo('adds failed operations into the context when it does not found the parent wallet') + }) + + describe('syncAddresses', () => { + let context: SyncContext + + beforeEach(async () => { + const walletSyncContext = await anchorageSyncService.syncWallets( + buildEmptyContext({ + connection, + now + }) + ) + + context = await anchorageSyncService.syncAccounts(walletSyncContext) + }) + + it('adds create operations into the context', async () => { + const result = await anchorageSyncService.syncAddresses(context) + + expect(result.addresses.filter(isCreateOperation)).toHaveLength(1) + expect(result.addresses.filter(isUpdateOperation)).toHaveLength(0) + expect(result.addresses.filter(isDeleteOperation)).toHaveLength(0) + expect(result.addresses.filter(isFailedOperation)).toHaveLength(0) + + expect(result.addresses.filter(isCreateOperation)[0]).toEqual({ + type: SyncOperationType.CREATE, + create: { + accountId: expect.any(String), + address: '2N18VkRep3F2z7Ggm8W94nkKdARMfEM3EWa', + addressId: expect.any(String), + clientId: connection.clientId, + createdAt: now, + externalId: '96bf95f1b59d50d9d1149057e8c0f9fd', + provider: Provider.ANCHORAGE, + updatedAt: now + } + }) + }) + + it('skips duplicate addresses', async () => { + const walletSyncContext = await anchorageSyncService.syncWallets( + buildEmptyContext({ + connection, + now + }) + ) + const accountSyncContext = await anchorageSyncService.syncAccounts(walletSyncContext) + const firstSync = await anchorageSyncService.syncAddresses(accountSyncContext) + + expect(firstSync.addresses.length).toBeGreaterThan(0) + + await walletService.bulkCreate(firstSync.wallets.filter(isCreateOperation).map(({ create }) => create)) + await accountService.bulkCreate(firstSync.accounts.filter(isCreateOperation).map(({ create }) => create)) + await addressService.bulkCreate(firstSync.addresses.filter(isCreateOperation).map(({ create }) => create)) + + const secondSync = await anchorageSyncService.syncAddresses(context) + + expect(secondSync.addresses).toHaveLength(0) + }) + + it.todo('adds failed operations into the context when it does not found the parent account') + }) + + describe('syncKnownDestinations', () => { + it('adds create operations into the context', async () => { + const result = await anchorageSyncService.syncKnownDestinations( + buildEmptyContext({ + connection, + now + }) + ) + + expect(result.knownDestinations.filter(isCreateOperation)).toHaveLength(4) + expect(result.knownDestinations.filter(isUpdateOperation)).toHaveLength(0) + expect(result.knownDestinations.filter(isDeleteOperation)).toHaveLength(0) + expect(result.knownDestinations.filter(isFailedOperation)).toHaveLength(0) + + expect(result.knownDestinations.filter(isCreateOperation)[0]).toEqual({ + type: SyncOperationType.CREATE, + create: { + address: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e', + assetId: 'ETH', + clientId, + connections: [toConnectionAssociation(connection)], + createdAt: now, + externalId: 'toBeConnected', + knownDestinationId: expect.any(String), + label: undefined, + networkId: 'ETH', + provider: Provider.ANCHORAGE, + updatedAt: now + } + }) + }) + + it('adds update operations when known destination already exist', async () => { + const context = buildEmptyContext({ connection, now }) + + // First sync, create initial destinations + mockServer.use(getTrustedDestinationHandlers(ANCHORAGE_TEST_API_BASE_URL).findAll) + + const firstSync = await anchorageSyncService.syncKnownDestinations(context) + await knownDestinationService.bulkCreate( + firstSync.knownDestinations.filter(isCreateOperation).map(({ create }) => create) + ) + + // Second sync with updated data + mockServer.use(getTrustedDestinationHandlers(ANCHORAGE_TEST_API_BASE_URL).deleteAndUpdate) + const secondSync = await anchorageSyncService.syncKnownDestinations(context) + + expect(secondSync.knownDestinations.filter(isCreateOperation)).toHaveLength(0) + expect(secondSync.knownDestinations.filter(isUpdateOperation)).toHaveLength(1) + expect(secondSync.knownDestinations.filter(isDeleteOperation)).toHaveLength(1) + expect(secondSync.knownDestinations.filter(isFailedOperation)).toHaveLength(0) + + // Only the modified destination should be in updated + expect(secondSync.knownDestinations.filter(isUpdateOperation)[0]).toEqual({ + type: SyncOperationType.UPDATE, + update: { + clientId, + address: '0x8Bc2B8F33e5AeF847B8973Fa669B948A3028D6bd', + assetId: 'USDC', + connections: expect.arrayContaining([toConnectionAssociation(connection)]), + createdAt: now, + externalClassification: null, + externalId: 'toBeUpdated', + knownDestinationId: expect.any(String), + label: 'new memo', + networkId: 'ETH', + provider: Provider.ANCHORAGE, + updatedAt: now + } + }) + }) + + it('adds update operations to associate known destinations with a new connection', async () => { + const secondConnectionWithCredentials = await connectionService.create(clientId, { + connectionId: uuid(), + provider: Provider.ANCHORAGE, + url: ANCHORAGE_TEST_API_BASE_URL, + credentials: { + apiKey: 'test-api-key', + privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) + } + }) + + // First sync - should create all destinations + mockServer.use(getTrustedDestinationHandlers(ANCHORAGE_TEST_API_BASE_URL).findAll) + const firstSync = await anchorageSyncService.syncKnownDestinations( + buildEmptyContext({ + connection, + now + }) + ) + await knownDestinationService.bulkCreate( + firstSync.knownDestinations.filter(isCreateOperation).map(({ create }) => create) + ) + + // Second sync with new connection that only finds one destination + mockServer.use(getTrustedDestinationHandlers(ANCHORAGE_TEST_API_BASE_URL).connect) + + const secondSync = await anchorageSyncService.syncKnownDestinations( + buildEmptyContext({ + connection: secondConnectionWithCredentials, + now + }) + ) + + expect(secondSync.knownDestinations.filter(isCreateOperation)).toHaveLength(0) + expect(secondSync.knownDestinations.filter(isUpdateOperation)).toHaveLength(1) + expect(secondSync.knownDestinations.filter(isDeleteOperation)).toHaveLength(3) + expect(secondSync.knownDestinations.filter(isFailedOperation)).toHaveLength(0) + + expect(secondSync.knownDestinations.filter(isUpdateOperation)[0]).toEqual({ + type: SyncOperationType.UPDATE, + update: { + clientId, + address: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e', + assetId: 'ETH', + connections: [toConnectionAssociation(connection), toConnectionAssociation(secondConnectionWithCredentials)], + createdAt: now, + externalClassification: null, + externalId: 'toBeConnected', + knownDestinationId: expect.any(String), + label: undefined, + networkId: 'ETH', + provider: Provider.ANCHORAGE, + updatedAt: now + } + }) + }) + }) +}) diff --git a/apps/vault/src/broker/core/service/__test__/integration/anchorage-transfer.service.spec.ts b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts similarity index 86% rename from apps/vault/src/broker/core/service/__test__/integration/anchorage-transfer.service.spec.ts rename to apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts index 5bacc4d6f..7651af479 100644 --- a/apps/vault/src/broker/core/service/__test__/integration/anchorage-transfer.service.spec.ts +++ b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts @@ -4,25 +4,31 @@ import { Ed25519PrivateKey, getPublicKey } from '@narval/signature' import { INestApplication } from '@nestjs/common' import { Test, TestingModule } from '@nestjs/testing' import { v4 as uuid } from 'uuid' -import { ClientService } from '../../../../../client/core/service/client.service' -import { MainModule } from '../../../../../main.module' -import { ProvisionService } from '../../../../../provision.service' -import { KeyValueRepository } from '../../../../../shared/module/key-value/core/repository/key-value.repository' -import { InMemoryKeyValueRepository } from '../../../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' -import { TestPrismaService } from '../../../../../shared/module/persistence/service/test-prisma.service' -import { getTestRawAesKeyring } from '../../../../../shared/testing/encryption.testing' -import { testClient } from '../../../../__test__/util/mock-data' -import { AccountRepository } from '../../../../persistence/repository/account.repository' -import { AddressRepository } from '../../../../persistence/repository/address.repository' -import { ConnectionRepository } from '../../../../persistence/repository/connection.repository' -import { KnownDestinationRepository } from '../../../../persistence/repository/known-destination.repository' -import { TransferRepository } from '../../../../persistence/repository/transfer.repository' -import { WalletRepository } from '../../../../persistence/repository/wallet.repository' -import { ActiveConnectionWithCredentials, ConnectionStatus, Provider } from '../../../type/connection.type' -import { Account, Address, KnownDestination, Wallet } from '../../../type/indexed-resources.type' -import { InternalTransfer, NetworkFeeAttribution, TransferPartyType, TransferStatus } from '../../../type/transfer.type' +import { ClientService } from '../../../../../../client/core/service/client.service' +import { MainModule } from '../../../../../../main.module' +import { ProvisionService } from '../../../../../../provision.service' +import { KeyValueRepository } from '../../../../../../shared/module/key-value/core/repository/key-value.repository' +import { InMemoryKeyValueRepository } from '../../../../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' +import { TestPrismaService } from '../../../../../../shared/module/persistence/service/test-prisma.service' +import { getTestRawAesKeyring } from '../../../../../../shared/testing/encryption.testing' +import { testClient } from '../../../../../__test__/util/mock-data' +import { AccountRepository } from '../../../../../persistence/repository/account.repository' +import { AddressRepository } from '../../../../../persistence/repository/address.repository' +import { ConnectionRepository } from '../../../../../persistence/repository/connection.repository' +import { KnownDestinationRepository } from '../../../../../persistence/repository/known-destination.repository' +import { TransferRepository } from '../../../../../persistence/repository/transfer.repository' +import { WalletRepository } from '../../../../../persistence/repository/wallet.repository' +import { setupMockServer, useRequestSpy } from '../../../../../shared/__test__/mock-server' +import { ActiveConnectionWithCredentials, ConnectionStatus, Provider } from '../../../../type/connection.type' +import { Account, Address, KnownDestination, Wallet } from '../../../../type/indexed-resources.type' +import { + InternalTransfer, + NetworkFeeAttribution, + TransferPartyType, + TransferStatus +} from '../../../../type/transfer.type' import { AnchorageTransferService } from '../../anchorage-transfer.service' -import { ANCHORAGE_TEST_API_BASE_URL, setupMockServer, useRequestSpy } from './mocks/anchorage/server' +import { ANCHORAGE_TEST_API_BASE_URL, getHandlers } from '../server-mock/server' describe(AnchorageTransferService.name, () => { let app: INestApplication @@ -39,7 +45,7 @@ describe(AnchorageTransferService.name, () => { let addressRepository: AddressRepository let knownDestinationRepository: KnownDestinationRepository - const server = setupMockServer() + const mockServer = setupMockServer(getHandlers()) const clientId = uuid() @@ -318,7 +324,7 @@ describe(AnchorageTransferService.name, () => { }) it('calls Anchorage', async () => { - const [spy] = useRequestSpy(server) + const [spy] = useRequestSpy(mockServer) const sendTransfer = { ...requiredSendTransfer, memo: 'Integration test transfer', @@ -343,7 +349,7 @@ describe(AnchorageTransferService.name, () => { amount: sendTransfer.amount, customerRefId: sendTransfer.customerRefId, transferMemo: sendTransfer.memo, - idempotenceId: sendTransfer.idempotenceId, + idempotentId: sendTransfer.idempotenceId, // Default `deductFeeFromAmountIfSameType` to false. deductFeeFromAmountIfSameType: false } @@ -352,7 +358,7 @@ describe(AnchorageTransferService.name, () => { }) it('handles provider specific', async () => { - const [spy] = useRequestSpy(server) + const [spy] = useRequestSpy(mockServer) const sendTransfer = { ...requiredSendTransfer, provider: Provider.ANCHORAGE, @@ -372,7 +378,7 @@ describe(AnchorageTransferService.name, () => { }) it('maps networkFeeAttribution on_top to deductFeeFromAmountIfSameType false', async () => { - const [spy] = useRequestSpy(server) + const [spy] = useRequestSpy(mockServer) await anchorageTransferService.send(connection, { ...requiredSendTransfer, @@ -389,7 +395,7 @@ describe(AnchorageTransferService.name, () => { }) it('maps networkFeeAttribution deduct to deductFeeFromAmountIfSameType true', async () => { - const [spy] = useRequestSpy(server) + const [spy] = useRequestSpy(mockServer) await anchorageTransferService.send(connection, { ...requiredSendTransfer, diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-transfer-200.json b/apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/response/get-transfer-200.json similarity index 100% rename from apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-transfer-200.json rename to apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/response/get-transfer-200.json diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200-second.json b/apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/response/get-trusted-destinations-200-second.json similarity index 100% rename from apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200-second.json rename to apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/response/get-trusted-destinations-200-second.json diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200-third.json b/apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/response/get-trusted-destinations-200-third.json similarity index 100% rename from apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200-third.json rename to apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/response/get-trusted-destinations-200-third.json diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200.json b/apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/response/get-trusted-destinations-200.json similarity index 100% rename from apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-trusted-destinations-200.json rename to apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/response/get-trusted-destinations-200.json diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-vaults-200-second.json b/apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/response/get-vaults-200-second.json similarity index 100% rename from apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-vaults-200-second.json rename to apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/response/get-vaults-200-second.json diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-vaults-200.json b/apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/response/get-vaults-200.json similarity index 100% rename from apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-vaults-200.json rename to apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/response/get-vaults-200.json diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-vaults-addresses-200.json b/apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/response/get-vaults-addresses-200.json similarity index 100% rename from apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-vaults-addresses-200.json rename to apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/response/get-vaults-addresses-200.json diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-wallets-200.json b/apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/response/get-wallets-200.json similarity index 100% rename from apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/get-wallets-200.json rename to apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/response/get-wallets-200.json diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/post-transfer-201.json b/apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/response/post-transfer-201.json similarity index 100% rename from apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/post-transfer-201.json rename to apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/response/post-transfer-201.json diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/post-transfer-400.json b/apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/response/post-transfer-400.json similarity index 100% rename from apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/response/post-transfer-400.json rename to apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/response/post-transfer-400.json diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/handlers.ts b/apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/server.ts similarity index 82% rename from apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/handlers.ts rename to apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/server.ts index c48ae796e..faceeb7fa 100644 --- a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/handlers.ts +++ b/apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/server.ts @@ -9,7 +9,9 @@ import getVaultAddressesOk from './response/get-vaults-addresses-200.json' import getWalletsOk from './response/get-wallets-200.json' import postTransferCreated from './response/post-transfer-201.json' -export const trustedDestinationsHandlers = (baseUrl: string) => { +export const ANCHORAGE_TEST_API_BASE_URL = 'https://test-mock-api.anchorage.com' + +export const getTrustedDestinationHandlers = (baseUrl = ANCHORAGE_TEST_API_BASE_URL) => { return { findAll: http.get(`${baseUrl}/v2/trusted_destinations`, () => { return new HttpResponse(JSON.stringify(trustedDestinationsFirst)) @@ -25,7 +27,7 @@ export const trustedDestinationsHandlers = (baseUrl: string) => { } } -export const vaultHandlers = (baseUrl: string) => { +export const getVaultHandlers = (baseUrl = ANCHORAGE_TEST_API_BASE_URL) => { return { findAll: http.get(`${baseUrl}/v2/vaults`, () => { return new HttpResponse(JSON.stringify(getVaultsOk)) @@ -36,7 +38,7 @@ export const vaultHandlers = (baseUrl: string) => { } } -export const getHandlers = (baseUrl: string) => [ +export const getHandlers = (baseUrl = ANCHORAGE_TEST_API_BASE_URL) => [ http.get(`${baseUrl}/v2/vaults/:vaultId/addresses`, () => { return new HttpResponse(JSON.stringify(getVaultAddressesOk)) }), @@ -53,7 +55,7 @@ export const getHandlers = (baseUrl: string) => [ return new HttpResponse(JSON.stringify(postTransferCreated)) }), - vaultHandlers(baseUrl).findAll, + getVaultHandlers(baseUrl).findAll, - trustedDestinationsHandlers(baseUrl).findAll + getTrustedDestinationHandlers(baseUrl).findAll ] diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage-sync.service.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage-sync.service.ts new file mode 100644 index 000000000..bd19aa22a --- /dev/null +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage-sync.service.ts @@ -0,0 +1,445 @@ +import { LoggerService } from '@narval/nestjs-shared' +import { Ed25519PrivateKey } from '@narval/signature' +import { Injectable } from '@nestjs/common' +import { randomUUID } from 'crypto' +import { uniq } from 'lodash' +import { AnchorageClient } from '../../../http/client/anchorage.client' +import { ConnectionInvalidException } from '../../exception/connection-invalid.exception' +import { AccountService } from '../../service/account.service' +import { AddressService } from '../../service/address.service' +import { KnownDestinationService } from '../../service/known-destination.service' +import { WalletService } from '../../service/wallet.service' +import { ActiveConnection, ActiveConnectionWithCredentials, Connection, Provider } from '../../type/connection.type' +import { Address, KnownDestination, Wallet } from '../../type/indexed-resources.type' +import { + ProviderSyncService, + SyncContext, + SyncOperationType, + SyncResult, + isCreateOperation +} from '../../type/provider.type' +import { buildEmptyContext } from '../../util/provider-sync.util' + +@Injectable() +export class AnchorageSyncService implements ProviderSyncService { + constructor( + private readonly anchorageClient: AnchorageClient, + private readonly walletService: WalletService, + private readonly accountService: AccountService, + private readonly addressService: AddressService, + private readonly knownDestinationService: KnownDestinationService, + private readonly logger: LoggerService + ) {} + + async sync(connection: ActiveConnectionWithCredentials): Promise { + const initialContext = buildEmptyContext({ connection, now: new Date() }) + + const syncWalletContext = await this.syncWallets(initialContext) + const syncAccountContext = await this.syncAccounts(syncWalletContext) + const syncAddressContext = await this.syncAddresses(syncAccountContext) + const lastSyncContext = await this.syncKnownDestinations(syncAddressContext) + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { connection: _conn, ...result } = lastSyncContext + + return result + } + + async syncWallets(context: SyncContext): Promise { + const { connection } = context + + this.logger.log('Sync Anchorage wallets', { + connectionId: connection.credentials, + clientId: connection.clientId, + url: connection.url + }) + + this.validateConnection(connection) + + const anchorageVaults = await this.anchorageClient.getVaults({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey + }) + + const { data: existingWallets } = await this.walletService.findAll(connection.clientId, { + filters: { + externalIds: anchorageVaults.map((vault) => vault.vaultId) + } + }) + + const existingWalletByExternalId = new Map(existingWallets.map((wallet) => [wallet.externalId, wallet])) + + const missingAnchorageVaults = anchorageVaults.filter( + (anchorageVault) => !existingWalletByExternalId.has(anchorageVault.vaultId) + ) + + const now = context.now ?? new Date() + + const createOperations = missingAnchorageVaults.map((vault) => { + return { + type: SyncOperationType.CREATE, + create: { + accounts: [], + clientId: connection.clientId, + connections: [ActiveConnection.parse(connection)], + createdAt: now, + externalId: vault.vaultId, + label: vault.name, + provider: Provider.ANCHORAGE, + updatedAt: now, + walletId: randomUUID() + } + } + }) + + const updateOperations = anchorageVaults + .reduce((acc, incoming) => { + const existing = existingWalletByExternalId.get(incoming.vaultId) + if (!existing) return acc + + const hasConnection = existing.connections.some((conn) => conn.connectionId === connection.connectionId) + const hasDataChanges = existing.label !== incoming.name + + if (hasDataChanges || !hasConnection) { + acc.push({ + ...existing, + label: incoming.name, + updatedAt: now, + connections: [...existing.connections, this.toConnectionAssociation(connection)] + }) + } + + return acc + }, []) + .map((update) => ({ type: SyncOperationType.UPDATE, update })) + + return { + ...context, + wallets: [...createOperations, ...updateOperations] + } + } + + private toConnectionAssociation(connection: Connection) { + return { + clientId: connection.clientId, + connectionId: connection.connectionId, + createdAt: connection.createdAt, + label: connection.label, + provider: connection.provider, + revokedAt: connection.revokedAt, + status: connection.status, + updatedAt: connection.updatedAt, + url: connection.url + } + } + + async syncAccounts(context: SyncContext): Promise { + const { connection } = context + + this.logger.log('Sync Anchorage accounts', { + connectionId: connection.credentials, + clientId: connection.clientId, + url: connection.url + }) + + this.validateConnection(connection) + + const anchorageWallets = await this.anchorageClient.getWallets({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey + }) + + const walletExternalIds = uniq(anchorageWallets.map(({ vaultId }) => vaultId)) + + const { data: existingWallets } = await this.walletService.findAll(connection.clientId, { + filters: { + externalIds: walletExternalIds + } + }) + + const { data: existingAccounts } = await this.accountService.findAll(connection.clientId, { + filters: { + externalIds: uniq(anchorageWallets.map((wallet) => wallet.walletId)) + } + }) + + const existingAccountsByExternalId = new Map(existingAccounts.map((account) => [account.externalId, account])) + + const missingAnchorageWallets = anchorageWallets.filter( + (anchorageVault) => !existingAccountsByExternalId.has(anchorageVault.walletId) + ) + + const walletsIndexedByExternalId = existingWallets.reduce( + (idx, wallet) => idx.set(wallet.externalId, wallet), + new Map() + ) + + const contextWalletsIndexedByExternalId = new Map( + context.wallets.filter(isCreateOperation).map(({ create }) => [create.externalId, create]) + ) + + const now = context.now ?? new Date() + + const operations = missingAnchorageWallets.map((anchorageWallet) => { + const externalId = anchorageWallet.walletId + const parentExternalId = anchorageWallet.vaultId + // Either look up the existing wallets in the database or in the sync context. + const wallet = + contextWalletsIndexedByExternalId.get(parentExternalId) || walletsIndexedByExternalId.get(parentExternalId) + + if (wallet) { + return { + type: SyncOperationType.CREATE, + create: { + accountId: randomUUID(), + walletId: wallet.walletId, + label: anchorageWallet.walletName, + clientId: connection.clientId, + provider: Provider.ANCHORAGE, + addresses: [], + externalId, + createdAt: now, + updatedAt: now, + // TODO: Map their networkId to SLIP 44 format. + networkId: anchorageWallet.networkId + } + } + } + + return { + type: SyncOperationType.FAILED, + externalId, + message: 'Parent wallet for account not found', + context: { anchorageWalletId: parentExternalId } + } + }) + + return { + ...context, + accounts: operations + } + } + + async syncAddresses(context: SyncContext): Promise { + const { connection } = context + + this.logger.log('Sync Anchorage addresses', { + connectionId: connection.credentials, + clientId: connection.clientId, + url: connection.url + }) + + this.validateConnection(connection) + + const now = context.now || new Date() + + const signKey = connection.credentials.privateKey + + const anchorageVaults = await this.anchorageClient.getVaults({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey + }) + + const getVaultAddressesRequests = anchorageVaults.flatMap((anchorageVault) => + anchorageVault.assets.map((asset) => ({ + signKey, + apiKey: connection.credentials.apiKey, + assetType: asset.assetType, + url: connection.url, + vaultId: anchorageVault.vaultId + })) + ) + + const anchorageAddresses = ( + await Promise.all(getVaultAddressesRequests.map((request) => this.anchorageClient.getVaultAddresses(request))) + ).flat() + + // Query existing accounts to associate them with their children addresses. + const { data: existingAccounts } = await this.accountService.findAll(connection.clientId, { + filters: { + externalIds: anchorageAddresses.map((anchorageAddress) => anchorageAddress.walletId) + } + }) + + const existingAccountsByExternalId = new Map(existingAccounts.map((account) => [account.externalId, account])) + + const { data: existingAddresses } = await this.addressService.findAll(connection.clientId, { + filters: { + externalIds: anchorageAddresses.map((anchorageAddress) => anchorageAddress.addressId) + } + }) + + const existingAddressesByExternalId = new Map(existingAddresses.map((address) => [address.externalId, address])) + + const contextAccountsIndexedByExternalId = new Map( + context.accounts.filter(isCreateOperation).map(({ create }) => [create.externalId, create]) + ) + + const uniqueAnchorageAddresses = Array.from( + new Map(anchorageAddresses.map((anchorageAddress) => [anchorageAddress.addressId, anchorageAddress])).values() + ) + + const missingAnchorageAddresses = uniqueAnchorageAddresses.filter( + (anchorageAddress) => !existingAddressesByExternalId.has(anchorageAddress.addressId) + ) + + const operations = missingAnchorageAddresses.map((anchorageAddress) => { + const externalId = anchorageAddress.addressId + const parentExternalId = anchorageAddress.walletId + const account = + existingAccountsByExternalId.get(parentExternalId) || contextAccountsIndexedByExternalId.get(parentExternalId) + + if (account) { + return { + type: SyncOperationType.CREATE, + create: { + accountId: account.accountId, + address: anchorageAddress.address, + addressId: randomUUID(), + clientId: connection.clientId, + createdAt: now, + externalId, + provider: Provider.ANCHORAGE, + updatedAt: now + } satisfies Address + } + } + + return { + type: SyncOperationType.FAILED, + externalId, + message: 'Anchorage address parent account not found' + } + }) + + return { + ...context, + addresses: operations + } + } + + async syncKnownDestinations(context: SyncContext): Promise { + const { connection } = context + + this.logger.log('Sync Anchorage known destinations', { + connectionId: connection.credentials, + clientId: connection.clientId, + url: connection.url + }) + + this.validateConnection(connection) + + // Fetch current state from Anchorage + const anchorageTrustedDestinations = await this.anchorageClient.getTrustedDestinations({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey + }) + + const now = context.now || new Date() + + const { data: existingKnownDestinations } = await this.knownDestinationService.findAll(connection.clientId) + + const incomingMap = new Map(anchorageTrustedDestinations.map((dest) => [dest.id, dest])) + const existingMap = new Map(existingKnownDestinations.map((dest) => [dest.externalId, dest])) + + // TODO: Review this before merge. + // 1. the parse on acc.push + // 2. the error handling on `.parse` + const updateOperations = anchorageTrustedDestinations + .reduce((acc, incoming) => { + const existing = existingMap.get(incoming.id) + if (!existing) return acc + + const hasConnection = existing.connections.some((conn) => conn.connectionId === connection.connectionId) + const hasDataChanges = + (existing.label || undefined) !== incoming.crypto.memo || + (existing.assetId || undefined) !== incoming.crypto.assetType + + if (hasDataChanges || !hasConnection) { + acc.push( + KnownDestination.parse({ + ...existing, + label: incoming.crypto.memo, + assetId: incoming.crypto.assetType, + updatedAt: now, + connections: [...existing.connections, connection] + }) + ) + } + + return acc + }, []) + .map((update) => ({ type: SyncOperationType.UPDATE, update })) + + const createOperations = anchorageTrustedDestinations + .filter((anchorageTrustedAddress) => !existingMap.has(anchorageTrustedAddress.id)) + .map((anchorageTrustedAddress) => + KnownDestination.parse({ + knownDestinationId: randomUUID(), + address: anchorageTrustedAddress.crypto.address, + clientId: connection.clientId, + externalId: anchorageTrustedAddress.id, + label: anchorageTrustedAddress.crypto.memo, + assetId: anchorageTrustedAddress.crypto.assetType, + provider: Provider.ANCHORAGE, + networkId: anchorageTrustedAddress.crypto.networkId, + createdAt: now, + updatedAt: now, + connections: [connection] + }) + ) + .map((kd) => ({ type: SyncOperationType.CREATE, create: kd })) + + const deleteOperations = existingKnownDestinations + .filter((dest) => !incomingMap.has(dest.externalId)) + .map((kd) => ({ type: SyncOperationType.DELETE, entityId: kd.knownDestinationId })) + + return { + ...context, + knownDestinations: [...createOperations, ...updateOperations, ...deleteOperations] + } + } + + private validateConnection( + connection: ActiveConnectionWithCredentials + ): asserts connection is ActiveConnectionWithCredentials & { + url: string + credentials: { + apiKey: string + privateKey: Ed25519PrivateKey + } + } { + const context = { + clientId: connection.clientId, + connectionId: connection.connectionId, + provider: connection.provider, + status: connection.status, + url: connection.url + } + + if (connection.provider !== Provider.ANCHORAGE) { + throw new ConnectionInvalidException({ + message: 'Invalid connection provider for Anchorage', + context + }) + } + + if (!connection.url) { + throw new ConnectionInvalidException({ + message: 'Cannot sync without a connection URL', + context + }) + } + + if (!connection.credentials?.apiKey && !connection.credentials?.privateKey) { + throw new ConnectionInvalidException({ + message: 'Cannot sync without API key and/or signing key', + context + }) + } + } +} diff --git a/apps/vault/src/broker/core/service/anchorage-transfer.service.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts similarity index 91% rename from apps/vault/src/broker/core/service/anchorage-transfer.service.ts rename to apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts index c72066d46..e3e33a1f2 100644 --- a/apps/vault/src/broker/core/service/anchorage-transfer.service.ts +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts @@ -1,10 +1,12 @@ import { LoggerService } from '@narval/nestjs-shared' import { HttpStatus, Injectable } from '@nestjs/common' import { v4 as uuid } from 'uuid' -import { AnchorageClient } from '../../http/client/anchorage.client' -import { TransferRepository } from '../../persistence/repository/transfer.repository' -import { BrokerException } from '../exception/broker.exception' -import { ActiveConnectionWithCredentials, Provider } from '../type/connection.type' +import { AnchorageClient } from '../../../http/client/anchorage.client' +import { TransferRepository } from '../../../persistence/repository/transfer.repository' +import { BrokerException } from '../../exception/broker.exception' +import { TransferPartyService } from '../../service/transfer-party.service' +import { ActiveConnectionWithCredentials, Provider } from '../../type/connection.type' +import { ProviderTransferService } from '../../type/provider.type' import { Destination, InternalTransfer, @@ -16,11 +18,10 @@ import { TransferStatus, isAddressDestination, isProviderSpecific -} from '../type/transfer.type' -import { TransferPartyService } from './transfer-party.service' +} from '../../type/transfer.type' @Injectable() -export class AnchorageTransferService { +export class AnchorageTransferService implements ProviderTransferService { constructor( private readonly anchorageClient: AnchorageClient, private readonly transferPartyService: TransferPartyService, @@ -128,7 +129,7 @@ export class AnchorageTransferService { amount: sendTransfer.amount, customerRefId: sendTransfer.customerRefId || null, transferMemo: sendTransfer.memo || null, - idempotenceId: sendTransfer.idempotenceId || null, + idempotentId: sendTransfer.idempotenceId || null, deductFeeFromAmountIfSameType: this.getDeductFeeFromAmountIfSameType(networkFeeAttribution), ...(isProviderSpecific(sendTransfer.providerSpecific) ? { ...sendTransfer.providerSpecific } : {}) } diff --git a/apps/vault/src/broker/core/service/__test__/integration/anchorage-sync.service.spec.ts b/apps/vault/src/broker/core/service/__test__/integration/anchorage-sync.service.spec.ts deleted file mode 100644 index ddf8cf774..000000000 --- a/apps/vault/src/broker/core/service/__test__/integration/anchorage-sync.service.spec.ts +++ /dev/null @@ -1,303 +0,0 @@ -import { EncryptionModuleOptionProvider } from '@narval/encryption-module' -import { LoggerModule } from '@narval/nestjs-shared' -import { Alg, generateJwk, privateKeyToHex } from '@narval/signature' -import { INestApplication } from '@nestjs/common' -import { EventEmitter2 } from '@nestjs/event-emitter' -import { Test, TestingModule } from '@nestjs/testing' -import { mock } from 'jest-mock-extended' -import { v4 as uuid } from 'uuid' -import { ClientService } from '../../../../../client/core/service/client.service' -import { MainModule } from '../../../../../main.module' -import { ProvisionService } from '../../../../../provision.service' -import { KeyValueRepository } from '../../../../../shared/module/key-value/core/repository/key-value.repository' -import { InMemoryKeyValueRepository } from '../../../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' -import { TestPrismaService } from '../../../../../shared/module/persistence/service/test-prisma.service' -import { getTestRawAesKeyring } from '../../../../../shared/testing/encryption.testing' -import { testClient } from '../../../../__test__/util/mock-data' -import { WalletRepository } from '../../../../persistence/repository/wallet.repository' -import { ActiveConnectionWithCredentials, Provider } from '../../../type/connection.type' -import { Account } from '../../../type/indexed-resources.type' -import { AccountService } from '../../account.service' -import { AddressService } from '../../address.service' -import { AnchorageSyncService } from '../../anchorage-sync.service' -import { ConnectionService } from '../../connection.service' -import { KnownDestinationService } from '../../known-destination.service' -import { WalletService } from '../../wallet.service' -import { trustedDestinationsHandlers, vaultHandlers } from './mocks/anchorage/handlers' -import { ANCHORAGE_TEST_API_BASE_URL, setupMockServer } from './mocks/anchorage/server' - -describe(AnchorageSyncService.name, () => { - let app: INestApplication - let module: TestingModule - let testPrismaService: TestPrismaService - let anchorageSyncService: AnchorageSyncService - let connectionService: ConnectionService - let connection: ActiveConnectionWithCredentials - let walletService: WalletRepository - let accountService: AccountService - let addressService: AddressService - let knownDestinationService: KnownDestinationService - let provisionService: ProvisionService - let clientService: ClientService - - const server = setupMockServer() - - const clientId = 'test-client-id' - - beforeAll(async () => { - module = await Test.createTestingModule({ - imports: [MainModule] - }) - .overrideModule(LoggerModule) - .useModule(LoggerModule.forTest()) - .overrideProvider(KeyValueRepository) - .useValue(new InMemoryKeyValueRepository()) - .overrideProvider(EncryptionModuleOptionProvider) - .useValue({ - keyring: getTestRawAesKeyring() - }) - // Mock the event emitter because we don't want to send a - // connection.activated event after the creation. - .overrideProvider(EventEmitter2) - .useValue(mock()) - .compile() - - app = module.createNestApplication() - - testPrismaService = module.get(TestPrismaService) - anchorageSyncService = module.get(AnchorageSyncService) - connectionService = module.get(ConnectionService) - walletService = module.get(WalletService) - accountService = module.get(AccountService) - addressService = module.get(AddressService) - knownDestinationService = module.get(KnownDestinationService) - provisionService = module.get(ProvisionService) - clientService = module.get(ClientService) - - await testPrismaService.truncateAll() - }) - - afterAll(async () => { - await testPrismaService.truncateAll() - await module.close() - await app.close() - }) - - beforeEach(async () => { - await testPrismaService.truncateAll() - - await provisionService.provision() - await clientService.save(testClient) - - connection = await connectionService.create(clientId, { - connectionId: uuid(), - provider: Provider.ANCHORAGE, - url: ANCHORAGE_TEST_API_BASE_URL, - credentials: { - apiKey: 'test-api-key', - privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) - } - }) - - await app.init() - }) - - describe('syncWallets', () => { - it('fetches anchorage vaults and persist them as wallets', async () => { - const { created } = await anchorageSyncService.syncWallets(connection) - - const { data: wallets } = await walletService.findAll(connection.clientId) - expect(created).toEqual(expect.arrayContaining(wallets)) - }) - - it('does not duplicate wallets', async () => { - const [first, second] = await Promise.all([ - await anchorageSyncService.syncWallets(connection), - await anchorageSyncService.syncWallets(connection) - ]) - - expect(first.created.length).toEqual(2) - expect(second.created.length).toEqual(0) - }) - - it('connects wallet with the new connection', async () => { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { credentials: firstCredentials, ...firstConnection } = connection - const secondConnectionWithCredentials = await connectionService.create(clientId, { - connectionId: uuid(), - provider: Provider.ANCHORAGE, - url: ANCHORAGE_TEST_API_BASE_URL, - credentials: { - apiKey: 'test-api-key', - privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) - } - }) - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { credentials: secondCredentials, ...secondConnection } = secondConnectionWithCredentials - - // First sync - should create all wallets - server.use(vaultHandlers(ANCHORAGE_TEST_API_BASE_URL).findAll) - await anchorageSyncService.syncWallets(connection) - - // Second sync with new connection that only finds one wallet and its label is changed - server.use(vaultHandlers(ANCHORAGE_TEST_API_BASE_URL).update) - const { updated } = await anchorageSyncService.syncWallets(secondConnectionWithCredentials) - - expect(updated).toHaveLength(1) - expect(updated[0]).toMatchObject({ - externalId: '084ff57c0984420efac31723579c94fc', - label: 'Vault 1 - renamed', - connections: [firstConnection, secondConnection] - }) - - // Verify other destinations weren't affected - const { data: allDestinations } = await walletService.findAll(connection.clientId) - const unchangedDestinations = allDestinations.filter((d) => d.externalId !== '084ff57c0984420efac31723579c94fc') - unchangedDestinations.forEach((dest) => { - expect(dest.connections).toEqual([firstConnection]) - }) - }) - }) - - describe('syncAccounts', () => { - const sortByExternalId = (a: Account, b: Account) => a.externalId.localeCompare(b.externalId) - - it('fetches anchorage wallets and persist them as accounts', async () => { - await anchorageSyncService.syncWallets(connection) - - const syncedAccounts = await anchorageSyncService.syncAccounts(connection) - - const { data: accounts } = await accountService.findAll(connection.clientId) - - expect(syncedAccounts.sort(sortByExternalId)).toEqual(accounts.sort(sortByExternalId)) - }) - - it('does not duplicate accounts', async () => { - await anchorageSyncService.syncWallets(connection) - - const [first, second] = await Promise.all([ - await anchorageSyncService.syncAccounts(connection), - await anchorageSyncService.syncAccounts(connection) - ]) - - expect(first.length).toEqual(18) - expect(second.length).toEqual(0) - }) - }) - - describe('syncAddresses', () => { - beforeEach(async () => { - await anchorageSyncService.syncWallets(connection) - await anchorageSyncService.syncAccounts(connection) - }) - - it('fetches anchorage addresses and persist them as addresses', async () => { - const syncedAddresses = await anchorageSyncService.syncAddresses(connection) - - const { data: addresses } = await addressService.findAll(connection.clientId) - - expect(syncedAddresses).toEqual( - addresses.map((address) => ({ - ...address, - addressId: expect.any(String) - })) - ) - }) - - it('does not duplicate addresses', async () => { - const [first, second] = await Promise.all([ - await anchorageSyncService.syncAddresses(connection), - await anchorageSyncService.syncAddresses(connection) - ]) - - expect(first.length).toEqual(1) - expect(second.length).toEqual(0) - }) - }) - - describe('syncKnownDestinations', () => { - it('fetches anchorage addresses and persist them as knownDestinations', async () => { - const { created } = await anchorageSyncService.syncKnownDestinations(connection) - const { data: knownDestinations } = await knownDestinationService.findAll(connection.clientId) - - expect(created).toEqual(expect.arrayContaining(knownDestinations)) - }) - - it('updates anchorage knownDestination when it already exists', async () => { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { credentials, ...expectedConnection } = connection - - // First sync - create initial destinations - server.use(trustedDestinationsHandlers(ANCHORAGE_TEST_API_BASE_URL).findAll) - await anchorageSyncService.syncKnownDestinations(connection) - - const { data: initialDestinations } = await knownDestinationService.findAll(connection.clientId) - // Second sync with updated data - server.use(trustedDestinationsHandlers(ANCHORAGE_TEST_API_BASE_URL).deleteAndUpdate) - const { created, updated, deleted } = await anchorageSyncService.syncKnownDestinations(connection) - - // Verify basic operations - expect(created).toEqual([]) - expect(deleted).toEqual(1) - - // Only the modified destination should be in updated - expect(updated).toHaveLength(1) - expect(updated[0]).toMatchObject({ - externalId: 'toBeUpdated', - address: '0x8Bc2B8F33e5AeF847B8973Fa669B948A3028D6bd', - label: 'new memo', - assetId: 'USDC', - networkId: 'ETH', - connections: expect.arrayContaining([expectedConnection]) - }) - - // Verify the update timestamp is newer - expect(updated[0].updatedAt.getTime()).toBeGreaterThan(updated[0].createdAt.getTime()) - - // Verify other destinations weren't affected - const { data: allDestinations } = await knownDestinationService.findAll(connection.clientId) - const unchangedDestination = allDestinations.find((d) => d.externalId === 'neverChanges') - const initialUnchangedDestination = initialDestinations.find((d) => d.externalId === 'neverChanges') - expect(unchangedDestination).toEqual(initialUnchangedDestination) - }) - - it('connects known-destination with the new connection', async () => { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { credentials, ...firstConnection } = connection - const secondConnectionWithCredentials = await connectionService.create(clientId, { - connectionId: uuid(), - provider: Provider.ANCHORAGE, - url: ANCHORAGE_TEST_API_BASE_URL, - credentials: { - apiKey: 'test-api-key', - privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) - } - }) - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { credentials: secondCredentials, ...secondConnection } = secondConnectionWithCredentials - - // First sync - should create all destinations - server.use(trustedDestinationsHandlers(ANCHORAGE_TEST_API_BASE_URL).findAll) - await anchorageSyncService.syncKnownDestinations(connection) - - // Second sync with new connection that only finds one destination - server.use(trustedDestinationsHandlers(ANCHORAGE_TEST_API_BASE_URL).connect) - const { updated } = await anchorageSyncService.syncKnownDestinations(secondConnectionWithCredentials) - - // We expect only one item to be updated - the one with connections to both accounts - expect(updated).toHaveLength(1) - expect(updated[0]).toMatchObject({ - externalId: 'toBeConnected', - connections: [firstConnection, secondConnection] - }) - - // Verify other destinations weren't affected - const { data: allDestinations } = await knownDestinationService.findAll(connection.clientId) - const unchangedDestinations = allDestinations.filter((d) => d.externalId !== 'toBeConnected') - unchangedDestinations.forEach((dest) => { - expect(dest.connections).toEqual([firstConnection]) - }) - }) - }) -}) diff --git a/apps/vault/src/broker/core/service/__test__/integration/sync.service.spec.ts b/apps/vault/src/broker/core/service/__test__/integration/sync.service.spec.ts new file mode 100644 index 000000000..588daa035 --- /dev/null +++ b/apps/vault/src/broker/core/service/__test__/integration/sync.service.spec.ts @@ -0,0 +1,449 @@ +import { EncryptionModuleOptionProvider } from '@narval/encryption-module' +import { LoggerModule } from '@narval/nestjs-shared' +import { Alg, generateJwk, privateKeyToHex } from '@narval/signature' +import { INestApplication } from '@nestjs/common' +import { EventEmitter2 } from '@nestjs/event-emitter' +import { Test, TestingModule } from '@nestjs/testing' +import { randomUUID } from 'crypto' +import { mock } from 'jest-mock-extended' +import { v4 as uuid } from 'uuid' +import { ClientService } from '../../../../../client/core/service/client.service' +import { MainModule } from '../../../../../main.module' +import { ProvisionService } from '../../../../../provision.service' +import { KeyValueRepository } from '../../../../../shared/module/key-value/core/repository/key-value.repository' +import { InMemoryKeyValueRepository } from '../../../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' +import { TestPrismaService } from '../../../../../shared/module/persistence/service/test-prisma.service' +import { getTestRawAesKeyring } from '../../../../../shared/testing/encryption.testing' +import { testClient } from '../../../../__test__/util/mock-data' +import { SyncRepository } from '../../../../persistence/repository/sync.repository' +import { WalletRepository } from '../../../../persistence/repository/wallet.repository' +import { ANCHORAGE_TEST_API_BASE_URL } from '../../../provider/anchorage/__test__/server-mock/server' +import { ActiveConnectionWithCredentials, Provider } from '../../../type/connection.type' +import { Account, Address, KnownDestination, Wallet } from '../../../type/indexed-resources.type' +import { SyncOperationType, SyncResult } from '../../../type/provider.type' +import { Sync, SyncStatus } from '../../../type/sync.type' +import { AccountService } from '../../account.service' +import { AddressService } from '../../address.service' +import { ConnectionService } from '../../connection.service' +import { KnownDestinationService } from '../../known-destination.service' +import { SyncService } from '../../sync.service' +import { WalletService } from '../../wallet.service' + +const toConnectionAssociation = (connection: ActiveConnectionWithCredentials) => ({ + clientId: connection.clientId, + connectionId: connection.connectionId, + createdAt: connection.createdAt, + label: undefined, + provider: connection.provider, + revokedAt: undefined, + status: connection.status, + updatedAt: connection.updatedAt, + url: connection.url +}) + +describe(SyncService.name, () => { + let app: INestApplication + let module: TestingModule + let testPrismaService: TestPrismaService + + let accountService: AccountService + let addressService: AddressService + let clientService: ClientService + let connection: ActiveConnectionWithCredentials + let connectionService: ConnectionService + let knownDestinationService: KnownDestinationService + let provisionService: ProvisionService + let syncRepository: SyncRepository + let syncService: SyncService + let walletService: WalletRepository + + const clientId = 'test-client-id' + + beforeAll(async () => { + module = await Test.createTestingModule({ + imports: [MainModule] + }) + .overrideModule(LoggerModule) + .useModule(LoggerModule.forTest()) + .overrideProvider(KeyValueRepository) + .useValue(new InMemoryKeyValueRepository()) + .overrideProvider(EncryptionModuleOptionProvider) + .useValue({ + keyring: getTestRawAesKeyring() + }) + .overrideProvider(EventEmitter2) + .useValue(mock()) + .compile() + + app = module.createNestApplication() + + accountService = module.get(AccountService) + addressService = module.get(AddressService) + clientService = module.get(ClientService) + connectionService = module.get(ConnectionService) + knownDestinationService = module.get(KnownDestinationService) + provisionService = module.get(ProvisionService) + syncRepository = module.get(SyncRepository) + syncService = module.get(SyncService) + testPrismaService = module.get(TestPrismaService) + walletService = module.get(WalletService) + + await testPrismaService.truncateAll() + }) + + afterAll(async () => { + await testPrismaService.truncateAll() + await module.close() + await app.close() + }) + + beforeEach(async () => { + await testPrismaService.truncateAll() + + await provisionService.provision() + await clientService.save(testClient) + + connection = await connectionService.create(clientId, { + connectionId: uuid(), + provider: Provider.ANCHORAGE, + url: ANCHORAGE_TEST_API_BASE_URL, + credentials: { + apiKey: 'test-api-key', + privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) + } + }) + + await app.init() + }) + + describe('execute', () => { + let sync: Sync + let walletOne: Wallet + let walletTwo: Wallet + let accountOne: Account + let accountTwo: Account + let addressOne: Address + let addressTwo: Address + let kdOne: KnownDestination + let kdTwo: KnownDestination + + const now = new Date() + + beforeEach(async () => { + sync = await syncRepository.create({ + clientId, + syncId: randomUUID(), + connectionId: connection.connectionId, + createdAt: now, + status: SyncStatus.PROCESSING + }) + + walletOne = { + accounts: [], + clientId: connection.clientId, + connections: [toConnectionAssociation(connection)], + createdAt: new Date('2023-01-01T00:00:00Z'), + externalId: 'external-id-one', + label: 'wallet one', + provider: connection.provider, + updatedAt: now, + walletId: randomUUID() + } + walletTwo = { + accounts: [], + clientId: connection.clientId, + connections: [toConnectionAssociation(connection)], + createdAt: new Date('2024-01-01T00:00:00Z'), + externalId: 'external-id-two', + label: 'wallet two', + provider: connection.provider, + updatedAt: now, + walletId: randomUUID() + } + + accountOne = { + accountId: randomUUID(), + addresses: [], + clientId: connection.clientId, + createdAt: new Date('2023-01-01T00:00:00Z'), + externalId: 'account-external-id-one', + label: 'accoutn one', + networkId: 'BTC', + provider: Provider.ANCHORAGE, + updatedAt: now, + walletId: walletOne.walletId + } + accountTwo = { + accountId: randomUUID(), + addresses: [], + clientId: connection.clientId, + createdAt: new Date('2024-01-01T00:00:00Z'), + externalId: 'account-external-id-two', + label: 'accoutn two', + networkId: 'BTC', + provider: Provider.ANCHORAGE, + updatedAt: now, + walletId: walletOne.walletId + } + + addressOne = { + accountId: accountOne.accountId, + address: 'address-one', + addressId: randomUUID(), + clientId: connection.clientId, + createdAt: new Date('2023-01-01T00:00:00Z'), + externalId: 'address-one-external-id', + provider: Provider.ANCHORAGE, + updatedAt: now + } + addressTwo = { + accountId: accountOne.accountId, + address: 'address-two', + addressId: randomUUID(), + clientId: connection.clientId, + createdAt: new Date('2024-01-01T00:00:00Z'), + externalId: 'address-two-external-id', + provider: Provider.ANCHORAGE, + updatedAt: now + } + + kdOne = { + address: 'known-destination-one-address', + assetId: 'USDC', + clientId, + connections: [toConnectionAssociation(connection)], + createdAt: new Date('2023-01-01T00:00:00Z'), + externalClassification: null, + externalId: 'known-destination-one-external-id', + knownDestinationId: randomUUID(), + label: 'known destination one', + networkId: 'ETH', + provider: Provider.ANCHORAGE, + updatedAt: now + } + kdTwo = { + address: 'known-destination-two-address', + assetId: 'USDC', + clientId, + connections: [toConnectionAssociation(connection)], + createdAt: new Date('2024-01-01T00:00:00Z'), + externalClassification: null, + externalId: 'known-destination-two-external-id', + knownDestinationId: randomUUID(), + label: 'known destination two', + networkId: 'ETH', + provider: Provider.ANCHORAGE, + updatedAt: now + } + }) + + it('creates wallets', async () => { + const operations: SyncResult = { + wallets: [ + { type: SyncOperationType.CREATE, create: walletOne }, + { type: SyncOperationType.CREATE, create: walletTwo } + ], + accounts: [], + addresses: [], + knownDestinations: [] + } + + await syncService.execute(sync, operations) + + const { data: wallets } = await walletService.findAll(clientId) + + expect(wallets).toEqual([walletTwo, walletOne]) + }) + + it('updates wallets', async () => { + await walletService.bulkCreate([walletOne, walletTwo]) + + const operations: SyncResult = { + wallets: [ + { + type: SyncOperationType.UPDATE, + update: { + ...walletTwo, + label: 'updated wallet label' + } + } + ], + accounts: [], + addresses: [], + knownDestinations: [] + } + + await syncService.execute(sync, operations) + + const updatedWallet = await walletService.findById(clientId, walletTwo.walletId) + + expect(updatedWallet.label).toEqual('updated wallet label') + }) + + it.todo('deletes wallets') + + it('creates accounts', async () => { + const operations: SyncResult = { + wallets: [{ type: SyncOperationType.CREATE, create: walletOne }], + accounts: [ + { type: SyncOperationType.CREATE, create: accountOne }, + { type: SyncOperationType.CREATE, create: accountTwo } + ], + addresses: [], + knownDestinations: [] + } + + await syncService.execute(sync, operations) + + const { data: accounts } = await accountService.findAll(clientId) + + expect(accounts).toEqual([accountTwo, accountOne]) + }) + + it('update accounts', async () => { + await walletService.bulkCreate([walletOne]) + await accountService.bulkCreate([accountOne, accountTwo]) + + const operations: SyncResult = { + wallets: [], + accounts: [ + { + type: SyncOperationType.UPDATE, + update: { + ...accountOne, + label: 'updated account label' + } + } + ], + addresses: [], + knownDestinations: [] + } + + await syncService.execute(sync, operations) + + const updatedAccount = await accountService.findById(clientId, accountOne.accountId) + + expect(updatedAccount.label).toEqual('updated account label') + }) + + it.todo('deletes accounts') + + it('creates addresses', async () => { + const operations: SyncResult = { + wallets: [{ type: SyncOperationType.CREATE, create: walletOne }], + accounts: [{ type: SyncOperationType.CREATE, create: accountOne }], + addresses: [ + { type: SyncOperationType.CREATE, create: addressOne }, + { type: SyncOperationType.CREATE, create: addressTwo } + ], + knownDestinations: [] + } + + await syncService.execute(sync, operations) + + const { data: addresses } = await addressService.findAll(clientId) + + expect(addresses).toEqual([addressTwo, addressOne]) + }) + + it.todo('deletes addresses') + + it('creates known destinations', async () => { + const operations: SyncResult = { + wallets: [], + accounts: [], + addresses: [], + knownDestinations: [ + { type: SyncOperationType.CREATE, create: kdOne }, + { type: SyncOperationType.CREATE, create: kdTwo } + ] + } + + await syncService.execute(sync, operations) + + const { data: knownDestinations } = await knownDestinationService.findAll(clientId) + + expect(knownDestinations).toEqual([kdTwo, kdOne]) + }) + + it('updates known destinations', async () => { + await knownDestinationService.bulkCreate([kdOne, kdTwo]) + + const operations: SyncResult = { + wallets: [], + accounts: [], + addresses: [], + knownDestinations: [ + { + type: SyncOperationType.UPDATE, + update: { + ...kdTwo, + label: 'updated kown destination label' + } + } + ] + } + + await syncService.execute(sync, operations) + + const updatedKd = await knownDestinationService.findById(clientId, kdTwo.knownDestinationId) + + expect(updatedKd.label).toEqual('updated kown destination label') + }) + + it('deletes known destinations', async () => { + await knownDestinationService.bulkCreate([kdOne, kdTwo]) + + const operations: SyncResult = { + wallets: [], + accounts: [], + addresses: [], + knownDestinations: [ + { type: SyncOperationType.DELETE, entityId: kdOne.knownDestinationId }, + { type: SyncOperationType.DELETE, entityId: kdTwo.knownDestinationId } + ] + } + + await syncService.execute(sync, operations) + + const { data: knownDestinations } = await knownDestinationService.findAll(clientId) + + expect(knownDestinations).toEqual([]) + }) + + it('completes sync on success', async () => { + const operations: SyncResult = { + wallets: [], + accounts: [], + addresses: [], + knownDestinations: [] + } + const successfulSync = await syncService.execute(sync, operations) + + expect(successfulSync).toMatchObject({ + completedAt: expect.any(Date), + status: SyncStatus.SUCCESS + }) + }) + + it('fails sync on error', async () => { + const operations: SyncResult = { + wallets: [{ type: SyncOperationType.CREATE, create: {} as unknown as Wallet }], + accounts: [], + addresses: [], + knownDestinations: [] + } + const failedSync = await syncService.execute(sync, operations) + + expect(failedSync).toMatchObject({ + completedAt: expect.any(Date), + status: SyncStatus.FAILED, + error: { + name: expect.any(String), + message: expect.any(String), + traceId: undefined + } + }) + }) + }) +}) diff --git a/apps/vault/src/broker/core/service/account.service.ts b/apps/vault/src/broker/core/service/account.service.ts index babc99c0d..749a0afc6 100644 --- a/apps/vault/src/broker/core/service/account.service.ts +++ b/apps/vault/src/broker/core/service/account.service.ts @@ -1,20 +1,12 @@ import { PaginatedResult, PaginationOptions } from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' -import { AccountRepository, FindAllOptions } from '../../persistence/repository/account.repository' +import { AccountRepository, FindAllOptions, UpdateAccount } from '../../persistence/repository/account.repository' import { Account, Address } from '../type/indexed-resources.type' @Injectable() export class AccountService { constructor(private readonly accountRepository: AccountRepository) {} - async getAccounts(clientId: string, options: PaginationOptions): Promise> { - return this.accountRepository.findByClientId(clientId, options) - } - - async getAccount(clientId: string, AccountId: string): Promise { - return this.accountRepository.findById(clientId, AccountId) - } - async getAccountAddresses( clientId: string, AccountId: string, @@ -31,7 +23,19 @@ export class AccountService { return this.accountRepository.bulkCreate(accounts) } + async bulkUpdate(updateAccounts: UpdateAccount[]): Promise { + return this.accountRepository.bulkUpdate(updateAccounts) + } + + async update(updateAccount: UpdateAccount): Promise { + return this.accountRepository.update(updateAccount) + } + async findAll(clientId: string, options?: FindAllOptions): Promise> { return this.accountRepository.findAll(clientId, options) } + + async findById(clientId: string, accountId: string): Promise { + return this.accountRepository.findById(clientId, accountId) + } } diff --git a/apps/vault/src/broker/core/service/anchorage-sync.service.ts b/apps/vault/src/broker/core/service/anchorage-sync.service.ts deleted file mode 100644 index 4bf9e1d3b..000000000 --- a/apps/vault/src/broker/core/service/anchorage-sync.service.ts +++ /dev/null @@ -1,427 +0,0 @@ -import { LoggerService } from '@narval/nestjs-shared' -import { Ed25519PrivateKey } from '@narval/signature' -import { HttpStatus, Injectable } from '@nestjs/common' -import { uniq } from 'lodash' -import { v4 as uuid } from 'uuid' -import { AnchorageClient } from '../../http/client/anchorage.client' -import { ConnectionInvalidException } from '../exception/connection-invalid.exception' -import { SyncException } from '../exception/sync.exception' -import { ActiveConnection, ActiveConnectionWithCredentials, Provider } from '../type/connection.type' -import { Account, Address, KnownDestination, Wallet } from '../type/indexed-resources.type' -import { AccountService } from './account.service' -import { AddressService } from './address.service' -import { KnownDestinationService } from './known-destination.service' -import { WalletService } from './wallet.service' - -@Injectable() -export class AnchorageSyncService { - constructor( - private readonly anchorageClient: AnchorageClient, - private readonly walletService: WalletService, - private readonly accountService: AccountService, - private readonly addressService: AddressService, - private readonly knownDestinationService: KnownDestinationService, - private readonly logger: LoggerService - ) {} - - async sync(connection: ActiveConnectionWithCredentials): Promise { - await this.syncWallets(connection) - await this.syncAccounts(connection) - await this.syncAddresses(connection) - await this.syncKnownDestinations(connection) - } - - async syncWallets(connection: ActiveConnectionWithCredentials) { - this.logger.log('Sync Anchorage wallets', { - connectionId: connection.credentials, - clientId: connection.clientId, - url: connection.url - }) - - this.validateConnection(connection) - - const anchorageVaults = await this.anchorageClient.getVaults({ - url: connection.url, - apiKey: connection.credentials.apiKey, - signKey: connection.credentials.privateKey - }) - - const { data: existingWallets } = await this.walletService.findAll(connection.clientId, { - filters: { - externalIds: anchorageVaults.map((vault) => vault.vaultId) - } - }) - - const now = new Date() - - const existingMap = new Map(existingWallets.map((wallet) => [wallet.externalId, wallet])) - - const toBeUpdated = anchorageVaults.reduce((acc, incoming) => { - const existing = existingMap.get(incoming.vaultId) - if (!existing) return acc - - const hasConnection = existing.connections.some((conn) => conn.connectionId === connection.connectionId) - const hasDataChanges = existing.label !== incoming.name - - if (hasDataChanges || !hasConnection) { - acc.push({ - ...existing, - label: incoming.name, - updatedAt: now, - connections: [...existing.connections, connection] - }) - } - - return acc - }, []) - - const toBeCreated: Wallet[] = anchorageVaults - .filter((vault) => !existingMap.has(vault.vaultId)) - .map((vault) => ({ - accounts: [], - clientId: connection.clientId, - connections: [ActiveConnection.parse(connection)], - createdAt: now, - externalId: vault.vaultId, - label: vault.name, - provider: Provider.ANCHORAGE, - updatedAt: now, - walletId: uuid() - })) - - try { - const created = await this.walletService.bulkCreate(toBeCreated) - const updated = await this.walletService.bulkUpdate(toBeUpdated) - - return { - created, - updated - } - } catch (error) { - throw new SyncException({ - message: 'Failed to persist wallets', - suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, - origin: error - }) - } - } - - async syncAccounts(connection: ActiveConnectionWithCredentials) { - this.logger.log('Sync Anchorage accounts', { - connectionId: connection.credentials, - clientId: connection.clientId, - url: connection.url - }) - - this.validateConnection(connection) - - const now = new Date() - - const anchorageWallets = await this.anchorageClient.getWallets({ - url: connection.url, - apiKey: connection.credentials.apiKey, - signKey: connection.credentials.privateKey - }) - - const walletExternalIds = uniq(anchorageWallets.map(({ vaultId }) => vaultId)) - - const { data: existingWallets } = await this.walletService.findAll(connection.clientId, { - filters: { - externalIds: walletExternalIds - } - }) - - const { data: existingAccounts } = await this.accountService.findAll(connection.clientId, { - filters: { - externalIds: uniq(anchorageWallets.map((wallet) => wallet.walletId)) - } - }) - - const existingAccountsByExternalId = new Map(existingAccounts.map((account) => [account.externalId, account])) - - const missingAnchorageWallets = anchorageWallets.filter( - (anchorageVault) => !existingAccountsByExternalId.has(anchorageVault.walletId) - ) - - const walletsIndexedByExternalId = existingWallets.reduce( - (idx, wallet) => idx.set(wallet.externalId, wallet), - new Map() - ) - - const accounts: Account[] = missingAnchorageWallets.map((anchorageWallet) => { - const wallet = walletsIndexedByExternalId.get(anchorageWallet.vaultId) - - if (!wallet) { - throw new SyncException({ - message: 'Parent wallet for account not found', - suggestedHttpStatusCode: HttpStatus.NOT_FOUND, - context: { - walletExternalId: anchorageWallet.vaultId, - accountExternalId: anchorageWallet.walletId - } - }) - } - - return { - accountId: uuid(), - walletId: wallet?.walletId, - label: anchorageWallet.walletName, - clientId: connection.clientId, - provider: Provider.ANCHORAGE, - addresses: [], - externalId: anchorageWallet.walletId, - createdAt: now, - updatedAt: now, - // TODO: Map their networkId to SLIP 44 format. - networkId: anchorageWallet.networkId - } - }) - - try { - await this.accountService.bulkCreate(accounts) - } catch (error) { - throw new SyncException({ - message: 'Fail to persist accounts', - suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, - origin: error - }) - } - - return accounts - } - - async syncAddresses(connection: ActiveConnectionWithCredentials) { - this.logger.log('Sync Anchorage addresses', { - connectionId: connection.credentials, - clientId: connection.clientId, - url: connection.url - }) - - this.validateConnection(connection) - - const now = new Date() - - const signKey = connection.credentials.privateKey - - const anchorageVaults = await this.anchorageClient.getVaults({ - url: connection.url, - apiKey: connection.credentials.apiKey, - signKey - }) - - const getVaultAddressesRequests = anchorageVaults.flatMap((anchorageVault) => - anchorageVault.assets.map((asset) => ({ - signKey, - apiKey: connection.credentials.apiKey, - assetType: asset.assetType, - url: connection.url, - vaultId: anchorageVault.vaultId - })) - ) - - const anchorageAddresses = ( - await Promise.all(getVaultAddressesRequests.map((request) => this.anchorageClient.getVaultAddresses(request))) - ).flat() - - // Query existing accounts to associate them with their children addresses. - const { data: existingAccounts } = await this.accountService.findAll(connection.clientId, { - filters: { - externalIds: anchorageAddresses.map((anchorageAddress) => anchorageAddress.walletId) - } - }) - - const existingAccountsByExternalId = new Map(existingAccounts.map((account) => [account.externalId, account])) - - const { data: existingAddresses } = await this.addressService.findAll(connection.clientId, { - filters: { - externalIds: anchorageAddresses.map((anchorageAddress) => anchorageAddress.addressId) - } - }) - - const existingAddressesByExternalId = new Map(existingAddresses.map((address) => [address.externalId, address])) - - const uniqueAnchorageAddresses = Array.from( - new Map(anchorageAddresses.map((anchorageAddress) => [anchorageAddress.addressId, anchorageAddress])).values() - ) - - const missingAnchorageAddresses = uniqueAnchorageAddresses.filter( - (anchorageAddress) => !existingAddressesByExternalId.has(anchorageAddress.addressId) - ) - - const addresses: Address[] = missingAnchorageAddresses.map((anchorageAddress) => { - const account = existingAccountsByExternalId.get(anchorageAddress.walletId) - - if (account) { - return { - accountId: account.accountId, - address: anchorageAddress.address, - addressId: uuid(), - clientId: connection.clientId, - createdAt: now, - externalId: anchorageAddress.addressId, - provider: Provider.ANCHORAGE, - updatedAt: now - } satisfies Address - } - - throw new SyncException({ - message: 'Anchorage address parent account not found', - suggestedHttpStatusCode: HttpStatus.NOT_FOUND - }) - }) - - try { - await this.addressService.bulkCreate(addresses) - } catch (error) { - throw new SyncException({ - message: 'Fail to persist addresses', - suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, - origin: error - }) - } - - return addresses - } - - async syncKnownDestinations(connection: ActiveConnectionWithCredentials): Promise<{ - created: KnownDestination[] - updated: KnownDestination[] - deleted: number - }> { - this.logger.log('Sync Anchorage known destinations', { - connectionId: connection.credentials, - clientId: connection.clientId, - url: connection.url - }) - - this.validateConnection(connection) - - // Fetch current state from Anchorage - const anchorageTrustedDestinations = await this.anchorageClient.getTrustedDestinations({ - url: connection.url, - apiKey: connection.credentials.apiKey, - signKey: connection.credentials.privateKey - }) - - const now = new Date() - - const { data: existingKnownDestinations } = await this.knownDestinationService.findAll(connection.clientId) - - const incomingMap = new Map(anchorageTrustedDestinations.map((dest) => [dest.id, dest])) - const existingMap = new Map(existingKnownDestinations.map((dest) => [dest.externalId, dest])) - - const toBeUpdated = anchorageTrustedDestinations.reduce((acc, incoming) => { - const existing = existingMap.get(incoming.id) - if (!existing) return acc - - const hasConnection = existing.connections.some((conn) => conn.connectionId === connection.connectionId) - const hasDataChanges = - (existing.label || undefined) !== incoming.crypto.memo || - (existing.assetId || undefined) !== incoming.crypto.assetType - - if (hasDataChanges || !hasConnection) { - acc.push({ - ...existing, - label: incoming.crypto.memo, - assetId: incoming.crypto.assetType, - updatedAt: now, - connections: [...existing.connections, connection] - }) - } - - return acc - }, []) - - const toBeCreated: KnownDestination[] = anchorageTrustedDestinations - .filter((anchorageDest) => !existingMap.has(anchorageDest.id)) - .map((anchorageDest) => - KnownDestination.parse({ - knownDestinationId: uuid(), - address: anchorageDest.crypto.address, - clientId: connection.clientId, - externalId: anchorageDest.id, - label: anchorageDest.crypto.memo, - assetId: anchorageDest.crypto.assetType, - provider: Provider.ANCHORAGE, - networkId: anchorageDest.crypto.networkId, - createdAt: now, - updatedAt: now, - connections: [connection] - }) - ) - - const toBeDeleted = existingKnownDestinations.filter((dest) => !incomingMap.has(dest.externalId)) - - try { - this.logger.log('Deleting removed trusted destinations in anchorage from known destinations', { - deleting: toBeDeleted.map((dest) => ({ - anchorageId: dest.externalId, - knownDestinationId: dest.knownDestinationId - })), - clientId: connection.clientId - }) - - const created = await this.knownDestinationService.bulkCreate(toBeCreated) - const deleted = await this.knownDestinationService.bulkDelete(toBeDeleted) - const updated = await this.knownDestinationService.bulkUpdate(toBeUpdated) - - this.logger.log('Known destinations sync completed', { - totalCreated: created.length, - totalUpdated: updated.length, - totalDeleted: deleted, - clientId: connection.clientId - }) - - return { - created, - updated, - deleted - } - } catch (error) { - throw new SyncException({ - message: 'Failed to sync known destinations', - suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, - origin: error - }) - } - } - - private validateConnection( - connection: ActiveConnectionWithCredentials - ): asserts connection is ActiveConnectionWithCredentials & { - url: string - credentials: { - apiKey: string - privateKey: Ed25519PrivateKey - } - } { - const context = { - clientId: connection.clientId, - connectionId: connection.connectionId, - provider: connection.provider, - status: connection.status, - url: connection.url - } - - if (connection.provider !== Provider.ANCHORAGE) { - throw new ConnectionInvalidException({ - message: 'Invalid connection provider for Anchorage', - context - }) - } - - if (!connection.url) { - throw new ConnectionInvalidException({ - message: 'Cannot sync without a connection URL', - context - }) - } - - if (!connection.credentials?.apiKey && !connection.credentials?.privateKey) { - throw new ConnectionInvalidException({ - message: 'Cannot sync without API key and/or signing key', - context - }) - } - } -} diff --git a/apps/vault/src/broker/core/service/known-destination.service.ts b/apps/vault/src/broker/core/service/known-destination.service.ts index 251fb2d17..1eb1a68e4 100644 --- a/apps/vault/src/broker/core/service/known-destination.service.ts +++ b/apps/vault/src/broker/core/service/known-destination.service.ts @@ -26,13 +26,14 @@ export class KnownDestinationService { return this.knownDestinationRepository.bulkCreate(knownDestinations) } - async bulkDelete(knownDestinationId: KnownDestination[]): Promise { - return this.knownDestinationRepository.bulkDelete(knownDestinationId) + async bulkDelete(knownDestinationIds: string[]): Promise { + return this.knownDestinationRepository.bulkDelete(knownDestinationIds) } async bulkUpdate(knownDestinations: KnownDestination[]): Promise { return Promise.all(knownDestinations.map((knownDestination) => this.update(knownDestination))) } + async update(knownDestination: UpdateKnownDestination): Promise { return this.knownDestinationRepository.update(knownDestination) } @@ -40,4 +41,8 @@ export class KnownDestinationService { async findAll(clientId: string, opts?: FindAllOptions): Promise> { return this.knownDestinationRepository.findAll(clientId, opts) } + + async findById(clientId: string, knownDestinationId: string): Promise { + return this.knownDestinationRepository.findById(clientId, knownDestinationId) + } } diff --git a/apps/vault/src/broker/core/service/sync.service.ts b/apps/vault/src/broker/core/service/sync.service.ts index 17f9b96f9..48870a48d 100644 --- a/apps/vault/src/broker/core/service/sync.service.ts +++ b/apps/vault/src/broker/core/service/sync.service.ts @@ -1,16 +1,37 @@ import { LoggerService, PaginatedResult, TraceService } from '@narval/nestjs-shared' +import { NotImplementedException } from '@nestjs/common' import { Inject, Injectable } from '@nestjs/common/decorators' +import { EventEmitter2 } from '@nestjs/event-emitter' +import { zip } from 'lodash' import { v4 as uuid } from 'uuid' import { FindAllOptions, SyncRepository } from '../../persistence/repository/sync.repository' -import { ActiveConnectionWithCredentials } from '../type/connection.type' +import { SyncStartedEvent } from '../../shared/event/sync-started.event' +import { AnchorageSyncService } from '../provider/anchorage/anchorage-sync.service' +import { ActiveConnectionWithCredentials, Provider } from '../type/connection.type' +import { + ProviderSyncService, + SyncResult, + isCreateOperation, + isDeleteOperation, + isFailedOperation, + isUpdateOperation +} from '../type/provider.type' import { StartSync, Sync, SyncStarted, SyncStatus } from '../type/sync.type' -import { AnchorageSyncService } from './anchorage-sync.service' +import { AccountService } from './account.service' +import { AddressService } from './address.service' +import { KnownDestinationService } from './known-destination.service' +import { WalletService } from './wallet.service' @Injectable() export class SyncService { constructor( private readonly syncRepository: SyncRepository, private readonly anchorageSyncService: AnchorageSyncService, + private readonly walletService: WalletService, + private readonly accountService: AccountService, + private readonly addressService: AddressService, + private readonly knownDestinationService: KnownDestinationService, + private readonly eventEmitter: EventEmitter2, private readonly logger: LoggerService, @Inject(TraceService) private readonly traceService: TraceService ) {} @@ -35,17 +56,14 @@ export class SyncService { ) ) - Promise.all( - connections.map(async (connection) => { - return this.anchorageSyncService.sync(connection) - }) - ) - .then(async () => { - await Promise.all(syncs.map((sync) => this.complete(sync))) - }) - .catch(async (error) => { - await Promise.all(syncs.map((sync) => this.fail(sync, error))) - }) + for (const [sync, connection] of zip(syncs, connections)) { + if (sync && connection) { + // NOTE: Emits an event that will delegate the sync process to + // another worker, allowing to unblock the request. The event handler + // will then invoke the `SyncService.sync` method. + this.eventEmitter.emit(SyncStartedEvent.EVENT_NAME, new SyncStartedEvent(sync, connection)) + } + } return { started: true, syncs } } @@ -55,6 +73,13 @@ export class SyncService { return { started: false, syncs: [] } } + async sync(sync: Sync, connection: ActiveConnectionWithCredentials): Promise { + const result = await this.getProviderSyncService(connection.provider).sync(connection) + const updatedSync = await this.execute(sync, result) + + return updatedSync + } + private toProcessingSync(input: StartSync & { connectionId: string; createdAt?: Date; syncId?: string }): Sync { return { ...input, @@ -74,7 +99,132 @@ export class SyncService { return this.syncRepository.findById(clientId, syncId) } + // TODO: pessimist lock if there's already a sync in process for the given + // connection. + async execute(sync: Sync, result: SyncResult): Promise { + // IMPORTANT: Thoroughly test the execution in the integration test + // `sync.service.spec.ts`. + + const { clientId, syncId } = sync + + const walletCreateOperations = result.wallets.filter(isCreateOperation).map(({ create }) => create) + const walletUpdateOperations = result.wallets.filter(isUpdateOperation).map(({ update }) => update) + const walletDeleteOperations = result.wallets.filter(isDeleteOperation).map(({ entityId }) => entityId) + const walletFailedOperations = result.wallets.filter(isFailedOperation) + + const accountCreateOperations = result.accounts.filter(isCreateOperation).map(({ create }) => create) + const accountUpdateOperations = result.accounts.filter(isUpdateOperation).map(({ update }) => update) + const accountDeleteOperations = result.accounts.filter(isDeleteOperation).map(({ entityId }) => entityId) + const accountFailedOperations = result.accounts.filter(isFailedOperation) + + const addressCreateOperations = result.addresses.filter(isCreateOperation).map(({ create }) => create) + const addressUpdateOperations = result.addresses.filter(isUpdateOperation).map(({ update }) => update) + const addressDeleteOperations = result.addresses.filter(isDeleteOperation).map(({ entityId }) => entityId) + const addressFailedOperations = result.addresses.filter(isFailedOperation) + + const knownDestinationCreateOperations = result.knownDestinations + .filter(isCreateOperation) + .map(({ create }) => create) + const knownDestinationUpdateOperations = result.knownDestinations + .filter(isUpdateOperation) + .map(({ update }) => update) + const knownDestinationDeleteOperations = result.knownDestinations + .filter(isDeleteOperation) + .map(({ entityId }) => entityId) + const knownDestinationFailedOperations = result.knownDestinations.filter(isFailedOperation) + + this.logger.log('Execute sync operations', { + clientId, + syncId, + operations: { + wallet: { + create: walletCreateOperations.length, + update: walletUpdateOperations.length, + delete: walletDeleteOperations.length, + failed: walletFailedOperations.length + }, + account: { + create: accountCreateOperations.length, + update: accountUpdateOperations.length, + delete: accountDeleteOperations.length, + failed: accountFailedOperations.length + }, + address: { + create: addressCreateOperations.length, + update: addressUpdateOperations.length, + delete: addressDeleteOperations.length, + failed: addressFailedOperations.length + }, + knownDestination: { + create: knownDestinationCreateOperations.length, + update: knownDestinationUpdateOperations.length, + delete: knownDestinationDeleteOperations.length, + failed: knownDestinationFailedOperations.length + } + } + }) + + if (walletFailedOperations.length) { + this.logger.warn('Sync operations contains failures for wallets', { + operations: walletFailedOperations + }) + } + + if (accountFailedOperations.length) { + this.logger.warn('Sync operations contains failures for accounts', { + operations: accountFailedOperations + }) + } + + if (addressFailedOperations.length) { + this.logger.warn('Sync operations contains failures for addresses', { + operations: addressFailedOperations + }) + } + + if (knownDestinationFailedOperations.length) { + this.logger.warn('Sync operations contains failures for known destinations', { + operations: knownDestinationFailedOperations + }) + } + + try { + this.logger.log('Execute wallet create operations', { syncId, clientId }) + await this.walletService.bulkCreate(walletCreateOperations) + + this.logger.log('Execute wallet update operations', { syncId, clientId }) + await this.walletService.bulkUpdate(walletUpdateOperations) + + this.logger.log('Execute account create operations', { syncId, clientId }) + await this.accountService.bulkCreate(accountCreateOperations) + this.logger.log('Execute account update operations', { syncId, clientId }) + await this.accountService.bulkUpdate(accountUpdateOperations) + + // TODO: address update + this.logger.log('Execute address create operations', { syncId, clientId }) + await this.addressService.bulkCreate(addressCreateOperations) + + this.logger.log('Execute known destination create operations', { syncId, clientId }) + await this.knownDestinationService.bulkCreate(knownDestinationCreateOperations) + + this.logger.log('Execute known destination update operations', { syncId, clientId }) + await this.knownDestinationService.bulkUpdate(knownDestinationUpdateOperations) + + this.logger.log('Execute known destination delete operations', { syncId, clientId }) + await this.knownDestinationService.bulkDelete(knownDestinationDeleteOperations) + + return await this.complete(sync) + } catch (error) { + return await this.fail(sync, error) + } + } + async complete(sync: Sync): Promise { + this.logger.log('Sync complete', { + clientId: sync.clientId, + syncId: sync.syncId + }) + const completedSync = { ...sync, status: SyncStatus.SUCCESS, @@ -87,6 +237,12 @@ export class SyncService { } async fail(sync: Sync, error: Error): Promise { + this.logger.log('Sync fail', { + clientId: sync.clientId, + syncId: sync.syncId, + error + }) + const failedSync = { ...sync, status: SyncStatus.FAILED, @@ -102,4 +258,13 @@ export class SyncService { return failedSync } + + private getProviderSyncService(provider: Provider): ProviderSyncService { + switch (provider) { + case Provider.ANCHORAGE: + return this.anchorageSyncService + default: + throw new NotImplementedException(`Unsupported sync for provider ${provider}`) + } + } } diff --git a/apps/vault/src/broker/core/service/transfer.service.ts b/apps/vault/src/broker/core/service/transfer.service.ts index 5cb9a2129..acc33e82a 100644 --- a/apps/vault/src/broker/core/service/transfer.service.ts +++ b/apps/vault/src/broker/core/service/transfer.service.ts @@ -1,9 +1,11 @@ +import { LoggerService } from '@narval/nestjs-shared' import { HttpStatus, Injectable, NotImplementedException } from '@nestjs/common' import { TransferRepository } from '../../persistence/repository/transfer.repository' import { BrokerException } from '../exception/broker.exception' +import { AnchorageTransferService } from '../provider/anchorage/anchorage-transfer.service' import { ConnectionStatus, Provider, isActiveConnection } from '../type/connection.type' +import { ProviderTransferService } from '../type/provider.type' import { InternalTransfer, SendTransfer } from '../type/transfer.type' -import { AnchorageTransferService } from './anchorage-transfer.service' import { ConnectionService } from './connection.service' import { TransferPartyService } from './transfer-party.service' @@ -13,7 +15,8 @@ export class TransferService { private readonly transferRepository: TransferRepository, private readonly connectionService: ConnectionService, private readonly transferPartyService: TransferPartyService, - private readonly anchorageTransferService: AnchorageTransferService + private readonly anchorageTransferService: AnchorageTransferService, + private readonly logger: LoggerService ) {} async findById(clientId: string, transferId: string): Promise { @@ -25,29 +28,36 @@ export class TransferService { } async send(clientId: string, sendTransfer: SendTransfer): Promise { - const source = await this.transferPartyService.resolve(clientId, sendTransfer.source) + this.logger.log('Send transfer', { clientId, sendTransfer }) - if (source.provider === Provider.ANCHORAGE) { - const { data: connections } = await this.connectionService.findAll( - clientId, - { - filters: { - status: ConnectionStatus.ACTIVE - } - }, - true - ) - - if (connections.length && isActiveConnection(connections[0])) { - return this.anchorageTransferService.send(connections[0], sendTransfer) - } - - throw new BrokerException({ - message: 'Cannot find an active connection for Anchorage', - suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY - }) + const source = await this.transferPartyService.resolve(clientId, sendTransfer.source) + const { data: connections } = await this.connectionService.findAll( + clientId, + { + filters: { + status: ConnectionStatus.ACTIVE + } + }, + true + ) + + if (connections.length && isActiveConnection(connections[0])) { + return this.getProviderTransferService(source.provider).send(connections[0], sendTransfer) } - throw new NotImplementedException() + throw new BrokerException({ + message: 'Cannot find an active connection for the source', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, + context: { source } + }) + } + + private getProviderTransferService(provider: Provider): ProviderTransferService { + switch (provider) { + case Provider.ANCHORAGE: + return this.anchorageTransferService + default: + throw new NotImplementedException(`Unsupported transfer for provider ${provider}`) + } } } diff --git a/apps/vault/src/broker/core/service/wallet.service.ts b/apps/vault/src/broker/core/service/wallet.service.ts index 6e46dca9d..804eb8024 100644 --- a/apps/vault/src/broker/core/service/wallet.service.ts +++ b/apps/vault/src/broker/core/service/wallet.service.ts @@ -1,4 +1,4 @@ -import { PaginatedResult, PaginationOptions } from '@narval/nestjs-shared' +import { PaginatedResult } from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' import { FindAllOptions, WalletRepository } from '../../persistence/repository/wallet.repository' import { UpdateWallet, Wallet } from '../type/indexed-resources.type' @@ -7,14 +7,6 @@ import { UpdateWallet, Wallet } from '../type/indexed-resources.type' export class WalletService { constructor(private readonly walletRepository: WalletRepository) {} - async getWallets(clientId: string, options: PaginationOptions): Promise> { - return this.walletRepository.findByClientId(clientId, options) - } - - async getWallet(clientId: string, walletId: string): Promise { - return this.walletRepository.findById(clientId, walletId) - } - async bulkCreate(wallets: Wallet[]): Promise { return this.walletRepository.bulkCreate(wallets) } @@ -30,4 +22,8 @@ export class WalletService { async findAll(clientId: string, options?: FindAllOptions): Promise> { return this.walletRepository.findAll(clientId, options) } + + async findById(clientId: string, accountId: string): Promise { + return this.walletRepository.findById(clientId, accountId) + } } diff --git a/apps/vault/src/broker/core/type/provider.type.ts b/apps/vault/src/broker/core/type/provider.type.ts new file mode 100644 index 000000000..7c5150cbf --- /dev/null +++ b/apps/vault/src/broker/core/type/provider.type.ts @@ -0,0 +1,247 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +import { HttpStatus } from '@nestjs/common' +import { UpdateAccount } from '../../persistence/repository/account.repository' +import { ActiveConnectionWithCredentials } from './connection.type' +import { Account, Address, KnownDestination, UpdateWallet, Wallet } from './indexed-resources.type' +import { InternalTransfer, SendTransfer, Transfer } from './transfer.type' + +export const SyncOperationType = { + CREATE: 'create', + UPDATE: 'update', + DELETE: 'delete', + FAILED: 'failed' +} as const +export type SyncOperationType = (typeof SyncOperationType)[keyof typeof SyncOperationType] + +export type CreateSyncOperation = { + type: typeof SyncOperationType.CREATE + create: CreateParams +} + +export type UpdateSyncOperation = { + type: typeof SyncOperationType.UPDATE + update: UpdateParams +} + +export type DeleteSyncOperation = { + type: typeof SyncOperationType.DELETE + entityId: string +} + +export type FailedSyncOperation = { + type: typeof SyncOperationType.FAILED + externalId: string + message: string + context?: unknown +} + +/** + * Represents a synchronization operation for a resource, which can be a + * creation, update, or deletion. Each operation type is associated with + * specific parameters. + * + * @template CreateParams - The parameters required for creating an entity. + * @template UpdateParams - The parameters required for updating an entity. + */ +export type SyncOperation = + | CreateSyncOperation + | UpdateSyncOperation + | DeleteSyncOperation + | FailedSyncOperation + +export const isCreateOperation = ( + operation: SyncOperation +): operation is CreateSyncOperation => { + return operation.type === SyncOperationType.CREATE +} + +export const isUpdateOperation = ( + operation: SyncOperation +): operation is UpdateSyncOperation => { + return operation.type === SyncOperationType.UPDATE +} + +export const isDeleteOperation = ( + operation: SyncOperation +): operation is DeleteSyncOperation => { + return operation.type === SyncOperationType.DELETE +} + +export const isFailedOperation = ( + operation: SyncOperation +): operation is FailedSyncOperation => { + return operation.type === SyncOperationType.FAILED +} + +/** + * Represents the context used during synchronization, containing the active + * connection and maps of synchronization operations for various resource + * types. + */ +export type SyncContext = { + /** + * The active connection with credentials used for synchronization. + */ + connection: ActiveConnectionWithCredentials + + /** + * A map of wallet synchronization operations, keyed by wallet external ID. + */ + wallets: SyncOperation[] + + /** + * A map of account synchronization operations, keyed by account external ID. + */ + accounts: SyncOperation[] + + /** + * A map of address synchronization operations, keyed by address external ID. + */ + addresses: SyncOperation[] + + /** + * A map of known destination synchronization operations, keyed by + * destination external ID. + */ + knownDestinations: SyncOperation[] + + /** + * An optional timestamp used for setting the `createdAt` and `updatedAt` + * fields during synchronization operations. + */ + now?: Date +} + +export type SyncResult = { + wallets: SyncOperation[] + accounts: SyncOperation[] + addresses: SyncOperation[] + knownDestinations: SyncOperation[] +} + +export interface ProviderSyncService { + /** + * The main entry point for synchronization, responsible for coordinating the + * synchronization process across different resources. It orchestrates the + * sync calls and passes the context between them. + * + * IMPORTANT: The synchronization **does not perform the writes** into the + * database. + * + * @param connection - The active connection with credentials required for + * synchronization. + * + * @returns A promise that resolves to an object containing the results of + * the sync operations for wallets, accounts, addresses, and known + * destinations. + */ + sync(connection: ActiveConnectionWithCredentials): Promise + + /** + * Synchronizes wallet data within the provided context and returns an + * updated context. + * + * @param context - The current synchronization context containing existing + * data and operations. + * + * @returns A promise that resolves to the updated synchronization context. + */ + syncWallets(context: SyncContext): Promise + + /** + * Synchronizes account data within the provided context and returns an + * updated context. + * + * @param context - The current synchronization context containing existing + * data and operations. + * + * @returns A promise that resolves to the updated synchronization context. + */ + syncAccounts(context: SyncContext): Promise + + /** + * Synchronizes address data within the provided context and returns an + * updated context. + * + * @param context - The current synchronization context containing existing + * data and operations. + * + * @returns A promise that resolves to the updated synchronization context. + */ + syncAddresses(context: SyncContext): Promise + + /** + * Synchronizes known destination data within the provided context and + * returns an updated context. + * + * @param context - The current synchronization context containing existing + * data and operations. + * + * @returns A promise that resolves to the updated synchronization context. + */ + syncKnownDestinations(context: SyncContext): Promise +} + +export interface ProviderTransferService { + /** + * Finds a transfer by its ID. + * + * @param connection - The active connection with credentials required for + * accessing the transfer data. + * @param transferId - The unique identifier of the transfer to be retrieved. + * + * @returns A promise that resolves to the transfer object if found. + */ + findById(connection: ActiveConnectionWithCredentials, transferId: string): Promise + + /** + * Sends a transfer using the provided active connection and transfer + * details. + * + * @param connection - The active connection with credentials required for + * sending the transfer. + * @param sendTransfer - The details of the transfer to be sent. + * + * @returns A promise that resolves to the internal transfer object after the + * transfer is successfully sent. + */ + send(connection: ActiveConnectionWithCredentials, sendTransfer: SendTransfer): Promise +} + +/** + * Options for making a proxy request, including connection ID, request data, + * endpoint, and HTTP method. + */ +export type ProxyRequestOptions = { + connectionId: string + data?: any + endpoint: string + method: string +} + +/** + * Represents the response from a proxy request, including the response data, + * HTTP status code, and headers. + */ +export type ProxyResponse = { + data: any + code: HttpStatus + headers: Record +} + +export interface ProviderProxyService { + /** + * Forwards a request to a specified endpoint using the provided active + * connection and request options. + * + * @param connection - The active connection with credentials required for + * forwarding the request. + * @param options - The options for the proxy request, including connection + * ID, request data, endpoint, and HTTP method. + * + * @returns A promise that resolves to the proxy response, containing the + * response data, HTTP status code, and headers. + */ + forward(connection: ActiveConnectionWithCredentials, options: ProxyRequestOptions): Promise +} diff --git a/apps/vault/src/broker/core/util/provider-sync.util.ts b/apps/vault/src/broker/core/util/provider-sync.util.ts new file mode 100644 index 000000000..71068b009 --- /dev/null +++ b/apps/vault/src/broker/core/util/provider-sync.util.ts @@ -0,0 +1,18 @@ +import { SetRequired } from 'type-fest' +import { SyncContext } from '../type/provider.type' + +export const buildEmptyContext = ({ + connection, + wallets, + accounts, + addresses, + knownDestinations, + now +}: SetRequired, 'connection'>): SyncContext => ({ + connection, + wallets: wallets || [], + accounts: accounts || [], + addresses: addresses || [], + knownDestinations: knownDestinations || [], + now: now || new Date() +}) diff --git a/apps/vault/src/broker/event/handler/connection-sync.event-handler.ts b/apps/vault/src/broker/event/handler/connection-sync.event-handler.ts index ecd5d43a7..d44926e80 100644 --- a/apps/vault/src/broker/event/handler/connection-sync.event-handler.ts +++ b/apps/vault/src/broker/event/handler/connection-sync.event-handler.ts @@ -3,6 +3,7 @@ import { Injectable } from '@nestjs/common' import { OnEvent } from '@nestjs/event-emitter' import { SyncService } from '../../core/service/sync.service' import { ConnectionActivatedEvent } from '../../shared/event/connection-activated.event' +import { SyncStartedEvent } from '../../shared/event/sync-started.event' @Injectable() export class ConnectionSyncEventHandler { @@ -13,11 +14,21 @@ export class ConnectionSyncEventHandler { @OnEvent(ConnectionActivatedEvent.EVENT_NAME) async handleConnectionActivatedEvent(event: ConnectionActivatedEvent) { - this.logger.log('Received connection.activated event', { + this.logger.log(`Received ${ConnectionActivatedEvent.EVENT_NAME} event`, { clientId: event.connection.clientId, connectionId: event.connection.connectionId }) await this.syncService.start([event.connection]) } + + @OnEvent(SyncStartedEvent.EVENT_NAME) + async handleSyncStarted(event: SyncStartedEvent) { + this.logger.log(`Received ${SyncStartedEvent.EVENT_NAME} event`, { + clientId: event.connection.clientId, + connectionId: event.connection.connectionId + }) + + await this.syncService.sync(event.sync, event.connection) + } } diff --git a/apps/vault/src/broker/http/client/anchorage.client.ts b/apps/vault/src/broker/http/client/anchorage.client.ts index e7ec54b08..c789f93bf 100644 --- a/apps/vault/src/broker/http/client/anchorage.client.ts +++ b/apps/vault/src/broker/http/client/anchorage.client.ts @@ -131,7 +131,7 @@ const CreateTransfer = z.object({ assetType: z.string(), deductFeeFromAmountIfSameType: z.boolean(), destination: Resource, - idempotenceId: z.string().max(128).nullable(), + idempotentId: z.string().max(128).nullable(), source: Resource, transferMemo: z.string().nullable() }) diff --git a/apps/vault/src/broker/http/rest/controller/account.controller.ts b/apps/vault/src/broker/http/rest/controller/account.controller.ts index bf7a9bd93..3e2bc7919 100644 --- a/apps/vault/src/broker/http/rest/controller/account.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/account.controller.ts @@ -29,9 +29,9 @@ export class ProviderAccountController { }) async list( @ClientId() clientId: string, - @PaginationParam() options: PaginationOptions + @PaginationParam() pagination: PaginationOptions ): Promise { - return PaginatedAccountsDto.create(await this.accountService.getAccounts(clientId, options)) + return PaginatedAccountsDto.create(await this.accountService.findAll(clientId, { pagination })) } @Get(':accountId') @@ -52,7 +52,7 @@ export class ProviderAccountController { description: 'Account not found' }) async getById(@ClientId() clientId: string, @Param('accountId') accountId: string): Promise { - const data = await this.accountService.getAccount(clientId, accountId) + const data = await this.accountService.findById(clientId, accountId) return ProviderAccountDto.create({ data }) } diff --git a/apps/vault/src/broker/http/rest/controller/wallet.controller.ts b/apps/vault/src/broker/http/rest/controller/wallet.controller.ts index 53c185e69..f75810c23 100644 --- a/apps/vault/src/broker/http/rest/controller/wallet.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/wallet.controller.ts @@ -33,9 +33,9 @@ export class ProviderWalletController { }) async list( @ClientId() clientId: string, - @PaginationParam() options: PaginationOptions + @PaginationParam() pagination: PaginationOptions ): Promise { - return PaginatedWalletsDto.create(await this.walletService.getWallets(clientId, options)) + return PaginatedWalletsDto.create(await this.walletService.findAll(clientId, { pagination })) } @Get(':walletId') @@ -56,7 +56,7 @@ export class ProviderWalletController { description: 'Wallet not found' }) async getById(@ClientId() clientId: string, @Param('walletId') walletId: string): Promise { - const data = await this.walletService.getWallet(clientId, walletId) + const data = await this.walletService.findById(clientId, walletId) return ProviderWalletDto.create({ data }) } diff --git a/apps/vault/src/broker/persistence/repository/account.repository.ts b/apps/vault/src/broker/persistence/repository/account.repository.ts index 8000cf7d5..0e6f49202 100644 --- a/apps/vault/src/broker/persistence/repository/account.repository.ts +++ b/apps/vault/src/broker/persistence/repository/account.repository.ts @@ -20,6 +20,14 @@ type FindAllFilters = { export type FindAllOptions = FindAllFilters & { pagination?: PaginationOptions } +export type UpdateAccount = { + clientId: string + accountId: string + label?: string + addresses?: Address[] + updatedAt?: Date +} + @Injectable() export class AccountRepository { constructor(private prismaService: PrismaService) {} @@ -116,20 +124,49 @@ export class AccountRepository { return accounts } + async bulkUpdate(updateAccounts: UpdateAccount[]): Promise { + await Promise.all(updateAccounts.map((u) => this.update(u))) + + return true + } + + async update(updateAccount: UpdateAccount): Promise { + await this.prismaService.providerAccount.update({ + where: { + clientId: updateAccount.clientId, + id: updateAccount.accountId + }, + data: { + label: updateAccount.label, + updatedAt: updateAccount.updatedAt || new Date() + } + }) + + return true + } + async findAll(clientId: string, options?: FindAllOptions): Promise> { const pagination = applyPagination(options?.pagination) const models = await this.prismaService.providerAccount.findMany({ where: { clientId, - walletId: options?.filters?.walletId, - wallet: { - connections: { - some: { - connectionId: options?.filters?.connectionId + ...(options?.filters?.walletId + ? { + walletId: options.filters.walletId + } + : {}), + ...(options?.filters?.connectionId + ? { + wallet: { + connections: { + some: { + connectionId: options?.filters?.connectionId + } + } + } } - } - }, + : {}), ...(options?.filters?.externalIds ? { externalId: { diff --git a/apps/vault/src/broker/persistence/repository/known-destination.repository.ts b/apps/vault/src/broker/persistence/repository/known-destination.repository.ts index 02711ea0e..8c3e7f8c6 100644 --- a/apps/vault/src/broker/persistence/repository/known-destination.repository.ts +++ b/apps/vault/src/broker/persistence/repository/known-destination.repository.ts @@ -23,7 +23,7 @@ type ProviderKnownDestinationAndRelations = ProviderKnownDestination & { export type FindAllOptions = FindAllFilters & { pagination?: PaginationOptions } -const UpdateKnownDestination = KnownDestination.pick({ +export const UpdateKnownDestination = KnownDestination.pick({ knownDestinationId: true, label: true, connections: true, @@ -45,12 +45,12 @@ export class KnownDestinationRepository { return ConnectionRepository.parseModel(join.connection) }) - return { + return KnownDestination.parse({ ...rest, connections: validConnections, knownDestinationId: id, - provider: z.nativeEnum(Provider).parse(model.provider) - } + provider: model.provider + }) } static parseEntity(entity: KnownDestination): ProviderKnownDestination { @@ -216,11 +216,11 @@ export class KnownDestinationRepository { return created.map(KnownDestinationRepository.parseModel) } - async bulkDelete(knownDestinations: KnownDestination[]): Promise { + async bulkDelete(knownDestinationIds: string[]): Promise { await this.prismaService.providerKnownDestinationConnection.deleteMany({ where: { knownDestinationId: { - in: knownDestinations.map((d) => d.knownDestinationId) + in: knownDestinationIds } } }) @@ -228,10 +228,11 @@ export class KnownDestinationRepository { const { count } = await this.prismaService.providerKnownDestination.deleteMany({ where: { id: { - in: knownDestinations.map((d) => d.knownDestinationId) + in: knownDestinationIds } } }) + return count } diff --git a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/server.ts b/apps/vault/src/broker/shared/__test__/mock-server.ts similarity index 83% rename from apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/server.ts rename to apps/vault/src/broker/shared/__test__/mock-server.ts index 567e4beba..82f1b1a80 100644 --- a/apps/vault/src/broker/core/service/__test__/integration/mocks/anchorage/server.ts +++ b/apps/vault/src/broker/shared/__test__/mock-server.ts @@ -1,11 +1,9 @@ import { afterAll, afterEach, beforeAll, jest } from '@jest/globals' +import { HttpHandler } from 'msw' import { SetupServerApi, setupServer } from 'msw/node' -import { disableNockProtection, restoreNockProtection } from '../../../../../../../../test/nock.util' -import { getHandlers } from './handlers' +import { disableNockProtection, restoreNockProtection } from '../../../../test/nock.util' -export const ANCHORAGE_TEST_API_BASE_URL = 'https://test-mock-api.anchorage.com' - -export const getMockServer = () => setupServer(...getHandlers(ANCHORAGE_TEST_API_BASE_URL)) +export const getMockServer = (handlers: HttpHandler[]) => setupServer(...handlers) export const useRequestSpy = (server: SetupServerApi): [jest.Mock, SetupServerApi] => { const spy = jest.fn() @@ -66,10 +64,10 @@ const attachToJestTestLifecycle = (server: SetupServerApi): SetupServerApi => { * `describe` or `it`. If you only need the server instance without attaching * it to the test lifecycle, use `getMockServer` instead. */ -export const setupMockServer = (server?: SetupServerApi): SetupServerApi => { +export const setupMockServer = (handlers: HttpHandler[], server?: SetupServerApi): SetupServerApi => { if (server) { return attachToJestTestLifecycle(server) } - return attachToJestTestLifecycle(getMockServer()) + return attachToJestTestLifecycle(getMockServer(handlers)) } diff --git a/apps/vault/src/broker/shared/event/sync-started.event.ts b/apps/vault/src/broker/shared/event/sync-started.event.ts new file mode 100644 index 000000000..5a5e6a453 --- /dev/null +++ b/apps/vault/src/broker/shared/event/sync-started.event.ts @@ -0,0 +1,11 @@ +import { ActiveConnectionWithCredentials } from '../../core/type/connection.type' +import { Sync } from '../../core/type/sync.type' + +export class SyncStartedEvent { + static EVENT_NAME = 'sync.started' + + constructor( + public readonly sync: Sync, + public readonly connection: ActiveConnectionWithCredentials + ) {} +} From 9364b720195fb0426f740250906be75fe8c6a5ca Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Mon, 30 Dec 2024 13:59:26 +0100 Subject: [PATCH 065/120] Infer type from Alg in generateJwk (#60) * Infer type from Alg in generateJwk * Fix broken tests * Bump SDK to 0.13.0 --- .../src/client/__test__/e2e/client.spec.ts | 5 +---- .../integration/encryption-key.service.spec.ts | 9 ++++----- .../core/service/encryption-key.service.ts | 3 +-- .../src/vault/__test__/e2e/wallet.spec.ts | 3 +-- .../unit/key-generation.service.spec.ts | 10 ++-------- package-lock.json | 8 ++++---- packages/armory-sdk/package.json | 2 +- .../src/lib/__test__/unit/encrypt.spec.ts | 4 ++-- .../src/lib/__test__/unit/util.spec.ts | 3 +-- packages/signature/src/lib/utils.ts | 18 +++++++++--------- 10 files changed, 26 insertions(+), 39 deletions(-) diff --git a/apps/vault/src/client/__test__/e2e/client.spec.ts b/apps/vault/src/client/__test__/e2e/client.spec.ts index e9cf03b00..c2475f484 100644 --- a/apps/vault/src/client/__test__/e2e/client.spec.ts +++ b/apps/vault/src/client/__test__/e2e/client.spec.ts @@ -2,7 +2,6 @@ import { EncryptionModuleOptionProvider } from '@narval/encryption-module' import { LoggerModule, REQUEST_HEADER_ADMIN_API_KEY } from '@narval/nestjs-shared' import { Alg, - PrivateKey, SMALLEST_RSA_MODULUS_LENGTH, generateJwk, rsaPublicKeySchema, @@ -160,9 +159,7 @@ describe('Client', () => { }) it('responds with unprocessable entity when backup key is not an RSA key', async () => { - const secpBackupKey = secp256k1PublicKeySchema.parse( - await generateJwk(Alg.ES256K, { keyId: 'secpBackupKeyId' }) - ) + const secpBackupKey = secp256k1PublicKeySchema.parse(await generateJwk(Alg.ES256K, { keyId: 'secpBackupKeyId' })) const invalidClientPayload = { ...payload, diff --git a/apps/vault/src/transit-encryption/core/service/__test__/integration/encryption-key.service.spec.ts b/apps/vault/src/transit-encryption/core/service/__test__/integration/encryption-key.service.spec.ts index 02c026b2b..c1664cffd 100644 --- a/apps/vault/src/transit-encryption/core/service/__test__/integration/encryption-key.service.spec.ts +++ b/apps/vault/src/transit-encryption/core/service/__test__/integration/encryption-key.service.spec.ts @@ -3,7 +3,6 @@ import { EncryptionModuleOptionProvider } from '@narval/encryption-module' import { LoggerModule } from '@narval/nestjs-shared' import { Alg, - RsaPrivateKey, RsaPublicKey, SMALLEST_RSA_MODULUS_LENGTH, Use, @@ -85,7 +84,7 @@ describe(EncryptionKeyService.name, () => { describe('decrypt', () => { it('decrypts data using rsa private key', async () => { - const privateKey = await generateJwk(Alg.RS256, { use: 'enc', modulusLength: 2048 }) + const privateKey = await generateJwk(Alg.RS256, { use: 'enc', modulusLength: 2048 }) const publicKey = rsaPrivateKeyToPublicKey(privateKey) const encryptionKey = { clientId, @@ -103,7 +102,7 @@ describe(EncryptionKeyService.name, () => { }) it('throws InvalidJweHeaderException when public key kid is missing', async () => { - const privateKey = await generateJwk(Alg.RS256, GENERATE_RSA_KEY_OPTIONS) + const privateKey = await generateJwk(Alg.RS256, GENERATE_RSA_KEY_OPTIONS) const publicKey = omit(rsaPrivateKeyToPublicKey(privateKey), 'kid') // Mock the repository to bypass schema validation @@ -133,7 +132,7 @@ describe(EncryptionKeyService.name, () => { }) it('throws NotFoundException when encryption key is not found', async () => { - const privateKey = await generateJwk(Alg.RS256, GENERATE_RSA_KEY_OPTIONS) + const privateKey = await generateJwk(Alg.RS256, GENERATE_RSA_KEY_OPTIONS) const publicKey = rsaPrivateKeyToPublicKey(privateKey) const encryptedData = await rsaEncrypt('secret', publicKey) @@ -148,7 +147,7 @@ describe(EncryptionKeyService.name, () => { it('throws UnauthorizedException when encryption key clientId is different than the given clientId', async () => { const differentClientId = uuid() - const privateKey = await generateJwk(Alg.RS256, GENERATE_RSA_KEY_OPTIONS) + const privateKey = await generateJwk(Alg.RS256, GENERATE_RSA_KEY_OPTIONS) const publicKey = rsaPrivateKeyToPublicKey(privateKey) const encryptionKey = { clientId: differentClientId, diff --git a/apps/vault/src/transit-encryption/core/service/encryption-key.service.ts b/apps/vault/src/transit-encryption/core/service/encryption-key.service.ts index 0070a68f0..027f37781 100644 --- a/apps/vault/src/transit-encryption/core/service/encryption-key.service.ts +++ b/apps/vault/src/transit-encryption/core/service/encryption-key.service.ts @@ -3,7 +3,6 @@ import { LoggerService } from '@narval/nestjs-shared' import { Alg, DEFAULT_RSA_MODULUS_LENGTH, - RsaPrivateKey, SMALLEST_RSA_MODULUS_LENGTH, generateJwk, rsaDecrypt, @@ -32,7 +31,7 @@ export class EncryptionKeyService { async generate(clientId: string, opts?: GenerateOptions): Promise { const modulusLength = this.getRsaModulusLength(opts) - const privateKey = await generateJwk(Alg.RS256, { use: 'enc', modulusLength }) + const privateKey = await generateJwk(Alg.RS256, { use: 'enc', modulusLength }) const publicKey = rsaPrivateKeyToPublicKey(privateKey) this.logger.log('Generate RSA encryption key', { diff --git a/apps/vault/src/vault/__test__/e2e/wallet.spec.ts b/apps/vault/src/vault/__test__/e2e/wallet.spec.ts index 86c5c22ed..50ed3f3e0 100644 --- a/apps/vault/src/vault/__test__/e2e/wallet.spec.ts +++ b/apps/vault/src/vault/__test__/e2e/wallet.spec.ts @@ -5,7 +5,6 @@ import { Alg, Curves, Payload, - RsaPrivateKey, RsaPublicKey, SMALLEST_RSA_MODULUS_LENGTH, SigningAlg, @@ -218,7 +217,7 @@ describe('Generate', () => { it('saves a backup when client got a backupKey', async () => { const accessToken = await getAccessToken([Permission.WALLET_CREATE]) const keyId = 'backupKeyId' - const backupKey = await generateJwk(Alg.RS256, { + const backupKey = await generateJwk(Alg.RS256, { keyId, modulusLength: SMALLEST_RSA_MODULUS_LENGTH }) diff --git a/apps/vault/src/vault/core/service/__test__/unit/key-generation.service.spec.ts b/apps/vault/src/vault/core/service/__test__/unit/key-generation.service.spec.ts index e28dea318..909460870 100644 --- a/apps/vault/src/vault/core/service/__test__/unit/key-generation.service.spec.ts +++ b/apps/vault/src/vault/core/service/__test__/unit/key-generation.service.spec.ts @@ -5,13 +5,7 @@ import { OpenTelemetryModule, StatefulMetricService } from '@narval/nestjs-shared' -import { - RsaPrivateKey, - generateJwk, - publicKeyToHex, - rsaDecrypt, - secp256k1PrivateKeyToPublicJwk -} from '@narval/signature' +import { Alg, generateJwk, publicKeyToHex, rsaDecrypt, secp256k1PrivateKeyToPublicJwk } from '@narval/signature' import { Test, TestingModule } from '@nestjs/testing' import { MockProxy, mock } from 'jest-mock-extended' import { v4 as uuid } from 'uuid' @@ -129,7 +123,7 @@ describe('GenerateService', () => { }) it('returns an encrypted backup if client has an RSA backupKey configured', async () => { - const rsaBackupKey = await generateJwk('RS256') + const rsaBackupKey = await generateJwk(Alg.RS256) clientServiceMock.findById.mockResolvedValue({ ...client, diff --git a/package-lock.json b/package-lock.json index f29160f06..7f84743c1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27717,9 +27717,9 @@ "peer": true }, "node_modules/flow-parser": { - "version": "0.256.0", - "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.256.0.tgz", - "integrity": "sha512-HFb/GgB7hq+TYosLJuMLdLp8aGlyAVfrJaTvcM0w2rz2T33PjkVbRU419ncK/69cjowUksewuspkBheq9ZX9Hw==", + "version": "0.257.1", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.257.1.tgz", + "integrity": "sha512-7+KYDpAXyBPD/wODhbPYO6IGUx+WwtJcLLG/r3DvbNyxaDyuYaTBKbSqeCldWQzuFcj+MsOVx2bpkEwVPB9JRw==", "license": "MIT", "peer": true, "engines": { @@ -46204,7 +46204,7 @@ }, "packages/armory-sdk": { "name": "@narval-xyz/armory-sdk", - "version": "0.12.0", + "version": "0.13.0", "license": "MPL-2.0", "dependencies": { "@noble/curves": "1.6.0", diff --git a/packages/armory-sdk/package.json b/packages/armory-sdk/package.json index 7e2af812f..b88214d9c 100644 --- a/packages/armory-sdk/package.json +++ b/packages/armory-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@narval-xyz/armory-sdk", - "version": "0.12.0", + "version": "0.13.0", "license": "MPL-2.0", "publishConfig": { "access": "public" diff --git a/packages/signature/src/lib/__test__/unit/encrypt.spec.ts b/packages/signature/src/lib/__test__/unit/encrypt.spec.ts index 1d4292c59..44ac5319a 100644 --- a/packages/signature/src/lib/__test__/unit/encrypt.spec.ts +++ b/packages/signature/src/lib/__test__/unit/encrypt.spec.ts @@ -1,10 +1,10 @@ import { rsaDecrypt, rsaEncrypt } from '../../encrypt' -import { Alg, RsaPrivateKey } from '../../types' +import { Alg } from '../../types' import { generateJwk, rsaPrivateKeyToPublicKey } from '../../utils' describe('encrypt / decrypt', () => { it('should encrypt & decrypt with RS256 key', async () => { - const rsaPrivate = await generateJwk(Alg.RS256, { use: 'enc' }) + const rsaPrivate = await generateJwk(Alg.RS256, { use: 'enc' }) const data = 'myTestDataString' const rsaPublic = rsaPrivateKeyToPublicKey(rsaPrivate) diff --git a/packages/signature/src/lib/__test__/unit/util.spec.ts b/packages/signature/src/lib/__test__/unit/util.spec.ts index 88c4c239a..af74a76e5 100644 --- a/packages/signature/src/lib/__test__/unit/util.spec.ts +++ b/packages/signature/src/lib/__test__/unit/util.spec.ts @@ -11,7 +11,6 @@ import { Alg, Header, Jwk, - RsaPrivateKey, Secp256k1PrivateKey, SigningAlg, p256PublicKeySchema, @@ -176,7 +175,7 @@ describe('generateKeys', () => { }) describe('rsaPrivateKeyToPublicKey', () => { it('converts private to public', async () => { - const privateKey = await generateJwk(Alg.RS256, { use: 'enc' }) + const privateKey = await generateJwk(Alg.RS256, { use: 'enc' }) const publicKey = rsaPrivateKeyToPublicKey(privateKey) expect(publicKey).toEqual({ alg: Alg.RS256, diff --git a/packages/signature/src/lib/utils.ts b/packages/signature/src/lib/utils.ts index e42632d01..2931d9f87 100644 --- a/packages/signature/src/lib/utils.ts +++ b/packages/signature/src/lib/utils.ts @@ -370,7 +370,7 @@ type AlgToPrivateKeyType = { [Alg.ES256K]: Secp256k1PrivateKey [Alg.ES256]: P256PrivateKey [Alg.EDDSA]: Ed25519PrivateKey - [Alg.RS256]: never + [Alg.RS256]: RsaPrivateKey } export const privateKeyToJwk = ( @@ -451,8 +451,8 @@ export const rsaPrivateKeyToPublicKey = (jwk: RsaPrivateKey) => { return publicKey } -export const generateJwk = async ( - alg: Alg, +export const generateJwk = async ( + alg: A, opts?: { keyId?: string /** @@ -467,23 +467,23 @@ export const generateJwk = async ( */ use?: Use } -): Promise => { +): Promise => { switch (alg) { case Alg.ES256K: { const privateKeyK1 = toHex(secp256k1.utils.randomPrivateKey()) - return secp256k1PrivateKeyToJwk(privateKeyK1, opts?.keyId) as T + return secp256k1PrivateKeyToJwk(privateKeyK1, opts?.keyId) as AlgToPrivateKeyType[A] } case Alg.ES256: { const privateKeyP256 = toHex(p256.utils.randomPrivateKey()) - return p256PrivateKeyToJwk(privateKeyP256, opts?.keyId) as T + return p256PrivateKeyToJwk(privateKeyP256, opts?.keyId) as AlgToPrivateKeyType[A] } case Alg.RS256: { const jwk = await generateRsaPrivateKey(opts) - return jwk as T + return jwk as AlgToPrivateKeyType[A] } case Alg.EDDSA: { const privateKeyEd25519 = toHex(ed25519.utils.randomPrivateKey()) - return ed25519PrivateKeyToJwk(privateKeyEd25519, opts?.keyId) as T + return ed25519PrivateKeyToJwk(privateKeyEd25519, opts?.keyId) as AlgToPrivateKeyType[A] } default: throw new Error(`Unsupported algorithm: ${alg}`) @@ -502,7 +502,7 @@ export const publicJwkToPem = async (jwk: Jwk): Promise => { export const publicHexToPem = async (publicKey: Hex, alg: Alg): Promise => { switch (alg) { case Alg.RS256: - return publicRsaJwkToPem((await publicKeyToJwk(publicKey, alg)) as RsaKey) + return publicRsaJwkToPem(publicKeyToJwk(publicKey, alg) as RsaKey) default: throw new Error('Unsupported algorithm') } From df2a2451ba13dcfcef4acaec38cfd46bae8c380d Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Mon, 30 Dec 2024 15:13:02 +0100 Subject: [PATCH 066/120] Add spans and logs on mission critical services (#59) --- .../src/broker/core/service/sync.service.ts | 60 +++++++++++++--- .../core/service/transfer-party.service.ts | 69 +++++++++++++++++-- .../broker/core/service/transfer.service.ts | 27 ++++++-- apps/vault/src/broker/shared/constant.ts | 7 ++ 4 files changed, 144 insertions(+), 19 deletions(-) create mode 100644 apps/vault/src/broker/shared/constant.ts diff --git a/apps/vault/src/broker/core/service/sync.service.ts b/apps/vault/src/broker/core/service/sync.service.ts index 48870a48d..2919ef416 100644 --- a/apps/vault/src/broker/core/service/sync.service.ts +++ b/apps/vault/src/broker/core/service/sync.service.ts @@ -2,9 +2,11 @@ import { LoggerService, PaginatedResult, TraceService } from '@narval/nestjs-sha import { NotImplementedException } from '@nestjs/common' import { Inject, Injectable } from '@nestjs/common/decorators' import { EventEmitter2 } from '@nestjs/event-emitter' +import { SpanStatusCode } from '@opentelemetry/api' import { zip } from 'lodash' import { v4 as uuid } from 'uuid' import { FindAllOptions, SyncRepository } from '../../persistence/repository/sync.repository' +import { OTEL_ATTR_CONNECTION_ID, OTEL_ATTR_CONNECTION_PROVIDER, OTEL_ATTR_SYNC_ID } from '../../shared/constant' import { SyncStartedEvent } from '../../shared/event/sync-started.event' import { AnchorageSyncService } from '../provider/anchorage/anchorage-sync.service' import { ActiveConnectionWithCredentials, Provider } from '../type/connection.type' @@ -38,8 +40,8 @@ export class SyncService { async start(connections: ActiveConnectionWithCredentials[]): Promise { this.logger.log('Start connections sync', { - count: connections.length, - ids: connections.map((connectionId) => connectionId) + connectionsCount: connections.length, + connectionIds: connections.map((connectionId) => connectionId) }) if (connections.length) { @@ -74,7 +76,29 @@ export class SyncService { } async sync(sync: Sync, connection: ActiveConnectionWithCredentials): Promise { + const { clientId, syncId } = sync + const { provider, connectionId } = connection + + this.logger.log('Sync connection', { + clientId, + syncId, + connectionId, + provider + }) + + const span = this.traceService.startSpan(`${SyncService.name}.sync`, { + attributes: { + [OTEL_ATTR_SYNC_ID]: syncId, + [OTEL_ATTR_CONNECTION_ID]: connectionId, + [OTEL_ATTR_CONNECTION_PROVIDER]: provider + } + }) + const result = await this.getProviderSyncService(connection.provider).sync(connection) + + // The execute method has its own span. + span.end() + const updatedSync = await this.execute(sync, result) return updatedSync @@ -107,6 +131,10 @@ export class SyncService { const { clientId, syncId } = sync + const span = this.traceService.startSpan(`${SyncService.name}.execute`, { + attributes: { [OTEL_ATTR_SYNC_ID]: syncId } + }) + const walletCreateOperations = result.wallets.filter(isCreateOperation).map(({ create }) => create) const walletUpdateOperations = result.wallets.filter(isUpdateOperation).map(({ update }) => update) const walletDeleteOperations = result.wallets.filter(isDeleteOperation).map(({ entityId }) => entityId) @@ -216,13 +244,18 @@ export class SyncService { return await this.complete(sync) } catch (error) { return await this.fail(sync, error) + } finally { + span.end() } } async complete(sync: Sync): Promise { - this.logger.log('Sync complete', { - clientId: sync.clientId, - syncId: sync.syncId + const { clientId, syncId } = sync + + this.logger.log('Sync complete', { clientId, syncId }) + + const span = this.traceService.startSpan(`${SyncService.name}.complete`, { + attributes: { [OTEL_ATTR_SYNC_ID]: syncId } }) const completedSync = { @@ -233,16 +266,23 @@ export class SyncService { await this.syncRepository.update(completedSync) + span.end() + return completedSync } async fail(sync: Sync, error: Error): Promise { - this.logger.log('Sync fail', { - clientId: sync.clientId, - syncId: sync.syncId, - error + const { clientId, syncId } = sync + + this.logger.log('Sync fail', { clientId, syncId, error }) + + const span = this.traceService.startSpan(`${SyncService.name}.fail`, { + attributes: { [OTEL_ATTR_SYNC_ID]: syncId } }) + span.recordException(error) + span.setStatus({ code: SpanStatusCode.ERROR }) + const failedSync = { ...sync, status: SyncStatus.FAILED, @@ -256,6 +296,8 @@ export class SyncService { await this.syncRepository.update(failedSync) + span.end() + return failedSync } diff --git a/apps/vault/src/broker/core/service/transfer-party.service.ts b/apps/vault/src/broker/core/service/transfer-party.service.ts index dd75706f5..36882313f 100644 --- a/apps/vault/src/broker/core/service/transfer-party.service.ts +++ b/apps/vault/src/broker/core/service/transfer-party.service.ts @@ -1,4 +1,6 @@ -import { HttpStatus, Injectable } from '@nestjs/common' +import { LoggerService, TraceService } from '@narval/nestjs-shared' +import { HttpStatus, Inject, Injectable } from '@nestjs/common' +import { SpanStatusCode } from '@opentelemetry/api' import { AccountRepository } from '../../persistence/repository/account.repository' import { AddressRepository } from '../../persistence/repository/address.repository' import { KnownDestinationRepository } from '../../persistence/repository/known-destination.repository' @@ -13,14 +15,43 @@ export class TransferPartyService { private readonly walletRepository: WalletRepository, private readonly accountRepository: AccountRepository, private readonly addressRepository: AddressRepository, - private readonly knownDestinationRepository: KnownDestinationRepository + private readonly knownDestinationRepository: KnownDestinationRepository, + private readonly logger: LoggerService, + @Inject(TraceService) private readonly traceService: TraceService ) {} async resolve( clientId: string, transferParty: Source | Destination ): Promise { + const span = this.traceService.startSpan(`${TransferPartyService.name}.resolve`) + + try { + return this.findTransferParty(clientId, transferParty) + } catch (error) { + this.logger.error('Unable to resolve transfer party', { clientId, transferParty, error }) + + span.recordException(error) + span.setStatus({ code: SpanStatusCode.ERROR }) + span.end() + + throw error + } finally { + span.end() + } + } + + private async findTransferParty( + clientId: string, + transferParty: Source | Destination + ): Promise { + this.logger.log('Find transfer party', { clientId, transferParty }) + if (isAddressDestination(transferParty)) { + const rawAddress = transferParty.address + + this.logger.log('Starting search address destination by raw address', { clientId, rawAddress }) + const { data: addresses } = await this.addressRepository.findAll(clientId, { filters: { addresses: [transferParty.address] @@ -33,14 +64,22 @@ export class TransferPartyService { message: 'Cannot resolve the right address due to ambiguity', suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, context: { + clientId, addresses: addresses.map(({ address, addressId }) => ({ addressId, address })) } }) } + this.logger.log('Successfully found address destination for raw address', { + clientId, + address: addresses[0] + }) + return addresses[0] } + this.logger.log('Starting search known destination by raw address', { clientId, rawAddress }) + const { data: knownDestinations } = await this.knownDestinationRepository.findAll(clientId, { filters: { addresses: [transferParty.address] @@ -53,31 +92,49 @@ export class TransferPartyService { message: 'Cannot resolve the known destination due to ambiguity', suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, context: { + clientId, addresses: knownDestinations.map(({ address, knownDestinationId }) => ({ knownDestinationId, address })) } }) } + this.logger.log('Successfully found known destination for raw address', { + clientId, + knownDestination: knownDestinations[0] + }) + return knownDestinations[0] } throw new BrokerException({ message: 'Cannot resolve destination address', suggestedHttpStatusCode: HttpStatus.NOT_FOUND, - context: { transferParty } + context: { clientId, transferParty } }) } if (transferParty.type === TransferPartyType.WALLET) { - return this.walletRepository.findById(clientId, transferParty.id) + this.logger.log('Starting search for wallet by ID', { clientId, walletId: transferParty.id }) + const wallet = await this.walletRepository.findById(clientId, transferParty.id) + this.logger.log('Successfully found wallet', { clientId, wallet }) + + return wallet } if (transferParty.type === TransferPartyType.ACCOUNT) { - return this.accountRepository.findById(clientId, transferParty.id) + this.logger.log('Starting search for account by ID', { clientId, accountId: transferParty.id }) + const account = await this.accountRepository.findById(clientId, transferParty.id) + this.logger.log('Successfully found account', { clientId, account }) + + return account } if (transferParty.type === TransferPartyType.ADDRESS) { - return this.addressRepository.findById(clientId, transferParty.id) + this.logger.log('Starting search for address by ID', { clientId, addressId: transferParty.id }) + const address = await this.addressRepository.findById(clientId, transferParty.id) + this.logger.log('Successfully found address', { clientId, address }) + + return address } throw new BrokerException({ diff --git a/apps/vault/src/broker/core/service/transfer.service.ts b/apps/vault/src/broker/core/service/transfer.service.ts index acc33e82a..f1601bfca 100644 --- a/apps/vault/src/broker/core/service/transfer.service.ts +++ b/apps/vault/src/broker/core/service/transfer.service.ts @@ -1,6 +1,8 @@ -import { LoggerService } from '@narval/nestjs-shared' -import { HttpStatus, Injectable, NotImplementedException } from '@nestjs/common' +import { LoggerService, TraceService } from '@narval/nestjs-shared' +import { HttpStatus, Inject, Injectable, NotImplementedException } from '@nestjs/common' +import { SpanStatusCode } from '@opentelemetry/api' import { TransferRepository } from '../../persistence/repository/transfer.repository' +import { OTEL_ATTR_CONNECTION_PROVIDER } from '../../shared/constant' import { BrokerException } from '../exception/broker.exception' import { AnchorageTransferService } from '../provider/anchorage/anchorage-transfer.service' import { ConnectionStatus, Provider, isActiveConnection } from '../type/connection.type' @@ -16,7 +18,8 @@ export class TransferService { private readonly connectionService: ConnectionService, private readonly transferPartyService: TransferPartyService, private readonly anchorageTransferService: AnchorageTransferService, - private readonly logger: LoggerService + private readonly logger: LoggerService, + @Inject(TraceService) private readonly traceService: TraceService ) {} async findById(clientId: string, transferId: string): Promise { @@ -30,6 +33,8 @@ export class TransferService { async send(clientId: string, sendTransfer: SendTransfer): Promise { this.logger.log('Send transfer', { clientId, sendTransfer }) + const span = this.traceService.startSpan(`${TransferService.name}.sync`) + const source = await this.transferPartyService.resolve(clientId, sendTransfer.source) const { data: connections } = await this.connectionService.findAll( clientId, @@ -42,9 +47,23 @@ export class TransferService { ) if (connections.length && isActiveConnection(connections[0])) { - return this.getProviderTransferService(source.provider).send(connections[0], sendTransfer) + const [connection] = connections + + span.setAttribute(OTEL_ATTR_CONNECTION_PROVIDER, connection.provider) + + const transfer = await this.getProviderTransferService(source.provider).send(connection, sendTransfer) + + span.end() + + return transfer } + span.setStatus({ + code: SpanStatusCode.ERROR, + message: 'Cannot find an active connection for the source' + }) + span.end() + throw new BrokerException({ message: 'Cannot find an active connection for the source', suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, diff --git a/apps/vault/src/broker/shared/constant.ts b/apps/vault/src/broker/shared/constant.ts new file mode 100644 index 000000000..bfcac904e --- /dev/null +++ b/apps/vault/src/broker/shared/constant.ts @@ -0,0 +1,7 @@ +// +// OpenTelemetry +// + +export const OTEL_ATTR_SYNC_ID = 'sync.id' +export const OTEL_ATTR_CONNECTION_ID = 'connection.id' +export const OTEL_ATTR_CONNECTION_PROVIDER = 'connection.provider' From 43457d6588d8f307cd437ade5bdbb0a6db6805d3 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Tue, 31 Dec 2024 12:41:06 +0100 Subject: [PATCH 067/120] Support base convert operations for RSA private key (#62) --- package-lock.json | 2 +- packages/armory-sdk/package.json | 2 +- .../src/lib/__test__/unit/util.spec.ts | 44 +++++++++++++++++ packages/signature/src/lib/utils.ts | 48 ++++++++++++++++++- 4 files changed, 93 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7f84743c1..847870119 100644 --- a/package-lock.json +++ b/package-lock.json @@ -46204,7 +46204,7 @@ }, "packages/armory-sdk": { "name": "@narval-xyz/armory-sdk", - "version": "0.13.0", + "version": "0.14.0", "license": "MPL-2.0", "dependencies": { "@noble/curves": "1.6.0", diff --git a/packages/armory-sdk/package.json b/packages/armory-sdk/package.json index b88214d9c..01368820a 100644 --- a/packages/armory-sdk/package.json +++ b/packages/armory-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@narval-xyz/armory-sdk", - "version": "0.13.0", + "version": "0.14.0", "license": "MPL-2.0", "publishConfig": { "access": "public" diff --git a/packages/signature/src/lib/__test__/unit/util.spec.ts b/packages/signature/src/lib/__test__/unit/util.spec.ts index af74a76e5..5016c55fe 100644 --- a/packages/signature/src/lib/__test__/unit/util.spec.ts +++ b/packages/signature/src/lib/__test__/unit/util.spec.ts @@ -10,7 +10,9 @@ import { buildSignerEip191, signJwt } from '../../sign' import { Alg, Header, + Hex, Jwk, + RsaPrivateKey, Secp256k1PrivateKey, SigningAlg, p256PublicKeySchema, @@ -22,8 +24,11 @@ import { ed25519polyfilled, ellipticPrivateKeyToHex, generateJwk, + privateJwkToPem, privateKeyToHex, privateKeyToJwk, + privateKeyToPem, + privateRsaPemToJwk, publicKeyToHex, publicKeyToJwk, publicKeyToPem, @@ -342,6 +347,45 @@ kwIDAQAB }) }) +describe('privateJwkToPem', () => { + it('maps round-trip private rsa key to pem', async () => { + const privateKey = await generateJwk(Alg.RS256, { modulusLength: SMALLEST_RSA_MODULUS_LENGTH }) + const pem = await privateJwkToPem(privateKey) + + const roundTripJwk = await privateRsaPemToJwk(pem) + + expect(roundTripJwk).toEqual(privateKey) + }) + + it('throws when privateJwkToPem fails', async () => { + const invalidJwk = { kty: 'RSA' } as RsaPrivateKey + + await expect(privateKeyToPem(invalidJwk, Alg.RS256)).rejects.toThrow() + }) +}) + +describe('privateKeyToPem', () => { + it('maps round-trip private rsa jwk to pem', async () => { + const privateKey = await generateJwk(Alg.RS256, { modulusLength: SMALLEST_RSA_MODULUS_LENGTH }) + const pem = await privateKeyToPem(privateKey, Alg.RS256) + const roundTripJwk = await privateRsaPemToJwk(pem) + + expect(roundTripJwk).toEqual(privateKey) + }) + + it('throws error when invalid hex is provided', async () => { + const invalidHex = 'invalid-hex' as Hex + await expect(privateKeyToPem(invalidHex, Alg.RS256)).rejects.toThrow() + }) + + it('throws error when invalid jwk is provided', async () => { + // Missing required JWK parameters + const invalidJwk = { kty: 'RSA' } as Jwk + + await expect(privateKeyToPem(invalidJwk, Alg.RS256)).rejects.toThrow() + }) +}) + describe('hashRequestWithoutWildcardFields', () => { const transaction = { chainId: 137, diff --git a/packages/signature/src/lib/utils.ts b/packages/signature/src/lib/utils.ts index 2931d9f87..79c22981f 100644 --- a/packages/signature/src/lib/utils.ts +++ b/packages/signature/src/lib/utils.ts @@ -4,7 +4,7 @@ import * as ed25519 from '@noble/ed25519' import { sha256 as sha256Hash } from '@noble/hashes/sha256' import { sha512 } from '@noble/hashes/sha512' import { subtle } from 'crypto' -import { exportJWK, exportSPKI, generateKeyPair, importJWK, importSPKI, KeyLike } from 'jose' +import { exportJWK, exportPKCS8, exportSPKI, generateKeyPair, importJWK, importPKCS8, importSPKI, KeyLike } from 'jose' import { cloneDeep, omit } from 'lodash' import { toHex } from 'viem' import { publicKeyToAddress } from 'viem/utils' @@ -544,6 +544,52 @@ export const publicPemToJwk = (pem: string, alg: Alg, kid?: string): T } } +export const privateJwkToPem = async (jwk: Jwk): Promise => { + switch (jwk.kty) { + case KeyTypes.RSA: + return privateRsaJwkToPem(jwk as RsaKey) + default: + throw new Error('Unsupported key type') + } +} + +export const privateRsaJwkToPem = async (rsaJwk: RsaKey): Promise => { + const jk = (await importJWK(rsaJwk, 'RS256')) as KeyLike + const k = await exportPKCS8(jk) + return k +} + +export const privateRsaPemToJwk = async (pem: string, opts?: { kid?: string }): Promise => { + const jk = await importPKCS8(pem, 'RS256', { + extractable: true + }) + + const key = await exportJWK(jk) + + return rsaPrivateKeySchema.parse({ + ...key, + alg: 'RS256', + kid: opts?.kid || rsaKeyToKid({ n: key.n, e: key.e }) + }) +} + +export const privateKeyToPem = async (privateKey: Jwk | Hex, alg: Alg): Promise => { + if (typeof privateKey === 'string') { + return privateHexToPem(privateKey, alg) + } + + return privateJwkToPem(privateKey) +} + +export const privateHexToPem = async (privateKey: Hex, alg: Alg): Promise => { + switch (alg) { + case Alg.RS256: + return privateRsaJwkToPem(privateKeyToJwk(privateKey, alg) as RsaKey) + default: + throw new Error('Unsupported algorithm') + } +} + export const nowSeconds = (): number => Math.floor(Date.now() / 1000) type AlgToPublicKeyType = { From cf926d7e4abb5a31cb636458fa4270693435e5a4 Mon Sep 17 00:00:00 2001 From: Ptroger <44851272+Ptroger@users.noreply.github.com> Date: Thu, 2 Jan 2025 15:48:58 +0100 Subject: [PATCH 068/120] correctly pass pagination through known-destinations (#67) --- .../__test__/e2e/known-destinations.spec.ts | 36 +++++++++++++++++++ .../known-destination.controller.ts | 15 ++++---- 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/apps/vault/src/broker/__test__/e2e/known-destinations.spec.ts b/apps/vault/src/broker/__test__/e2e/known-destinations.spec.ts index 2cdff5264..d95a35a37 100644 --- a/apps/vault/src/broker/__test__/e2e/known-destinations.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/known-destinations.spec.ts @@ -289,6 +289,42 @@ describe('KnownDestination', () => { }) expect(status).toBe(HttpStatus.OK) }) + + it('returns known destinations for a connection with pagination', async () => { + const { status, body } = await request(app.getHttpServer()) + .get('/provider/known-destinations') + .set(REQUEST_HEADER_CLIENT_ID, testClient.clientId) + .query({ connectionId: connection1Id, limit: 1 }) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: `/provider/known-destinations?connectionId=${connection1Id}&limit=1`, + payload: {}, + htm: 'GET' + }) + ) + + const expectedDestinations = [knownDestinations[0]] + expect(body).toEqual({ + data: expectedDestinations.map((knownDestination) => ({ + ...knownDestination, + createdAt: now.toISOString(), + updatedAt: now.toISOString(), + connections: knownDestination.connections.map((connection) => ({ + updatedAt: expect.any(String), + createdAt: expect.any(String), + status: connection.status, + provider: connection.provider, + url: connection.url, + connectionId: connection.connectionId, + clientId: connection.clientId + })) + })), + page: { next: 'MjAyNS0wMS0wMVQwMDowMDowMC4wMDBafGMyZjdkMmYxLWUwYjUtNDk2Ni1hNTVmLTcyNTc0MjBkZjgxZg==' } + }) + expect(status).toBe(HttpStatus.OK) + }) }) describe('GET /provider/known-destinations/:knownDestinationId', () => { diff --git a/apps/vault/src/broker/http/rest/controller/known-destination.controller.ts b/apps/vault/src/broker/http/rest/controller/known-destination.controller.ts index fc20c4f50..4b9f0e4da 100644 --- a/apps/vault/src/broker/http/rest/controller/known-destination.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/known-destination.controller.ts @@ -1,4 +1,4 @@ -import { ApiClientIdHeader, PaginationOptions, PaginationParam } from '@narval/nestjs-shared' +import { ApiClientIdHeader, Paginated, PaginationOptions, PaginationParam } from '@narval/nestjs-shared' import { Controller, Get, HttpStatus, Param, Query } from '@nestjs/common' import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../shared/decorator/client-id.decorator' @@ -20,21 +20,20 @@ export class KnownDestinationController { @Get() @PermissionGuard(VaultPermission.CONNECTION_READ) @ApiOperation({ summary: 'Get known destinations across providers' }) - @ApiResponse({ - status: HttpStatus.OK, - description: 'Returns paginated known destinations', - type: PaginatedKnownDestinationsDto + @Paginated({ + type: PaginatedKnownDestinationsDto, + description: 'Returns a paginated list of known-destinations for the client' }) async list( @ClientId() clientId: string, - @PaginationParam() paginationOptions: PaginationOptions, + @PaginationParam() pagination: PaginationOptions, @Query('connectionId') connectionId?: string ): Promise { const filters = connectionId ? { connections: [connectionId] } : {} const { data, page } = await this.knownDestinationService.findAll(clientId, { - ...paginationOptions, - filters + filters, + pagination }) return PaginatedKnownDestinationsDto.create({ data, page }) From 5183e512c7fb111aa29b792f471c9baa80054cd7 Mon Sep 17 00:00:00 2001 From: Matt Schoch Date: Thu, 2 Jan 2025 16:17:25 +0100 Subject: [PATCH 069/120] SDK v0.15.0 - vault provider sdk - add all new endpoints (#66) * Allow SDK to do jwsd without binding to an access token; fix jwsd created verification * Generate Vault OpenApi sdk with known-destination endpoints * Expose Provider SDK endpoints in VaultClient * Adding e2e scenario test for using SDK with a Vault client for Provider endpoints * Adding the missing pagination fields into Known Desitnation query in sdk * SDK v0.15.0 bump --- package-lock.json | 2 +- .../e2e/scenario/vault-provider.spec.ts | 152 +++++ packages/armory-sdk/README.md | 4 +- packages/armory-sdk/package.json | 2 +- .../src/lib/http/client/vault/api.ts | 444 +++++++++++++ .../src/lib/shared/__test__/unit/gnap.spec.ts | 97 ++- packages/armory-sdk/src/lib/shared/gnap.ts | 41 +- packages/armory-sdk/src/lib/vault/client.ts | 589 +++++++++++++++++- packages/signature/src/lib/verify.ts | 9 + 9 files changed, 1307 insertions(+), 33 deletions(-) create mode 100644 packages/armory-e2e-testing/src/__test__/e2e/scenario/vault-provider.spec.ts diff --git a/package-lock.json b/package-lock.json index 847870119..1bfb80e11 100644 --- a/package-lock.json +++ b/package-lock.json @@ -46204,7 +46204,7 @@ }, "packages/armory-sdk": { "name": "@narval-xyz/armory-sdk", - "version": "0.14.0", + "version": "0.15.0", "license": "MPL-2.0", "dependencies": { "@noble/curves": "1.6.0", diff --git a/packages/armory-e2e-testing/src/__test__/e2e/scenario/vault-provider.spec.ts b/packages/armory-e2e-testing/src/__test__/e2e/scenario/vault-provider.spec.ts new file mode 100644 index 000000000..565342aef --- /dev/null +++ b/packages/armory-e2e-testing/src/__test__/e2e/scenario/vault-provider.spec.ts @@ -0,0 +1,152 @@ +import { ClientDto, VaultAdminClient, VaultClient } from '@narval/armory-sdk' +import { + Alg, + Ed25519PrivateKey, + Ed25519PublicKey, + buildSignerForAlg, + generateJwk, + getPublicKey +} from '@narval/signature' +import { InitiateConnectionDtoProviderEnum } from 'packages/armory-sdk/src/lib/http/client/vault/api' +import { v4 as uuid } from 'uuid' + +const TEST_TIMEOUT_MS = 30_000 + +jest.setTimeout(TEST_TIMEOUT_MS) + +let userPrivateKey: Ed25519PrivateKey +let userPublicKey: Ed25519PublicKey + +const VAULT_HOST_URL = 'http://localhost:3011' + +const VAULT_ADMIN_API_KEY = 'vault-admin-api-key' + +// IMPORTANT: The order of tests matters. +// These tests are meant to be run in series, not in parallel, because they +// represent an end-to-end user journey. +describe('User Journeys', () => { + let clientVault: ClientDto + const clientId = uuid() + + beforeAll(async () => { + userPrivateKey = await generateJwk(Alg.EDDSA) + userPublicKey = getPublicKey(userPrivateKey) + }) + + describe('As an admin', () => { + const vaultAdminClient = new VaultAdminClient({ + host: VAULT_HOST_URL, + adminApiKey: VAULT_ADMIN_API_KEY + }) + + it('I can create a new client in the vault', async () => { + clientVault = await vaultAdminClient.createClient({ + clientId, + name: `provider-e2e-testing-${clientId}`, + baseUrl: VAULT_HOST_URL, + auth: { + local: { + jwsd: { + maxAge: 300, + requiredComponents: ['htm', 'uri', 'created', 'ath'] + }, + allowedUsers: [ + { + userId: 'provider-e2e-testing-user-123', + publicKey: userPublicKey + } + ] + }, + tokenValidation: { + disabled: true + } + } + }) + + expect(clientVault).toEqual({ + clientId, + name: expect.any(String), + backupPublicKey: null, + baseUrl: VAULT_HOST_URL, + configurationSource: 'dynamic', + auth: { + disabled: false, + local: { + jwsd: { + maxAge: 300, + requiredComponents: ['htm', 'uri', 'created', 'ath'] + }, + allowedUsersJwksUrl: null, + allowedUsers: [ + { + userId: 'provider-e2e-testing-user-123', + publicKey: userPublicKey + } + ] + }, + tokenValidation: { + disabled: true, + url: null, + jwksUrl: null, + pinnedPublicKey: null, + verification: { + audience: null, + issuer: null, + maxTokenAge: null, + requireBoundTokens: true, + allowBearerTokens: false, + allowWildcard: null + } + } + }, + createdAt: expect.any(String), + updatedAt: expect.any(String) + }) + }) + }) + + describe('As a client', () => { + let vaultClient: VaultClient + + beforeAll(async () => { + vaultClient = new VaultClient({ + host: VAULT_HOST_URL, + clientId, + signer: { + jwk: userPublicKey, + alg: userPrivateKey.alg, + sign: await buildSignerForAlg(userPrivateKey) + } + }) + }) + + describe('I want to interact with the vault', () => { + it('I can generate an encryption key', async () => { + const encryptionKey = await vaultClient.generateEncryptionKey() + + expect(encryptionKey.alg).toEqual('RS256') + expect(encryptionKey.kty).toEqual('RSA') + expect(encryptionKey.use).toEqual('enc') + }) + + it('I can list connections', async () => { + const connections = await vaultClient.listConnections() + + expect(connections).toEqual({ + data: [], + page: { next: null } + }) + }) + + it('I can initiate a connection', async () => { + const connection = await vaultClient.initiateConnection({ + data: { + provider: InitiateConnectionDtoProviderEnum.Anchorage + } + }) + + expect(connection.data.connectionId).toBeDefined() + }) + }) + }) +}) diff --git a/packages/armory-sdk/README.md b/packages/armory-sdk/README.md index 5ff07d7bd..7a9bf4483 100644 --- a/packages/armory-sdk/README.md +++ b/packages/armory-sdk/README.md @@ -24,8 +24,8 @@ make armory/start/dev make policy-engine/start/dev make vault/start/dev -make armory-sdk/test/e2e -make armory-sdk/test/e2e/watch +make armory-e2e-testing/test/e2e +make armory-e2e-testing/test/e2e/watch ``` The tests MUST run in series because each step depends on state changes from diff --git a/packages/armory-sdk/package.json b/packages/armory-sdk/package.json index 01368820a..f7f974458 100644 --- a/packages/armory-sdk/package.json +++ b/packages/armory-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@narval-xyz/armory-sdk", - "version": "0.14.0", + "version": "0.15.0", "license": "MPL-2.0", "publishConfig": { "access": "public" diff --git a/packages/armory-sdk/src/lib/http/client/vault/api.ts b/packages/armory-sdk/src/lib/http/client/vault/api.ts index 7638bb3d6..509d52c33 100644 --- a/packages/armory-sdk/src/lib/http/client/vault/api.ts +++ b/packages/armory-sdk/src/lib/http/client/vault/api.ts @@ -1284,6 +1284,19 @@ export const InitiateConnectionDtoProviderEnum = { export type InitiateConnectionDtoProviderEnum = typeof InitiateConnectionDtoProviderEnum[keyof typeof InitiateConnectionDtoProviderEnum]; +/** + * + * @export + * @interface KnownDestinationDto + */ +export interface KnownDestinationDto { + /** + * + * @type {PaginatedKnownDestinationsDtoDataInner} + * @memberof KnownDestinationDto + */ + 'data': PaginatedKnownDestinationsDtoDataInner; +} /** * * @export @@ -1490,6 +1503,111 @@ export interface PaginatedConnectionsDto { */ 'page'?: PaginatedAccountsDtoPage; } +/** + * + * @export + * @interface PaginatedKnownDestinationsDto + */ +export interface PaginatedKnownDestinationsDto { + /** + * + * @type {Array} + * @memberof PaginatedKnownDestinationsDto + */ + 'data': Array; + /** + * + * @type {PaginatedAccountsDtoPage} + * @memberof PaginatedKnownDestinationsDto + */ + 'page'?: PaginatedAccountsDtoPage; +} +/** + * + * @export + * @interface PaginatedKnownDestinationsDtoDataInner + */ +export interface PaginatedKnownDestinationsDtoDataInner { + /** + * + * @type {string} + * @memberof PaginatedKnownDestinationsDtoDataInner + */ + 'knownDestinationId': string; + /** + * + * @type {string} + * @memberof PaginatedKnownDestinationsDtoDataInner + */ + 'clientId': string; + /** + * + * @type {Array} + * @memberof PaginatedKnownDestinationsDtoDataInner + */ + 'connections': Array; + /** + * + * @type {string} + * @memberof PaginatedKnownDestinationsDtoDataInner + */ + 'provider': PaginatedKnownDestinationsDtoDataInnerProviderEnum; + /** + * + * @type {string} + * @memberof PaginatedKnownDestinationsDtoDataInner + */ + 'label'?: string | null; + /** + * + * @type {string} + * @memberof PaginatedKnownDestinationsDtoDataInner + */ + 'externalId': string; + /** + * + * @type {string} + * @memberof PaginatedKnownDestinationsDtoDataInner + */ + 'externalClassification'?: string | null; + /** + * + * @type {string} + * @memberof PaginatedKnownDestinationsDtoDataInner + */ + 'address': string; + /** + * + * @type {string} + * @memberof PaginatedKnownDestinationsDtoDataInner + */ + 'assetId'?: string | null; + /** + * + * @type {string} + * @memberof PaginatedKnownDestinationsDtoDataInner + */ + 'networkId': string; + /** + * + * @type {any} + * @memberof PaginatedKnownDestinationsDtoDataInner + */ + 'createdAt': any; + /** + * + * @type {any} + * @memberof PaginatedKnownDestinationsDtoDataInner + */ + 'updatedAt': any; +} + +export const PaginatedKnownDestinationsDtoDataInnerProviderEnum = { + Anchorage: 'anchorage' +} as const; + +export type PaginatedKnownDestinationsDtoDataInnerProviderEnum = typeof PaginatedKnownDestinationsDtoDataInnerProviderEnum[keyof typeof PaginatedKnownDestinationsDtoDataInnerProviderEnum]; + /** * * @export @@ -5687,6 +5805,332 @@ export class ProviderConnectionApi extends BaseAPI { +/** + * ProviderKnownDestinationApi - axios parameter creator + * @export + */ +export const ProviderKnownDestinationApiAxiosParamCreator = function (configuration?: Configuration) { + return { + /** + * + * @summary Get known destination by ID + * @param {string} xClientId + * @param {string} knownDestinationId + * @param {string} [authorization] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getById: async (xClientId: string, knownDestinationId: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('getById', 'xClientId', xClientId) + // verify required parameter 'knownDestinationId' is not null or undefined + assertParamExists('getById', 'knownDestinationId', knownDestinationId) + const localVarPath = `/v1/provider/known-destinations/{knownDestinationId}` + .replace(`{${"knownDestinationId"}}`, encodeURIComponent(String(knownDestinationId))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @summary Get known destinations across providers + * @param {string} xClientId + * @param {string} connectionId + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [authorization] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + list: async (xClientId: string, connectionId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('list', 'xClientId', xClientId) + // verify required parameter 'connectionId' is not null or undefined + assertParamExists('list', 'connectionId', connectionId) + const localVarPath = `/v1/provider/known-destinations`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + + if (connectionId !== undefined) { + localVarQueryParameter['connectionId'] = connectionId; + } + + if (cursor !== undefined) { + localVarQueryParameter['cursor'] = cursor; + } + + if (limit !== undefined) { + localVarQueryParameter['limit'] = limit; + } + + if (orderBy !== undefined) { + localVarQueryParameter['orderBy'] = orderBy; + } + + if (desc !== undefined) { + localVarQueryParameter['desc'] = desc; + } + + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + } +}; + +/** + * ProviderKnownDestinationApi - functional programming interface + * @export + */ +export const ProviderKnownDestinationApiFp = function(configuration?: Configuration) { + const localVarAxiosParamCreator = ProviderKnownDestinationApiAxiosParamCreator(configuration) + return { + /** + * + * @summary Get known destination by ID + * @param {string} xClientId + * @param {string} knownDestinationId + * @param {string} [authorization] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getById(xClientId: string, knownDestinationId: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getById(xClientId, knownDestinationId, authorization, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderKnownDestinationApi.getById']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + /** + * + * @summary Get known destinations across providers + * @param {string} xClientId + * @param {string} connectionId + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [authorization] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async list(xClientId: string, connectionId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.list(xClientId, connectionId, cursor, limit, orderBy, desc, authorization, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderKnownDestinationApi.list']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + } +}; + +/** + * ProviderKnownDestinationApi - factory interface + * @export + */ +export const ProviderKnownDestinationApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { + const localVarFp = ProviderKnownDestinationApiFp(configuration) + return { + /** + * + * @summary Get known destination by ID + * @param {ProviderKnownDestinationApiGetByIdRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getById(requestParameters: ProviderKnownDestinationApiGetByIdRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.getById(requestParameters.xClientId, requestParameters.knownDestinationId, requestParameters.authorization, options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary Get known destinations across providers + * @param {ProviderKnownDestinationApiListRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + list(requestParameters: ProviderKnownDestinationApiListRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.list(requestParameters.xClientId, requestParameters.connectionId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(axios, basePath)); + }, + }; +}; + +/** + * Request parameters for getById operation in ProviderKnownDestinationApi. + * @export + * @interface ProviderKnownDestinationApiGetByIdRequest + */ +export interface ProviderKnownDestinationApiGetByIdRequest { + /** + * + * @type {string} + * @memberof ProviderKnownDestinationApiGetById + */ + readonly xClientId: string + + /** + * + * @type {string} + * @memberof ProviderKnownDestinationApiGetById + */ + readonly knownDestinationId: string + + /** + * + * @type {string} + * @memberof ProviderKnownDestinationApiGetById + */ + readonly authorization?: string +} + +/** + * Request parameters for list operation in ProviderKnownDestinationApi. + * @export + * @interface ProviderKnownDestinationApiListRequest + */ +export interface ProviderKnownDestinationApiListRequest { + /** + * + * @type {string} + * @memberof ProviderKnownDestinationApiList + */ + readonly xClientId: string + + /** + * + * @type {string} + * @memberof ProviderKnownDestinationApiList + */ + readonly connectionId: string + + /** + * Cursor for pagination. Use the next cursor from previous response to get next page + * @type {string} + * @memberof ProviderKnownDestinationApiList + */ + readonly cursor?: string + + /** + * Number of records to return per page + * @type {number} + * @memberof ProviderKnownDestinationApiList + */ + readonly limit?: number + + /** + * Field to order results by + * @type {string} + * @memberof ProviderKnownDestinationApiList + */ + readonly orderBy?: string + + /** + * Set to \"true\" or \"1\" for descending order + * @type {string} + * @memberof ProviderKnownDestinationApiList + */ + readonly desc?: string + + /** + * + * @type {string} + * @memberof ProviderKnownDestinationApiList + */ + readonly authorization?: string +} + +/** + * ProviderKnownDestinationApi - object-oriented interface + * @export + * @class ProviderKnownDestinationApi + * @extends {BaseAPI} + */ +export class ProviderKnownDestinationApi extends BaseAPI { + /** + * + * @summary Get known destination by ID + * @param {ProviderKnownDestinationApiGetByIdRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderKnownDestinationApi + */ + public getById(requestParameters: ProviderKnownDestinationApiGetByIdRequest, options?: RawAxiosRequestConfig) { + return ProviderKnownDestinationApiFp(this.configuration).getById(requestParameters.xClientId, requestParameters.knownDestinationId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * + * @summary Get known destinations across providers + * @param {ProviderKnownDestinationApiListRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderKnownDestinationApi + */ + public list(requestParameters: ProviderKnownDestinationApiListRequest, options?: RawAxiosRequestConfig) { + return ProviderKnownDestinationApiFp(this.configuration).list(requestParameters.xClientId, requestParameters.connectionId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + } +} + + + /** * ProviderProxyApi - axios parameter creator * @export diff --git a/packages/armory-sdk/src/lib/shared/__test__/unit/gnap.spec.ts b/packages/armory-sdk/src/lib/shared/__test__/unit/gnap.spec.ts index e0ed6b4a2..f39d51521 100644 --- a/packages/armory-sdk/src/lib/shared/__test__/unit/gnap.spec.ts +++ b/packages/armory-sdk/src/lib/shared/__test__/unit/gnap.spec.ts @@ -1,7 +1,16 @@ -import { SigningAlg, buildSignerForAlg, privateKeyToJwk } from '@narval/signature' +import { + SigningAlg, + buildSignerForAlg, + hash, + hexToBase64Url, + privateKeyToHex, + privateKeyToJwk, + secp256k1PrivateKeyToPublicJwk, + verifyJwsd +} from '@narval/signature' import { AxiosHeaders, InternalAxiosRequestConfig } from 'axios' import { generatePrivateKey } from 'viem/accounts' -import { REQUEST_HEADER_DETACHED_JWS, interceptRequestAddDetachedJwsHeader } from '../../gnap' +import { REQUEST_HEADER_DETACHED_JWS, interceptRequestAddDetachedJwsHeader, parseToken } from '../../gnap' import { Signer } from '../../type' describe('interceptRequestAddDetachedJwsHeader', () => { @@ -20,7 +29,8 @@ describe('interceptRequestAddDetachedJwsHeader', () => { interceptor = interceptRequestAddDetachedJwsHeader(signer) }) - it(`adds ${REQUEST_HEADER_DETACHED_JWS} header with jws`, async () => { + it(`adds ${REQUEST_HEADER_DETACHED_JWS} header with jws, bound to Authorization header token`, async () => { + expect.assertions(2) const data = { foo: 'bar' } const config = { transitional: { @@ -50,6 +60,87 @@ describe('interceptRequestAddDetachedJwsHeader', () => { const signature = actualConfig.headers.get(REQUEST_HEADER_DETACHED_JWS) + const verified = await verifyJwsd( + signature as string, + secp256k1PrivateKeyToPublicJwk(await privateKeyToHex(signer.jwk)), + { + uri: 'http://localhost:3011/accounts/import', + htm: 'POST', + maxTokenAge: 60, + requestBody: data + } + ) + + expect(signature).toEqual(expect.any(String)) + expect(verified.header.ath).toEqual( + hexToBase64Url( + hash( + 'eyJhbGciOiJFSVAxOTEiLCJraWQiOiIweDAwNjgxM2ZlNDIwODRhZDUyM2M1ZmJjODY5NTlmNjYxNWY4MjA3NGQ3YTE5YjFiMGNiZTIyYmNkY2I2ODI3ZTUiLCJ0eXAiOiJKV1QifQ.eyJhY2Nlc3MiOlt7InBlcm1pc3Npb25zIjpbIndhbGxldDppbXBvcnQiLCJ3YWxsZXQ6Y3JlYXRlIiwid2FsbGV0OnJlYWQiXSwicmVzb3VyY2UiOiJ2YXVsdCJ9XSwiY25mIjp7ImFsZyI6IkVTMjU2SyIsImNydiI6InNlY3AyNTZrMSIsImtpZCI6IjB4YTc2MzQzMTAyYzMwMjM5MTIxYmIxZDUyOWY3ODg3OTI1Y2ZhYTlmMTY4NGIxOWE0NjlmOGQ3YzU1MzgwNThiZiIsImt0eSI6IkVDIiwieCI6Ik11N2kxYTdrSE1ZS3lERzB3NTBsN19HU0pKTjhiSERhWGswQzMxVmItUVkiLCJ5IjoiclhBZVN6RDUteGhZSEY4TFlDX3lkaW5pWEhTbVdnWldFUnU3UlFVUFhtayJ9LCJleHAiOjE3MTkyMTk1ODUsImlhdCI6MTcxOTIxODk4NSwiaXNzIjoiNzI4NmM4MjEtMzg5NC00MDhiLWJmOGEtMzk3N2M5ZDU0MzRkLmFybW9yeS5uYXJ2YWwueHl6Iiwic3ViIjoiZDMzYmRjMDYtODk2My00M2ExLTkyYWQtOTcwZTUyZjRjZTE0In0.xZkmWN3zjbNrZqulkfHz01wFeIGNwGFDvr528s4EnHQ2qStIwBXNeimmtlJRoGQzlPrlrWCCmpS_3PW7VJ1tbBs' + ) + ) + ) + }) + + it(`adds ${REQUEST_HEADER_DETACHED_JWS} header even without Authorization header`, async () => { + // expect.assertions(2) + const data = { foo: 'bar' } + const config = { + transitional: { + silentJSONParsing: true, + forcedJSONParsing: true, + clarifyTimeoutError: false + }, + adapter: ['xhr', 'http', 'fetch'], + timeout: 0, + xsrfCookieName: 'XSRF-TOKEN', + xsrfHeaderName: 'X-XSRF-TOKEN', + maxContentLength: -1, + maxBodyLength: -1, + headers: new AxiosHeaders({ + Accept: 'application/json, text/plain, */*', + 'Content-Type': 'application/json', + 'x-client-id': '7286c821-3894-408b-bf8a-3977c9d5434d' + }), + method: 'post', + data: JSON.stringify(data), + url: 'http://localhost:3011/accounts/import' + } + + const actualConfig = await interceptor(config) + + const signature = actualConfig.headers.get(REQUEST_HEADER_DETACHED_JWS) + + const verified = await verifyJwsd( + signature as string, + secp256k1PrivateKeyToPublicJwk(await privateKeyToHex(signer.jwk)), + { + uri: 'http://localhost:3011/accounts/import', + htm: 'POST', + maxTokenAge: 60, + requestBody: data + } + ) + expect(signature).toEqual(expect.any(String)) + expect(verified.header.ath).toBeUndefined() + }) +}) + +describe('parseToken', () => { + it('removes GNAP prefix', () => { + expect(parseToken('GNAP 123AAa4567890')).toEqual('123AAa4567890') + }) + + it('removes bearer prefix', () => { + expect(parseToken('bearer 1234567890')).toEqual('1234567890') + }) + + it('trims whitespace', () => { + expect(parseToken(' GNAP 1234567890 ')).toEqual('1234567890') + }) + + it('handles mixed case', () => { + expect(parseToken('Bearer 1234567890')).toEqual('1234567890') + expect(parseToken('gnap 1234567890')).toEqual('1234567890') }) }) diff --git a/packages/armory-sdk/src/lib/shared/gnap.ts b/packages/armory-sdk/src/lib/shared/gnap.ts index 80429d707..d06e4ffa9 100644 --- a/packages/armory-sdk/src/lib/shared/gnap.ts +++ b/packages/armory-sdk/src/lib/shared/gnap.ts @@ -1,5 +1,5 @@ import { AccessToken } from '@narval/policy-engine-shared' -import { Jwk, JwsdHeader, Payload, SigningAlg, hash, hexToBase64Url, signJwsd } from '@narval/signature' +import { Jwk, JwsdHeader, SigningAlg, hash, hexToBase64Url, signJwsd } from '@narval/signature' import assert from 'assert' import { InternalAxiosRequestConfig } from 'axios' import { ArmorySdkException } from '../exceptions' @@ -19,7 +19,7 @@ type BuildJwsdHeader = { htm: Htm jwk: Jwk alg?: SigningAlg - accessToken: AccessToken + accessToken?: AccessToken } const buildJwsdHeader = (args: BuildJwsdHeader): JwsdHeader => { @@ -34,6 +34,7 @@ const buildJwsdHeader = (args: BuildJwsdHeader): JwsdHeader => { } }) } + const now = Math.floor(Date.now() / 1000) // Now in seconds return { alg, @@ -41,14 +42,14 @@ const buildJwsdHeader = (args: BuildJwsdHeader): JwsdHeader => { typ: 'gnap-binding-jwsd', htm, uri, - created: new Date().getTime(), - ath: hexToBase64Url(hash(accessToken.value)) + created: now, + ath: accessToken ? hexToBase64Url(hash(accessToken.value)) : undefined } } export type GetJwsdProof = { - payload: Payload - accessToken: AccessToken + payload: string | object // Request body + accessToken: AccessToken | undefined uri: string htm: Htm signer: Signer @@ -92,21 +93,19 @@ export const interceptRequestAddDetachedJwsHeader = const authorizationHeader = config.headers['Authorization'] || config.headers['authorization'] - if (authorizationHeader) { - const token = parseToken(authorizationHeader) - const htm = getHtm(config.method) - const payload = config.data ? JSON.parse(config.data) : {} - - const signature = await getJwsdProof({ - accessToken: { value: token }, - htm, - payload, - signer: signer, - uri: config.url - }) - - config.headers[REQUEST_HEADER_DETACHED_JWS] = signature - } + const token = authorizationHeader ? parseToken(authorizationHeader) : undefined + const htm = getHtm(config.method) + const payload = config.data ? JSON.parse(config.data) : {} + + const signature = await getJwsdProof({ + accessToken: token ? { value: token } : undefined, + htm, + payload, + signer: signer, + uri: config.url + }) + + config.headers[REQUEST_HEADER_DETACHED_JWS] = signature return config } diff --git a/packages/armory-sdk/src/lib/vault/client.ts b/packages/armory-sdk/src/lib/vault/client.ts index 274daeedb..4d1e9b5e9 100644 --- a/packages/armory-sdk/src/lib/vault/client.ts +++ b/packages/armory-sdk/src/lib/vault/client.ts @@ -17,11 +17,42 @@ import { GenerateWalletDto, ImportPrivateKeyDto, ImportWalletDto, + InitiateConnectionDto, + KnownDestinationDto, + PaginatedAccountsDto, + PaginatedAddressesDto, + PaginatedConnectionsDto, + PaginatedKnownDestinationsDto, + PaginatedSyncsDto, + PaginatedWalletsDto, PongDto, + ProviderAccountApiFactory, + ProviderAccountDto, + ProviderAddressApiFactory, ProviderConnectionApiFactory, ProviderConnectionDto, + ProviderKnownDestinationApiFactory, + ProviderPendingConnectionDto, + ProviderProxyApiDeleteRequest, + ProviderProxyApiFactory, + ProviderProxyApiGetRequest, + ProviderProxyApiHeadRequest, + ProviderProxyApiOptionsRequest, + ProviderProxyApiPatchRequest, + ProviderProxyApiPostRequest, + ProviderProxyApiPutRequest, + ProviderSyncApiFactory, + ProviderTransferApiFactory, + ProviderWalletApiFactory, + ProviderWalletDto, + SendTransferDto, SignApiFactory, SignatureDto, + StartSyncDto, + SyncDto, + SyncStartedDto, + TransferDto, + UpdateConnectionDto, WalletApiFactory, WalletDto, WalletsDto @@ -29,6 +60,12 @@ import { import { interceptRequestAddDetachedJwsHeader, prefixGnapToken } from '../shared/gnap' import { VaultAdminConfig, VaultConfig } from './type' +interface RequestPagination { + cursor?: string + limit?: number + desc?: 'true' | 'false' +} + export class VaultAdminClient { private config: VaultAdminConfig @@ -66,7 +103,21 @@ export class VaultClient { private signHttp - private connectionHttp + private providerConnectionHttp + + private providerSyncHttp + + private providerWalletHttp + + private providerAccountHttp + + private providerAddressHttp + + private providerKnownDestinationHttp + + private providerTransferHttp + + private providerProxyHttp private applicationApi @@ -81,11 +132,21 @@ export class VaultClient { this.config = config + // Local keygen & signing clients this.walletHttp = WalletApiFactory(httpConfig, config.host, axiosInstance) this.encryptionKeyHttp = EncryptionKeyApiFactory(httpConfig, config.host, axiosInstance) this.accountHttp = AccountApiFactory(httpConfig, config.host, axiosInstance) this.signHttp = SignApiFactory(httpConfig, config.host, axiosInstance) - this.connectionHttp = ProviderConnectionApiFactory(httpConfig, config.host, axiosInstance) + + // Provider API clients + this.providerConnectionHttp = ProviderConnectionApiFactory(httpConfig, config.host, axiosInstance) + this.providerSyncHttp = ProviderSyncApiFactory(httpConfig, config.host, axiosInstance) + this.providerWalletHttp = ProviderWalletApiFactory(httpConfig, config.host, axiosInstance) + this.providerAccountHttp = ProviderAccountApiFactory(httpConfig, config.host, axiosInstance) + this.providerAddressHttp = ProviderAddressApiFactory(httpConfig, config.host, axiosInstance) + this.providerKnownDestinationHttp = ProviderKnownDestinationApiFactory(httpConfig, config.host, axiosInstance) + this.providerTransferHttp = ProviderTransferApiFactory(httpConfig, config.host, axiosInstance) + this.providerProxyHttp = ProviderProxyApiFactory(httpConfig, config.host, axiosInstance) this.applicationApi = new ApplicationApi(httpConfig, config.host, axiosInstance) } @@ -95,8 +156,8 @@ export class VaultClient { return data } - async generateEncryptionKey({ accessToken }: { accessToken: AccessToken }): Promise { - const token = prefixGnapToken(accessToken) + async generateEncryptionKey({ accessToken }: { accessToken?: AccessToken } = {}): Promise { + const token = accessToken ? prefixGnapToken(accessToken) : undefined const { data: encryptionKey } = await this.encryptionKeyHttp.generate({ xClientId: this.config.clientId, @@ -226,6 +287,10 @@ export class VaultClient { return signature } + /** + * Provider Connection + */ + async createConnection({ data, accessToken @@ -235,7 +300,7 @@ export class VaultClient { }): Promise { const token = accessToken ? prefixGnapToken(accessToken) : undefined - const { data: connection } = await this.connectionHttp.create({ + const { data: connection } = await this.providerConnectionHttp.create({ xClientId: this.config.clientId, authorization: token, createConnectionDto: data @@ -243,4 +308,518 @@ export class VaultClient { return connection } + + async initiateConnection({ + data, + accessToken + }: { + data: InitiateConnectionDto + accessToken?: AccessToken + }): Promise { + const token = accessToken ? prefixGnapToken(accessToken) : undefined + + const { data: connection } = await this.providerConnectionHttp.initiate({ + xClientId: this.config.clientId, + authorization: token, + initiateConnectionDto: data + }) + + return connection + } + + async listConnections({ + accessToken, + pagination + }: { + accessToken?: AccessToken + pagination?: RequestPagination + } = {}): Promise { + const token = accessToken ? prefixGnapToken(accessToken) : undefined + + const { data: connections } = await this.providerConnectionHttp.list({ + xClientId: this.config.clientId, + authorization: token, + cursor: pagination?.cursor, + limit: pagination?.limit, + desc: pagination?.desc + }) + + return connections + } + + async getConnection({ + connectionId, + accessToken + }: { + connectionId: string + accessToken?: AccessToken + }): Promise { + const token = accessToken ? prefixGnapToken(accessToken) : undefined + + const { data: connection } = await this.providerConnectionHttp.getById({ + xClientId: this.config.clientId, + connectionId, + authorization: token + }) + + return connection + } + + async revokeConnection({ + connectionId, + accessToken + }: { + connectionId: string + accessToken?: AccessToken + }): Promise { + const token = accessToken ? prefixGnapToken(accessToken) : undefined + + await this.providerConnectionHttp.revoke({ xClientId: this.config.clientId, connectionId, authorization: token }) + } + + async updateConnection({ + connectionId, + data, + accessToken + }: { + connectionId: string + data: UpdateConnectionDto + accessToken?: AccessToken + }): Promise { + const token = accessToken ? prefixGnapToken(accessToken) : undefined + + const { data: connection } = await this.providerConnectionHttp.update({ + xClientId: this.config.clientId, + connectionId, + authorization: token, + updateConnectionDto: data + }) + + return connection + } + + async listProviderAccounts({ + connectionId, + walletId, + accessToken, + pagination + }: { + connectionId?: string + walletId?: string + accessToken?: AccessToken + pagination?: RequestPagination + }): Promise { + const token = accessToken ? prefixGnapToken(accessToken) : undefined + if (walletId) { + const { data: accounts } = await this.providerWalletHttp.listAccounts({ + xClientId: this.config.clientId, + walletId, + authorization: token, + cursor: pagination?.cursor, + limit: pagination?.limit, + desc: pagination?.desc + }) + + return accounts + } else if (connectionId) { + const { data: accounts } = await this.providerConnectionHttp.listAccounts({ + xClientId: this.config.clientId, + connectionId, + authorization: token, + cursor: pagination?.cursor, + limit: pagination?.limit, + desc: pagination?.desc + }) + + return accounts + } + + const { data: accounts } = await this.providerAccountHttp.list({ + xClientId: this.config.clientId, + authorization: token, + cursor: pagination?.cursor, + limit: pagination?.limit, + desc: pagination?.desc + }) + return accounts + } + + /** + * Provider Sync + */ + + async startSync({ data, accessToken }: { data: StartSyncDto; accessToken?: AccessToken }): Promise { + const token = accessToken ? prefixGnapToken(accessToken) : undefined + + const { data: sync } = await this.providerSyncHttp.start({ + xClientId: this.config.clientId, + authorization: token, + startSyncDto: data + }) + + return sync + } + + async getSync({ syncId, accessToken }: { syncId: string; accessToken?: AccessToken }): Promise { + const token = accessToken ? prefixGnapToken(accessToken) : undefined + + const { data: sync } = await this.providerSyncHttp.getById({ + xClientId: this.config.clientId, + syncId, + authorization: token + }) + + return sync + } + + async listSyncs({ + connectionId, + accessToken, + pagination + }: { + connectionId: string + accessToken?: AccessToken + pagination?: RequestPagination + }): Promise { + const token = accessToken ? prefixGnapToken(accessToken) : undefined + + const { data: syncs } = await this.providerSyncHttp.list({ + xClientId: this.config.clientId, + connectionId, + authorization: token, + cursor: pagination?.cursor, + limit: pagination?.limit, + desc: pagination?.desc + }) + + return syncs + } + + /** + * Provider Wallet + */ + + async getProviderWallet({ + walletId, + accessToken + }: { + walletId: string + accessToken?: AccessToken + }): Promise { + const token = accessToken ? prefixGnapToken(accessToken) : undefined + + const { data: wallet } = await this.providerWalletHttp.getById({ + xClientId: this.config.clientId, + walletId, + authorization: token + }) + + return wallet + } + + async listProviderWallets({ + accessToken, + pagination + }: { + accessToken?: AccessToken + pagination?: RequestPagination + } = {}): Promise { + const token = accessToken ? prefixGnapToken(accessToken) : undefined + + const { data: wallets } = await this.providerWalletHttp.list({ + xClientId: this.config.clientId, + authorization: token, + cursor: pagination?.cursor, + limit: pagination?.limit, + desc: pagination?.desc + }) + + return wallets + } + + /** + * Provider Account + */ + + async getProviderAccount({ + accountId, + accessToken + }: { + accountId: string + accessToken?: AccessToken + }): Promise { + const token = accessToken ? prefixGnapToken(accessToken) : undefined + + const { data: account } = await this.providerAccountHttp.getById({ + xClientId: this.config.clientId, + accountId, + authorization: token + }) + + return account + } + + async listProviderAddresses({ + accountId, + accessToken, + pagination + }: { + accountId?: string + accessToken?: AccessToken + pagination?: RequestPagination + }): Promise { + const token = accessToken ? prefixGnapToken(accessToken) : undefined + + if (!accountId) { + const { data: addresses } = await this.providerAddressHttp.list({ + xClientId: this.config.clientId, + authorization: token, + cursor: pagination?.cursor, + limit: pagination?.limit, + desc: pagination?.desc + }) + return addresses + } + + const { data: addresses } = await this.providerAccountHttp.listAddresses({ + xClientId: this.config.clientId, + accountId, + authorization: token, + cursor: pagination?.cursor, + limit: pagination?.limit, + desc: pagination?.desc + }) + + return addresses + } + + /** + * Provider Address + */ + + async getProviderAddress({ + addressId, + accessToken + }: { + addressId: string + accessToken?: AccessToken + }): Promise { + const token = accessToken ? prefixGnapToken(accessToken) : undefined + + const { data: address } = await this.providerAddressHttp.getById({ + xClientId: this.config.clientId, + addressId, + authorization: token + }) + + return address + } + + /** + * Provider Known Destination + */ + + async listProviderKnownDestinations({ + connectionId, + accessToken, + pagination + }: { + connectionId: string + accessToken?: AccessToken + pagination?: RequestPagination + }): Promise { + const token = accessToken ? prefixGnapToken(accessToken) : undefined + + const { data: knownDestinations } = await this.providerKnownDestinationHttp.list({ + xClientId: this.config.clientId, + connectionId, + authorization: token, + cursor: pagination?.cursor, + limit: pagination?.limit, + desc: pagination?.desc + }) + + return knownDestinations + } + + async getProviderKnownDestination({ + knownDestinationId, + accessToken + }: { + knownDestinationId: string + accessToken?: AccessToken + }): Promise { + const token = accessToken ? prefixGnapToken(accessToken) : undefined + + const { data: knownDestination } = await this.providerKnownDestinationHttp.getById({ + xClientId: this.config.clientId, + knownDestinationId, + authorization: token + }) + + return knownDestination + } + + /** + * Provider Transfer + */ + + async sendTransfer({ + data, + accessToken + }: { + data: SendTransferDto + accessToken?: AccessToken + }): Promise { + const token = accessToken ? prefixGnapToken(accessToken) : undefined + + const { data: transfer } = await this.providerTransferHttp.send({ + xClientId: this.config.clientId, + authorization: token, + sendTransferDto: data + }) + + return transfer + } + + async getTransfer({ + transferId, + accessToken + }: { + transferId: string + accessToken?: AccessToken + }): Promise { + const token = accessToken ? prefixGnapToken(accessToken) : undefined + + const { data: transfer } = await this.providerTransferHttp.getById({ + xClientId: this.config.clientId, + transferId, + authorization: token + }) + + return transfer + } + + /** + * Provider Proxy + */ + + async proxyDelete({ + data, + accessToken + }: { + data: ProviderProxyApiDeleteRequest + accessToken?: AccessToken + }): Promise { + const token = accessToken ? prefixGnapToken(accessToken) : undefined + + await this.providerProxyHttp._delete({ + xClientId: this.config.clientId, + authorization: token, + endpoint: data.endpoint, + xConnectionId: data.xConnectionId + }) + } + + async proxyOptions({ + data, + accessToken + }: { + data: ProviderProxyApiOptionsRequest + accessToken?: AccessToken + }): Promise { + const token = accessToken ? prefixGnapToken(accessToken) : undefined + + await this.providerProxyHttp._options({ + xClientId: this.config.clientId, + authorization: token, + endpoint: data.endpoint, + xConnectionId: data.xConnectionId + }) + } + + async proxyGet({ + data, + accessToken + }: { + data: ProviderProxyApiGetRequest + accessToken?: AccessToken + }): Promise { + const token = accessToken ? prefixGnapToken(accessToken) : undefined + + await this.providerProxyHttp.get({ + xClientId: this.config.clientId, + authorization: token, + endpoint: data.endpoint, + xConnectionId: data.xConnectionId + }) + } + + async proxyPost({ + data, + accessToken + }: { + data: ProviderProxyApiPostRequest + accessToken?: AccessToken + }): Promise { + const token = accessToken ? prefixGnapToken(accessToken) : undefined + + await this.providerProxyHttp.post({ + xClientId: this.config.clientId, + authorization: token, + endpoint: data.endpoint, + xConnectionId: data.xConnectionId + }) + } + + async proxyPut({ + data, + accessToken + }: { + data: ProviderProxyApiPutRequest + accessToken?: AccessToken + }): Promise { + const token = accessToken ? prefixGnapToken(accessToken) : undefined + + await this.providerProxyHttp.put({ + xClientId: this.config.clientId, + authorization: token, + endpoint: data.endpoint, + xConnectionId: data.xConnectionId + }) + } + + async proxyPatch({ + data, + accessToken + }: { + data: ProviderProxyApiPatchRequest + accessToken?: AccessToken + }): Promise { + const token = accessToken ? prefixGnapToken(accessToken) : undefined + + await this.providerProxyHttp.patch({ + xClientId: this.config.clientId, + authorization: token, + endpoint: data.endpoint, + xConnectionId: data.xConnectionId + }) + } + + async proxyHead({ + data, + accessToken + }: { + data: ProviderProxyApiHeadRequest + accessToken?: AccessToken + }): Promise { + const token = accessToken ? prefixGnapToken(accessToken) : undefined + + await this.providerProxyHttp.head({ + xClientId: this.config.clientId, + authorization: token, + endpoint: data.endpoint, + xConnectionId: data.xConnectionId + }) + } } diff --git a/packages/signature/src/lib/verify.ts b/packages/signature/src/lib/verify.ts index 55614cfa8..2093bb808 100644 --- a/packages/signature/src/lib/verify.ts +++ b/packages/signature/src/lib/verify.ts @@ -338,6 +338,9 @@ export function verifyJwsdHeader( context: { header, opts } }) } + + // Ensure the token isn't too old. We also check the created timestamp wasn't created "in the future" (with 3s grace period); + // A future created stamp generally means milliseconds was used instead of seconds const now = nowSeconds() if (jwsdHeader.created && now - jwsdHeader.created > opts.maxTokenAge) { throw new JwtError({ @@ -345,6 +348,12 @@ export function verifyJwsdHeader( context: { header, opts } }) } + if (jwsdHeader.created && now - jwsdHeader.created < -3) { + throw new JwtError({ + message: 'JWS is too old, created field is too far in the future, did you use milliseconds instead of seconds?', + context: { header, opts } + }) + } if (opts.ath && jwsdHeader.ath !== opts.ath) { throw new JwtError({ From 7b2a1d1db5f52e33869111e3ee97c6b6eaaf2b9b Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Fri, 3 Jan 2025 14:34:30 +0100 Subject: [PATCH 070/120] Fireblocks connection (#64) * Decouple connection from its credentials * Remove CredentialService * Rafactor connection service * Rollout new connection types * Remove connection duplicated files * Fix sync on connection activation * Update sync status to fail * Add docstring on toMatchZodSchema * Allow provider-specific options for generate credentials --- .../broker/__test__/e2e/connection.spec.ts | 264 +++++----- .../__test__/e2e/known-destinations.spec.ts | 60 ++- .../src/broker/__test__/e2e/proxy.spec.ts | 9 +- .../src/broker/__test__/e2e/sync.spec.ts | 24 +- .../src/broker/__test__/e2e/transfer.spec.ts | 11 +- .../__test__/util/map-db-to-returned.ts | 39 +- apps/vault/src/broker/broker.module.ts | 16 +- .../core/exception/provider-http.exception.ts | 2 +- .../anchorage-sync.service.spec.ts | 20 +- .../anchorage-transfer.service.spec.ts | 7 +- .../unit/anchorage-credential.service.spec.ts | 98 ++++ .../anchorage/anchorage-credential.service.ts | 64 +++ .../anchorage/anchorage-proxy.service.ts | 35 ++ .../anchorage/anchorage-sync.service.ts | 80 +-- .../anchorage/anchorage-transfer.service.ts | 13 +- .../core/provider/anchorage/anchorage.type.ts | 16 + .../core/provider/anchorage/anchorage.util.ts | 53 ++ .../fireblocks-credential.service.spec.ts | 100 ++++ .../fireblocks-credential.service.ts | 66 +++ .../provider/fireblocks/fireblocks.type.ts | 15 + .../__test__/integration/sync.service.spec.ts | 26 +- .../broker/core/service/connection.service.ts | 498 ++++++++---------- .../src/broker/core/service/proxy.service.ts | 50 +- .../src/broker/core/service/sync.service.ts | 40 +- .../broker/core/service/transfer.service.ts | 27 +- .../src/broker/core/type/connection.type.ts | 85 +-- .../core/type/indexed-resources.type.ts | 12 +- .../src/broker/core/type/provider.type.ts | 78 ++- .../src/broker/core/type/transfer.type.ts | 2 +- .../util/user-friendly-key-format.util.ts | 19 + .../broker/http/client/anchorage.client.ts | 2 +- .../rest/controller/address.controller.ts | 2 +- .../rest/controller/connection.controller.ts | 25 +- .../http/rest/controller/sync.controller.ts | 25 +- .../rest/dto/request/update-connection.dto.ts | 10 +- .../dto/response/paginated-connections.dto.ts | 4 +- .../dto/response/paginated-wallets.dto.ts | 4 +- .../dto/response/pending-connection.dto.ts | 28 - .../dto/response/provider-connection.dto.ts | 4 +- .../rest/dto/response/provider-wallet.dto.ts | 4 +- .../src/broker/persistence/connection.seed.ts | 6 +- .../repository/address.repository.ts | 2 +- .../repository/connection.repository.ts | 142 +++-- .../known-destination.repository.ts | 14 +- .../repository/wallet.repository.ts | 13 +- .../src/broker/shared/__test__/matcher.ts | 60 +++ .../event/connection-activated.event.ts | 4 +- .../broker/shared/event/sync-started.event.ts | 4 +- .../src/shared/module/persistence/seed.ts | 7 +- 49 files changed, 1332 insertions(+), 857 deletions(-) create mode 100644 apps/vault/src/broker/core/provider/anchorage/__test__/unit/anchorage-credential.service.spec.ts create mode 100644 apps/vault/src/broker/core/provider/anchorage/anchorage-credential.service.ts create mode 100644 apps/vault/src/broker/core/provider/anchorage/anchorage-proxy.service.ts create mode 100644 apps/vault/src/broker/core/provider/anchorage/anchorage.type.ts create mode 100644 apps/vault/src/broker/core/provider/anchorage/anchorage.util.ts create mode 100644 apps/vault/src/broker/core/provider/fireblocks/__test__/unit/fireblocks-credential.service.spec.ts create mode 100644 apps/vault/src/broker/core/provider/fireblocks/fireblocks-credential.service.ts create mode 100644 apps/vault/src/broker/core/provider/fireblocks/fireblocks.type.ts create mode 100644 apps/vault/src/broker/core/util/user-friendly-key-format.util.ts delete mode 100644 apps/vault/src/broker/http/rest/dto/response/pending-connection.dto.ts create mode 100644 apps/vault/src/broker/shared/__test__/matcher.ts diff --git a/apps/vault/src/broker/__test__/e2e/connection.spec.ts b/apps/vault/src/broker/__test__/e2e/connection.spec.ts index d5149b463..d553baa46 100644 --- a/apps/vault/src/broker/__test__/e2e/connection.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/connection.spec.ts @@ -4,10 +4,13 @@ import { hexSchema } from '@narval/policy-engine-shared' import { Alg, Ed25519PrivateKey, + Hex, + SMALLEST_RSA_MODULUS_LENGTH, ed25519PublicKeySchema, generateJwk, getPublicKey, privateKeyToHex, + privateKeyToJwk, rsaEncrypt, rsaPublicKeySchema } from '@narval/signature' @@ -18,7 +21,6 @@ import { MockProxy, mock } from 'jest-mock-extended' import { times } from 'lodash' import request from 'supertest' import { v4 as uuid } from 'uuid' -import { ZodSchema } from 'zod' import { ClientService } from '../../../client/core/service/client.service' import { MainModule } from '../../../main.module' import { ProvisionService } from '../../../provision.service' @@ -27,15 +29,12 @@ import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/per import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' import { EncryptionKeyService } from '../../../transit-encryption/core/service/encryption-key.service' +import { AnchorageCredentialService } from '../../core/provider/anchorage/anchorage-credential.service' import { ConnectionService } from '../../core/service/connection.service' import { SyncService } from '../../core/service/sync.service' -import { - ActiveConnectionWithCredentials, - ConnectionStatus, - Provider, - isActiveConnection, - isRevokedConnection -} from '../../core/type/connection.type' +import { ConnectionStatus } from '../../core/type/connection.type' +import { Provider } from '../../core/type/provider.type' +import '../../shared/__test__/matcher' import { ConnectionActivatedEvent } from '../../shared/event/connection-activated.event' import { getExpectedAccount, getExpectedWallet } from '../util/map-db-to-returned' import { @@ -48,24 +47,6 @@ import { testUserPrivateJwk } from '../util/mock-data' -const toMatchZodSchema = (received: unknown, schema: ZodSchema): void => { - const parse = schema.safeParse(received) - - if (parse.success) { - return - } - - const message = [ - 'Expected value to match schema:', - 'Received:', - `${JSON.stringify(received, null, 2)}`, - 'Validation errors:', - parse.error.errors.map((err) => `- ${err.message}`).join('\n') - ].join('\n') - - throw new Error(message) -} - describe('Connection', () => { let app: INestApplication let module: TestingModule @@ -112,11 +93,11 @@ describe('Connection', () => { app = module.createNestApplication() - testPrismaService = module.get(TestPrismaService) + clientService = module.get(ClientService) connectionService = module.get(ConnectionService) encryptionKeyService = module.get(EncryptionKeyService) - provisionService = module.get(ProvisionService) - clientService = module.get(ClientService) + provisionService = module.get(ProvisionService) + testPrismaService = module.get(TestPrismaService) await testPrismaService.truncateAll() }) @@ -159,11 +140,13 @@ describe('Connection', () => { const { data } = body - expect(data).toMatchObject({ - clientId, - connectionId: connection.connectionId, - provider: connection.provider, - status: ConnectionStatus.PENDING + expect(body).toMatchObject({ + data: { + clientId, + connectionId: connection.connectionId, + provider: connection.provider, + status: ConnectionStatus.PENDING + } }) // Ensure it doesn't leak the private key. @@ -172,10 +155,10 @@ describe('Connection', () => { // Ensure it doesn't leak a private key as JWK by including the `d` // property. - toMatchZodSchema(data.publicKey.jwk, ed25519PublicKeySchema) - toMatchZodSchema(data.encryptionPublicKey.jwk, rsaPublicKeySchema) + expect(data.publicKey.jwk).toMatchZodSchema(ed25519PublicKeySchema) + expect(data.encryptionPublicKey.jwk).toMatchZodSchema(rsaPublicKeySchema) - toMatchZodSchema(data.publicKey.hex, hexSchema) + expect(data.publicKey.hex).toMatchZodSchema(hexSchema) expect(data.publicKey.keyId).toEqual(expect.any(String)) expect(data.encryptionPublicKey.keyId).toEqual(expect.any(String)) @@ -214,11 +197,14 @@ describe('Connection', () => { ) .send(connection) - const createdConnection = await connectionService.findById(clientId, connection.connectionId, true) + const createdConnectionWithCredentials = await connectionService.findWithCredentialsById( + clientId, + connection.connectionId + ) expect(eventEmitterMock.emit).toHaveBeenCalledWith( ConnectionActivatedEvent.EVENT_NAME, - new ConnectionActivatedEvent(createdConnection as ActiveConnectionWithCredentials) + new ConnectionActivatedEvent(createdConnectionWithCredentials) ) }) @@ -250,28 +236,26 @@ describe('Connection', () => { ) .send(connection) - const createdConnection = await connectionService.findById(clientId, connection.connectionId, true) + const createdConnection = await connectionService.findById(clientId, connection.connectionId) + const createdCredentials = await connectionService.findCredentials(createdConnection) - expect(body.data).toEqual({ - clientId, - connectionId, - url, - createdAt: expect.any(String), - label: connection.label, - provider: connection.provider, - status: ConnectionStatus.ACTIVE, - updatedAt: expect.any(String) + expect(body).toEqual({ + data: { + clientId, + connectionId, + url, + createdAt: expect.any(String), + label: connection.label, + provider: connection.provider, + status: ConnectionStatus.ACTIVE, + updatedAt: expect.any(String) + } }) expect(status).toEqual(HttpStatus.CREATED) expect(createdConnection).toMatchObject({ clientId, - credentials: { - apiKey: connection.credentials.apiKey, - privateKey, - publicKey: getPublicKey(privateKey as Ed25519PrivateKey) - }, createdAt: expect.any(Date), connectionId, label: connection.label, @@ -280,6 +264,12 @@ describe('Connection', () => { updatedAt: expect.any(Date), url: connection.url }) + + expect(createdCredentials).toEqual({ + apiKey: connection.credentials.apiKey, + privateKey, + publicKey: getPublicKey(privateKey as Ed25519PrivateKey) + }) }) it('emits connection.activated on connection activation', async () => { @@ -300,6 +290,7 @@ describe('Connection', () => { }) ) .send({ connectionId, provider }) + .expect(HttpStatus.CREATED) await request(app.getHttpServer()) .post('/provider/connections') @@ -325,12 +316,13 @@ describe('Connection', () => { provider, url }) + .expect(HttpStatus.CREATED) - const createdConnection = await connectionService.findById(clientId, connectionId, true) + const createdConnectionWithCredentials = await connectionService.findWithCredentialsById(clientId, connectionId) expect(eventEmitterMock.emit).toHaveBeenCalledWith( - 'connection.activated', - new ConnectionActivatedEvent(createdConnection as ActiveConnectionWithCredentials) + ConnectionActivatedEvent.EVENT_NAME, + new ConnectionActivatedEvent(createdConnectionWithCredentials) ) }) @@ -378,20 +370,23 @@ describe('Connection', () => { url }) - expect(body.data).toEqual({ - clientId, - connectionId, - label, - provider, - url, - createdAt: expect.any(String), - status: ConnectionStatus.ACTIVE, - updatedAt: expect.any(String) + const createdConnection = await connectionService.findById(clientId, connectionId) + const createdCredentials = await connectionService.findCredentials(createdConnection) + + expect(body).toEqual({ + data: { + clientId, + connectionId, + label, + provider, + url, + createdAt: expect.any(String), + status: ConnectionStatus.ACTIVE, + updatedAt: expect.any(String) + } }) expect(status).toEqual(HttpStatus.CREATED) - const createdConnection = await connectionService.findById(clientId, connectionId, true) - expect(createdConnection).toMatchObject({ clientId, connectionId, @@ -403,14 +398,10 @@ describe('Connection', () => { updatedAt: expect.any(Date) }) - if (isActiveConnection(createdConnection)) { - expect(createdConnection.credentials).toMatchObject({ - apiKey: credentials.apiKey, - publicKey: pendingConnection.data.publicKey.jwk - }) - } else { - fail('expected an active connection') - } + expect(createdCredentials).toMatchObject({ + apiKey: credentials.apiKey, + publicKey: pendingConnection.data.publicKey.jwk + }) }) it('activates an anchorage pending connection with encrypted credentials', async () => { @@ -464,19 +455,22 @@ describe('Connection', () => { encryptedCredentials }) - expect(body.data).toEqual({ - clientId, - connectionId, - label, - provider, - url, - createdAt: expect.any(String), - status: ConnectionStatus.ACTIVE, - updatedAt: expect.any(String) + expect(body).toEqual({ + data: { + clientId, + connectionId, + label, + provider, + url, + createdAt: expect.any(String), + status: ConnectionStatus.ACTIVE, + updatedAt: expect.any(String) + } }) expect(status).toEqual(HttpStatus.CREATED) - const createdConnection = await connectionService.findById(clientId, connectionId, true) + const createdConnection = await connectionService.findById(clientId, connectionId) + const createdCredentials = await connectionService.findCredentials(createdConnection) expect(createdConnection).toMatchObject({ clientId, @@ -489,25 +483,20 @@ describe('Connection', () => { updatedAt: expect.any(Date) }) - if (isActiveConnection(createdConnection)) { - expect(createdConnection.credentials).toMatchObject({ - apiKey: credentials.apiKey, - publicKey: pendingConnection.data.publicKey.jwk - }) - } else { - fail('expected an active connection') - } + expect(createdCredentials).toMatchObject({ + apiKey: credentials.apiKey, + publicKey: pendingConnection.data.publicKey.jwk + }) }) - it('overrides the existing connection privateKey when providing a new one on pending connection activation', async () => { - expect.assertions(6) - + it('overrides the existing connection private key when providing a new one on pending connection activation', async () => { const connectionId = uuid() const provider = Provider.ANCHORAGE const label = 'Test Anchorage Connection' const credentials = { apiKey: 'test-api-key', - privateKey: '0x9ead9e0c93e9f4d02a09d4d3fdd35eac82452717a04ca98580302c16485b2480' // Adding private key to test override + // Adding private key to test override + privateKey: '0x9ead9e0c93e9f4d02a09d4d3fdd35eac82452717a04ca98580302c16485b2480' } // First create a pending connection @@ -556,21 +545,23 @@ describe('Connection', () => { encryptedCredentials }) - // Verify the response structure - expect(body.data).toEqual({ - clientId, - connectionId, - label, - provider, - url, - createdAt: expect.any(String), - status: ConnectionStatus.ACTIVE, - updatedAt: expect.any(String) + expect(body).toEqual({ + data: { + clientId, + connectionId, + label, + provider, + url, + createdAt: expect.any(String), + status: ConnectionStatus.ACTIVE, + updatedAt: expect.any(String) + } }) + expect(status).toEqual(HttpStatus.CREATED) - // Verify the created connection in the database - const createdConnection = await connectionService.findById(clientId, connectionId, true) + const createdConnection = await connectionService.findById(clientId, connectionId) + const createdCredential = await connectionService.findCredentials(createdConnection) expect(createdConnection).toMatchObject({ clientId, @@ -583,15 +574,10 @@ describe('Connection', () => { updatedAt: expect.any(Date) }) - if (isActiveConnection(createdConnection)) { - // Verify the private key was actually changed - expect(createdConnection.credentials.privateKey.d).not.toEqual(pendingConnection.data.privateKey?.d) - expect(createdConnection.credentials.publicKey.x).not.toEqual(pendingConnection.data.publicKey?.x) - const createdHex = await privateKeyToHex(createdConnection.credentials.privateKey) - expect(createdHex).toEqual(credentials.privateKey) - } else { - fail('expected an active connection') - } + const givenPrivateKey = privateKeyToJwk(credentials.privateKey as Hex, AnchorageCredentialService.SIGNING_KEY_ALG) + + expect(createdCredential?.publicKey).toEqual(getPublicKey(givenPrivateKey)) + expect(createdCredential?.privateKey).toEqual(givenPrivateKey) }) }) @@ -624,14 +610,12 @@ describe('Connection', () => { expect(status).toEqual(HttpStatus.NO_CONTENT) - const updatedConnection = await connectionService.findById(clientId, connection.connectionId, true) + const updatedConnection = await connectionService.findById(clientId, connection.connectionId) + const credentials = await connectionService.findCredentials(connection) - if (isRevokedConnection(updatedConnection)) { - expect(updatedConnection.credentials).toEqual(null) - expect(updatedConnection.revokedAt).toEqual(expect.any(Date)) - } else { - fail('expected a revoked connection') - } + expect(updatedConnection.revokedAt).toEqual(expect.any(Date)) + expect(updatedConnection.status).toEqual(ConnectionStatus.REVOKED) + expect(credentials).toEqual(null) }) }) @@ -807,7 +791,9 @@ describe('Connection', () => { apiKey: 'new-api-key', privateKey: await privateKeyToHex(newPrivateKey) } - const encryptionKey = await encryptionKeyService.generate(clientId, { modulusLength: 2048 }) + const encryptionKey = await encryptionKeyService.generate(clientId, { + modulusLength: SMALLEST_RSA_MODULUS_LENGTH + }) const encryptedCredentials = await rsaEncrypt(JSON.stringify(newCredentials), encryptionKey.publicKey) const { status, body } = await request(app.getHttpServer()) @@ -830,16 +816,22 @@ describe('Connection', () => { encryptedCredentials }) - expect(body.data).toMatchObject({ label: 'new label' }) + expect(body).toMatchObject({ + data: expect.objectContaining({ + label: 'new label' + }) + }) + expect(body.data).not.toHaveProperty('credentials') expect(status).toEqual(HttpStatus.OK) - const updatedConnection = await connectionService.findById(clientId, connection.connectionId, true) + const updatedConnection = await connectionService.findById(clientId, connection.connectionId) + const updatedCredentials = await connectionService.findCredentials(updatedConnection) - expect(updatedConnection.credentials?.apiKey).toEqual(newCredentials.apiKey) - expect(updatedConnection.credentials?.privateKey).toEqual(newPrivateKey) - expect(updatedConnection.credentials?.publicKey).toEqual(getPublicKey(newPrivateKey as Ed25519PrivateKey)) + expect(updatedCredentials?.apiKey).toEqual(newCredentials.apiKey) + expect(updatedCredentials?.privateKey).toEqual(newPrivateKey) + expect(updatedCredentials?.publicKey).toEqual(getPublicKey(newPrivateKey as Ed25519PrivateKey)) }) }) @@ -861,11 +853,11 @@ describe('Connection', () => { ) .send() - expect(status).toEqual(HttpStatus.OK) expect(body).toMatchObject({ data: [getExpectedWallet(TEST_WALLETS[0])], page: {} }) + expect(status).toEqual(HttpStatus.OK) }) it('returns empty array when connection has no wallets', async () => { @@ -896,11 +888,11 @@ describe('Connection', () => { ) .send() - expect(status).toEqual(HttpStatus.OK) expect(body).toMatchObject({ data: [], page: {} }) + expect(status).toEqual(HttpStatus.OK) }) }) @@ -931,11 +923,11 @@ describe('Connection', () => { ) .send() - expect(status).toEqual(HttpStatus.OK) expect(body).toMatchObject({ data: accountsForConnection.map(getExpectedAccount).reverse(), page: {} }) + expect(status).toEqual(HttpStatus.OK) }) it('returns empty array when connection has no accounts', async () => { @@ -967,11 +959,11 @@ describe('Connection', () => { ) .send() - expect(status).toEqual(HttpStatus.OK) expect(body).toMatchObject({ data: [], page: {} }) + expect(status).toEqual(HttpStatus.OK) }) }) }) diff --git a/apps/vault/src/broker/__test__/e2e/known-destinations.spec.ts b/apps/vault/src/broker/__test__/e2e/known-destinations.spec.ts index d95a35a37..f1e96c85c 100644 --- a/apps/vault/src/broker/__test__/e2e/known-destinations.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/known-destinations.spec.ts @@ -6,7 +6,7 @@ import { EventEmitter2 } from '@nestjs/event-emitter' import { Test, TestingModule } from '@nestjs/testing' import { mock } from 'jest-mock-extended' import request from 'supertest' -import { v4 } from 'uuid' +import { v4 as uuid } from 'uuid' import { ClientService } from '../../../client/core/service/client.service' import { MainModule } from '../../../main.module' import { ProvisionService } from '../../../provision.service' @@ -17,8 +17,9 @@ import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing import { ANCHORAGE_TEST_API_BASE_URL } from '../../core/provider/anchorage/__test__/server-mock/server' import { ConnectionService } from '../../core/service/connection.service' import { KnownDestinationService } from '../../core/service/known-destination.service' -import { Provider } from '../../core/type/connection.type' +import { Connection } from '../../core/type/connection.type' import { KnownDestination } from '../../core/type/indexed-resources.type' +import { Provider } from '../../core/type/provider.type' import { getJwsd, testClient, testUserPrivateJwk } from '../util/mock-data' describe('KnownDestination', () => { @@ -52,12 +53,13 @@ describe('KnownDestination', () => { .compile() app = module.createNestApplication() + testPrismaService = module.get(TestPrismaService) - provisionService = module.get(ProvisionService) - clientService = module.get(ClientService) - connectionService = module.get(ConnectionService) + provisionService = module.get(ProvisionService) + clientService = module.get(ClientService) + connectionService = module.get(ConnectionService) + knownDestinationService = module.get(KnownDestinationService) - knownDestinationService = module.get(KnownDestinationService) await testPrismaService.truncateAll() }) @@ -77,27 +79,31 @@ describe('KnownDestination', () => { await app.init() - const connection1 = await connectionService.create(testClient.clientId, { - connectionId: v4(), - provider: Provider.ANCHORAGE, - url: ANCHORAGE_TEST_API_BASE_URL, - createdAt: now, - credentials: { - apiKey: 'test-api-key', - privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) - } - }) + const connection1 = Connection.parse( + await connectionService.create(testClient.clientId, { + connectionId: uuid(), + provider: Provider.ANCHORAGE, + url: ANCHORAGE_TEST_API_BASE_URL, + createdAt: now, + credentials: { + apiKey: 'test-api-key', + privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) + } + }) + ) - const connection2 = await connectionService.create(testClient.clientId, { - connectionId: v4(), - provider: Provider.ANCHORAGE, - url: ANCHORAGE_TEST_API_BASE_URL, - createdAt: now, - credentials: { - apiKey: 'test-api-key', - privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) - } - }) + const connection2 = Connection.parse( + await connectionService.create(testClient.clientId, { + connectionId: uuid(), + provider: Provider.ANCHORAGE, + url: ANCHORAGE_TEST_API_BASE_URL, + createdAt: now, + credentials: { + apiKey: 'test-api-key', + privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) + } + }) + ) connection1Id = connection1.connectionId connection2Id = connection2.connectionId @@ -359,7 +365,7 @@ describe('KnownDestination', () => { }) it('returns 404 for unknown known destination', async () => { - const { status, body } = await request(app.getHttpServer()) + const { status } = await request(app.getHttpServer()) .get('/provider/known-destinations/unknown') .set(REQUEST_HEADER_CLIENT_ID, testClient.clientId) .set( diff --git a/apps/vault/src/broker/__test__/e2e/proxy.spec.ts b/apps/vault/src/broker/__test__/e2e/proxy.spec.ts index 07749c2d0..86018ae02 100644 --- a/apps/vault/src/broker/__test__/e2e/proxy.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/proxy.spec.ts @@ -16,7 +16,7 @@ import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/per import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' import { ConnectionService } from '../../core/service/connection.service' -import { Provider } from '../../core/type/connection.type' +import { Provider } from '../../core/type/provider.type' import { getJwsd, testClient, testUserPrivateJwk } from '../util/mock-data' describe('Proxy', () => { @@ -51,10 +51,11 @@ describe('Proxy', () => { app = module.createNestApplication() testPrismaService = module.get(TestPrismaService) - provisionService = module.get(ProvisionService) - clientService = module.get(ClientService) - await testPrismaService.truncateAll() + provisionService = module.get(ProvisionService) + clientService = module.get(ClientService) connectionService = module.get(ConnectionService) + + await testPrismaService.truncateAll() }) afterAll(async () => { diff --git a/apps/vault/src/broker/__test__/e2e/sync.spec.ts b/apps/vault/src/broker/__test__/e2e/sync.spec.ts index b35a4c5ce..026f24ee1 100644 --- a/apps/vault/src/broker/__test__/e2e/sync.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/sync.spec.ts @@ -18,7 +18,8 @@ import { ANCHORAGE_TEST_API_BASE_URL, getHandlers } from '../../core/provider/an import { AnchorageSyncService } from '../../core/provider/anchorage/anchorage-sync.service' import { ConnectionService } from '../../core/service/connection.service' import { SyncService } from '../../core/service/sync.service' -import { ActiveConnectionWithCredentials, Provider } from '../../core/type/connection.type' +import { ConnectionWithCredentials } from '../../core/type/connection.type' +import { Provider } from '../../core/type/provider.type' import { SyncStatus } from '../../core/type/sync.type' import { setupMockServer } from '../../shared/__test__/mock-server' import { SyncStartedEvent } from '../../shared/event/sync-started.event' @@ -35,7 +36,7 @@ describe('Sync', () => { let anchorageSyncServiceMock: MockProxy let provisionService: ProvisionService let clientService: ClientService - let activeConnection: ActiveConnectionWithCredentials + let connection: ConnectionWithCredentials const url = ANCHORAGE_TEST_API_BASE_URL @@ -92,7 +93,7 @@ describe('Sync', () => { await provisionService.provision() await clientService.save(testClient) - activeConnection = await connectionService.create(clientId, { + connection = await connectionService.create(clientId, { connectionId: uuid(), provider: Provider.ANCHORAGE, url, @@ -132,10 +133,11 @@ describe('Sync', () => { .send() const { data: syncs } = await syncService.findAll(clientId) + const credentials = await connectionService.findCredentials(connection) expect(eventEmitterMock.emit).toHaveBeenCalledWith( SyncStartedEvent.EVENT_NAME, - new SyncStartedEvent(syncs[0], activeConnection) + new SyncStartedEvent(syncs[0], { ...connection, credentials }) ) }) @@ -184,11 +186,11 @@ describe('Sync', () => { await getJwsd({ userPrivateJwk: testUserPrivateJwk, requestUrl: '/provider/syncs', - payload: { connectionId: activeConnection.connectionId }, + payload: { connectionId: connection.connectionId }, htm: 'POST' }) ) - .send({ connectionId: activeConnection.connectionId }) + .send({ connectionId: connection.connectionId }) const syncs = await syncService.findAll(clientId) const [sync] = syncs.data @@ -198,7 +200,7 @@ describe('Sync', () => { syncs: [ { clientId: sync.clientId, - connectionId: activeConnection.connectionId, + connectionId: connection.connectionId, createdAt: sync.createdAt.toISOString(), syncId: sync.syncId, status: SyncStatus.PROCESSING @@ -214,7 +216,7 @@ describe('Sync', () => { describe('GET /syncs/:syncId', () => { it('responds with the specific sync', async () => { - const { syncs } = await syncService.start([activeConnection]) + const { syncs } = await syncService.start([connection]) const [sync] = syncs const { status, body } = await request(app.getHttpServer()) @@ -245,7 +247,7 @@ describe('Sync', () => { describe('GET /syncs', () => { it('responds with a list of syncs', async () => { - const { syncs } = await syncService.start([activeConnection]) + const { syncs } = await syncService.start([connection]) const [sync] = syncs const { status, body } = await request(app.getHttpServer()) @@ -280,7 +282,7 @@ describe('Sync', () => { }) it('responds with the specific sync filter by connection', async () => { - const { syncs } = await syncService.start([activeConnection]) + const { syncs } = await syncService.start([connection]) const [sync] = syncs const { status, body } = await request(app.getHttpServer()) @@ -316,7 +318,7 @@ describe('Sync', () => { }) it('responds with limited number of syncs when limit is given', async () => { - await syncService.start([activeConnection]) + await syncService.start([connection]) const { body } = await request(app.getHttpServer()) .get('/provider/syncs') diff --git a/apps/vault/src/broker/__test__/e2e/transfer.spec.ts b/apps/vault/src/broker/__test__/e2e/transfer.spec.ts index 39927904e..fb88bc93c 100644 --- a/apps/vault/src/broker/__test__/e2e/transfer.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/transfer.spec.ts @@ -17,8 +17,9 @@ import { TestPrismaService } from '../../../shared/module/persistence/service/te import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' import postAnchorageTransferBadRequest from '../../core/provider/anchorage/__test__/server-mock/response/post-transfer-400.json' import { ANCHORAGE_TEST_API_BASE_URL, getHandlers } from '../../core/provider/anchorage/__test__/server-mock/server' -import { ActiveConnectionWithCredentials, ConnectionStatus, Provider } from '../../core/type/connection.type' +import { Connection, ConnectionStatus, ConnectionWithCredentials } from '../../core/type/connection.type' import { Account, Wallet } from '../../core/type/indexed-resources.type' +import { Provider } from '../../core/type/provider.type' import { InternalTransfer, NetworkFeeAttribution, @@ -61,7 +62,7 @@ describe('Transfer', () => { d: 'evo-fY2BX60V1n3Z690LadH5BvizcM9bESaYk0LsxyQ' } - const connection: ActiveConnectionWithCredentials = { + const connection: ConnectionWithCredentials = { clientId, connectionId: uuid(), createdAt: new Date(), @@ -104,7 +105,7 @@ describe('Transfer', () => { const wallet: Wallet = { clientId, - connections: [connection], + connections: [Connection.parse(connection)], createdAt: new Date(), externalId: uuid(), label: null, @@ -159,8 +160,8 @@ describe('Transfer', () => { app = module.createNestApplication() testPrismaService = module.get(TestPrismaService) - provisionService = module.get(ProvisionService) - clientService = module.get(ClientService) + provisionService = module.get(ProvisionService) + clientService = module.get(ClientService) transferRepository = module.get(TransferRepository) connectionRepository = module.get(ConnectionRepository) diff --git a/apps/vault/src/broker/__test__/util/map-db-to-returned.ts b/apps/vault/src/broker/__test__/util/map-db-to-returned.ts index 7dcb27c2a..9be4c7403 100644 --- a/apps/vault/src/broker/__test__/util/map-db-to-returned.ts +++ b/apps/vault/src/broker/__test__/util/map-db-to-returned.ts @@ -1,26 +1,23 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import { ProviderAccount, ProviderAddress, ProviderConnection, ProviderWallet } from '@prisma/client/vault' -import { PublicConnection } from '../../core/type/connection.type' +import { ConnectionRepository } from '../../persistence/repository/connection.repository' import { TEST_ACCOUNTS, TEST_ADDRESSES, TEST_CONNECTIONS, TEST_WALLET_CONNECTIONS } from './mock-data' // Helper function to get expected connection format for API response -export const getExpectedConnection = (connection: ProviderConnection): PublicConnection => { - const { - credentials, - revokedAt, - clientId, - createdAt, - updatedAt, - url, - integrity, - id, - ...connectionWithoutPrivateData - } = connection - return PublicConnection.parse({ - ...connectionWithoutPrivateData, - connectionId: connection.id - }) +export const getExpectedConnection = (model: ProviderConnection) => { + const entity = ConnectionRepository.parseModel(model) + + return { + clientId: entity.clientId, + connectionId: entity.connectionId, + createdAt: entity.createdAt.toISOString(), + label: entity.label, + provider: entity.provider, + status: entity.status, + updatedAt: entity.updatedAt.toISOString(), + url: entity.url + } } // Helper function to get expected address format @@ -43,8 +40,8 @@ export const getExpectedAccount = (account: ProviderAccount) => { walletId, accountId: account.id, addresses: addresses.map(getExpectedAddress), - createdAt: new Date(account.createdAt).toISOString(), - updatedAt: new Date(account.updatedAt).toISOString() + createdAt: account.createdAt.toISOString(), + updatedAt: account.updatedAt.toISOString() } } @@ -66,7 +63,7 @@ export const getExpectedWallet = (wallet: ProviderWallet) => { walletId: wallet.id, accounts: accounts.map(getExpectedAccount), connections: connections.map(getExpectedConnection), - createdAt: new Date(wallet.createdAt).toISOString(), - updatedAt: new Date(wallet.updatedAt).toISOString() + createdAt: wallet.createdAt.toISOString(), + updatedAt: wallet.updatedAt.toISOString() } } diff --git a/apps/vault/src/broker/broker.module.ts b/apps/vault/src/broker/broker.module.ts index 450c79f78..a6ecc7899 100644 --- a/apps/vault/src/broker/broker.module.ts +++ b/apps/vault/src/broker/broker.module.ts @@ -9,8 +9,11 @@ import { PersistenceModule } from '../shared/module/persistence/persistence.modu import { EncryptionKeyService } from '../transit-encryption/core/service/encryption-key.service' import { EncryptionKeyRepository } from '../transit-encryption/persistence/encryption-key.repository' import { TransitEncryptionModule } from '../transit-encryption/transit-encryption.module' +import { AnchorageCredentialService } from './core/provider/anchorage/anchorage-credential.service' +import { AnchorageProxyService } from './core/provider/anchorage/anchorage-proxy.service' import { AnchorageSyncService } from './core/provider/anchorage/anchorage-sync.service' import { AnchorageTransferService } from './core/provider/anchorage/anchorage-transfer.service' +import { FireblocksCredentialService } from './core/provider/fireblocks/fireblocks-credential.service' import { AccountService } from './core/service/account.service' import { AddressService } from './core/service/address.service' import { ConnectionService } from './core/service/connection.service' @@ -23,7 +26,7 @@ import { WalletService } from './core/service/wallet.service' import { ConnectionSyncEventHandler } from './event/handler/connection-sync.event-handler' import { AnchorageClient } from './http/client/anchorage.client' import { ProviderAccountController } from './http/rest/controller/account.controller' -import { AddressController } from './http/rest/controller/address.controller' +import { ProviderAddressController } from './http/rest/controller/address.controller' import { ConnectionController } from './http/rest/controller/connection.controller' import { KnownDestinationController } from './http/rest/controller/known-destination.controller' import { ProxyController } from './http/rest/controller/proxy.controller' @@ -49,14 +52,14 @@ import { WalletRepository } from './persistence/repository/wallet.repository' TransitEncryptionModule ], controllers: [ - ProviderAccountController, - AddressController, ConnectionController, KnownDestinationController, + ProviderAccountController, + ProviderAddressController, + ProviderWalletController, ProxyController, SyncController, - TransferController, - ProviderWalletController + TransferController ], providers: [ ...DEFAULT_HTTP_MODULE_PROVIDERS, @@ -69,6 +72,8 @@ import { WalletRepository } from './persistence/repository/wallet.repository' AddressRepository, AddressService, AnchorageClient, + AnchorageCredentialService, + AnchorageProxyService, AnchorageSyncService, AnchorageTransferService, ConnectionRepository, @@ -77,6 +82,7 @@ import { WalletRepository } from './persistence/repository/wallet.repository' ConnectionSyncEventHandler, EncryptionKeyRepository, EncryptionKeyService, + FireblocksCredentialService, KnownDestinationRepository, KnownDestinationService, ProxyService, diff --git a/apps/vault/src/broker/core/exception/provider-http.exception.ts b/apps/vault/src/broker/core/exception/provider-http.exception.ts index 218757825..9a4b28f30 100644 --- a/apps/vault/src/broker/core/exception/provider-http.exception.ts +++ b/apps/vault/src/broker/core/exception/provider-http.exception.ts @@ -1,5 +1,5 @@ import { AxiosError } from 'axios' -import { Provider } from '../type/connection.type' +import { Provider } from '../type/provider.type' type ProviderHttpResponse = { status: number diff --git a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-sync.service.spec.ts b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-sync.service.spec.ts index 02f1b08be..736016f91 100644 --- a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-sync.service.spec.ts +++ b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-sync.service.spec.ts @@ -21,8 +21,9 @@ import { AddressService } from '../../../../service/address.service' import { ConnectionService } from '../../../../service/connection.service' import { KnownDestinationService } from '../../../../service/known-destination.service' import { WalletService } from '../../../../service/wallet.service' -import { ActiveConnectionWithCredentials, Provider } from '../../../../type/connection.type' +import { ConnectionWithCredentials } from '../../../../type/connection.type' import { + Provider, SyncContext, SyncOperationType, isCreateOperation, @@ -39,7 +40,7 @@ import { getVaultHandlers } from '../server-mock/server' -const toConnectionAssociation = (connection: ActiveConnectionWithCredentials) => ({ +const toConnectionAssociation = (connection: ConnectionWithCredentials) => ({ clientId: connection.clientId, connectionId: connection.connectionId, createdAt: connection.createdAt, @@ -54,16 +55,17 @@ const toConnectionAssociation = (connection: ActiveConnectionWithCredentials) => describe(AnchorageSyncService.name, () => { let app: INestApplication let module: TestingModule - let testPrismaService: TestPrismaService + + let accountService: AccountService + let addressService: AddressService let anchorageSyncService: AnchorageSyncService + let clientService: ClientService + let connection: ConnectionWithCredentials let connectionService: ConnectionService - let connection: ActiveConnectionWithCredentials let knownDestinationService: KnownDestinationService - let addressService: AddressService let provisionService: ProvisionService - let clientService: ClientService + let testPrismaService: TestPrismaService let walletService: WalletRepository - let accountService: AccountService const mockServer = setupMockServer(getHandlers()) @@ -98,8 +100,8 @@ describe(AnchorageSyncService.name, () => { accountService = module.get(AccountService) addressService = module.get(AddressService) knownDestinationService = module.get(KnownDestinationService) - provisionService = module.get(ProvisionService) - clientService = module.get(ClientService) + provisionService = module.get(ProvisionService) + clientService = module.get(ClientService) await testPrismaService.truncateAll() }) diff --git a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts index 7651af479..1c831b41b 100644 --- a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts +++ b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts @@ -19,8 +19,9 @@ import { KnownDestinationRepository } from '../../../../../persistence/repositor import { TransferRepository } from '../../../../../persistence/repository/transfer.repository' import { WalletRepository } from '../../../../../persistence/repository/wallet.repository' import { setupMockServer, useRequestSpy } from '../../../../../shared/__test__/mock-server' -import { ActiveConnectionWithCredentials, ConnectionStatus, Provider } from '../../../../type/connection.type' +import { Connection, ConnectionStatus, ConnectionWithCredentials } from '../../../../type/connection.type' import { Account, Address, KnownDestination, Wallet } from '../../../../type/indexed-resources.type' +import { Provider } from '../../../../type/provider.type' import { InternalTransfer, NetworkFeeAttribution, @@ -62,7 +63,7 @@ describe(AnchorageTransferService.name, () => { d: 'evo-fY2BX60V1n3Z690LadH5BvizcM9bESaYk0LsxyQ' } - const connection: ActiveConnectionWithCredentials = { + const connection: ConnectionWithCredentials = { clientId, connectionId: uuid(), createdAt: new Date(), @@ -116,7 +117,7 @@ describe(AnchorageTransferService.name, () => { const wallet: Wallet = { clientId, - connections: [connection], + connections: [Connection.parse(connection)], createdAt: new Date(), externalId: uuid(), label: null, diff --git a/apps/vault/src/broker/core/provider/anchorage/__test__/unit/anchorage-credential.service.spec.ts b/apps/vault/src/broker/core/provider/anchorage/__test__/unit/anchorage-credential.service.spec.ts new file mode 100644 index 000000000..05bae6f0e --- /dev/null +++ b/apps/vault/src/broker/core/provider/anchorage/__test__/unit/anchorage-credential.service.spec.ts @@ -0,0 +1,98 @@ +import { + Alg, + Hex, + ed25519PrivateKeySchema, + ed25519PublicKeySchema, + generateJwk, + getPublicKey, + privateKeyToHex +} from '@narval/signature' +import { Test } from '@nestjs/testing' +import { ParseException } from '../../../../../../shared/module/persistence/exception/parse.exception' +import '../../../../../shared/__test__/matcher' +import { ConnectionInvalidPrivateKeyException } from '../../../../exception/connection-invalid-private-key.exception' +import { AnchorageCredentialService } from '../../anchorage-credential.service' +import { AnchorageCredentials, AnchorageInputCredentials } from '../../anchorage.type' + +describe(AnchorageCredentialService.name, () => { + let service: AnchorageCredentialService + + beforeEach(async () => { + const module = await Test.createTestingModule({ + providers: [AnchorageCredentialService] + }).compile() + + service = module.get(AnchorageCredentialService) + }) + + describe('parse', () => { + it('validates and parses raw credentials into typed AnchorageCredentials', async () => { + const privateKey = await generateJwk(Alg.EDDSA) + const validCredentials: AnchorageCredentials = { + privateKey, + publicKey: getPublicKey(privateKey), + apiKey: 'test-api-key' + } + + const result = service.parse(validCredentials) + expect(result).toStrictEqual(validCredentials) + }) + + it('throws error when parsing invalid credentials format', () => { + const invalidCredentials = { + apiKey: 'test-api-key', + // Missing required EdDSA key properties + publicKey: { kty: 'OKP' }, + privateKey: { kty: 'OKP' } + } + + expect(() => service.parse(invalidCredentials)).toThrow(ParseException) + }) + }) + + describe('build', () => { + it('transforms input credentials into provider-ready format', async () => { + const eddsaPrivateKey = await generateJwk(Alg.EDDSA) + const input: AnchorageInputCredentials = { + apiKey: 'test-api-key', + privateKey: await privateKeyToHex(eddsaPrivateKey) + } + + const credentials = await service.build(input) + + expect(credentials).toEqual({ + apiKey: input.apiKey, + privateKey: eddsaPrivateKey, + publicKey: getPublicKey(eddsaPrivateKey) + }) + }) + + it('throws error when input private key is invalid', async () => { + const invalidPrivateKey = 'invalid-key-string' + const input: AnchorageInputCredentials = { + apiKey: 'test-api-key', + privateKey: invalidPrivateKey as Hex + } + + await expect(service.build(input)).rejects.toThrow(ConnectionInvalidPrivateKeyException) + }) + + it('throws error when input private key is undefined', async () => { + const input: AnchorageInputCredentials = { + apiKey: 'test-api-key', + privateKey: undefined + } + + await expect(service.build(input)).rejects.toThrow(ConnectionInvalidPrivateKeyException) + }) + }) + + describe('generate', () => { + it('creates new EdDSA key pair with api credentials', async () => { + const credentials = await service.generate() + + expect(credentials.publicKey).toMatchZodSchema(ed25519PublicKeySchema) + expect(credentials.privateKey).toMatchZodSchema(ed25519PrivateKeySchema) + }) + }) +}) diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage-credential.service.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage-credential.service.ts new file mode 100644 index 000000000..00f82e749 --- /dev/null +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage-credential.service.ts @@ -0,0 +1,64 @@ +import { Alg, generateJwk, getPublicKey, privateKeyToJwk } from '@narval/signature' +import { Injectable } from '@nestjs/common' +import { ParseException } from '../../../../shared/module/persistence/exception/parse.exception' +import { ConnectionInvalidPrivateKeyException } from '../../exception/connection-invalid-private-key.exception' +import { ProviderCredentialService } from '../../type/provider.type' +import { AnchorageCredentials, AnchorageInputCredentials } from './anchorage.type' + +@Injectable() +export class AnchorageCredentialService + implements ProviderCredentialService +{ + static SIGNING_KEY_ALG = Alg.EDDSA + + parse(value: unknown): AnchorageCredentials { + const parse = AnchorageCredentials.safeParse(value) + + if (parse.success) { + return parse.data + } + + throw new ParseException(parse.error) + } + + parseInput(value: unknown): AnchorageInputCredentials { + const parse = AnchorageInputCredentials.safeParse(value) + + if (parse.success) { + return parse.data + } + + throw new ParseException(parse.error) + } + + async build(input: AnchorageInputCredentials): Promise { + if (input.privateKey) { + try { + const privateKey = privateKeyToJwk(input.privateKey, Alg.EDDSA) + const publicKey = getPublicKey(privateKey) + + return { + apiKey: input.apiKey, + privateKey, + publicKey + } + } catch (error) { + throw new ConnectionInvalidPrivateKeyException({ + message: error.message, + origin: error + }) + } + } + + throw new ConnectionInvalidPrivateKeyException() + } + + async generate(): Promise { + const privateKey = await generateJwk(Alg.EDDSA) + + return { + privateKey, + publicKey: getPublicKey(privateKey) + } + } +} diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage-proxy.service.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage-proxy.service.ts new file mode 100644 index 000000000..07d339954 --- /dev/null +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage-proxy.service.ts @@ -0,0 +1,35 @@ +import { Injectable } from '@nestjs/common' +import { AnchorageClient } from '../../../http/client/anchorage.client' +import { ConnectionWithCredentials } from '../../type/connection.type' +import { ProviderProxyService, ProxyRequestOptions, ProxyResponse } from '../../type/provider.type' +import { validateConnection } from './anchorage.util' + +@Injectable() +export class AnchorageProxyService implements ProviderProxyService { + constructor(private readonly anchorageClient: AnchorageClient) {} + + async forward( + connection: ConnectionWithCredentials, + { data, endpoint, method }: ProxyRequestOptions + ): Promise { + validateConnection(connection) + + const { url, credentials } = connection + const { apiKey, privateKey } = credentials + const fullUrl = `${url}${endpoint}` + + const response = await this.anchorageClient.forward({ + url: fullUrl, + method, + data, + apiKey, + signKey: privateKey + }) + + return { + data: response.data, + code: response.status, + headers: response.headers + } + } +} diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage-sync.service.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage-sync.service.ts index bd19aa22a..4e9830f82 100644 --- a/apps/vault/src/broker/core/provider/anchorage/anchorage-sync.service.ts +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage-sync.service.ts @@ -1,17 +1,16 @@ import { LoggerService } from '@narval/nestjs-shared' -import { Ed25519PrivateKey } from '@narval/signature' import { Injectable } from '@nestjs/common' import { randomUUID } from 'crypto' import { uniq } from 'lodash' import { AnchorageClient } from '../../../http/client/anchorage.client' -import { ConnectionInvalidException } from '../../exception/connection-invalid.exception' import { AccountService } from '../../service/account.service' import { AddressService } from '../../service/address.service' import { KnownDestinationService } from '../../service/known-destination.service' import { WalletService } from '../../service/wallet.service' -import { ActiveConnection, ActiveConnectionWithCredentials, Connection, Provider } from '../../type/connection.type' +import { Connection, ConnectionWithCredentials } from '../../type/connection.type' import { Address, KnownDestination, Wallet } from '../../type/indexed-resources.type' import { + Provider, ProviderSyncService, SyncContext, SyncOperationType, @@ -19,6 +18,8 @@ import { isCreateOperation } from '../../type/provider.type' import { buildEmptyContext } from '../../util/provider-sync.util' +import { AnchorageCredentialService } from './anchorage-credential.service' +import { validateConnection } from './anchorage.util' @Injectable() export class AnchorageSyncService implements ProviderSyncService { @@ -28,12 +29,12 @@ export class AnchorageSyncService implements ProviderSyncService { private readonly accountService: AccountService, private readonly addressService: AddressService, private readonly knownDestinationService: KnownDestinationService, + private readonly anchorageCredentialService: AnchorageCredentialService, private readonly logger: LoggerService ) {} - async sync(connection: ActiveConnectionWithCredentials): Promise { + async sync(connection: ConnectionWithCredentials): Promise { const initialContext = buildEmptyContext({ connection, now: new Date() }) - const syncWalletContext = await this.syncWallets(initialContext) const syncAccountContext = await this.syncAccounts(syncWalletContext) const syncAddressContext = await this.syncAddresses(syncAccountContext) @@ -54,7 +55,7 @@ export class AnchorageSyncService implements ProviderSyncService { url: connection.url }) - this.validateConnection(connection) + validateConnection(connection) const anchorageVaults = await this.anchorageClient.getVaults({ url: connection.url, @@ -68,7 +69,9 @@ export class AnchorageSyncService implements ProviderSyncService { } }) - const existingWalletByExternalId = new Map(existingWallets.map((wallet) => [wallet.externalId, wallet])) + const existingWalletByExternalId = new Map( + existingWallets.map((wallet) => [wallet.externalId, wallet]) + ) const missingAnchorageVaults = anchorageVaults.filter( (anchorageVault) => !existingWalletByExternalId.has(anchorageVault.vaultId) @@ -82,7 +85,7 @@ export class AnchorageSyncService implements ProviderSyncService { create: { accounts: [], clientId: connection.clientId, - connections: [ActiveConnection.parse(connection)], + connections: [Connection.parse(connection)], createdAt: now, externalId: vault.vaultId, label: vault.name, @@ -106,7 +109,7 @@ export class AnchorageSyncService implements ProviderSyncService { ...existing, label: incoming.name, updatedAt: now, - connections: [...existing.connections, this.toConnectionAssociation(connection)] + connections: [...existing.connections, Connection.parse(connection)] }) } @@ -120,20 +123,6 @@ export class AnchorageSyncService implements ProviderSyncService { } } - private toConnectionAssociation(connection: Connection) { - return { - clientId: connection.clientId, - connectionId: connection.connectionId, - createdAt: connection.createdAt, - label: connection.label, - provider: connection.provider, - revokedAt: connection.revokedAt, - status: connection.status, - updatedAt: connection.updatedAt, - url: connection.url - } - } - async syncAccounts(context: SyncContext): Promise { const { connection } = context @@ -143,7 +132,7 @@ export class AnchorageSyncService implements ProviderSyncService { url: connection.url }) - this.validateConnection(connection) + validateConnection(connection) const anchorageWallets = await this.anchorageClient.getWallets({ url: connection.url, @@ -231,7 +220,7 @@ export class AnchorageSyncService implements ProviderSyncService { url: connection.url }) - this.validateConnection(connection) + validateConnection(connection) const now = context.now || new Date() @@ -330,7 +319,7 @@ export class AnchorageSyncService implements ProviderSyncService { url: connection.url }) - this.validateConnection(connection) + validateConnection(connection) // Fetch current state from Anchorage const anchorageTrustedDestinations = await this.anchorageClient.getTrustedDestinations({ @@ -403,43 +392,4 @@ export class AnchorageSyncService implements ProviderSyncService { knownDestinations: [...createOperations, ...updateOperations, ...deleteOperations] } } - - private validateConnection( - connection: ActiveConnectionWithCredentials - ): asserts connection is ActiveConnectionWithCredentials & { - url: string - credentials: { - apiKey: string - privateKey: Ed25519PrivateKey - } - } { - const context = { - clientId: connection.clientId, - connectionId: connection.connectionId, - provider: connection.provider, - status: connection.status, - url: connection.url - } - - if (connection.provider !== Provider.ANCHORAGE) { - throw new ConnectionInvalidException({ - message: 'Invalid connection provider for Anchorage', - context - }) - } - - if (!connection.url) { - throw new ConnectionInvalidException({ - message: 'Cannot sync without a connection URL', - context - }) - } - - if (!connection.credentials?.apiKey && !connection.credentials?.privateKey) { - throw new ConnectionInvalidException({ - message: 'Cannot sync without API key and/or signing key', - context - }) - } - } } diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts index e3e33a1f2..65ab6373e 100644 --- a/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts @@ -5,8 +5,8 @@ import { AnchorageClient } from '../../../http/client/anchorage.client' import { TransferRepository } from '../../../persistence/repository/transfer.repository' import { BrokerException } from '../../exception/broker.exception' import { TransferPartyService } from '../../service/transfer-party.service' -import { ActiveConnectionWithCredentials, Provider } from '../../type/connection.type' -import { ProviderTransferService } from '../../type/provider.type' +import { ConnectionWithCredentials } from '../../type/connection.type' +import { Provider, ProviderTransferService } from '../../type/provider.type' import { Destination, InternalTransfer, @@ -19,6 +19,7 @@ import { isAddressDestination, isProviderSpecific } from '../../type/transfer.type' +import { validateConnection } from './anchorage.util' @Injectable() export class AnchorageTransferService implements ProviderTransferService { @@ -29,13 +30,15 @@ export class AnchorageTransferService implements ProviderTransferService { private readonly logger: LoggerService ) {} - async findById(connection: ActiveConnectionWithCredentials, transferId: string): Promise { + async findById(connection: ConnectionWithCredentials, transferId: string): Promise { this.logger.log('Find Anchorage transfer by ID', { clientId: connection.clientId, connectionId: connection.connectionId, transferId }) + validateConnection(connection) + const internalTransfer = await this.transferRepository.findById(connection.clientId, transferId) this.logger.log('Found internal transfer by ID', internalTransfer) @@ -101,13 +104,15 @@ export class AnchorageTransferService implements ProviderTransferService { }) } - async send(connection: ActiveConnectionWithCredentials, sendTransfer: SendTransfer): Promise { + async send(connection: ConnectionWithCredentials, sendTransfer: SendTransfer): Promise { this.logger.log('Send Anchorage transfer', { clientId: connection.clientId, connectionId: connection.connectionId, sendTransfer }) + validateConnection(connection) + const source = await this.transferPartyService.resolve(connection.clientId, sendTransfer.source) const destination = await this.transferPartyService.resolve(connection.clientId, sendTransfer.destination) diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage.type.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage.type.ts new file mode 100644 index 000000000..438ce6b25 --- /dev/null +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage.type.ts @@ -0,0 +1,16 @@ +import { hexSchema } from '@narval/policy-engine-shared' +import { ed25519PrivateKeySchema, ed25519PublicKeySchema } from '@narval/signature' +import { z } from 'zod' + +export const AnchorageInputCredentials = z.object({ + apiKey: z.string(), + privateKey: hexSchema.optional().describe('Ed25519 private key in hex format') +}) +export type AnchorageInputCredentials = z.infer + +export const AnchorageCredentials = z.object({ + apiKey: z.string().optional(), + publicKey: ed25519PublicKeySchema, + privateKey: ed25519PrivateKeySchema +}) +export type AnchorageCredentials = z.infer diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage.util.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage.util.ts new file mode 100644 index 000000000..93fa1032d --- /dev/null +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage.util.ts @@ -0,0 +1,53 @@ +import { Ed25519PrivateKey } from '@narval/signature' +import { ConnectionInvalidException } from '../../exception/connection-invalid.exception' +import { ConnectionWithCredentials } from '../../type/connection.type' +import { Provider } from '../../type/provider.type' +import { AnchorageCredentials } from './anchorage.type' + +export function validateConnection( + connection: ConnectionWithCredentials +): asserts connection is ConnectionWithCredentials & { + url: string + credentials: { + apiKey: string + privateKey: Ed25519PrivateKey + } +} { + const context = { + clientId: connection.clientId, + connectionId: connection.connectionId, + provider: connection.provider, + status: connection.status, + url: connection.url + } + + if (connection.provider !== Provider.ANCHORAGE) { + throw new ConnectionInvalidException({ + message: 'Invalid connection provider for Anchorage', + context + }) + } + + if (!connection.url) { + throw new ConnectionInvalidException({ + message: 'Anchorage connection missing URL', + context + }) + } + + if (!connection.credentials) { + throw new ConnectionInvalidException({ + message: 'Anchorage connection missing credentials', + context + }) + } + + const credentials = AnchorageCredentials.parse(connection.credentials) + + if (!credentials.apiKey) { + throw new ConnectionInvalidException({ + message: 'Anchorage connection missing API key', + context + }) + } +} diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/unit/fireblocks-credential.service.spec.ts b/apps/vault/src/broker/core/provider/fireblocks/__test__/unit/fireblocks-credential.service.spec.ts new file mode 100644 index 000000000..a92fff3ff --- /dev/null +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/unit/fireblocks-credential.service.spec.ts @@ -0,0 +1,100 @@ +import { + Alg, + SMALLEST_RSA_MODULUS_LENGTH, + generateJwk, + getPublicKey, + privateKeyToPem, + rsaPrivateKeySchema, + rsaPublicKeySchema +} from '@narval/signature' +import { Test } from '@nestjs/testing' +import { ParseException } from '../../../../../../shared/module/persistence/exception/parse.exception' +import '../../../../../shared/__test__/matcher' +import { ConnectionInvalidPrivateKeyException } from '../../../../exception/connection-invalid-private-key.exception' +import { FireblocksCredentialService } from '../../fireblocks-credential.service' +import { FireblocksCredentials, FireblocksInputCredentials } from '../../fireblocks.type' + +describe('FireblocksCredentialService', () => { + let service: FireblocksCredentialService + + beforeEach(async () => { + const module = await Test.createTestingModule({ + providers: [FireblocksCredentialService] + }).compile() + + service = module.get(FireblocksCredentialService) + }) + + describe('parse', () => { + it('validates and parses raw credentials into typed FireblocksCredentials', async () => { + const privateKey = await generateJwk(Alg.RS256, { modulusLength: SMALLEST_RSA_MODULUS_LENGTH }) + const validCredentials: FireblocksCredentials = { + privateKey, + publicKey: getPublicKey(privateKey), + apiKey: 'test-api-key' + } + + const result = service.parse(validCredentials) + + expect(result).toStrictEqual(validCredentials) + }) + + it('throws error when parsing invalid credentials format', () => { + const invalidCredentials = { + apiKey: 'test-api-key', + // Missing required RSA key properties + publicKey: { kty: 'RSA' }, + privateKey: { kty: 'RSA' } + } + + expect(() => service.parse(invalidCredentials)).toThrow(ParseException) + }) + }) + + describe('build', () => { + it('transforms input credentials into provider-ready format', async () => { + const rsaPrivateKey = await generateJwk(Alg.RS256, { modulusLength: SMALLEST_RSA_MODULUS_LENGTH }) + const pem = await privateKeyToPem(rsaPrivateKey, Alg.RS256) + const input: FireblocksInputCredentials = { + apiKey: 'test-api-key', + privateKey: Buffer.from(pem).toString('base64') + } + + const credentials = await service.build(input) + + expect(credentials).toEqual({ + apiKey: input.apiKey, + privateKey: rsaPrivateKey, + publicKey: getPublicKey(rsaPrivateKey) + }) + }) + + it('throws error when input private key is invalid', async () => { + const invalidPrivateKey = 'invalid-base64-string' + const input: FireblocksInputCredentials = { + apiKey: 'test-api-key', + privateKey: invalidPrivateKey + } + + await expect(service.build(input)).rejects.toThrow(ConnectionInvalidPrivateKeyException) + }) + + it('throws error when input private key is undefined', async () => { + const input: FireblocksInputCredentials = { + apiKey: 'test-api-key', + privateKey: undefined + } + + await expect(service.build(input)).rejects.toThrow(ConnectionInvalidPrivateKeyException) + }) + }) + + describe('generate', () => { + it('creates new RSA key pair with api credentials', async () => { + const credentials = await service.generate({ modulusLength: SMALLEST_RSA_MODULUS_LENGTH }) + + expect(credentials.publicKey).toMatchZodSchema(rsaPublicKeySchema) + expect(credentials.privateKey).toMatchZodSchema(rsaPrivateKeySchema) + }) + }) +}) diff --git a/apps/vault/src/broker/core/provider/fireblocks/fireblocks-credential.service.ts b/apps/vault/src/broker/core/provider/fireblocks/fireblocks-credential.service.ts new file mode 100644 index 000000000..6bf91f8de --- /dev/null +++ b/apps/vault/src/broker/core/provider/fireblocks/fireblocks-credential.service.ts @@ -0,0 +1,66 @@ +import { Alg, DEFAULT_RSA_MODULUS_LENGTH, generateJwk, getPublicKey, privateRsaPemToJwk } from '@narval/signature' +import { Injectable } from '@nestjs/common' +import { ParseException } from '../../../../shared/module/persistence/exception/parse.exception' +import { ConnectionInvalidPrivateKeyException } from '../../exception/connection-invalid-private-key.exception' +import { ProviderCredentialService } from '../../type/provider.type' +import { FireblocksCredentials, FireblocksInputCredentials } from './fireblocks.type' + +@Injectable() +export class FireblocksCredentialService + implements ProviderCredentialService +{ + parse(value: unknown): FireblocksCredentials { + const parse = FireblocksCredentials.safeParse(value) + + if (parse.success) { + return parse.data + } + + throw new ParseException(parse.error) + } + + parseInput(value: unknown): FireblocksInputCredentials { + const parse = FireblocksInputCredentials.safeParse(value) + + if (parse.success) { + return parse.data + } + + throw new ParseException(parse.error) + } + + async build(input: FireblocksInputCredentials): Promise { + if (input.privateKey) { + try { + const pem = Buffer.from(input.privateKey, 'base64').toString('utf8') + const privateKey = await privateRsaPemToJwk(pem) + const publicKey = getPublicKey(privateKey) + + return { + apiKey: input.apiKey, + privateKey, + publicKey + } + } catch (error) { + throw new ConnectionInvalidPrivateKeyException({ + message: error.message, + origin: error + }) + } + } + + throw new ConnectionInvalidPrivateKeyException() + } + + async generate( + opts?: Options + ): Promise { + const modulusLength = opts?.modulusLength || DEFAULT_RSA_MODULUS_LENGTH + const privateKey = await generateJwk(Alg.RS256, { modulusLength }) + + return { + privateKey, + publicKey: getPublicKey(privateKey) + } + } +} diff --git a/apps/vault/src/broker/core/provider/fireblocks/fireblocks.type.ts b/apps/vault/src/broker/core/provider/fireblocks/fireblocks.type.ts new file mode 100644 index 000000000..5c1318b57 --- /dev/null +++ b/apps/vault/src/broker/core/provider/fireblocks/fireblocks.type.ts @@ -0,0 +1,15 @@ +import { rsaPrivateKeySchema, rsaPublicKeySchema } from '@narval/signature' +import { z } from 'zod' + +export const FireblocksInputCredentials = z.object({ + apiKey: z.string(), + privateKey: z.string().optional().describe('RSA private key pem base64 encoded') +}) +export type FireblocksInputCredentials = z.infer + +export const FireblocksCredentials = z.object({ + apiKey: z.string().optional(), + publicKey: rsaPublicKeySchema, + privateKey: rsaPrivateKeySchema +}) +export type FireblocksCredentials = z.infer diff --git a/apps/vault/src/broker/core/service/__test__/integration/sync.service.spec.ts b/apps/vault/src/broker/core/service/__test__/integration/sync.service.spec.ts index 588daa035..3aefff59c 100644 --- a/apps/vault/src/broker/core/service/__test__/integration/sync.service.spec.ts +++ b/apps/vault/src/broker/core/service/__test__/integration/sync.service.spec.ts @@ -18,9 +18,9 @@ import { testClient } from '../../../../__test__/util/mock-data' import { SyncRepository } from '../../../../persistence/repository/sync.repository' import { WalletRepository } from '../../../../persistence/repository/wallet.repository' import { ANCHORAGE_TEST_API_BASE_URL } from '../../../provider/anchorage/__test__/server-mock/server' -import { ActiveConnectionWithCredentials, Provider } from '../../../type/connection.type' +import { Connection, ConnectionWithCredentials } from '../../../type/connection.type' import { Account, Address, KnownDestination, Wallet } from '../../../type/indexed-resources.type' -import { SyncOperationType, SyncResult } from '../../../type/provider.type' +import { Provider, SyncOperationType, SyncResult } from '../../../type/provider.type' import { Sync, SyncStatus } from '../../../type/sync.type' import { AccountService } from '../../account.service' import { AddressService } from '../../address.service' @@ -29,18 +29,6 @@ import { KnownDestinationService } from '../../known-destination.service' import { SyncService } from '../../sync.service' import { WalletService } from '../../wallet.service' -const toConnectionAssociation = (connection: ActiveConnectionWithCredentials) => ({ - clientId: connection.clientId, - connectionId: connection.connectionId, - createdAt: connection.createdAt, - label: undefined, - provider: connection.provider, - revokedAt: undefined, - status: connection.status, - updatedAt: connection.updatedAt, - url: connection.url -}) - describe(SyncService.name, () => { let app: INestApplication let module: TestingModule @@ -49,7 +37,7 @@ describe(SyncService.name, () => { let accountService: AccountService let addressService: AddressService let clientService: ClientService - let connection: ActiveConnectionWithCredentials + let connection: ConnectionWithCredentials let connectionService: ConnectionService let knownDestinationService: KnownDestinationService let provisionService: ProvisionService @@ -141,7 +129,7 @@ describe(SyncService.name, () => { walletOne = { accounts: [], clientId: connection.clientId, - connections: [toConnectionAssociation(connection)], + connections: [Connection.parse(connection)], createdAt: new Date('2023-01-01T00:00:00Z'), externalId: 'external-id-one', label: 'wallet one', @@ -152,7 +140,7 @@ describe(SyncService.name, () => { walletTwo = { accounts: [], clientId: connection.clientId, - connections: [toConnectionAssociation(connection)], + connections: [Connection.parse(connection)], createdAt: new Date('2024-01-01T00:00:00Z'), externalId: 'external-id-two', label: 'wallet two', @@ -211,7 +199,7 @@ describe(SyncService.name, () => { address: 'known-destination-one-address', assetId: 'USDC', clientId, - connections: [toConnectionAssociation(connection)], + connections: [Connection.parse(connection)], createdAt: new Date('2023-01-01T00:00:00Z'), externalClassification: null, externalId: 'known-destination-one-external-id', @@ -225,7 +213,7 @@ describe(SyncService.name, () => { address: 'known-destination-two-address', assetId: 'USDC', clientId, - connections: [toConnectionAssociation(connection)], + connections: [Connection.parse(connection)], createdAt: new Date('2024-01-01T00:00:00Z'), externalClassification: null, externalId: 'known-destination-two-external-id', diff --git a/apps/vault/src/broker/core/service/connection.service.ts b/apps/vault/src/broker/core/service/connection.service.ts index 38e559844..b8df4d717 100644 --- a/apps/vault/src/broker/core/service/connection.service.ts +++ b/apps/vault/src/broker/core/service/connection.service.ts @@ -1,73 +1,82 @@ import { ConfigService } from '@narval/config-module' import { LoggerService, PaginatedResult } from '@narval/nestjs-shared' -import { - Alg, - Ed25519PrivateKey, - Ed25519PublicKey, - Hex, - generateJwk, - getPublicKey, - privateKeyToJwk -} from '@narval/signature' -import { HttpStatus, Injectable, NotImplementedException } from '@nestjs/common' +import { HttpStatus, Injectable } from '@nestjs/common' import { EventEmitter2 } from '@nestjs/event-emitter' +import { randomUUID } from 'crypto' import { SetRequired } from 'type-fest' -import { v4 as uuid } from 'uuid' import { Config, Env } from '../../../main.config' import { EncryptionKeyService } from '../../../transit-encryption/core/service/encryption-key.service' import { ConnectionRepository, FindAllOptions } from '../../persistence/repository/connection.repository' import { ConnectionActivatedEvent } from '../../shared/event/connection-activated.event' import { BrokerException } from '../exception/broker.exception' import { ConnectionInvalidCredentialsException } from '../exception/connection-invalid-credentials.exception' -import { ConnectionInvalidPrivateKeyException } from '../exception/connection-invalid-private-key.exception' import { ConnectionInvalidStatusException } from '../exception/connection-invalid-status.exception' import { NotFoundException } from '../exception/not-found.exception' -import { UpdateException } from '../exception/update.exception' +import { AnchorageCredentialService } from '../provider/anchorage/anchorage-credential.service' +import { AnchorageCredentials, AnchorageInputCredentials } from '../provider/anchorage/anchorage.type' +import { FireblocksCredentialService } from '../provider/fireblocks/fireblocks-credential.service' +import { FireblocksCredentials, FireblocksInputCredentials } from '../provider/fireblocks/fireblocks.type' import { - ActiveConnectionWithCredentials, - AnchorageCredentials, Connection, ConnectionStatus, ConnectionWithCredentials, CreateConnection, - CreateCredentials, InitiateConnection, - PendingConnectionWithCredentials, - Provider, + PendingConnection, UpdateConnection, isActiveConnection, isPendingConnection, isRevokedConnection } from '../type/connection.type' +import { Provider, ProviderCredentialService } from '../type/provider.type' + +type ProviderInputCredentialsMap = { + anchorage: AnchorageInputCredentials + fireblocks: FireblocksInputCredentials +} + +type ProviderCredentialsMap = { + anchorage: AnchorageCredentials + fireblocks: FireblocksCredentials +} @Injectable() export class ConnectionService { + private readonly providerCredentialServices: { + [P in Provider]: ProviderCredentialService + } + constructor( private readonly connectionRepository: ConnectionRepository, private readonly encryptionKeyService: EncryptionKeyService, - private readonly logger: LoggerService, + private readonly configService: ConfigService, private readonly eventEmitter: EventEmitter2, - private readonly configService: ConfigService - ) {} + private readonly logger: LoggerService, + // Provider Specific Credential Services + fireblocksCredentialService: FireblocksCredentialService, + anchorageCredentialService: AnchorageCredentialService + ) { + this.providerCredentialServices = { + [Provider.ANCHORAGE]: anchorageCredentialService, + [Provider.FIREBLOCKS]: fireblocksCredentialService + } + } - async initiate(clientId: string, input: InitiateConnection): Promise { + async initiate(clientId: string, input: InitiateConnection): Promise { this.logger.log('Initiate pending connection', { clientId }) const now = new Date() - const privateKey = await this.generatePrivateKey() + const generatedCredentials = await this.generateProviderCredentials(input.provider) const encryptionKey = await this.encryptionKeyService.generate(clientId) const connection = { - connectionId: input.connectionId || uuid(), clientId, + connectionId: input.connectionId || randomUUID(), createdAt: now, - provider: input.provider, - credentials: { - privateKey, - publicKey: getPublicKey(privateKey) - }, + credentials: generatedCredentials, encryptionPublicKey: encryptionKey.publicKey, - status: ConnectionStatus.PENDING, + provider: input.provider, revokedAt: undefined, + status: ConnectionStatus.PENDING, updatedAt: now } @@ -82,133 +91,77 @@ export class ConnectionService { clientId: connection.clientId, connectionId: connection.connectionId, createdAt: connection.createdAt, - updatedAt: connection.updatedAt, - credentials: { - privateKey, - publicKey: connection.credentials.publicKey - }, encryptionPublicKey: encryptionKey.publicKey, provider: connection.provider, - status: connection.status + status: connection.status, + updatedAt: connection.updatedAt } } - // TODO: (@wcalderipe, 05/12/24): The return type is Anchorage specific. - private async generatePrivateKey(): Promise { - return await generateJwk(Alg.EDDSA) - } - - async create(clientId: string, input: CreateConnection): Promise { - this.logger.log('Create active connection', { clientId }) - - // If a connection ID is provided, check if the connection already exists. - // If it does, activate the connection. - if (input.connectionId) { - if (await this.connectionRepository.exists(clientId, input.connectionId)) { - return this.activate(clientId, { - ...input, - connectionId: input.connectionId - }) - } - } - - if (input.credentials) { - this.logger.log('Create active account from plain credentials', { clientId }) - - return this.createActiveConnection(clientId, input) - } - - if (input.encryptedCredentials) { - this.logger.log('Create active account from encrypted credentials', { clientId }) - - const credentials = await this.getInputCredentials(clientId, input) - - return this.createActiveConnection(clientId, { ...input, credentials }) - } - - throw new ConnectionInvalidCredentialsException() - } - - private async createActiveConnection( - clientId: string, - input: CreateConnection - ): Promise { - // By this point, the credentials should have already been decrypted and - // decoded. - if (!input.credentials) { - throw new ConnectionInvalidCredentialsException() - } - - const now = new Date() - const { privateKey, publicKey } = await this.parseInputCredentials(clientId, input.provider, input) - - if (privateKey.kty) { - const connection = { - clientId, - createdAt: now, - credentials: { - apiKey: input.credentials.apiKey, - privateKey, - publicKey - }, - connectionId: input.connectionId || uuid(), - label: input.label, - provider: input.provider, - url: input.url, - revokedAt: undefined, - status: ConnectionStatus.ACTIVE, - updatedAt: now - } - - await this.connectionRepository.create(connection) - - this.eventEmitter.emit(ConnectionActivatedEvent.EVENT_NAME, new ConnectionActivatedEvent(connection)) - - return connection - } - - throw new ConnectionInvalidPrivateKeyException() - } - async activate( clientId: string, input: SetRequired - ): Promise { - const pendingConnection = await this.connectionRepository.findById(clientId, input.connectionId, true) + ): Promise { + const pendingConnection = await this.connectionRepository.findById(clientId, input.connectionId) + const existingCredentials = await this.findCredentials(pendingConnection) + + if (!existingCredentials) { + throw new ConnectionInvalidCredentialsException({ + message: "Cannot activate a connection that's missing credentials", + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY + }) + } - if (isPendingConnection(pendingConnection) && pendingConnection.credentials) { + if (isPendingConnection(pendingConnection)) { this.logger.log('Activate pending connection', { clientId, connectionId: pendingConnection.connectionId }) - const now = new Date() - - const credentials = await this.getInputCredentials(clientId, input) - - const mergedCredentials = { - ...pendingConnection.credentials, - apiKey: credentials.apiKey - } - - // If a private key is provided in the input, it overrides the private and public key from the pending connection. - if (credentials.privateKey) { - mergedCredentials.privateKey = privateKeyToJwk(credentials.privateKey, Alg.EDDSA) - mergedCredentials.publicKey = getPublicKey(mergedCredentials.privateKey) - } - - const connection: ActiveConnectionWithCredentials = { + const now = input.createdAt || new Date() + const provider = pendingConnection.provider + const inputCredentials = await this.getInputCredentials(provider, clientId, input) + let connection = { ...pendingConnection, clientId, connectionId: input.connectionId, - status: ConnectionStatus.ACTIVE, + createdAt: pendingConnection.createdAt, + credentials: existingCredentials, label: input.label, - url: input.url, + status: ConnectionStatus.ACTIVE, updatedAt: now, - createdAt: pendingConnection.createdAt, - credentials: mergedCredentials + url: input.url + } + + // If a private key is provided in the input, it overrides the existing + // private and public key. Otherwise, adds the API key to the + // generated credentials. + if (inputCredentials.privateKey) { + this.logger.log('Existing private key is being overridden with a new one', { + clientId, + connectionId: connection.connectionId + }) + + const updatedCredentials = inputCredentials.privateKey + ? await this.buildProviderCredentials(provider, inputCredentials) + : { ...existingCredentials, apiKey: inputCredentials.apiKey } + + connection = { + ...connection, + credentials: updatedCredentials + } + } else { + connection = { + ...connection, + credentials: { + ...inputCredentials, + ...existingCredentials + } + } } + await this.connectionRepository.update(connection) + this.eventEmitter.emit(ConnectionActivatedEvent.EVENT_NAME, new ConnectionActivatedEvent(connection)) return connection @@ -228,126 +181,124 @@ export class ConnectionService { }) } - // TODO: (@wcalderipe, 05/12/24): The return type is Anchorage specific. - private async parseInputCredentials( - clientId: string, - provider: Provider, - input: CreateConnection | UpdateConnection - ): Promise { - // During the creation process, the input credentials can be one of the - // following: - // - A plain credential object containing an API key and a private key in - // hex format. - // - Encrypted credentials, which are an RSA-encrypted JSON representation - // of the plain credentials. - // - // Steps to handle the credentials: - // - Extract the credentials from the input data. - // - Ensure that either `credentials` or `encryptedCredentials` is - // provided. - // - If the credentials are encrypted, decrypt and parse the JSON. - // - Validate the credentials against the expected schema. - - if (provider === Provider.ANCHORAGE) { - if (input.encryptedCredentials) { - const raw = await this.encryptionKeyService.decrypt(clientId, input.encryptedCredentials) - - const parse = CreateCredentials.safeParse(JSON.parse(raw)) - - if (parse.success) { - const { privateKey, publicKey } = this.privateKeyHexToKeyPair(Alg.EDDSA, parse.data.privateKey) - - return { - apiKey: parse.data.apiKey, - privateKey: privateKey as Ed25519PrivateKey, - publicKey: publicKey as Ed25519PublicKey - } - } + async create(clientId: string, input: CreateConnection): Promise { + this.logger.log('Create active connection', { clientId }) - throw new ConnectionInvalidPrivateKeyException({ - message: 'Invalid input private key schema', - context: { errors: parse.error.errors } + // If a connection ID is provided, check if the connection already exists. + // If it does, activate the connection. + if (input.connectionId) { + if (await this.connectionRepository.exists(clientId, input.connectionId)) { + return this.activate(clientId, { + ...input, + connectionId: input.connectionId }) } + } - if (input.credentials) { - const { privateKey, publicKey } = this.privateKeyHexToKeyPair(Alg.EDDSA, input.credentials.privateKey) + const now = input.createdAt || new Date() + const provider = input.provider + const inputCredentials = await this.getInputCredentials(provider, clientId, input) + const credentials = await this.buildProviderCredentials(provider, inputCredentials) + const connection = { + clientId, + credentials, + createdAt: now, + connectionId: input.connectionId || randomUUID(), + label: input.label, + provider: input.provider, + url: input.url, + revokedAt: undefined, + status: ConnectionStatus.ACTIVE, + updatedAt: now + } - return { - apiKey: input.credentials.apiKey, - privateKey: privateKey as Ed25519PrivateKey, - publicKey: publicKey as Ed25519PublicKey - } - } + await this.connectionRepository.create(connection) - throw new ConnectionInvalidCredentialsException({ - message: 'Missing input credentials or encryptedCredentials' + this.eventEmitter.emit(ConnectionActivatedEvent.EVENT_NAME, new ConnectionActivatedEvent(connection)) + + return connection + } + + async revoke(clientId: string, connectionId: string): Promise { + const connection = await this.connectionRepository.findById(clientId, connectionId) + + if (isRevokedConnection(connection)) { + this.logger.log("Skip connection revoke because it's already revoked", { + clientId, + connectionId: connection.connectionId + }) + + throw new ConnectionInvalidStatusException({ + from: connection.status, + to: ConnectionStatus.REVOKED, + clientId, + connectionId }) } - throw new NotImplementedException(`Unsupported provider private key getter: ${provider}`) - } + if (isActiveConnection(connection) || isPendingConnection(connection)) { + this.logger.log('Revoke active or pending connection', { + clientId, + connectionId: connection.connectionId + }) - private privateKeyHexToKeyPair(alg: Alg, privateKeyHex?: Hex) { - if (privateKeyHex) { - const privateKey = privateKeyToJwk(privateKeyHex, alg) + await this.connectionRepository.update({ + ...connection, + clientId, + connectionId: connectionId, + credentials: null, + revokedAt: new Date(), + status: ConnectionStatus.REVOKED + }) - return { - privateKey: privateKey, - publicKey: getPublicKey(privateKey) - } + return true } - throw new ConnectionInvalidPrivateKeyException({ - message: 'Invalid private key hex' + throw new NotFoundException({ + message: 'Connection not found', + context: { clientId, connectionId } }) } - async update(input: UpdateConnection): Promise { - const connection = await this.connectionRepository.findById(input.clientId, input.connectionId, true) - const hasCredentials = input.credentials || input.encryptedCredentials + async update(updateConnection: UpdateConnection): Promise { + const connection = await this.connectionRepository.findById( + updateConnection.clientId, + updateConnection.connectionId + ) + const hasCredentials = updateConnection.credentials || updateConnection.encryptedCredentials const update = { ...connection, - createdAt: connection.createdAt, // must include the existing createdAt value for integrity verification - ...input, - ...(hasCredentials - ? { credentials: await this.parseInputCredentials(input.clientId, connection.provider, input) } - : {}) + // Must include the existing createdAt value for integrity verification. + createdAt: connection.createdAt, + ...updateConnection } - const isUpdated = await this.connectionRepository.update(update) + if (hasCredentials) { + const inputCredentials = await this.getInputCredentials( + connection.provider, + connection.clientId, + updateConnection + ) + const credentials = await this.buildProviderCredentials(connection.provider, inputCredentials) - if (isUpdated) { - return Connection.parse({ - ...connection, - ...update + await this.connectionRepository.update({ + ...update, + credentials }) + } else { + await this.connectionRepository.update(update) } - throw new UpdateException({ - context: { - model: 'Connection', - connectionId: input.connectionId, - clientId: input.clientId - } - }) + // Strip credentials out of the connection. + return Connection.parse(update) } - private async getInputCredentials( - clientId: string, - input: CreateConnection | UpdateConnection - ): Promise { + private async getInputCredentials(provider: Provider, clientId: string, input: CreateConnection | UpdateConnection) { if (input.encryptedCredentials) { const raw = await this.encryptionKeyService.decrypt(clientId, input.encryptedCredentials) - const parse = CreateCredentials.safeParse(JSON.parse(raw)) - - if (parse.success) { - return parse.data - } + const json = JSON.parse(raw) - throw new ConnectionInvalidPrivateKeyException({ - context: { errors: parse.error.errors } - }) + return this.parseProviderInputCredentials(provider, json) } if (input.credentials) { @@ -358,71 +309,68 @@ export class ConnectionService { }) } - return input.credentials + return this.parseProviderInputCredentials(provider, input.credentials) } throw new ConnectionInvalidCredentialsException() } - async exists(clientId: string, connectionId?: string): Promise { - if (connectionId) { - return this.connectionRepository.exists(clientId, connectionId) - } - - return false + async findById(clientId: string, connectionId: string): Promise { + return this.connectionRepository.findById(clientId, connectionId) } - async findById( - clientId: string, - connectionId: string, - includeCredentials?: T - ): Promise { - return this.connectionRepository.findById(clientId, connectionId, includeCredentials) + async findAll(clientId: string, options?: FindAllOptions): Promise> { + return this.connectionRepository.findAll(clientId, options) } - async findAll( + async findAllWithCredentials( clientId: string, - options?: FindAllOptions, - includeCredentials?: T - ): Promise : PaginatedResult> { - return this.connectionRepository.findAll(clientId, options, includeCredentials) + options?: FindAllOptions + ): Promise> { + return this.connectionRepository.findAllWithCredentials(clientId, options) } - async revoke(clientId: string, connectionId: string): Promise { - const connection = await this.connectionRepository.findById(clientId, connectionId) - - if (isRevokedConnection(connection)) { - this.logger.log("Skip connection revoke because it's already revoked", { - clientId, - connectionId: connection.connectionId - }) + async findWithCredentialsById(clientId: string, connectionId: string): Promise { + return this.connectionRepository.findWithCredentialsById(clientId, connectionId) + } - throw new ConnectionInvalidStatusException({ - from: connection.status, - to: ConnectionStatus.REVOKED, - clientId, - connectionId - }) + async findCredentials

(connection: { + provider: P + connectionId: string + }): Promise { + const json = await this.connectionRepository.findCredentialsJson(connection) + + if (json) { + try { + return this.parseProviderCredentials(connection.provider, json) + } catch (error) { + throw new ConnectionInvalidCredentialsException({ + message: `Invalid stored ${connection.provider} connection`, + suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, + origin: error + }) + } } - if (isActiveConnection(connection) || isPendingConnection(connection)) { - this.logger.log('Revoke active or pending connection', { - clientId, - connectionId: connection.connectionId - }) + return null + } - await this.connectionRepository.update({ - ...connection, - clientId, - connectionId: connectionId, - credentials: null, - status: ConnectionStatus.REVOKED, - revokedAt: new Date() - }) + parseProviderCredentials

(provider: P, value: unknown): ProviderCredentialsMap[P] { + return this.providerCredentialServices[provider].parse(value) + } - return true - } + parseProviderInputCredentials

(provider: P, value: unknown): ProviderInputCredentialsMap[P] { + return this.providerCredentialServices[provider].parseInput(value) + } + + buildProviderCredentials

( + provider: P, + input: ProviderInputCredentialsMap[P] + ): Promise { + return this.providerCredentialServices[provider].build(input) + } - throw new NotFoundException({ context: { clientId, connectionId } }) + generateProviderCredentials

(provider: P): Promise { + return this.providerCredentialServices[provider].generate() } } diff --git a/apps/vault/src/broker/core/service/proxy.service.ts b/apps/vault/src/broker/core/service/proxy.service.ts index bff19698d..c3a3ffea8 100644 --- a/apps/vault/src/broker/core/service/proxy.service.ts +++ b/apps/vault/src/broker/core/service/proxy.service.ts @@ -1,10 +1,9 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ - -import { HttpStatus, Injectable } from '@nestjs/common' -import { AnchorageClient } from '../../http/client/anchorage.client' -import { ConnectionRepository } from '../../persistence/repository/connection.repository' +import { Injectable, NotImplementedException } from '@nestjs/common' import { ConnectionInvalidException } from '../exception/connection-invalid.exception' +import { AnchorageProxyService } from '../provider/anchorage/anchorage-proxy.service' import { isActiveConnection } from '../type/connection.type' +import { Provider, ProviderProxyService, ProxyResponse } from '../type/provider.type' +import { ConnectionService } from './connection.service' type ProxyRequestOptions = { connectionId: string @@ -16,15 +15,13 @@ type ProxyRequestOptions = { @Injectable() export class ProxyService { constructor( - private readonly anchorageClient: AnchorageClient, - private readonly connectionRepository: ConnectionRepository + private readonly connectionRepository: ConnectionService, + private readonly anchorageProxyService: AnchorageProxyService ) {} - async forward( - clientId: string, - { connectionId, data, endpoint, method }: ProxyRequestOptions - ): Promise<{ data: any; code: HttpStatus; headers: Record }> { - const connection = await this.connectionRepository.findById(clientId, connectionId, true) + async forward(clientId: string, options: ProxyRequestOptions): Promise { + const { connectionId } = options + const connection = await this.connectionRepository.findById(clientId, connectionId) if (!isActiveConnection(connection)) { throw new ConnectionInvalidException({ @@ -33,22 +30,23 @@ export class ProxyService { }) } - const { url, credentials } = connection - const { apiKey, privateKey } = credentials - const fullUrl = `${url}${endpoint}` + const credentials = await this.connectionRepository.findCredentials(connection) - const response = await this.anchorageClient.forward({ - url: fullUrl, - method, - data, - apiKey, - signKey: privateKey - }) + return this.getProviderProxyService(connection.provider).forward( + { + ...connection, + credentials + }, + options + ) + } - return { - data: response.data, - code: response.status, - headers: response.headers + private getProviderProxyService(provider: Provider): ProviderProxyService { + switch (provider) { + case Provider.ANCHORAGE: + return this.anchorageProxyService + default: + throw new NotImplementedException(`Unsupported proxy for provider ${provider}`) } } } diff --git a/apps/vault/src/broker/core/service/sync.service.ts b/apps/vault/src/broker/core/service/sync.service.ts index 2919ef416..b9650fad9 100644 --- a/apps/vault/src/broker/core/service/sync.service.ts +++ b/apps/vault/src/broker/core/service/sync.service.ts @@ -9,8 +9,9 @@ import { FindAllOptions, SyncRepository } from '../../persistence/repository/syn import { OTEL_ATTR_CONNECTION_ID, OTEL_ATTR_CONNECTION_PROVIDER, OTEL_ATTR_SYNC_ID } from '../../shared/constant' import { SyncStartedEvent } from '../../shared/event/sync-started.event' import { AnchorageSyncService } from '../provider/anchorage/anchorage-sync.service' -import { ActiveConnectionWithCredentials, Provider } from '../type/connection.type' +import { ConnectionWithCredentials } from '../type/connection.type' import { + Provider, ProviderSyncService, SyncResult, isCreateOperation, @@ -38,7 +39,7 @@ export class SyncService { @Inject(TraceService) private readonly traceService: TraceService ) {} - async start(connections: ActiveConnectionWithCredentials[]): Promise { + async start(connections: ConnectionWithCredentials[]): Promise { this.logger.log('Start connections sync', { connectionsCount: connections.length, connectionIds: connections.map((connectionId) => connectionId) @@ -75,16 +76,17 @@ export class SyncService { return { started: false, syncs: [] } } - async sync(sync: Sync, connection: ActiveConnectionWithCredentials): Promise { + async sync(sync: Sync, connection: ConnectionWithCredentials): Promise { const { clientId, syncId } = sync const { provider, connectionId } = connection - - this.logger.log('Sync connection', { + const context = { clientId, syncId, connectionId, provider - }) + } + + this.logger.log('Sync connection', context) const span = this.traceService.startSpan(`${SyncService.name}.sync`, { attributes: { @@ -94,14 +96,30 @@ export class SyncService { } }) - const result = await this.getProviderSyncService(connection.provider).sync(connection) + let result: SyncResult | null = null - // The execute method has its own span. - span.end() + // Ensure the sync status is updated on failures. The `execute` method is + // not wrapped in the try/catch block because it already handles errors + // internally. + try { + result = await this.getProviderSyncService(connection.provider).sync(connection) + } catch (error) { + this.logger.error('Sync connection failed', { ...context, error }) - const updatedSync = await this.execute(sync, result) + span.recordException(error) + span.setStatus({ code: SpanStatusCode.ERROR }) + + return await this.fail(sync, error) + } finally { + // The execute method has its own span. + span.end() + } + + if (result) { + return await this.execute(sync, result) + } - return updatedSync + return sync } private toProcessingSync(input: StartSync & { connectionId: string; createdAt?: Date; syncId?: string }): Sync { diff --git a/apps/vault/src/broker/core/service/transfer.service.ts b/apps/vault/src/broker/core/service/transfer.service.ts index f1601bfca..e5cf3f7f3 100644 --- a/apps/vault/src/broker/core/service/transfer.service.ts +++ b/apps/vault/src/broker/core/service/transfer.service.ts @@ -5,8 +5,8 @@ import { TransferRepository } from '../../persistence/repository/transfer.reposi import { OTEL_ATTR_CONNECTION_PROVIDER } from '../../shared/constant' import { BrokerException } from '../exception/broker.exception' import { AnchorageTransferService } from '../provider/anchorage/anchorage-transfer.service' -import { ConnectionStatus, Provider, isActiveConnection } from '../type/connection.type' -import { ProviderTransferService } from '../type/provider.type' +import { ConnectionStatus, isActiveConnection } from '../type/connection.type' +import { Provider, ProviderTransferService } from '../type/provider.type' import { InternalTransfer, SendTransfer } from '../type/transfer.type' import { ConnectionService } from './connection.service' import { TransferPartyService } from './transfer-party.service' @@ -36,22 +36,25 @@ export class TransferService { const span = this.traceService.startSpan(`${TransferService.name}.sync`) const source = await this.transferPartyService.resolve(clientId, sendTransfer.source) - const { data: connections } = await this.connectionService.findAll( - clientId, - { - filters: { - status: ConnectionStatus.ACTIVE - } - }, - true - ) + const { data: connections } = await this.connectionService.findAll(clientId, { + filters: { + status: ConnectionStatus.ACTIVE + } + }) if (connections.length && isActiveConnection(connections[0])) { const [connection] = connections + const credentials = await this.connectionService.findCredentials(connection) span.setAttribute(OTEL_ATTR_CONNECTION_PROVIDER, connection.provider) - const transfer = await this.getProviderTransferService(source.provider).send(connection, sendTransfer) + const transfer = await this.getProviderTransferService(source.provider).send( + { + ...connection, + credentials + }, + sendTransfer + ) span.end() diff --git a/apps/vault/src/broker/core/type/connection.type.ts b/apps/vault/src/broker/core/type/connection.type.ts index cf69eefb1..eb1273ea3 100644 --- a/apps/vault/src/broker/core/type/connection.type.ts +++ b/apps/vault/src/broker/core/type/connection.type.ts @@ -1,11 +1,10 @@ -import { hexSchema } from '@narval/policy-engine-shared' -import { ed25519PrivateKeySchema, ed25519PublicKeySchema, rsaPublicKeySchema } from '@narval/signature' +import { rsaPublicKeySchema } from '@narval/signature' import { z } from 'zod' +import { Provider } from './provider.type' -export const Provider = { - ANCHORAGE: 'anchorage' -} as const -export type Provider = (typeof Provider)[keyof typeof Provider] +// +// Type +// export const ConnectionStatus = { PENDING: 'pending', @@ -14,7 +13,7 @@ export const ConnectionStatus = { } as const export type ConnectionStatus = (typeof ConnectionStatus)[keyof typeof ConnectionStatus] -export const BaseConnection = z.object({ +export const ConnectionWithCredentials = z.object({ clientId: z.string(), connectionId: z.string(), createdAt: z.date(), @@ -23,63 +22,41 @@ export const BaseConnection = z.object({ revokedAt: z.date().optional(), status: z.nativeEnum(ConnectionStatus).default(ConnectionStatus.ACTIVE), updatedAt: z.date(), - url: z.string().url().optional() + url: z.string().url().optional(), + credentials: z.unknown().nullish() }) +export type ConnectionWithCredentials = z.infer -export const AnchorageCredentials = z.object({ - apiKey: z.string().optional(), - publicKey: ed25519PublicKeySchema, - privateKey: ed25519PrivateKeySchema -}) -export type AnchorageCredentials = z.infer +// +// Read Connection (without credentials) +// -export const ActiveAnchorageCredentials = AnchorageCredentials.extend({ - apiKey: z.string() -}) -export type ActiveAnchorageCredentials = z.infer +const ReadConnection = ConnectionWithCredentials.omit({ credentials: true }).strip() -export const ActiveConnection = BaseConnection.extend({ +export const ActiveConnection = ReadConnection.extend({ status: z.literal(ConnectionStatus.ACTIVE), - provider: z.literal(Provider.ANCHORAGE), url: z.string().url() }) export type ActiveConnection = z.infer -export const ActiveConnectionWithCredentials = ActiveConnection.extend({ - credentials: ActiveAnchorageCredentials -}) -export type ActiveConnectionWithCredentials = z.infer -const RevokedConnection = BaseConnection.extend({ +const RevokedConnection = ReadConnection.extend({ status: z.literal(ConnectionStatus.REVOKED), - provider: z.literal(Provider.ANCHORAGE), revokedAt: z.date() }) export type RevokedConnection = z.infer -export const RevokedConnectionWithCredentials = RevokedConnection.extend({ - credentials: z.null() -}) -export type RevokedConnectionWithCredentials = z.infer -export const PendingConnection = BaseConnection.extend({ +export const PendingConnection = ReadConnection.extend({ status: z.literal(ConnectionStatus.PENDING), - provider: z.literal(Provider.ANCHORAGE), encryptionPublicKey: rsaPublicKeySchema.optional() }) export type PendingConnection = z.infer -export const PendingConnectionWithCredentials = PendingConnection.extend({ - credentials: AnchorageCredentials.nullable() -}) -export type PendingConnectionWithCredentials = z.infer export const Connection = z.discriminatedUnion('status', [ActiveConnection, RevokedConnection, PendingConnection]) export type Connection = z.infer -// This is the only type that should be including Credentials on it. The rest do not, so we don't accidentally use them. -export const ConnectionWithCredentials = z.discriminatedUnion('status', [ - ActiveConnectionWithCredentials, - RevokedConnectionWithCredentials, - PendingConnectionWithCredentials -]) -export type ConnectionWithCredentials = z.infer + +// +// Operation +// export const InitiateConnection = z.object({ connectionId: z.string().optional(), @@ -87,27 +64,21 @@ export const InitiateConnection = z.object({ }) export type InitiateConnection = z.infer -export const CreateCredentials = z.object({ - apiKey: z.string(), - privateKey: hexSchema.optional().describe('Ed25519 private key in hex format') -}) -export type CreateCredentials = z.infer - export const CreateConnection = z.object({ connectionId: z.string().optional(), createdAt: z.date().optional(), encryptedCredentials: z.string().optional().describe('RSA encrypted JSON string of the credentials'), label: z.string().optional(), - provider: z.literal(Provider.ANCHORAGE), + provider: z.nativeEnum(Provider), url: z.string().url(), - credentials: CreateCredentials.optional() + credentials: z.unknown().optional() }) export type CreateConnection = z.infer export const UpdateConnection = z.object({ clientId: z.string(), connectionId: z.string(), - credentials: CreateCredentials.nullish(), + credentials: z.unknown().nullish(), encryptedCredentials: z.string().optional().describe('RSA encrypted JSON string of the credentials'), label: z.string().optional(), status: z.nativeEnum(ConnectionStatus).optional(), @@ -116,6 +87,10 @@ export const UpdateConnection = z.object({ }) export type UpdateConnection = z.infer +// +// Type Guard +// + export const isPendingConnection = (connection: Connection): connection is PendingConnection => { return connection.status === ConnectionStatus.PENDING } @@ -127,9 +102,3 @@ export const isActiveConnection = (connection: Connection): connection is Active export const isRevokedConnection = (connection: Connection): connection is RevokedConnection => { return connection.status === ConnectionStatus.REVOKED } - -export const PublicConnection = BaseConnection.pick({ connectionId: true, status: true, label: true, provider: true }) -export type PublicConnection = z.infer - -// Connection is "special". It has encrypted data that must be queried more specifically, therefore we will separate the -// types to have one that includes "encrypted" data and another that does not. diff --git a/apps/vault/src/broker/core/type/indexed-resources.type.ts b/apps/vault/src/broker/core/type/indexed-resources.type.ts index a0fda7f1b..58e7f9bf7 100644 --- a/apps/vault/src/broker/core/type/indexed-resources.type.ts +++ b/apps/vault/src/broker/core/type/indexed-resources.type.ts @@ -1,10 +1,11 @@ import { z } from 'zod' -import { BaseConnection, Provider, PublicConnection } from './connection.type' +import { Connection } from './connection.type' +import { Provider } from './provider.type' export const KnownDestination = z.object({ knownDestinationId: z.string(), clientId: z.string(), - connections: z.array(BaseConnection), + connections: z.array(Connection), provider: z.nativeEnum(Provider), label: z.string().nullable().optional(), externalId: z.string(), @@ -46,7 +47,7 @@ export type Account = z.infer export const Wallet = z.object({ accounts: z.array(Account).optional(), clientId: z.string(), - connections: z.array(BaseConnection), + connections: z.array(Connection), createdAt: z.date(), externalId: z.string(), label: z.string().nullable().optional(), @@ -64,8 +65,3 @@ export const UpdateWallet = Wallet.pick({ updatedAt: true }) export type UpdateWallet = z.infer - -export const PublicWallet = Wallet.extend({ - connections: z.array(PublicConnection) -}) -export type PublicWallet = z.infer diff --git a/apps/vault/src/broker/core/type/provider.type.ts b/apps/vault/src/broker/core/type/provider.type.ts index 7c5150cbf..abd57713a 100644 --- a/apps/vault/src/broker/core/type/provider.type.ts +++ b/apps/vault/src/broker/core/type/provider.type.ts @@ -2,10 +2,20 @@ import { HttpStatus } from '@nestjs/common' import { UpdateAccount } from '../../persistence/repository/account.repository' -import { ActiveConnectionWithCredentials } from './connection.type' +import { ConnectionWithCredentials } from './connection.type' import { Account, Address, KnownDestination, UpdateWallet, Wallet } from './indexed-resources.type' import { InternalTransfer, SendTransfer, Transfer } from './transfer.type' +export const Provider = { + ANCHORAGE: 'anchorage', + FIREBLOCKS: 'fireblocks' +} as const +export type Provider = (typeof Provider)[keyof typeof Provider] + +// +// Sync +// + export const SyncOperationType = { CREATE: 'create', UPDATE: 'update', @@ -83,7 +93,7 @@ export type SyncContext = { /** * The active connection with credentials used for synchronization. */ - connection: ActiveConnectionWithCredentials + connection: ConnectionWithCredentials /** * A map of wallet synchronization operations, keyed by wallet external ID. @@ -136,7 +146,7 @@ export interface ProviderSyncService { * the sync operations for wallets, accounts, addresses, and known * destinations. */ - sync(connection: ActiveConnectionWithCredentials): Promise + sync(connection: ConnectionWithCredentials): Promise /** * Synchronizes wallet data within the provided context and returns an @@ -183,6 +193,10 @@ export interface ProviderSyncService { syncKnownDestinations(context: SyncContext): Promise } +// +// Transfer +// + export interface ProviderTransferService { /** * Finds a transfer by its ID. @@ -193,7 +207,7 @@ export interface ProviderTransferService { * * @returns A promise that resolves to the transfer object if found. */ - findById(connection: ActiveConnectionWithCredentials, transferId: string): Promise + findById(connection: ConnectionWithCredentials, transferId: string): Promise /** * Sends a transfer using the provided active connection and transfer @@ -206,9 +220,13 @@ export interface ProviderTransferService { * @returns A promise that resolves to the internal transfer object after the * transfer is successfully sent. */ - send(connection: ActiveConnectionWithCredentials, sendTransfer: SendTransfer): Promise + send(connection: ConnectionWithCredentials, sendTransfer: SendTransfer): Promise } +// +// Proxy +// + /** * Options for making a proxy request, including connection ID, request data, * endpoint, and HTTP method. @@ -243,5 +261,53 @@ export interface ProviderProxyService { * @returns A promise that resolves to the proxy response, containing the * response data, HTTP status code, and headers. */ - forward(connection: ActiveConnectionWithCredentials, options: ProxyRequestOptions): Promise + forward(connection: ConnectionWithCredentials, options: ProxyRequestOptions): Promise +} + +// +// Credential +// + +/** + * Defines methods for managing credentials in various formats. This includes + * handling credentials used during data operations, typically in JSON Web Key + * (JWK) format, and credentials in transit, which may be represented as + * strings of private keys. + */ +export interface ProviderCredentialService { + /** + * Parses a value into the final form of credentials used within the + * repository or service. + * + * @param value - The value to be parsed into credentials. + * @returns The parsed credentials. + */ + parse(value: unknown): Credentials + + /** + * Parses input credentials, ensuring the correct format of string + * representations for private keys when necessary. + * + * @param value - The input value to be parsed into input credentials. + * @returns The parsed input credentials. + */ + parseInput(value: unknown): InputCredentials + + /** + * Builds the final form of credentials from input credentials, validating + * and converting them from hexadecimal to JSON Web Key (JWK) format. + * + * @param input - The input credentials to be converted. + * @returns A promise that resolves to the final form of credentials. + */ + build(input: InputCredentials): Promise + + /** + * Generates signing keys for credential operations. + * + * @param options - Provider-specific configuration options for key + * generation. + * @returns A promise that resolves to the generated credentials. + */ + generate>(options?: Options): Promise } diff --git a/apps/vault/src/broker/core/type/transfer.type.ts b/apps/vault/src/broker/core/type/transfer.type.ts index 4e04afd8f..42f9d0c22 100644 --- a/apps/vault/src/broker/core/type/transfer.type.ts +++ b/apps/vault/src/broker/core/type/transfer.type.ts @@ -1,5 +1,5 @@ import { z } from 'zod' -import { Provider } from './connection.type' +import { Provider } from './provider.type' export const NetworkFeeAttribution = { ON_TOP: 'on_top', diff --git a/apps/vault/src/broker/core/util/user-friendly-key-format.util.ts b/apps/vault/src/broker/core/util/user-friendly-key-format.util.ts new file mode 100644 index 000000000..0d58e3795 --- /dev/null +++ b/apps/vault/src/broker/core/util/user-friendly-key-format.util.ts @@ -0,0 +1,19 @@ +import { PublicKey, RsaPublicKey, publicKeyToHex, publicKeyToPem } from '@narval/signature' + +export const formatPublicKey = async (publicKey: PublicKey) => { + return { + keyId: publicKey.kid, + jwk: publicKey, + hex: await publicKeyToHex(publicKey) + } +} + +export const formatRsaPublicKey = async (rsaPublicKey: RsaPublicKey) => { + const pem = await publicKeyToPem(rsaPublicKey, rsaPublicKey.alg) + + return { + keyId: rsaPublicKey.kid, + jwk: rsaPublicKey, + pem: Buffer.from(pem).toString('base64') + } +} diff --git a/apps/vault/src/broker/http/client/anchorage.client.ts b/apps/vault/src/broker/http/client/anchorage.client.ts index c789f93bf..4064a4c17 100644 --- a/apps/vault/src/broker/http/client/anchorage.client.ts +++ b/apps/vault/src/broker/http/client/anchorage.client.ts @@ -22,7 +22,7 @@ import { ZodType, z } from 'zod' import { BrokerException } from '../../core/exception/broker.exception' import { ProviderHttpException } from '../../core/exception/provider-http.exception' import { UrlParserException } from '../../core/exception/url-parser.exception' -import { Provider } from '../../core/type/connection.type' +import { Provider } from '../../core/type/provider.type' // // Response Schema diff --git a/apps/vault/src/broker/http/rest/controller/address.controller.ts b/apps/vault/src/broker/http/rest/controller/address.controller.ts index e878e08dd..969cb3ea7 100644 --- a/apps/vault/src/broker/http/rest/controller/address.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/address.controller.ts @@ -14,7 +14,7 @@ import { ProviderAddressDto } from '../dto/response/provider-address.dto' }) @ApiClientIdHeader() @ApiTags('Provider Address') -export class AddressController { +export class ProviderAddressController { constructor(private readonly addressService: AddressService) {} @Get() diff --git a/apps/vault/src/broker/http/rest/controller/connection.controller.ts b/apps/vault/src/broker/http/rest/controller/connection.controller.ts index 8e08fff90..9223eec17 100644 --- a/apps/vault/src/broker/http/rest/controller/connection.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/connection.controller.ts @@ -1,5 +1,4 @@ import { ApiClientIdHeader, Paginated, PaginationOptions, PaginationParam } from '@narval/nestjs-shared' -import { publicKeyToHex, publicKeyToPem } from '@narval/signature' import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Patch, Post } from '@nestjs/common' import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../shared/decorator/client-id.decorator' @@ -8,6 +7,7 @@ import { VaultPermission } from '../../../../shared/type/domain.type' import { AccountService } from '../../../core/service/account.service' import { ConnectionService } from '../../../core/service/connection.service' import { WalletService } from '../../../core/service/wallet.service' +import { formatPublicKey, formatRsaPublicKey } from '../../../core/util/user-friendly-key-format.util' import { CreateConnectionDto } from '../dto/request/create-connection.dto' import { InitiateConnectionDto } from '../dto/request/initiate-connection.dto' import { UpdateConnectionDto } from '../dto/request/update-connection.dto' @@ -47,25 +47,18 @@ export class ConnectionController { @Body() body: InitiateConnectionDto ): Promise { const pendingConnection = await this.connectionService.initiate(clientId, body) - - const encryptionPem = pendingConnection.encryptionPublicKey - ? await publicKeyToPem(pendingConnection.encryptionPublicKey, pendingConnection.encryptionPublicKey.alg) - : undefined + const credentials = await this.connectionService.findCredentials(pendingConnection) const data = { ...pendingConnection, - encryptionPublicKey: { - keyId: pendingConnection.encryptionPublicKey?.kid, - jwk: pendingConnection.encryptionPublicKey, - pem: encryptionPem ? Buffer.from(encryptionPem).toString('base64') : undefined - }, - ...(pendingConnection.credentials + ...(pendingConnection.encryptionPublicKey + ? { + encryptionPublicKey: await formatRsaPublicKey(pendingConnection.encryptionPublicKey) + } + : {}), + ...(credentials ? { - publicKey: { - keyId: pendingConnection.credentials.publicKey.kid, - jwk: pendingConnection.credentials.publicKey, - hex: await publicKeyToHex(pendingConnection.credentials.publicKey) - } + publicKey: await formatPublicKey(credentials.publicKey) } : {}) } diff --git a/apps/vault/src/broker/http/rest/controller/sync.controller.ts b/apps/vault/src/broker/http/rest/controller/sync.controller.ts index 6cb500937..a8502fadb 100644 --- a/apps/vault/src/broker/http/rest/controller/sync.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/sync.controller.ts @@ -6,7 +6,7 @@ import { PermissionGuard } from '../../../../shared/decorator/permission-guard.d import { VaultPermission } from '../../../../shared/type/domain.type' import { ConnectionService } from '../../../core/service/connection.service' import { SyncService } from '../../../core/service/sync.service' -import { ActiveConnectionWithCredentials, ConnectionStatus } from '../../../core/type/connection.type' +import { ConnectionStatus } from '../../../core/type/connection.type' import { StartSyncDto } from '../dto/request/start-sync.dto' import { PaginatedSyncsDto } from '../dto/response/paginated-syncs.dto' import { SyncStartedDto } from '../dto/response/sync-started.dto' @@ -25,7 +25,8 @@ export class SyncController { ) {} @Post() - @PermissionGuard(VaultPermission.CONNECTION_READ) // Sync is a read operation even though it's a POST. + // Sync is a read operation even though it's a POST. + @PermissionGuard(VaultPermission.CONNECTION_READ) @ApiOperation({ summary: 'Start a synchronization process', description: 'This endpoint starts synchronization process for the client.' @@ -37,23 +38,19 @@ export class SyncController { }) async start(@ClientId() clientId: string, @Body() body: StartSyncDto): Promise { if (body.connectionId) { - const connection = await this.connectionService.findById(clientId, body.connectionId, true) - const data = await this.syncService.start([connection as ActiveConnectionWithCredentials]) + const connection = await this.connectionService.findWithCredentialsById(clientId, body.connectionId) + const data = await this.syncService.start([connection]) return SyncStartedDto.create({ data }) } - const { data: connections } = await this.connectionService.findAll( - clientId, - { - filters: { - status: ConnectionStatus.ACTIVE - } - }, - true - ) + const { data: connections } = await this.connectionService.findAllWithCredentials(clientId, { + filters: { + status: ConnectionStatus.ACTIVE + } + }) - const data = await this.syncService.start(connections as ActiveConnectionWithCredentials[]) + const data = await this.syncService.start(connections) return SyncStartedDto.create({ data }) } diff --git a/apps/vault/src/broker/http/rest/dto/request/update-connection.dto.ts b/apps/vault/src/broker/http/rest/dto/request/update-connection.dto.ts index c37ea52ff..aaa3d5387 100644 --- a/apps/vault/src/broker/http/rest/dto/request/update-connection.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/request/update-connection.dto.ts @@ -1,10 +1,10 @@ import { createZodDto } from 'nestjs-zod' -import { CreateConnection } from '../../../../core/type/connection.type' +import { UpdateConnection } from '../../../../core/type/connection.type' export class UpdateConnectionDto extends createZodDto( - CreateConnection.pick({ - label: true, - encryptedCredentials: true, - credentials: true + UpdateConnection.omit({ + // These are passed in the route path and request headers. + connectionId: true, + clientId: true }) ) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/paginated-connections.dto.ts b/apps/vault/src/broker/http/rest/dto/response/paginated-connections.dto.ts index 8ade32dc6..36747e49e 100644 --- a/apps/vault/src/broker/http/rest/dto/response/paginated-connections.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/paginated-connections.dto.ts @@ -1,11 +1,11 @@ import { Page } from '@narval/nestjs-shared' import { createZodDto } from 'nestjs-zod' import { z } from 'zod' -import { BaseConnection } from '../../../../core/type/connection.type' +import { Connection } from '../../../../core/type/connection.type' export class PaginatedConnectionsDto extends createZodDto( z.object({ - data: z.array(BaseConnection), + data: z.array(Connection), page: Page }) ) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/paginated-wallets.dto.ts b/apps/vault/src/broker/http/rest/dto/response/paginated-wallets.dto.ts index d278e1b8c..43cc2f268 100644 --- a/apps/vault/src/broker/http/rest/dto/response/paginated-wallets.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/paginated-wallets.dto.ts @@ -1,11 +1,11 @@ import { Page } from '@narval/nestjs-shared' import { createZodDto } from 'nestjs-zod' import { z } from 'zod' -import { PublicWallet } from '../../../../core/type/indexed-resources.type' +import { Wallet } from '../../../../core/type/indexed-resources.type' export class PaginatedWalletsDto extends createZodDto( z.object({ - data: z.array(PublicWallet), + data: z.array(Wallet), page: Page }) ) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/pending-connection.dto.ts b/apps/vault/src/broker/http/rest/dto/response/pending-connection.dto.ts deleted file mode 100644 index 4fda145ff..000000000 --- a/apps/vault/src/broker/http/rest/dto/response/pending-connection.dto.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { hexSchema } from '@narval/policy-engine-shared' -import { publicKeySchema } from '@narval/signature' -import { createZodDto } from 'nestjs-zod' -import { z } from 'zod' -import { PendingConnection } from '../../../../core/type/connection.type' - -export class PendingConnectionDto extends createZodDto( - PendingConnection.pick({ - clientId: true, - connectionId: true, - provider: true, - status: true, - createdAt: true - }).extend({ - publicKey: z - .object({ - keyId: z.string().optional(), - jwk: publicKeySchema.optional(), - hex: hexSchema.optional() - }) - .optional(), - encryptionPublicKey: z.object({ - keyId: z.string().optional(), - jwk: publicKeySchema.optional().describe('JWK format of the public key'), - pem: z.string().optional().describe('Base64 encoded PEM public key') - }) - }) -) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/provider-connection.dto.ts b/apps/vault/src/broker/http/rest/dto/response/provider-connection.dto.ts index a3d4ef079..b18511afa 100644 --- a/apps/vault/src/broker/http/rest/dto/response/provider-connection.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/provider-connection.dto.ts @@ -1,9 +1,9 @@ import { createZodDto } from 'nestjs-zod' import { z } from 'zod' -import { BaseConnection } from '../../../../core/type/connection.type' +import { Connection } from '../../../../core/type/connection.type' export class ProviderConnectionDto extends createZodDto( z.object({ - data: BaseConnection + data: Connection }) ) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/provider-wallet.dto.ts b/apps/vault/src/broker/http/rest/dto/response/provider-wallet.dto.ts index 5135341e1..fd4c6a767 100644 --- a/apps/vault/src/broker/http/rest/dto/response/provider-wallet.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/provider-wallet.dto.ts @@ -1,9 +1,9 @@ import { createZodDto } from 'nestjs-zod' import { z } from 'zod' -import { PublicWallet } from '../../../../core/type/indexed-resources.type' +import { Wallet } from '../../../../core/type/indexed-resources.type' export class ProviderWalletDto extends createZodDto( z.object({ - data: PublicWallet + data: Wallet }) ) {} diff --git a/apps/vault/src/broker/persistence/connection.seed.ts b/apps/vault/src/broker/persistence/connection.seed.ts index 1277fee00..6d2e7552f 100644 --- a/apps/vault/src/broker/persistence/connection.seed.ts +++ b/apps/vault/src/broker/persistence/connection.seed.ts @@ -1,4 +1,3 @@ -import { LoggerService } from '@narval/nestjs-shared' import { hexSchema } from '@narval/policy-engine-shared' import { privateKeyToJwk } from '@narval/signature' import { Injectable } from '@nestjs/common' @@ -11,10 +10,7 @@ const NARVAL_DEV_CLIENT = 'narval-dev-client' @Injectable() export class ConnectionSeedService extends SeedService { - constructor( - private logger: LoggerService, - private connectionRepository: ConnectionRepository - ) { + constructor(private connectionRepository: ConnectionRepository) { super() } diff --git a/apps/vault/src/broker/persistence/repository/address.repository.ts b/apps/vault/src/broker/persistence/repository/address.repository.ts index 5d2e1cc19..cba5ed4b9 100644 --- a/apps/vault/src/broker/persistence/repository/address.repository.ts +++ b/apps/vault/src/broker/persistence/repository/address.repository.ts @@ -4,8 +4,8 @@ import { ProviderAddress } from '@prisma/client/vault' import { z } from 'zod' import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' import { NotFoundException } from '../../core/exception/not-found.exception' -import { Provider } from '../../core/type/connection.type' import { Address } from '../../core/type/indexed-resources.type' +import { Provider } from '../../core/type/provider.type' type FindAllFilters = { filters?: { diff --git a/apps/vault/src/broker/persistence/repository/connection.repository.ts b/apps/vault/src/broker/persistence/repository/connection.repository.ts index d01192035..4ade1775b 100644 --- a/apps/vault/src/broker/persistence/repository/connection.repository.ts +++ b/apps/vault/src/broker/persistence/repository/connection.repository.ts @@ -3,16 +3,18 @@ import { HttpStatus, Injectable } from '@nestjs/common' import { ProviderConnection } from '@prisma/client/vault' import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' import { BrokerException } from '../../core/exception/broker.exception' +import { ConnectionInvalidCredentialsException } from '../../core/exception/connection-invalid-credentials.exception' import { ConnectionParseException } from '../../core/exception/connection-parse.exception' import { NotFoundException } from '../../core/exception/not-found.exception' import { Connection, ConnectionStatus, ConnectionWithCredentials } from '../../core/type/connection.type' +import { Provider } from '../../core/type/provider.type' export type UpdateConnection = { clientId: string connectionId: string credentials?: unknown | null label?: string - provider?: string + provider: Provider revokedAt?: Date status?: ConnectionStatus updatedAt?: Date @@ -28,7 +30,7 @@ export type FilterOptions = { export type FindAllOptions = FilterOptions & { pagination?: PaginationOptions } -export const connectionSelectWithoutCredentials = { +export const SELECT_WITHOUT_CREDENTIALS = { id: true, clientId: true, provider: true, @@ -44,15 +46,11 @@ export const connectionSelectWithoutCredentials = { @Injectable() export class ConnectionRepository { - constructor(private prismaService: PrismaService) {} + constructor(private readonly prismaService: PrismaService) {} - static parseModel( - model?: Partial | null, - includeCredentials?: T - ): T extends true ? ConnectionWithCredentials : Connection { - const connectionData = { + static parseModel(model?: Partial | null): Connection { + const parse = Connection.safeParse({ ...model, - credentials: model?.credentials ? JSON.parse(model.credentials) : null, connectionId: model?.id, // Prisma always returns null for optional fields that don't have a // value, rather than undefined. This is actually by design and aligns @@ -60,13 +58,10 @@ export class ConnectionRepository { label: model?.label || undefined, revokedAt: model?.revokedAt || undefined, url: model?.url || undefined - } - - const schema = includeCredentials ? ConnectionWithCredentials : Connection - const parse = schema.safeParse(connectionData) + }) if (parse.success) { - return parse.data as T extends true ? ConnectionWithCredentials : Connection + return parse.data } throw new ConnectionParseException({ @@ -76,15 +71,15 @@ export class ConnectionRepository { async create(connection: ConnectionWithCredentials): Promise { const data = { - id: connection.connectionId, clientId: connection.clientId, - credentials: connection.credentials !== null ? JSON.stringify(connection.credentials) : null, + createdAt: connection.createdAt, + credentials: PrismaService.toStringJson(connection.credentials), + id: connection.connectionId, label: connection.label || null, provider: connection.provider, status: connection.status, - url: connection.url || null, - createdAt: connection.createdAt, - updatedAt: connection.updatedAt + updatedAt: connection.updatedAt, + url: connection.url || null } await this.prismaService.providerConnection.upsert({ @@ -110,68 +105,51 @@ export class ConnectionRepository { clientId: updateConnection.clientId }, data: { - id: updateConnection.connectionId, clientId: updateConnection.clientId, - provider: updateConnection.provider, - url: updateConnection.url, - label: updateConnection.label, - credentials: updateConnection.credentials !== null ? JSON.stringify(updateConnection.credentials) : null, - status: updateConnection.status, createdAt: updateConnection.createdAt, + credentials: PrismaService.toStringJson(updateConnection.credentials), + id: updateConnection.connectionId, + label: updateConnection.label, + provider: updateConnection.provider, revokedAt: updateConnection.revokedAt, - updatedAt: updateConnection.updatedAt + status: updateConnection.status, + updatedAt: updateConnection.updatedAt, + url: updateConnection.url } }) return true } - async findById( - clientId: string, - connectionId: string, - includeCredentials?: T - ): Promise { + async findById(clientId: string, connectionId: string): Promise { const model = await this.prismaService.providerConnection.findUnique({ - where: { clientId, id: connectionId } + where: { clientId, id: connectionId }, + select: SELECT_WITHOUT_CREDENTIALS }) if (model) { - return ConnectionRepository.parseModel(model, includeCredentials) + return ConnectionRepository.parseModel(model) } throw new NotFoundException({ context: { clientId, connectionId } }) } - async findAll( - clientId: string, - options?: FindAllOptions, - includeCredentials?: T - ): Promise : PaginatedResult> { + async findAll(clientId: string, options?: FindAllOptions): Promise> { const pagination = applyPagination(options?.pagination) const models = await this.prismaService.providerConnection.findMany({ where: { clientId, status: options?.filters?.status }, - ...(includeCredentials - ? {} - : { - select: connectionSelectWithoutCredentials - }), + select: SELECT_WITHOUT_CREDENTIALS, ...pagination }) const { data, page } = getPaginatedResult({ items: models, pagination }) - const parsedData = data.map((model) => ConnectionRepository.parseModel(model, includeCredentials)) - - const result = { - data: parsedData, + return { + data: data.map((model) => ConnectionRepository.parseModel(model)), page } - - return result as unknown as T extends true - ? PaginatedResult - : PaginatedResult } async exists(clientId: string, id: string): Promise { @@ -181,4 +159,66 @@ export class ConnectionRepository { return count > 0 } + + async findCredentialsJson({ connectionId }: { connectionId: string }): Promise { + const model = await this.prismaService.providerConnection.findUnique({ + where: { id: connectionId } + }) + + if (model && model.credentials) { + return this.toCredentialsJson(model.credentials) + } + + return null + } + + async findAllWithCredentials( + clientId: string, + options?: FindAllOptions + ): Promise> { + const pagination = applyPagination(options?.pagination) + const models = await this.prismaService.providerConnection.findMany({ + where: { + clientId, + status: options?.filters?.status + }, + ...pagination + }) + const { data, page } = getPaginatedResult({ items: models, pagination }) + + return { + data: data.map((model) => ({ + ...ConnectionRepository.parseModel(model), + credentials: model.credentials ? this.toCredentialsJson(model.credentials) : null + })), + page + } + } + + async findWithCredentialsById(clientId: string, connectionId: string): Promise { + const model = await this.prismaService.providerConnection.findUnique({ + where: { clientId, id: connectionId } + }) + + if (model) { + return { + ...ConnectionRepository.parseModel(model), + credentials: model.credentials ? this.toCredentialsJson(model.credentials) : null + } + } + + throw new NotFoundException({ context: { clientId, connectionId } }) + } + + private toCredentialsJson(value: string) { + try { + return JSON.parse(value) + } catch (error) { + throw new ConnectionInvalidCredentialsException({ + message: `Invalid stored connection credential JSON`, + suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, + origin: error + }) + } + } } diff --git a/apps/vault/src/broker/persistence/repository/known-destination.repository.ts b/apps/vault/src/broker/persistence/repository/known-destination.repository.ts index 8c3e7f8c6..ef1ac211f 100644 --- a/apps/vault/src/broker/persistence/repository/known-destination.repository.ts +++ b/apps/vault/src/broker/persistence/repository/known-destination.repository.ts @@ -4,9 +4,9 @@ import { ProviderConnection, ProviderKnownDestination, ProviderKnownDestinationC import { z } from 'zod' import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' import { NotFoundException } from '../../core/exception/not-found.exception' -import { Provider } from '../../core/type/connection.type' import { KnownDestination } from '../../core/type/indexed-resources.type' -import { ConnectionRepository, connectionSelectWithoutCredentials } from './connection.repository' +import { Provider } from '../../core/type/provider.type' +import { ConnectionRepository, SELECT_WITHOUT_CREDENTIALS } from './connection.repository' type FindAllFilters = { filters?: { @@ -78,7 +78,7 @@ export class KnownDestinationRepository { connections: { include: { connection: { - select: connectionSelectWithoutCredentials + select: SELECT_WITHOUT_CREDENTIALS } } } @@ -100,7 +100,7 @@ export class KnownDestinationRepository { connections: { include: { connection: { - select: connectionSelectWithoutCredentials + select: SELECT_WITHOUT_CREDENTIALS } } } @@ -159,7 +159,7 @@ export class KnownDestinationRepository { connections: { include: { connection: { - select: connectionSelectWithoutCredentials + select: SELECT_WITHOUT_CREDENTIALS } } } @@ -205,7 +205,7 @@ export class KnownDestinationRepository { connections: { include: { connection: { - select: connectionSelectWithoutCredentials + select: SELECT_WITHOUT_CREDENTIALS } } } @@ -265,7 +265,7 @@ export class KnownDestinationRepository { connections: { include: { connection: { - select: connectionSelectWithoutCredentials + select: SELECT_WITHOUT_CREDENTIALS } } } diff --git a/apps/vault/src/broker/persistence/repository/wallet.repository.ts b/apps/vault/src/broker/persistence/repository/wallet.repository.ts index 925707274..9e7275709 100644 --- a/apps/vault/src/broker/persistence/repository/wallet.repository.ts +++ b/apps/vault/src/broker/persistence/repository/wallet.repository.ts @@ -11,7 +11,7 @@ import { PrismaService } from '../../../shared/module/persistence/service/prisma import { NotFoundException } from '../../core/exception/not-found.exception' import { Account, UpdateWallet, Wallet } from '../../core/type/indexed-resources.type' import { AccountRepository } from './account.repository' -import { ConnectionRepository, connectionSelectWithoutCredentials } from './connection.repository' +import { ConnectionRepository, SELECT_WITHOUT_CREDENTIALS } from './connection.repository' type ProviderWalletsAndRelations = ProviderWallet & { connections: { connection: Partial }[] @@ -85,7 +85,7 @@ export class WalletRepository { connections: { include: { connection: { - select: connectionSelectWithoutCredentials + select: SELECT_WITHOUT_CREDENTIALS } } } @@ -113,12 +113,13 @@ export class WalletRepository { connections: { include: { connection: { - select: connectionSelectWithoutCredentials + select: SELECT_WITHOUT_CREDENTIALS } } } } }) + if (!wallet) { throw new NotFoundException({ message: 'Wallet not found', @@ -160,7 +161,7 @@ export class WalletRepository { connections: { include: { connection: { - select: connectionSelectWithoutCredentials + select: SELECT_WITHOUT_CREDENTIALS } } } @@ -192,7 +193,7 @@ export class WalletRepository { connections: { include: { connection: { - select: connectionSelectWithoutCredentials + select: SELECT_WITHOUT_CREDENTIALS } } } @@ -256,7 +257,7 @@ export class WalletRepository { connections: { include: { connection: { - select: connectionSelectWithoutCredentials + select: SELECT_WITHOUT_CREDENTIALS } } }, diff --git a/apps/vault/src/broker/shared/__test__/matcher.ts b/apps/vault/src/broker/shared/__test__/matcher.ts new file mode 100644 index 000000000..cd2f6c2d7 --- /dev/null +++ b/apps/vault/src/broker/shared/__test__/matcher.ts @@ -0,0 +1,60 @@ +/* eslint-disable @typescript-eslint/no-namespace */ + +import { expect } from '@jest/globals' +import type { MatcherContext } from 'expect' +import { ZodSchema } from 'zod' + +declare global { + namespace jest { + interface Matchers { + /** + * Custom Jest matcher to validate if a given value matches a Zod schema. + * + * @param {unknown} received - The value to be validated against the + * schema. + * @param {ZodSchema} schema - The Zod schema to validate the value + * against. + * @returns {object} - An object containing the result of the validation + * and a message. + * + * @example + * expect({ name: "John", age: 30 }).toMatchZodSchema(userSchema); + */ + toMatchZodSchema(schema: ZodSchema): R + } + } +} + +const toMatchZodSchema = function (this: MatcherContext, received: unknown, schema: ZodSchema) { + const parse = schema.safeParse(received) + + return { + pass: parse.success, + message: () => { + if (parse.success) { + return 'Matched value to schema' + } + + const errors = parse.error.errors.map((error) => { + if (error.path.length) { + return { + message: error.message, + path: error.path + } + } + + return { + message: error.message + } + }) + + return [ + 'Expected value to match schema:', + `Received: ${JSON.stringify(received, null, 2)}`, + `Errors: ${JSON.stringify(errors, null, 2)}` + ].join('\n') + } + } +} + +expect.extend({ toMatchZodSchema }) diff --git a/apps/vault/src/broker/shared/event/connection-activated.event.ts b/apps/vault/src/broker/shared/event/connection-activated.event.ts index 186427a16..22440cf18 100644 --- a/apps/vault/src/broker/shared/event/connection-activated.event.ts +++ b/apps/vault/src/broker/shared/event/connection-activated.event.ts @@ -1,7 +1,7 @@ -import { ActiveConnectionWithCredentials } from '../../core/type/connection.type' +import { ConnectionWithCredentials } from '../../core/type/connection.type' export class ConnectionActivatedEvent { static EVENT_NAME = 'connection.activated' - constructor(public readonly connection: ActiveConnectionWithCredentials) {} + constructor(public readonly connection: ConnectionWithCredentials) {} } diff --git a/apps/vault/src/broker/shared/event/sync-started.event.ts b/apps/vault/src/broker/shared/event/sync-started.event.ts index 5a5e6a453..608b55c9b 100644 --- a/apps/vault/src/broker/shared/event/sync-started.event.ts +++ b/apps/vault/src/broker/shared/event/sync-started.event.ts @@ -1,4 +1,4 @@ -import { ActiveConnectionWithCredentials } from '../../core/type/connection.type' +import { ConnectionWithCredentials } from '../../core/type/connection.type' import { Sync } from '../../core/type/sync.type' export class SyncStartedEvent { @@ -6,6 +6,6 @@ export class SyncStartedEvent { constructor( public readonly sync: Sync, - public readonly connection: ActiveConnectionWithCredentials + public readonly connection: ConnectionWithCredentials ) {} } diff --git a/apps/vault/src/shared/module/persistence/seed.ts b/apps/vault/src/shared/module/persistence/seed.ts index 1f0cb316d..7e2b7bd1b 100644 --- a/apps/vault/src/shared/module/persistence/seed.ts +++ b/apps/vault/src/shared/module/persistence/seed.ts @@ -3,11 +3,12 @@ import { ConfigService } from '@narval/config-module' import { LoggerService } from '@narval/nestjs-shared' import { ed25519PrivateKeySchema, ed25519PublicKeySchema } from '@narval/signature' import { PrismaClient } from '@prisma/client/vault' -import { ConnectionStatus, Provider } from 'apps/vault/src/broker/core/type/connection.type' import { ConnectionSeedService } from 'apps/vault/src/broker/persistence/connection.seed' -import { ConnectionRepository } from 'apps/vault/src/broker/persistence/repository/connection.repository' import { Config, load } from 'apps/vault/src/main.config' import { v4 } from 'uuid' +import { ConnectionStatus } from '../../../broker/core/type/connection.type' +import { Provider } from '../../../broker/core/type/provider.type' +import { ConnectionRepository } from '../../../broker/persistence/repository/connection.repository' import { PrismaService } from './service/prisma.service' const prisma = new PrismaClient() @@ -193,7 +194,7 @@ async function main() { const config = new ConfigService(load()) const prismaService = new PrismaService(config, logger) const connRepository = new ConnectionRepository(prismaService) - const connSeed = new ConnectionSeedService(logger, connRepository) + const connSeed = new ConnectionSeedService(connRepository) logger.log('Seeding Vault database with Anchorage provider data') From d6b370e5160b88b8ed85b176aa9947dddd3a316b Mon Sep 17 00:00:00 2001 From: Ptroger <44851272+Ptroger@users.noreply.github.com> Date: Fri, 3 Jan 2025 14:53:07 +0100 Subject: [PATCH 071/120] Unified example with SDK (#40) * wip * cleaned up example * updated readme * add encryption over activation flow * added base url as env to quickly switch envs * added generatekey snippet * points to staging * cancel transaction * udpated examples with sdk - removed the .env dev anchorage configs and seed * deleted unzipped file * naming * casing on env vairiable --- apps/vault/.env.default | 6 - .../src/broker/persistence/connection.seed.ts | 27 - .../src/shared/module/persistence/seed.ts | 4 - examples/unified-api/.env.default | 12 + examples/unified-api/1-activate.ts | 39 + examples/unified-api/2-read-wallets.ts | 11 + examples/unified-api/3-read-accounts.ts | 11 + examples/unified-api/4-read-addresses.ts | 11 + examples/unified-api/5-create-transfer.ts | 29 + examples/unified-api/README.md | 67 ++ examples/unified-api/generate-key.ts | 18 + examples/unified-api/package-lock.json | 856 ++++++++++++++++++ examples/unified-api/package.json | 16 + examples/unified-api/tsconfig.json | 101 +++ examples/unified-api/unified-api.example.zip | Bin 10353 -> 0 bytes examples/unified-api/vault.client.ts | 25 + 16 files changed, 1196 insertions(+), 37 deletions(-) create mode 100644 examples/unified-api/.env.default create mode 100644 examples/unified-api/1-activate.ts create mode 100644 examples/unified-api/2-read-wallets.ts create mode 100644 examples/unified-api/3-read-accounts.ts create mode 100644 examples/unified-api/4-read-addresses.ts create mode 100644 examples/unified-api/5-create-transfer.ts create mode 100644 examples/unified-api/README.md create mode 100644 examples/unified-api/generate-key.ts create mode 100644 examples/unified-api/package-lock.json create mode 100644 examples/unified-api/package.json create mode 100644 examples/unified-api/tsconfig.json delete mode 100644 examples/unified-api/unified-api.example.zip create mode 100644 examples/unified-api/vault.client.ts diff --git a/apps/vault/.env.default b/apps/vault/.env.default index cb83b91c4..f902b20ee 100644 --- a/apps/vault/.env.default +++ b/apps/vault/.env.default @@ -30,9 +30,3 @@ OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf OTEL_LOGS_EXPORTER=otlp OTEL_LOG_LEVEL=error OTEL_RESOURCE_ATTRIBUTES=deployment.environment=local - -# === External Api Keys, for local dev db seeding === - -# Used to generate a valid connection to Anchorage sandbox access using your credentials -ANCHORAGE_API_KEY= -ANCHORAGE_SECRET_KEY= \ No newline at end of file diff --git a/apps/vault/src/broker/persistence/connection.seed.ts b/apps/vault/src/broker/persistence/connection.seed.ts index 6d2e7552f..964199de2 100644 --- a/apps/vault/src/broker/persistence/connection.seed.ts +++ b/apps/vault/src/broker/persistence/connection.seed.ts @@ -1,13 +1,8 @@ -import { hexSchema } from '@narval/policy-engine-shared' -import { privateKeyToJwk } from '@narval/signature' import { Injectable } from '@nestjs/common' -import { ed25519PublicKeySchema } from 'packages/signature/src/lib/schemas' import { SeedService } from '../../shared/module/persistence/service/seed.service' import { ConnectionWithCredentials } from '../core/type/connection.type' import { ConnectionRepository } from './repository/connection.repository' -const NARVAL_DEV_CLIENT = 'narval-dev-client' - @Injectable() export class ConnectionSeedService extends SeedService { constructor(private connectionRepository: ConnectionRepository) { @@ -18,26 +13,4 @@ export class ConnectionSeedService extends SeedService { const createdConnection = await this.connectionRepository.create(connection) return createdConnection } - - async createNarvalDevConnection() { - if (process.env.ANCHORAGE_API_KEY && process.env.ANCHORAGE_SECRET_KEY) { - const privateKey = privateKeyToJwk(hexSchema.parse(process.env.ANCHORAGE_SECRET_KEY), 'EDDSA') - const publicKey = ed25519PublicKeySchema.parse(privateKey) - await this.connectionRepository.create({ - clientId: NARVAL_DEV_CLIENT, - connectionId: '13198cdc-e508-4be5-9a5e-141a1a6e3526', - credentials: { - apiKey: process.env.ANCHORAGE_API_KEY, - privateKey, - publicKey - }, - label: 'Anchorage Staging - Narval Dev Client', - provider: 'anchorage', - url: 'https://api.anchorage-staging.com', - createdAt: new Date(), - updatedAt: new Date(), - status: 'active' - }) - } - } } diff --git a/apps/vault/src/shared/module/persistence/seed.ts b/apps/vault/src/shared/module/persistence/seed.ts index 7e2b7bd1b..158a8027e 100644 --- a/apps/vault/src/shared/module/persistence/seed.ts +++ b/apps/vault/src/shared/module/persistence/seed.ts @@ -198,10 +198,6 @@ async function main() { logger.log('Seeding Vault database with Anchorage provider data') - if (process.env.NODE_ENV === 'development') { - await connSeed.createNarvalDevConnection() - } - await prisma.$transaction(async (txn) => { // Process each connection group for (const group of ANCHORAGE_CONNECTIONS) { diff --git a/examples/unified-api/.env.default b/examples/unified-api/.env.default new file mode 100644 index 000000000..35ea01dd5 --- /dev/null +++ b/examples/unified-api/.env.default @@ -0,0 +1,12 @@ +# SETUP +# You should replace the values of the variables below with the ones you received or provided during setup +# During onboarding +CLIENT_ID='' +MASTER_PRIVATE_KEY='' +BASE_URL='https://vault.armory.playnarval.com' + +# ANCHORAGE CONNECTION VARIABLES +CONNECTION_ID='' +CONNECTION_PRIVATE_KEY='' +CONNECTION_API_KEY='' +CONNECTION_URL='https://api.anchorage-staging.com' diff --git a/examples/unified-api/1-activate.ts b/examples/unified-api/1-activate.ts new file mode 100644 index 000000000..a66aef329 --- /dev/null +++ b/examples/unified-api/1-activate.ts @@ -0,0 +1,39 @@ +import { rsaPublicKeySchema } from '@narval-xyz/armory-sdk' +import { rsaEncrypt } from '@narval-xyz/armory-sdk/signature' +import dotenv from 'dotenv' +import { vaultClient } from './vault.client' +dotenv.config() + +const main = async () => { + const apiKey = process.env.CONNECTION_API_KEY + const privateKey = process.env.CONNECTION_PRIVATE_KEY + const connectionId = process.env.CONNECTION_ID + const url = process.env.CONNECTION_URL + + if (!apiKey || !privateKey || !connectionId || !url) { + console.error( + 'Please provide CONNECTION_API_KEY, CONNECTION_PRIVATE_KEY, CONNECTION_ID, and CONNECTION_URL in your .env file' + ) + process.exit(1) + } + + const credentials = { + apiKey, + privateKey + } + + const jwk = await vaultClient.generateEncryptionKey() + const encryptionKey = rsaPublicKeySchema.parse(jwk) + + const encryptedCredentials = await rsaEncrypt(JSON.stringify(credentials), encryptionKey) + + const connection = await vaultClient.createConnection({ + data: { connectionId, url, encryptedCredentials, provider: 'anchorage' } + }) + + console.dir(connection) +} + +main() + .then(() => console.log('done')) + .catch(console.error) diff --git a/examples/unified-api/2-read-wallets.ts b/examples/unified-api/2-read-wallets.ts new file mode 100644 index 000000000..8b36da920 --- /dev/null +++ b/examples/unified-api/2-read-wallets.ts @@ -0,0 +1,11 @@ +import { vaultClient } from './vault.client' + +const main = async () => { + const wallets = await vaultClient.listProviderWallets() + + console.log(wallets) +} + +main() + .then(() => console.log('done')) + .catch(console.error) diff --git a/examples/unified-api/3-read-accounts.ts b/examples/unified-api/3-read-accounts.ts new file mode 100644 index 000000000..8a4761e7b --- /dev/null +++ b/examples/unified-api/3-read-accounts.ts @@ -0,0 +1,11 @@ +import { vaultClient } from './vault.client' + +const main = async () => { + const accounts = await vaultClient.listProviderAccounts({}) + + console.log(accounts) +} + +main() + .then(() => console.log('done')) + .catch(console.error) diff --git a/examples/unified-api/4-read-addresses.ts b/examples/unified-api/4-read-addresses.ts new file mode 100644 index 000000000..aaa4b52a8 --- /dev/null +++ b/examples/unified-api/4-read-addresses.ts @@ -0,0 +1,11 @@ +import { vaultClient } from './vault.client' + +const main = async () => { + const addresses = await vaultClient.listProviderAddresses({}) + + console.log(addresses) +} + +main() + .then(() => console.log('done')) + .catch(console.error) diff --git a/examples/unified-api/5-create-transfer.ts b/examples/unified-api/5-create-transfer.ts new file mode 100644 index 000000000..9d8c04a0c --- /dev/null +++ b/examples/unified-api/5-create-transfer.ts @@ -0,0 +1,29 @@ +import { vaultClient } from './vault.client' + +const fromId = '11904d17-f621-4cbe-bdcb-d587e7bc8045' +const toId = '3b102898-5468-445b-99ac-f672033d6f37' +const assetType = 'BTC_S' +const amount = '0.00001' + +const main = async () => { + const transfer = await vaultClient.sendTransfer({ + data: { + source: { + type: 'account', + id: fromId + }, + destination: { + type: 'account', + id: toId + }, + assetId: assetType, + amount + } + }) + + console.dir(transfer) +} + +main() + .then(() => console.log('done')) + .catch(console.error) diff --git a/examples/unified-api/README.md b/examples/unified-api/README.md new file mode 100644 index 000000000..ebbc4d453 --- /dev/null +++ b/examples/unified-api/README.md @@ -0,0 +1,67 @@ +## Prerequisites + +### Anchorage API Setup + +You need to have an API connection registered with Anchorage, which requires: +A generated Private Key (you provide them the hex public key) +An API secret key (provided by Anchorage in exchange for your hex public key) + +To generate EDDSA keys in hexadecimal format for Anchorage registration, run: +npx tsx generate-key.ts +This will output: +{ +"publicHexKey": "0x432...", // Provide this to Anchorage +"privateHex": "0xa288..." // Store this securely +} + +### Narval Client Console Onboarding + +Complete the following steps in the Narval Client Console: +Generate a master key +Securely store the private hex component +Register the public component in the Narval cloud console + +Note: You can use the same key generation process as described above for Anchorage credentials. + +Installation +Run from the project directory: +`npm i` + +## Configuration + +Set up the following environment variables: + +### Narval Config + +CLIENT_ID=your_narval_client_id +MASTER_PRIVATE_KEY=private_key_from_onboarding +BASE_URL=url_to_environment + +### Connection Configuration + +CONNECTION_ID=arbitrary_string +CONNECTION_PRIVATE_KEY=hex_private_key_registered_with_anchorage +CONNECTION_API_KEY=api_key_from_anchorage +CONNECTION_URL=provider_url # defaults to Anchorage + +## Usage Guide + +Execute the following commands in sequence: + +1. Activate Connection + Activates the connection in our provider unified API: + `tsx 1-activate.ts` + +2. List Available Wallets + Retrieves all readable wallets for this connection: + `tsx 2-read-wallets.ts` + +3. List Available Accounts + `tsx 3-read-accounts.ts` + +4. List Available Addresses + `tsx 4-read-addresses.ts` + +5. Create Transfer + Create a transfer between two accounts. You will need to modify the script with relevant data from previous responses + `tsx 5-create-transfer.ts` diff --git a/examples/unified-api/generate-key.ts b/examples/unified-api/generate-key.ts new file mode 100644 index 000000000..aab055d8d --- /dev/null +++ b/examples/unified-api/generate-key.ts @@ -0,0 +1,18 @@ +import { Alg, generateJwk } from '@narval-xyz/armory-sdk' +import { privateKeyToHex, publicKeyToHex } from '@narval-xyz/armory-sdk/signature' + +const main = async () => { + const key = await generateJwk(Alg.EDDSA) + const privateKeyHex = await privateKeyToHex(key) + const publicKeyHex = await publicKeyToHex(key) + + console.log({ + key, + privateKeyHex, + publicKeyHex + }) +} + +main() + .then(() => console.log('done')) + .catch(console.error) diff --git a/examples/unified-api/package-lock.json b/examples/unified-api/package-lock.json new file mode 100644 index 000000000..e1754c39e --- /dev/null +++ b/examples/unified-api/package-lock.json @@ -0,0 +1,856 @@ +{ + "name": "unified-api", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "unified-api", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@narval-xyz/armory-sdk": "0.15.0", + "dotenv": "16.4.5", + "tsx": "4.19.2" + } + }, + "node_modules/@adraffy/ens-normalize": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz", + "integrity": "sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q==" + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz", + "integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz", + "integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz", + "integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz", + "integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz", + "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz", + "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz", + "integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz", + "integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz", + "integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz", + "integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz", + "integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz", + "integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz", + "integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==", + "cpu": [ + "mips64el" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz", + "integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz", + "integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz", + "integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz", + "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz", + "integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz", + "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz", + "integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz", + "integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz", + "integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz", + "integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz", + "integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@narval-xyz/armory-sdk": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@narval-xyz/armory-sdk/-/armory-sdk-0.15.0.tgz", + "integrity": "sha512-WB58ecz/1nozojAvn8F42HpuFa7FKIYW8U0pAcFi9gPxq4iK+0bKvRfiqf7I3geE3yGimAMLQBAUuN5DpgdMRg==", + "dependencies": { + "@noble/curves": "1.6.0", + "@noble/ed25519": "1.7.1", + "@noble/hashes": "1.4.0", + "axios": "1.7.7", + "jose": "5.5.0", + "lodash": "4.17.21", + "tslib": "2.6.3", + "uuid": "9.0.1", + "viem": "2.16.2", + "zod": "3.23.8" + } + }, + "node_modules/@noble/curves": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.6.0.tgz", + "integrity": "sha512-TlaHRXDehJuRNR9TfZDNQ45mMEd5dwUwmicsafcIX4SsNiqnCHKjE/1alYPd/lDRVhxdhUAlv8uEhMCI5zjIJQ==", + "dependencies": { + "@noble/hashes": "1.5.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/curves/node_modules/@noble/hashes": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.5.0.tgz", + "integrity": "sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/ed25519": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/ed25519/-/ed25519-1.7.1.tgz", + "integrity": "sha512-Rk4SkJFaXZiznFyC/t77Q0NKS4FL7TLJJsVG2V2oiEq3kJVeTdxysEe/yRWSpnWMe808XRDJ+VFh5pt/FN5plw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ] + }, + "node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/base": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", + "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.2.tgz", + "integrity": "sha512-N1ZhksgwD3OBlwTv3R6KFEcPojl/W4ElJOeCZdi+vuI5QmTFwLq3OFf2zd2ROpKvxFdgZ6hUpb0dx9bVNEwYCA==", + "dependencies": { + "@noble/curves": "~1.2.0", + "@noble/hashes": "~1.3.2", + "@scure/base": "~1.1.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32/node_modules/@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "dependencies": { + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32/node_modules/@noble/curves/node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32/node_modules/@noble/hashes": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", + "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz", + "integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==", + "dependencies": { + "@noble/hashes": "~1.3.0", + "@scure/base": "~1.1.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39/node_modules/@noble/hashes": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", + "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/abitype": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.4.tgz", + "integrity": "sha512-UivtYZOGJGE8rsrM/N5vdRkUpqEZVmuTumfTuolm7m/6O09wprd958rx8kUBwVAAAhQDveGAgD0GJdBuR8s6tw==", + "funding": { + "url": "https://github.com/sponsors/wevm" + }, + "peerDependencies": { + "typescript": ">=5.0.4", + "zod": "^3 >=3.22.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/esbuild": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", + "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==", + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.23.1", + "@esbuild/android-arm": "0.23.1", + "@esbuild/android-arm64": "0.23.1", + "@esbuild/android-x64": "0.23.1", + "@esbuild/darwin-arm64": "0.23.1", + "@esbuild/darwin-x64": "0.23.1", + "@esbuild/freebsd-arm64": "0.23.1", + "@esbuild/freebsd-x64": "0.23.1", + "@esbuild/linux-arm": "0.23.1", + "@esbuild/linux-arm64": "0.23.1", + "@esbuild/linux-ia32": "0.23.1", + "@esbuild/linux-loong64": "0.23.1", + "@esbuild/linux-mips64el": "0.23.1", + "@esbuild/linux-ppc64": "0.23.1", + "@esbuild/linux-riscv64": "0.23.1", + "@esbuild/linux-s390x": "0.23.1", + "@esbuild/linux-x64": "0.23.1", + "@esbuild/netbsd-x64": "0.23.1", + "@esbuild/openbsd-arm64": "0.23.1", + "@esbuild/openbsd-x64": "0.23.1", + "@esbuild/sunos-x64": "0.23.1", + "@esbuild/win32-arm64": "0.23.1", + "@esbuild/win32-ia32": "0.23.1", + "@esbuild/win32-x64": "0.23.1" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-tsconfig": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz", + "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/isows": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.4.tgz", + "integrity": "sha512-hEzjY+x9u9hPmBom9IIAqdJCwNLax+xrPb51vEPpERoFlIxgmZcHzsT5jKG06nvInKOBGvReAVz80Umed5CczQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wagmi-dev" + } + ], + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/jose": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/jose/-/jose-5.5.0.tgz", + "integrity": "sha512-DUPr/1kYXbuqYpkCj9r66+B4SGCKXCLQ5ZbKCgmn4sJveJqcwNqWtAR56u4KPmpXjrmBO2uNuLdEAEiqIhFNBg==", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + }, + "node_modules/tsx": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.2.tgz", + "integrity": "sha512-pOUl6Vo2LUq/bSa8S5q7b91cgNSjctn9ugq/+Mvow99qW6x/UZYwzxy/3NmqoT66eHYfCVvFvACC58UBPFf28g==", + "dependencies": { + "esbuild": "~0.23.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/viem": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.16.2.tgz", + "integrity": "sha512-qor3v1cJFR3jcPtcJxPbKfKURAH2agNf2IWZIaSReV6teNLERiu4Sr7kbqpkIeTAEpiDCVQwg336M+mub1m+pg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "dependencies": { + "@adraffy/ens-normalize": "1.10.0", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.2", + "@scure/bip32": "1.3.2", + "@scure/bip39": "1.2.1", + "abitype": "1.0.4", + "isows": "1.0.4", + "ws": "8.17.1" + }, + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/viem/node_modules/@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "dependencies": { + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/viem/node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/examples/unified-api/package.json b/examples/unified-api/package.json new file mode 100644 index 000000000..b079e2dc1 --- /dev/null +++ b/examples/unified-api/package.json @@ -0,0 +1,16 @@ +{ + "name": "unified-api", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "@narval-xyz/armory-sdk": "0.15.0", + "dotenv": "16.4.5", + "tsx": "4.19.2" + } +} diff --git a/examples/unified-api/tsconfig.json b/examples/unified-api/tsconfig.json new file mode 100644 index 000000000..cd04af0b0 --- /dev/null +++ b/examples/unified-api/tsconfig.json @@ -0,0 +1,101 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "ES2022" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "ES2022" /* Specify what module code is generated. */, + // "rootDir": "./", /* Specify the root folder within your source files. */ + "moduleResolution": "Node" /* Specify how TypeScript looks up a file from a given module specifier. */, + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ + // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ + // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ + // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */, + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, + /* Type Checking */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +} diff --git a/examples/unified-api/unified-api.example.zip b/examples/unified-api/unified-api.example.zip deleted file mode 100644 index e9914198a344f5fe82563c040fdcaa9bf4c7bfce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10353 zcma)C1yEdDwr$)kxVyVG?(Xj1xD#B0y9I~f7D6Csa0^Z#gy0a|8u#Fu-066V4$|u228~Du4vQX6@q5W@T+- z;pOD1qm2ZBseJ(1p21t%dikONpkS{cKl|Iios%RS!^JTpPoLvLNrY#YQ3Ra6PO&vH zIY0}Hyf-rW&j0a*=<#L+82YZP<>nK@#i~;gc$O0b=thTdA+G9U4t`soVUB==;y`a( zl+?kEOnfXs&1ksnV`Zn2KcCO-aAc7=r}F8*t$_y^@$P~v z2D^8<5--|>0RFV9%2#7IlD|G~-u3ZO=B5gKRWI+oVSdab=GuZH=uFLn&*cclucamu z<8#=50skqg?A%ee4j=tx<~!jU>CC=Z+^}P8Q+Tnn)d#?{rx*@U z0e3t`M^EuBI)&>0benU0s=<00e*_rf3v*Zi01e_cPF4#`PkV0*Pir<$kH7it_y%N4 zcnkWo-vYH%Tyw=SyH0E0TIE+`%DmvdQJz6S>=v{SM130xD<`Z_CPY2wuBg= zYGKTA%cyOmgvqB=Fr)X!cza~ zJbpJv&~2?`+bGIlzbLs}Jh01+@Fn9g)lDO%P_%_0@$7;_0b4|HfIb`OP<~&znpxBh zSJv_v>drn!Wc#k{?CB-wk`TIhdnkFBBZf^EkN1NYe|t?9h0cJQAms&XRnohCNy-9JXzufcHsa|hyTMK+J(3DbrYo#ZydzAxd@Hoe0`j&*Y5*6g;iPN;7q3E z5`^)q_0Mt0EFPU-1Z@Lj3wbeSF=g0vIHQawC}z}R>(IwYQJ~~dcWn?(ldsyFUq8Q& z1|ystRghLoubrv_Y6F?B`OTW_+i13eXy6mOL>ymOyljN}qdka|hft9aTV@~&8)6U7 z|Jq|^0-L{>919sLVh((M|7RYTyQtxkmMTnXV)`|0|P-j`vCD`L|kJ{Qw zOwrZn)Q-}>S`X$H=vKeh34Q@yQ$2nb{QliA>0&g@GYqiE!WeFA z6A#9?T`|xH@mZP{KG3SN1gE5IZmxs%SesJ%Ug>KSC4vXX`4P)|=$-L1YJlNHgo(1b zm>#WWJm*2W*uH*>%$5E!5Dkz5)3$;tx-DCywWEnD>{lU^{h3Cx>#oxb1M`9Lj02iZ z7Cd_wLVeFK;TY^GEUD(mX}*6r!R0rvextN|XttU)+LAT98Q5mfxr4qK)}9T-S>et8 zqW7K?mOTCO{e*Ocs!r=>=-c%La+tj#`AT&>w9g!Ox%wjDW$WeCfbl6bv#8so42Sj^ zikCT{mvb_JJaBd>&zub}*g5N+`<%im4V&|)fnl(+%_F{)x6Ps$!Bk`-O!YWu=EK{f z`)TBqlQ9hC?IqsR$%^aPtJ#dTipxC{%__$FsAE$Td$Sm`KZY_(Y?ML}5=td#0Du4z zN+7GPwdX(M$m-!~;pz3CGSoU%%(agLbI>O^?hwaF@}#i-g^3*k-g|9eM6z|Bn#z>Juy92yam ze-xNqoTRxj@Wz`yaPJOWd}76NAJTZxmH#=tt2Nz#k39InD>^ltQs~QLZ6d>KXw6K!U_VQ$|8sMTX7U>Tl&< z@!zybI!i7~{Fs5edZ?ROY?vKOG_1%leiMrh^YS2s=IPNiNhQm8;@Fwgbasa8H6Qse zsfXY}%qWi?_noh;^Wk!dL_ez|vGC9=yG${tvUe0O&?GPUL*W+NK}Y445>z(kxZqdu zJ!QeF8R>5fi)rkZ5iJ>w;e{+N*uK#oxu@)`W83pc;q}7PI=GD7XvDJy_K=dTuY^u% z8#>EGnR~FTV1QerD@}2!BJqVEdrOiR%_}Dbu{#|(2&>TPuTYR$)jZht1FCt{J)f9} zj4GRnVm@!lfRBbkM>1^R#HHe+o4FtMdm>4WM!bDymzZ}SwrWCfymlTIg(KGQ&urru zP|^sgbkCYtBn{pw$mu5N8!UXtJ^avX?)DPtbPbzZjtWt+v&9dIK%Uwvh&}ES+sj|3;+-;i1wvsLc#1$WzCj74}7E08G zKEjMO{YdA($km8CI!uv9r}dF^6aFZp1s#cKP02I(pztTnyk8S2|sBX3FopXFqd|Q z;oJ0lmnIsG@B3_iVc2K*;p4u{lhl25LPWl1bTnl^rVi5P0_VxFLA(m-M{cTqNt67S z@$Srxsb!8HqfP4{`i_TPVJ3z<}m!gg$V&siyV-Mav={3frmES!%SH}-jg5Rbl2hBL&7|@q4coHRLrY+3q^j|4X z5ba4xF0E4)3K!x@VXLX49H`1}s>=2mMHa#qncSG0#@591iI^~t(M}*;!HVSk$eE86 zSt94lq2JnhY@)Lr+7ubN%s5a8qRq<2|5Usc$wiyrfB_Q|gHyZlni75@ClSNbotQDC zL*(;jQ6`90-hXCk0;+Ij^w^?TVHn+$bgnmkfC*n=O8_hhLs6s70WS)Y)Jl za)oO`54QRo*WMO%;5yNqaUI^x>?@G;E}q?!kZ#NNTI~N0@ox#K2A`J%zkng#MGxd4 z$ABChw$?7z?!W4>qqW~ZN^!(J$hHQu{&dTVOj2^`r@)N5$pd+Zfcfd=XXPt!ct@|H z)0IiBh^sjLCWd|3Z#7b!+QYN&p6`Yl^Qkd>z5{ija1Cj;&z}tY0c&8x^;+FY8Qu>@ zw+74(q>(zoRRY{73n^{VJ0Tm>$LG4@KFpmxb15IuuOQ^L|!P^YKe^wS==7!?lAYvib ziv=T$R1=V6L&L*Z8I-xKgO!oFtrU4gWyb68 zQb732(5jJwb<)$yN{-6{<4yscnba@RvKzxmY5%j`MvrM%OAyMC zB#?st2&FHy7X-zx3EQjr!?0$=L)b9*r(X$~3d5f3X$Rpq3rP-$W79E+D9~8ng<1vji+-(m zYZ8W?TFz70G%nEb4pT;DqJx>HK$@^CW=E5)l%|v>Ym(R0`Xk=vV4Tf9K?(h%-ca;{ z@*Va51wQ+A5ECUay~oEMMV`-~8nF?ZK2uAHpvMjB@tKj269siXhs<7Y)inr!QpX`E zt_;|LJ+I!Asg8&-Q_+Bh${L^ps$6rOoe%eFmA`?c6T_quX9aNY{ zPF55clSV5YqrQ*3tE;wMM4&k@NcNh(bowG~x?e0RZSwA6vQYQw%1v1Cr?3CagwN+L zvV5wa3j2?v_?H81>f@@M6J^OB-{u(T9eFnMUakqflLU}5O>)0p?Dds!-F?wzY_@Oi zP8pj$!NeJWnZe0dD(bVqUE99iF7&OC<}_sONf_s;A!o*wr1ItdYAfc}`wcHL%0 zrK8ADjES+NPceHLA{7I#57c6CMJZ?Ou6lK#XTr8{o((FpHvlWr?Ery6GGM$w1STZ^ z2d%i(qB2y|kan}tc&#nr3|p=Mj-G951r|7CY!hCR5}2PbfvaL9$W->G!ZfcCq z_8#)r?NM&cVNu;+9KEhIjICG^vzJ7rYHF@5CyGaJIs^Q*B)cE1F0n=6DN%cd@&Gn3 zn@IL_EQ@X(zTM&`QivzZ7NjzcDIm*wdpV(KuY5fxO<~%*Vzx$<6rgWA?N`vyizq=% zEM8O^(0xIaS_G#uodA#vIn}ZglMusBOD807W9#A5M;hcRow|`^pFlReoL^m|xDpQR zLrUmeM(k6P^(gP0magAa65$|LiPCd-i3Tm$;qA9t+Q3)Jd=EqZ;bC<9@!J;BtLEH5 z7`cXH7eCI3oe=1(RV8v9U(2~199lsYt|6^hxZ@FVn^@z@2* z_cb<(%VHR{mkBVl{nTlr+K`cOtTnw2Wcw1vUimuj4&0sHpHy%GT^o_U1L6QUxlfYy z3>}(|#W_6JwRG=D9}I9OYpM?|l7l>Gelkl=oY?Y@#*l&Va@S9A=6AkrO+7ekkDLUL z$%8zkP2d~@ak%o|Znf6Oq} z*agNJZ@sDy2P>&z%*bLj=8vrby!mY02W0TdVCncTk$%NIU*K9D+uK`5snRb_>)e** zrVa)Zm5FIP%=er1oeuZ$Qwq_NUdM60xy-woFh;5fTv*y_FPG2Ia1G27uT4rc4r zuV=Uis+*Z~bG=5!xqJ_JA(oWKXwiS{Z`tTg&{TngOQ_ydt<9|6uh4C!jdY;lV0gMF zYDzxQSaWNM)ctcXP(iDJchBARQFQh!zF;-|-OBa+^Qg;6L%w_(wStY2S?()Rdc zc}c)!AnBW>p}f*XQ)y)OaORJJ92@PrTQBlHfBQNCeetJq2$0f#bVG;KLyo`C89hBL zU0rPKZU0yg+5cJ(s|}r9savp~gSx}cvYatemv^+VaAaNuDLChiBOK=8F~o%|meCA# zfHT31y5WyE-%v+PPU1~Tc=#zY8^N7!JK45T4~Gat-v)BAE9-368X5*SNuC9A9h)+9 z2jh(DZwDQ`fZ+(^;|nd(9}upkjuTc9FGRRYrr5*UsvD2Im~pnOkqTk8HZ!V;GlVK| z*~^wV4Q9*UN4S@mYfegSCT?YA_Bx#FIxam~#qY`_$1E|S3H8;gZiz1PHv`*28M=!x zhTJvYxQ|V@Av@sqN^8ciQi)TORc0HG-;byt6b$#j&$TTE1qXdAyes)w-PGEF)oI>} zyT!c1@47(bZAm`9MQ4`yECc@5Y?j}^UEwY@cm4t_FdaiEbW48J0A6p8Z1^CX8L924 z62?*qwazP*C|Wzf^hnH@!N zwrk!^`a807Y+s~F^}=|4LA6uPOQ(tYDAd|)_l5!wNQs?r)UG|Uag7%}DUpG#x$1qz`Nz)pSd9wOCo@hJ~YS->@rL4d69OqQ9kv6TQ4`tmEu$z3hIt3QP;QmJcax7nCv=Xz6pEx!?e#@zD5F~ z+~(;m3I>+pP@-u>y(dkwOi3zwD7_#0wm58t3gw=!xQy_rW(_J|$EEsyl}&Z|I?}|Z z*-z0N1MK>**|?tSA7pW98F(n!N&q(Ilq_}~KSZy|%-?CK>V_2Lr}@+0#Rp2UORO7O zm=16>pdZ}CNuFl@giQ)D0^9>7k<^uNM6dvJee#9=dQ|gg5x{G}rYA)jn{{)A$eVtw z3{d}t$`oK!G0po^5yq!;fPi``f`2Y6#U7T%k>0h3SyoY zXyX#0r2Y@BS<%T+rlt>Qi;9E*T#p%Y;Jc&Jkn+8kjR8Xg&|G|_uK0kEqN^tMDnb~g zkIq2N=`*zFpqzGWhat2V;*>Iz9*1YSB30gMhpmNrtxr5N51C9|a>rYus+TpMlj83U z?irvm<(FOy9eD)T71zHHh9{!v4Yl1l+x`5>|MCgn6v^m9tC6@}rxvle%ztvcH_hND z2Y$~h3aBRN8L*d$BB%RHSwpMpv;ZQer|ggenirTn2{PkbRB-^%EC^@2hvg0njd37H zYO*&PZxEzD-*c)5V$Eos-1!KeTb0+qLkOXwJGk0@iu}Ca<`putjN<{juj!81PtpSI zjZ_$UOR9)C>!K=*&`XW6hur!PxGiSkeo!I}pIg;MJ#BV$<9MCUK2aQn) zQ>$w@mMAWZNFMeA`JxG*W0<)@;`VsJK~!gy(kL+jcPYki@Gyj@U=&}zr4EfsEwoTE z-)8{iJ8^C04%KdqDMdf0SGv3Z#@T%L^%*PyK}k%^Tbz~fk;6c)qJ6jbNku~=f^Un2 zG{X#INQyTM>YQHIP`nO82aN}d8vu!8#a13a`Bv_S435h`?G=UNLw~*qM4kd?h+iye z%Cgd{O&6DAUx};foLg4tb#@LHHwZ|3rfO|mvV8Gx?*~LYUU&U;S*V)-aZJNb zVV{{vl{|%>2rs)mUwWRo7_-rKK@sRwR@-v+l`kL>8;ZDnm(j?GIZZstNiY;%Q@Jsh zH3avuJk+y^C3iepA6veDBqkSypDl#NSJl1>set9{Zs?;->NVhs6GaZ~j-O#F0?sT@ zd)c76W=(!65CKtF!~jcB)lj-0BNM5c?Lx+OZ;HUX7hlfv%q6HB-Qq?>P*w@}wOO??iRgMlom2nLGtBEtkFUxlod zM;TMuzbXoXS>(2S{Vyg4x6EOX)QNkzk6g@Xnwm;8(H!}CO&sJ0$hvw@-wab=m0lv3 z7eJjtH_Nr98GMQ8ZbrOrVd+7ZX0%eZvN2IQ8B>^=g2t3Y?5)=fjS~q_v`tm@BW!Oh z&N@Yh*_fb9!XNo`+=!xy@3|gTmoSXP(8$?o*jSM~3A^Qj#Gw9Je!xbb0A{6_kG!Bk zD?i8VUewyMC2onEg!8_qXP>6^rK-{OE|O&%Zm`q=*z)n4Y3!o2M64Kj+(r6wkG}!0 z4vi~Z%_&i>_gn5C34+s^S13?A$_4Jz(PXaCVi8A^%V4BcE+5tnl-v?odlf}rLzRyA%!4* zh|zo%fqKBvD~B}=o)etY+c9lfQ?Fj3xHp_x9uHsKQry_$a`dh!Br52QSn5g|GT8xL z_o>x=aV>@9zCc)6Jp8HG4D95)sj5 zO>>oPavT=6J23`EnGF4FwXwBEc|g$Ykd1}kziNWZ#51p z7n~%s+B1vNZPQ&g-E`pjYOqjDWVt&DY(DIEeR*v2jDKy9up>qwT^it0ut09!A|{)m3!={G z>w))?-XpR|e^Fc5i{&fb#yDTTA{;?Xq93mcYY3yC-w_fU_-bFS42FD}$yYPqdsh(7 zsLNigY!{E+x`Ev4J3k6pa?}cIt!EIT^`K{g<>@rljns}e zOe&`N2wsUtS2yi+R=qib6gf4G>v-~fRN3W2;fKY(SDvx>U*;#GNiGza*4)H`%9rfu z%)Nl^>H9C-VX;R_%QJR2%tblcyx+xGd>92@w(l82+5*uWL=vMpCudLciSV|-T-vXU9syRrzGpCF-nLEabvLQURt8|DG z&|@Vovo|J$-_&IJj%PfIHHOpqr=LqB`gSfR)zN$tT*y=`PbMQ>zGgohL%1M zy1wMw!k-fYO3NfK;6}KZ=EIWWIEMCLUw&z}v>sM!YB%yuQ)%yfF(b1yVS7?9;HaP; zfWdyASp2LapO}bFn>Ho@!O@o!f>p5z29o6~NdSj?=;CFNBxgp0oy5*nO^& zV^4T4ROl_wGDOtGNrJH)peRYrg^CMO zdZ3_iO0u!P1j6xS4IR7SQXsN#2jASVRlDLK}ZB36@kY zFqoh|MPT~M$9MYc1%1!U7f?s6fOKUOp!yzsNWXKU3($xmsBg8B);#dj%4t3fa&^a8 zowWafqrDiS3d4w2;Cvc#>8+95VlKmL;|Zz^CV!b8vk-N`hqEFyfZL;yxPFt{t_c14 zS=eb5-sc+ccIoLLD3czP&O%D&;(d54Mq%_Q2h3Lcs(cH|uF;84@+o#WrPD&|@VAtH zRtgs?$-)!KJXFu1@Ukf(4*n1}optpBxE^tozQDqD6s~@vliE=c@v{tmbj+?fR}!3J zMkf1OMul7C8N4jB1M1Ii+L|4+MIRt+%_}w17kHm-?Pmiry+TgM-DR$h>=aD Date: Fri, 3 Jan 2025 15:18:34 +0100 Subject: [PATCH 072/120] Add FB connection E2E test (#68) --- .../broker/__test__/e2e/connection.spec.ts | 508 ++++++++++-------- 1 file changed, 291 insertions(+), 217 deletions(-) diff --git a/apps/vault/src/broker/__test__/e2e/connection.spec.ts b/apps/vault/src/broker/__test__/e2e/connection.spec.ts index d553baa46..a7be0f17b 100644 --- a/apps/vault/src/broker/__test__/e2e/connection.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/connection.spec.ts @@ -11,6 +11,7 @@ import { getPublicKey, privateKeyToHex, privateKeyToJwk, + privateKeyToPem, rsaEncrypt, rsaPublicKeySchema } from '@narval/signature' @@ -208,70 +209,6 @@ describe('Connection', () => { ) }) - it('creates a new connection to anchorage with plain credentials', async () => { - const privateKey = await generateJwk(Alg.EDDSA) - const privateKeyHex = await privateKeyToHex(privateKey) - const connectionId = uuid() - const connection = { - provider: Provider.ANCHORAGE, - connectionId, - label: 'Test Anchorage Connection', - url, - credentials: { - apiKey: 'test-api-key', - privateKey: privateKeyHex - } - } - - const { status, body } = await request(app.getHttpServer()) - .post('/provider/connections') - .set(REQUEST_HEADER_CLIENT_ID, clientId) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk, - requestUrl: '/provider/connections', - payload: connection - }) - ) - .send(connection) - - const createdConnection = await connectionService.findById(clientId, connection.connectionId) - const createdCredentials = await connectionService.findCredentials(createdConnection) - - expect(body).toEqual({ - data: { - clientId, - connectionId, - url, - createdAt: expect.any(String), - label: connection.label, - provider: connection.provider, - status: ConnectionStatus.ACTIVE, - updatedAt: expect.any(String) - } - }) - - expect(status).toEqual(HttpStatus.CREATED) - - expect(createdConnection).toMatchObject({ - clientId, - createdAt: expect.any(Date), - connectionId, - label: connection.label, - provider: connection.provider, - status: ConnectionStatus.ACTIVE, - updatedAt: expect.any(Date), - url: connection.url - }) - - expect(createdCredentials).toEqual({ - apiKey: connection.credentials.apiKey, - privateKey, - publicKey: getPublicKey(privateKey as Ed25519PrivateKey) - }) - }) - it('emits connection.activated on connection activation', async () => { const connectionId = uuid() const provider = Provider.ANCHORAGE @@ -326,92 +263,17 @@ describe('Connection', () => { ) }) - it('activates an anchorage pending connection with plain credentials', async () => { - const connectionId = uuid() - const provider = Provider.ANCHORAGE - const label = 'Test Anchorage Connection' - const credentials = { apiKey: 'test-api-key' } - - const { body: pendingConnection } = await request(app.getHttpServer()) - .post('/provider/connections/initiate') - .set(REQUEST_HEADER_CLIENT_ID, clientId) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk, - requestUrl: '/provider/connections/initiate', - payload: { connectionId, provider } - }) - ) - .send({ connectionId, provider }) - - const { status, body } = await request(app.getHttpServer()) - .post('/provider/connections') - .set(REQUEST_HEADER_CLIENT_ID, clientId) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk, - requestUrl: '/provider/connections', - payload: { - connectionId, - credentials, - label, - provider, - url - } - }) - ) - .send({ - connectionId, - credentials, - label, - provider, - url - }) - - const createdConnection = await connectionService.findById(clientId, connectionId) - const createdCredentials = await connectionService.findCredentials(createdConnection) - - expect(body).toEqual({ - data: { - clientId, - connectionId, - label, - provider, - url, - createdAt: expect.any(String), - status: ConnectionStatus.ACTIVE, - updatedAt: expect.any(String) - } - }) - expect(status).toEqual(HttpStatus.CREATED) - - expect(createdConnection).toMatchObject({ - clientId, - connectionId, - label, - provider, - url, - createdAt: expect.any(Date), - status: ConnectionStatus.ACTIVE, - updatedAt: expect.any(Date) - }) - - expect(createdCredentials).toMatchObject({ - apiKey: credentials.apiKey, - publicKey: pendingConnection.data.publicKey.jwk - }) - }) - - it('activates an anchorage pending connection with encrypted credentials', async () => { + it('overrides the existing connection private key when providing a new one on pending connection activation', async () => { const connectionId = uuid() const provider = Provider.ANCHORAGE const label = 'Test Anchorage Connection' const credentials = { - apiKey: 'test-api-key' + apiKey: 'test-api-key', + // Adding private key to test override + privateKey: '0x9ead9e0c93e9f4d02a09d4d3fdd35eac82452717a04ca98580302c16485b2480' } + // First create a pending connection const { body: pendingConnection } = await request(app.getHttpServer()) .post('/provider/connections/initiate') .set(REQUEST_HEADER_CLIENT_ID, clientId) @@ -425,11 +287,13 @@ describe('Connection', () => { ) .send({ connectionId, provider }) + // Encrypt the credentials including the new private key const encryptedCredentials = await rsaEncrypt( JSON.stringify(credentials), pendingConnection.data.encryptionPublicKey.jwk ) + // Activate the connection with the new credentials const { status, body } = await request(app.getHttpServer()) .post('/provider/connections') .set(REQUEST_HEADER_CLIENT_ID, clientId) @@ -467,10 +331,11 @@ describe('Connection', () => { updatedAt: expect.any(String) } }) + expect(status).toEqual(HttpStatus.CREATED) const createdConnection = await connectionService.findById(clientId, connectionId) - const createdCredentials = await connectionService.findCredentials(createdConnection) + const createdCredential = await connectionService.findCredentials(createdConnection) expect(createdConnection).toMatchObject({ clientId, @@ -483,101 +348,310 @@ describe('Connection', () => { updatedAt: expect.any(Date) }) - expect(createdCredentials).toMatchObject({ - apiKey: credentials.apiKey, - publicKey: pendingConnection.data.publicKey.jwk - }) + const givenPrivateKey = privateKeyToJwk(credentials.privateKey as Hex, AnchorageCredentialService.SIGNING_KEY_ALG) + + expect(createdCredential?.publicKey).toEqual(getPublicKey(givenPrivateKey)) + expect(createdCredential?.privateKey).toEqual(givenPrivateKey) }) - it('overrides the existing connection private key when providing a new one on pending connection activation', async () => { - const connectionId = uuid() - const provider = Provider.ANCHORAGE - const label = 'Test Anchorage Connection' - const credentials = { - apiKey: 'test-api-key', - // Adding private key to test override - privateKey: '0x9ead9e0c93e9f4d02a09d4d3fdd35eac82452717a04ca98580302c16485b2480' - } + describe('anchorage', () => { + it('creates a new connection to anchorage with plain credentials', async () => { + const privateKey = await generateJwk(Alg.EDDSA) + const privateKeyHex = await privateKeyToHex(privateKey) + const connectionId = uuid() + const connection = { + provider: Provider.ANCHORAGE, + connectionId, + label: 'Test Anchorage Connection', + url, + credentials: { + apiKey: 'test-api-key', + privateKey: privateKeyHex + } + } - // First create a pending connection - const { body: pendingConnection } = await request(app.getHttpServer()) - .post('/provider/connections/initiate') - .set(REQUEST_HEADER_CLIENT_ID, clientId) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk, - requestUrl: '/provider/connections/initiate', - payload: { connectionId, provider } - }) - ) - .send({ connectionId, provider }) + const { status, body } = await request(app.getHttpServer()) + .post('/provider/connections') + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk, + requestUrl: '/provider/connections', + payload: connection + }) + ) + .send(connection) + + const createdConnection = await connectionService.findById(clientId, connection.connectionId) + const createdCredentials = await connectionService.findCredentials(createdConnection) + + expect(body).toEqual({ + data: { + clientId, + connectionId, + url, + createdAt: expect.any(String), + label: connection.label, + provider: connection.provider, + status: ConnectionStatus.ACTIVE, + updatedAt: expect.any(String) + } + }) - // Encrypt the credentials including the new private key - const encryptedCredentials = await rsaEncrypt( - JSON.stringify(credentials), - pendingConnection.data.encryptionPublicKey.jwk - ) + expect(status).toEqual(HttpStatus.CREATED) - // Activate the connection with the new credentials - const { status, body } = await request(app.getHttpServer()) - .post('/provider/connections') - .set(REQUEST_HEADER_CLIENT_ID, clientId) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk, - requestUrl: '/provider/connections', - payload: { - provider, - connectionId, - label, - url, - encryptedCredentials - } + expect(createdConnection).toMatchObject({ + clientId, + createdAt: expect.any(Date), + connectionId, + label: connection.label, + provider: connection.provider, + status: ConnectionStatus.ACTIVE, + updatedAt: expect.any(Date), + url: connection.url + }) + + expect(createdCredentials).toEqual({ + apiKey: connection.credentials.apiKey, + privateKey, + publicKey: getPublicKey(privateKey as Ed25519PrivateKey) + }) + }) + + it('activates an anchorage pending connection with plain credentials', async () => { + const connectionId = uuid() + const provider = Provider.ANCHORAGE + const label = 'Test Anchorage Connection' + const credentials = { apiKey: 'test-api-key' } + + const { body: pendingConnection } = await request(app.getHttpServer()) + .post('/provider/connections/initiate') + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk, + requestUrl: '/provider/connections/initiate', + payload: { connectionId, provider } + }) + ) + .send({ connectionId, provider }) + + const { status, body } = await request(app.getHttpServer()) + .post('/provider/connections') + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk, + requestUrl: '/provider/connections', + payload: { + connectionId, + credentials, + label, + provider, + url + } + }) + ) + .send({ + connectionId, + credentials, + label, + provider, + url }) - ) - .send({ - provider, + + const createdConnection = await connectionService.findById(clientId, connectionId) + const createdCredentials = await connectionService.findCredentials(createdConnection) + + expect(body).toEqual({ + data: { + clientId, + connectionId, + label, + provider, + url, + createdAt: expect.any(String), + status: ConnectionStatus.ACTIVE, + updatedAt: expect.any(String) + } + }) + expect(status).toEqual(HttpStatus.CREATED) + + expect(createdConnection).toMatchObject({ + clientId, connectionId, label, + provider, url, - encryptedCredentials + createdAt: expect.any(Date), + status: ConnectionStatus.ACTIVE, + updatedAt: expect.any(Date) }) - expect(body).toEqual({ - data: { + expect(createdCredentials).toMatchObject({ + apiKey: credentials.apiKey, + publicKey: pendingConnection.data.publicKey.jwk + }) + }) + + it('activates an anchorage pending connection with encrypted credentials', async () => { + const connectionId = uuid() + const provider = Provider.ANCHORAGE + const label = 'Test Anchorage Connection' + const credentials = { + apiKey: 'test-api-key' + } + + const { body: pendingConnection } = await request(app.getHttpServer()) + .post('/provider/connections/initiate') + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk, + requestUrl: '/provider/connections/initiate', + payload: { connectionId, provider } + }) + ) + .send({ connectionId, provider }) + + const encryptedCredentials = await rsaEncrypt( + JSON.stringify(credentials), + pendingConnection.data.encryptionPublicKey.jwk + ) + + const { status, body } = await request(app.getHttpServer()) + .post('/provider/connections') + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk, + requestUrl: '/provider/connections', + payload: { + provider, + connectionId, + label, + url, + encryptedCredentials + } + }) + ) + .send({ + provider, + connectionId, + label, + url, + encryptedCredentials + }) + + expect(body).toEqual({ + data: { + clientId, + connectionId, + label, + provider, + url, + createdAt: expect.any(String), + status: ConnectionStatus.ACTIVE, + updatedAt: expect.any(String) + } + }) + expect(status).toEqual(HttpStatus.CREATED) + + const createdConnection = await connectionService.findById(clientId, connectionId) + const createdCredentials = await connectionService.findCredentials(createdConnection) + + expect(createdConnection).toMatchObject({ clientId, connectionId, label, provider, url, - createdAt: expect.any(String), + createdAt: expect.any(Date), status: ConnectionStatus.ACTIVE, - updatedAt: expect.any(String) - } + updatedAt: expect.any(Date) + }) + + expect(createdCredentials).toMatchObject({ + apiKey: credentials.apiKey, + publicKey: pendingConnection.data.publicKey.jwk + }) }) + }) - expect(status).toEqual(HttpStatus.CREATED) + // NOTE: When adding tests for a new provider, focus only on testing + // provider-specific credential formats. Common functionality like + // credential encryption/decryption is already covered by existing tests. + // The main goal is to verify that the API correctly handles the unique + // input credential structure for each provider. + describe('fireblocks', () => { + it('creates a new connection to fireblocks with plain credentials', async () => { + const rsaPrivateKey = await generateJwk(Alg.RS256, { modulusLength: SMALLEST_RSA_MODULUS_LENGTH }) + const pem = await privateKeyToPem(rsaPrivateKey, Alg.RS256) + const connectionId = uuid() + const connection = { + provider: Provider.FIREBLOCKS, + connectionId, + label: 'Test Fireblocks Connection', + url, + credentials: { + apiKey: 'test-api-key', + privateKey: Buffer.from(pem).toString('base64') + } + } - const createdConnection = await connectionService.findById(clientId, connectionId) - const createdCredential = await connectionService.findCredentials(createdConnection) + const { status, body } = await request(app.getHttpServer()) + .post('/provider/connections') + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk, + requestUrl: '/provider/connections', + payload: connection + }) + ) + .send(connection) + + const createdConnection = await connectionService.findById(clientId, connection.connectionId) + const createdCredentials = await connectionService.findCredentials(createdConnection) + + expect(body).toEqual({ + data: { + clientId, + connectionId, + url, + createdAt: expect.any(String), + label: connection.label, + provider: connection.provider, + status: ConnectionStatus.ACTIVE, + updatedAt: expect.any(String) + } + }) - expect(createdConnection).toMatchObject({ - clientId, - connectionId, - label, - provider, - url, - createdAt: expect.any(Date), - status: ConnectionStatus.ACTIVE, - updatedAt: expect.any(Date) - }) + expect(status).toEqual(HttpStatus.CREATED) - const givenPrivateKey = privateKeyToJwk(credentials.privateKey as Hex, AnchorageCredentialService.SIGNING_KEY_ALG) + expect(createdConnection).toMatchObject({ + clientId, + createdAt: expect.any(Date), + connectionId, + label: connection.label, + provider: connection.provider, + status: ConnectionStatus.ACTIVE, + updatedAt: expect.any(Date), + url: connection.url + }) - expect(createdCredential?.publicKey).toEqual(getPublicKey(givenPrivateKey)) - expect(createdCredential?.privateKey).toEqual(givenPrivateKey) + expect(createdCredentials).toEqual({ + apiKey: connection.credentials.apiKey, + privateKey: rsaPrivateKey, + publicKey: getPublicKey(rsaPrivateKey) + }) + }) }) }) From 694084d4631a017fc967d4702dec42d0925271fa Mon Sep 17 00:00:00 2001 From: Ptroger <44851272+Ptroger@users.noreply.github.com> Date: Mon, 6 Jan 2025 15:22:26 +0100 Subject: [PATCH 073/120] Feature/nar 1982 raw proxy fireblocks (#63) * wip * cleaned up example * add encryption over activation flow * added base url as env to quickly switch envs * cancel transaction * fireblocks client forward request * fireblocks client with nonce management * fireblocks client * types from read queries * conflict solving * moving fireblocks proxy to a module * deleted unzipped examples --- apps/vault/src/broker/broker.module.ts | 4 + .../fireblocks/fireblocks-proxy.service.ts | 37 ++++ .../provider/fireblocks/fireblocks.util.ts | 53 +++++ .../src/broker/core/service/proxy.service.ts | 6 +- .../src/broker/core/type/provider.type.ts | 1 + .../__test__/unit/fireblocks.client.spec.ts | 194 ++++++++++++++++++ .../broker/http/client/fireblocks.client.ts | 194 ++++++++++++++++++ examples/unified-api/generate-key.ts | 18 -- packages/armory-sdk/src/lib/vault/client.ts | 37 ++-- 9 files changed, 510 insertions(+), 34 deletions(-) create mode 100644 apps/vault/src/broker/core/provider/fireblocks/fireblocks-proxy.service.ts create mode 100644 apps/vault/src/broker/core/provider/fireblocks/fireblocks.util.ts create mode 100644 apps/vault/src/broker/http/client/__test__/unit/fireblocks.client.spec.ts create mode 100644 apps/vault/src/broker/http/client/fireblocks.client.ts delete mode 100644 examples/unified-api/generate-key.ts diff --git a/apps/vault/src/broker/broker.module.ts b/apps/vault/src/broker/broker.module.ts index a6ecc7899..6f11f837a 100644 --- a/apps/vault/src/broker/broker.module.ts +++ b/apps/vault/src/broker/broker.module.ts @@ -14,6 +14,7 @@ import { AnchorageProxyService } from './core/provider/anchorage/anchorage-proxy import { AnchorageSyncService } from './core/provider/anchorage/anchorage-sync.service' import { AnchorageTransferService } from './core/provider/anchorage/anchorage-transfer.service' import { FireblocksCredentialService } from './core/provider/fireblocks/fireblocks-credential.service' +import { FireblocksProxyService } from './core/provider/fireblocks/fireblocks-proxy.service' import { AccountService } from './core/service/account.service' import { AddressService } from './core/service/address.service' import { ConnectionService } from './core/service/connection.service' @@ -25,6 +26,7 @@ import { TransferService } from './core/service/transfer.service' import { WalletService } from './core/service/wallet.service' import { ConnectionSyncEventHandler } from './event/handler/connection-sync.event-handler' import { AnchorageClient } from './http/client/anchorage.client' +import { FireblocksClient } from './http/client/fireblocks.client' import { ProviderAccountController } from './http/rest/controller/account.controller' import { ProviderAddressController } from './http/rest/controller/address.controller' import { ConnectionController } from './http/rest/controller/connection.controller' @@ -83,6 +85,8 @@ import { WalletRepository } from './persistence/repository/wallet.repository' EncryptionKeyRepository, EncryptionKeyService, FireblocksCredentialService, + FireblocksClient, + FireblocksProxyService, KnownDestinationRepository, KnownDestinationService, ProxyService, diff --git a/apps/vault/src/broker/core/provider/fireblocks/fireblocks-proxy.service.ts b/apps/vault/src/broker/core/provider/fireblocks/fireblocks-proxy.service.ts new file mode 100644 index 000000000..9f9dbc5ae --- /dev/null +++ b/apps/vault/src/broker/core/provider/fireblocks/fireblocks-proxy.service.ts @@ -0,0 +1,37 @@ +import { Injectable } from '@nestjs/common' +import { v4 } from 'uuid' +import { FireblocksClient } from '../../../http/client/fireblocks.client' +import { ConnectionWithCredentials } from '../../type/connection.type' +import { ProviderProxyService, ProxyRequestOptions, ProxyResponse } from '../../type/provider.type' +import { validateConnection } from './fireblocks.util' + +@Injectable() +export class FireblocksProxyService implements ProviderProxyService { + constructor(private readonly fireblocksClient: FireblocksClient) {} + + async forward( + connection: ConnectionWithCredentials, + { data, endpoint, method, nonce }: ProxyRequestOptions + ): Promise { + validateConnection(connection) + + const { url, credentials } = connection + const { apiKey, privateKey } = credentials + const fullUrl = `${url}${endpoint}` + + const response = await this.fireblocksClient.forward({ + url: fullUrl, + method, + data, + apiKey, + nonce: nonce || v4(), + signKey: privateKey + }) + + return { + data: response.data, + code: response.status, + headers: response.headers + } + } +} diff --git a/apps/vault/src/broker/core/provider/fireblocks/fireblocks.util.ts b/apps/vault/src/broker/core/provider/fireblocks/fireblocks.util.ts new file mode 100644 index 000000000..160494940 --- /dev/null +++ b/apps/vault/src/broker/core/provider/fireblocks/fireblocks.util.ts @@ -0,0 +1,53 @@ +import { RsaPrivateKey } from '@narval/signature' +import { ConnectionInvalidException } from '../../exception/connection-invalid.exception' +import { ConnectionWithCredentials } from '../../type/connection.type' +import { Provider } from '../../type/provider.type' +import { FireblocksCredentials } from './fireblocks.type' + +export function validateConnection( + connection: ConnectionWithCredentials +): asserts connection is ConnectionWithCredentials & { + url: string + credentials: { + apiKey: string + privateKey: RsaPrivateKey + } +} { + const context = { + clientId: connection.clientId, + connectionId: connection.connectionId, + provider: connection.provider, + status: connection.status, + url: connection.url + } + + if (connection.provider !== Provider.FIREBLOCKS) { + throw new ConnectionInvalidException({ + message: 'Invalid connection provider for Fireblocks', + context + }) + } + + if (!connection.url) { + throw new ConnectionInvalidException({ + message: 'Fireblocks connection missing URL', + context + }) + } + + if (!connection.credentials) { + throw new ConnectionInvalidException({ + message: 'Fireblocks connection missing credentials', + context + }) + } + + const credentials = FireblocksCredentials.parse(connection.credentials) + + if (!credentials.apiKey) { + throw new ConnectionInvalidException({ + message: 'Fireblocks connection missing API key', + context + }) + } +} diff --git a/apps/vault/src/broker/core/service/proxy.service.ts b/apps/vault/src/broker/core/service/proxy.service.ts index c3a3ffea8..1a82e65c3 100644 --- a/apps/vault/src/broker/core/service/proxy.service.ts +++ b/apps/vault/src/broker/core/service/proxy.service.ts @@ -1,6 +1,7 @@ import { Injectable, NotImplementedException } from '@nestjs/common' import { ConnectionInvalidException } from '../exception/connection-invalid.exception' import { AnchorageProxyService } from '../provider/anchorage/anchorage-proxy.service' +import { FireblocksProxyService } from '../provider/fireblocks/fireblocks-proxy.service' import { isActiveConnection } from '../type/connection.type' import { Provider, ProviderProxyService, ProxyResponse } from '../type/provider.type' import { ConnectionService } from './connection.service' @@ -16,7 +17,8 @@ type ProxyRequestOptions = { export class ProxyService { constructor( private readonly connectionRepository: ConnectionService, - private readonly anchorageProxyService: AnchorageProxyService + private readonly anchorageProxyService: AnchorageProxyService, + private readonly fireblocksProxyService: FireblocksProxyService ) {} async forward(clientId: string, options: ProxyRequestOptions): Promise { @@ -45,6 +47,8 @@ export class ProxyService { switch (provider) { case Provider.ANCHORAGE: return this.anchorageProxyService + case Provider.FIREBLOCKS: + return this.fireblocksProxyService default: throw new NotImplementedException(`Unsupported proxy for provider ${provider}`) } diff --git a/apps/vault/src/broker/core/type/provider.type.ts b/apps/vault/src/broker/core/type/provider.type.ts index abd57713a..7dc67e8f8 100644 --- a/apps/vault/src/broker/core/type/provider.type.ts +++ b/apps/vault/src/broker/core/type/provider.type.ts @@ -234,6 +234,7 @@ export interface ProviderTransferService { export type ProxyRequestOptions = { connectionId: string data?: any + nonce?: string endpoint: string method: string } diff --git a/apps/vault/src/broker/http/client/__test__/unit/fireblocks.client.spec.ts b/apps/vault/src/broker/http/client/__test__/unit/fireblocks.client.spec.ts new file mode 100644 index 000000000..4231c5f96 --- /dev/null +++ b/apps/vault/src/broker/http/client/__test__/unit/fireblocks.client.spec.ts @@ -0,0 +1,194 @@ +import { RsaPrivateKey } from '@narval/signature' +import axios from 'axios' +import { mockReset } from 'jest-mock-extended' +import { BrokerException } from '../../../../core/exception/broker.exception' +import { UrlParserException } from '../../../../core/exception/url-parser.exception' +import { FireblocksClient } from '../../fireblocks.client' + +jest.mock('axios') + +describe(FireblocksClient.name, () => { + let client: FireblocksClient + const mockedAxios = axios as jest.MockedFunction + + const mockSignKey: RsaPrivateKey = { + kty: 'RSA', + alg: 'RS256', + kid: '0x52920ad0d19d7779106bd9d9d600d26c4b976cdb3cbc49decb7fdc29db00b8e9', + n: 'xNdTjWL9hGa4bz4tLKbmFZ4yjQsQzW35-CMS0kno3403jEqg5y2Cs6sLVyPBX4N2hdK5ERPytpf1PrThHqB-eEO6LtEWpENBgFuNIf8DRHrv0tne7dLNxf7sx1aocGRrkgIk4Ws6Is4Ot3whm3-WihmDGnHoogE-EPwVkkSc2FYPXYlNq4htCZXC8_MUI3LuXry2Gn4tna5HsYSehYhfKDD-nfSajeWxdNUv_3wOeSCr9ICm9Udlo7hpIUHQgnX3Nz6kvfGYuweLGoj_ot-oEUCIdlbQqmrfStAclugbM5NI6tY__6wD0z_4ZBjToupXCBlXbYsde6_ZG9xPmYSykw', + e: 'AQAB', + d: 'QU4rIzpXX8jwob-gHzNUHJH6tX6ZWX6GM0P3p5rrztc8Oag8z9XyigdSYNu0-SpVdTqfOcJDgT7TF7XNBms66k2WBJhMCb1iiuJU5ZWEkQC0dmDgLEkHCgx0pAHlKjy2z580ezEm_YsdqNRfFgbze-fQ7kIiazU8UUhBI-DtpHv7baBgsfqEfQ5nCTiURUPmmpiIU74-ZIJWZjBXTOoJNH0EIsJK9IpZzxpeC9mTMTsWTcHKiR3acze1qf-9I97v461TTZ8e33N6YINyr9I4HZuvxlCJdV_lOM3fLvYM9gPvgkPozhVWL3VKR6xa9JpGGHrCRgH92INuviBB_SmF8Q', + p: '9BNku_-t4Df9Dg7M2yjiNgZgcTNKrDnNqexliIUAt67q0tGmSBubjxeI5unDJZ_giXWUR3q-02v7HT5GYx-ZVgKk2lWnbrrm_F7UZW-ueHzeVvQcjDXTk0z8taXzrDJgnIwZIaZ2XSG3P-VPOrXCaMba8GzSq38Gpzi4g3lTO9s', + q: 'znUtwrqdnVew14_aFjNTRgzOQNN8JhkjzJy3aTSLBScK5NbiuUUZBWs5dQ7Nv7aAoDss1-o9XVQZ1DVV-o9UufJtyrPNcvTnC0cWRrtJrSN5YiuUbECU3Uj3OvGxnhx9tsmhDHnMTo50ObPYUbHcIkNaXkf2FVgL84y1JRWdPak', + dp: 'UNDrFeS-6fMf8zurURXkcQcDf_f_za8GDjGcHOwNJMTiNBP-_vlFNMgSKINWfmrFqj4obtKRxOeIKlKoc8HOv8_4TeL2oY95VC8CHOQx3Otbo2cI3NQlziw7sNnWKTo1CyDIYYAAyS2Uw69l4Ia2bIMLk3g0-VwCE_SQA9h0Wuk', + dq: 'VBe6ieSFKn97UnIPfJdvRcsVf6YknUgEIuV6d2mlbnXWpBs6wgf5BxIDl0BuYbYuchVoUJHiaM9Grf8DhEk5U3wBaF0QQ9CpAxjzY-AJRHJ8kJX7oJQ1jmSX_vRPSn2EXx2FcZVyuFSh1pcAd1YgufwBJQHepBb21z7q0a4aG_E', + qi: 'KhZpFs6xfyRIjbJV8Q9gWxqF37ONayIzBpgio5mdAQlZ-FUmaWZ2_2VWP2xvsP48BmwFXydHqewHBqGnZYCQ1ZHXJgD_-KKEejoqS5AJN1pdI0ZKjs7UCfZ4RJ4DH5p0_35gpuKRzzdvcIhl1CjIC5W8o7nhwmLBJ_QAo9e4t9U' + } + + beforeEach(() => { + client = new FireblocksClient() + mockReset(mockedAxios) + }) + + describe('parseEndpoint', () => { + it('extracts version path from valid URLs', () => { + const testCases = [ + { + input: 'https://api.anchorage.com/v2/accounts', + expected: '/v2/accounts' + }, + { + input: 'https://api.anchorage.com/v1/trading/quotes', + expected: '/v1/trading/quotes' + }, + { + input: 'https://api.anchorage.com/v3/something/nested/path', + expected: '/v3/something/nested/path' + }, + { + input: 'https://api.anchorage.com/v4/something/nested/path?query=param&another=param&yetAnother=param', + expected: '/v4/something/nested/path?query=param&another=param&yetAnother=param' + } + ] + + for (const { input, expected } of testCases) { + expect(client.parseEndpoint(input)).toBe(expected) + } + }) + + it('throws UrlParserException for invalid URLs', () => { + const invalidUrls = [ + 'https://api.anchorage.com/accounts', + 'https://api.anchorage.com/invalidv1/', + 'not-even-an-url' + ] + + for (const url of invalidUrls) { + expect(() => client.parseEndpoint(url)).toThrow(UrlParserException) + } + }) + }) + + describe('validateRequest', () => { + it('throws BrokerException when URL is missing', async () => { + const request: any = { method: 'GET' } + + await expect( + client.authorize({ + request, + apiKey: 'test-api-key', + signKey: mockSignKey + }) + ).rejects.toThrow(BrokerException) + }) + + it('throws BrokerException when method is missing', async () => { + const request: any = { url: 'https://api.fireblocks.com/v1/test' } + + await expect( + client.authorize({ + request, + apiKey: 'test-api-key', + signKey: mockSignKey + }) + ).rejects.toThrow(BrokerException) + }) + }) + + describe('authorize', () => { + const mockDate = new Date('2024-01-01T00:00:00Z') + + it('creates valid authorization headers for GET request', async () => { + const request = { + url: 'https://api.fireblocks.com/v1/test', + method: 'GET' + } + + const result = await client.authorize({ + request, + apiKey: 'test-api-key', + signKey: mockSignKey, + now: mockDate + }) + + // Check header structure + expect(result.headers).toHaveProperty('X-API-Key', 'test-api-key') + expect(result.headers).toHaveProperty('Authorization') + + // Verify the Bearer token format + const authHeader = result.headers?.Authorization + expect(authHeader).toMatch(/^Bearer [A-Za-z0-9-_=]+\.[A-Za-z0-9-_=]+\.[A-Za-z0-9-_.+/=]+$/) + }) + + it('creates valid authorization headers for POST request with data', async () => { + const requestData = { test: 'data' } + const request = { + url: 'https://api.fireblocks.com/v1/test', + method: 'POST', + data: requestData + } + + const result = await client.authorize({ + request, + apiKey: 'test-api-key', + signKey: mockSignKey, + now: mockDate + }) + + // Verify the basic structure stays the same for POST + expect(result.headers).toHaveProperty('X-API-Key', 'test-api-key') + expect(result.headers?.Authorization).toMatch(/^Bearer [A-Za-z0-9-_=]+\.[A-Za-z0-9-_=]+\.[A-Za-z0-9-_.+/=]+$/) + + // Verify the data is properly set in the request + expect(result.data).toEqual(requestData) + }) + }) + + describe('forward', () => { + it('forwards authorized request to Fireblocks API', async () => { + const mockResponse = { data: 'test-response', status: 200 } + mockedAxios.mockResolvedValue(mockResponse) + + const result = await client.forward({ + url: 'https://api.fireblocks.com/v1/test', + method: 'GET', + apiKey: 'test-api-key', + signKey: mockSignKey, + nonce: 'test-nonce' + }) + + expect(result).toBe(mockResponse) + expect(mockedAxios).toHaveBeenCalledWith( + expect.objectContaining({ + url: 'https://api.fireblocks.com/v1/test', + method: 'GET', + responseType: 'stream', + validateStatus: null + }) + ) + }) + + it('forwards POST request with data', async () => { + const mockResponse = { data: 'test-response', status: 200 } + mockedAxios.mockResolvedValue(mockResponse) + + const requestData = { test: 'data' } + + await client.forward({ + url: 'https://api.fireblocks.com/v1/test', + method: 'POST', + data: requestData, + apiKey: 'test-api-key', + signKey: mockSignKey, + nonce: 'test-nonce' + }) + + expect(mockedAxios).toHaveBeenCalledWith( + expect.objectContaining({ + data: requestData, + method: 'POST' + }) + ) + }) + }) +}) diff --git a/apps/vault/src/broker/http/client/fireblocks.client.ts b/apps/vault/src/broker/http/client/fireblocks.client.ts new file mode 100644 index 000000000..e1be7fd5c --- /dev/null +++ b/apps/vault/src/broker/http/client/fireblocks.client.ts @@ -0,0 +1,194 @@ +import { RsaPrivateKey, hash, signJwt } from '@narval/signature' +import { HttpStatus, Injectable } from '@nestjs/common' +import axios, { AxiosRequestConfig, AxiosResponse } from 'axios' +import { isNil, omitBy } from 'lodash' +import { v4 } from 'uuid' +import { z } from 'zod' +import { BrokerException } from '../../core/exception/broker.exception' +import { UrlParserException } from '../../core/exception/url-parser.exception' + +interface ForwardRequestOptions { + url: string + method: string + data?: unknown + apiKey: string + signKey: RsaPrivateKey + nonce: string +} + +const RewardsInfo = z.object({ + pendingRewards: z.coerce.number().positive() +}) +type RewardsInfo = z.infer + +// Fireblocks API is not consistent in the response format for Asset and AssetWallet, but they seem to be the same underlying data +const Asset = z.object({ + // !![This is NOT discretionary.](https://developers.fireblocks.com/docs/list-supported-assets-1) + id: z.string(), + total: z.string(), + available: z.string(), + pending: z.string(), + frozen: z.string(), + lockedAmount: z.string(), + blockHeight: z.string().optional(), + blockHash: z.string().optional(), + rewardsInfo: RewardsInfo.optional(), + hiddenOnUI: z.boolean(), + customerRefId: z.string().optional(), + autoFuel: z.boolean().optional() +}) +type Asset = z.infer + +const VaultAccount = z.object({ + id: z.string(), + name: z.string().optional(), + assets: z.array(Asset), + hiddenOnUI: z.boolean(), + customerRefId: z.string(), + autoFuel: z.boolean() +}) +type VaultAccount = z.infer + +const Paging = z.object({ + before: z.string(), + after: z.string() +}) +type Paging = z.infer + +const GetVaultAccountsResponse = z.object({ + accounts: z.array(VaultAccount), + paging: Paging +}) +type GetVaultAccountsResponse = z.infer + +// Fireblocks API is not consistent in the response format for Asset and AssetWallet, but they seem to be the same underlying data +const AssetWallet = z.object({ + // id of the vaultAccount + vaultId: z.string(), + // !![This is NOT discretionary.](https://developers.fireblocks.com/docs/list-supported-assets-1) + assetId: z.string(), + available: z.string(), + //The total wallet balance. + // Total = available + pending + lockedAmount + frozen + // In EOS this value includes the network balance, self staking and pending refund. + // For all other coins it is the balance as it appears on the blockchain. + total: z.string(), + pending: z.string(), + staked: z.string(), + frozen: z.string(), + lockedAmount: z.string(), + blockHeight: z.string().nullable(), + blockHash: z.string().nullable(), + creationTimestamp: z.string() +}) +type AssetWallet = z.infer + +const GetVaultWalletsResponse = z.object({ + assetWallets: z.array(AssetWallet), + paging: Paging +}) +type GetVaultWalletsResponse = z.infer + +@Injectable() +export class FireblocksClient { + async forward({ url, method, data, apiKey, signKey, nonce }: ForwardRequestOptions): Promise { + const signedRequest = await this.authorize({ + request: { + url, + method, + data, + responseType: 'stream', + // Don't reject on error status codes. Needed to re-throw our exception + validateStatus: null + }, + apiKey, + signKey, + nonce + }) + + const response = await axios(signedRequest) + + return response + } + + async authorize(opts: { + request: AxiosRequestConfig + apiKey: string + signKey: RsaPrivateKey + nonce?: string + now?: Date + }): Promise { + const { request, signKey, apiKey } = opts + + this.validateRequest(request) + + const endpoint = this.parseEndpoint(request.url) + + // Subtract 10 seconds to avoid clock skew + const now = Math.floor((opts.now ? opts.now.getTime() : Date.now()) / 1000) - 10 + + const queryParams = new URLSearchParams(omitBy(request.params, isNil)).toString() + const uri = queryParams ? `${endpoint}?${queryParams}` : endpoint + + const exp = now + 30 + + const bodyHash = request.data ? hash(request.data) : '' + + const payload = { + uri, + nonce: opts.nonce || v4(), + iat: now, + sub: apiKey, + exp, + bodyHash + } + + const token = await signJwt(payload, signKey) + + const headers = { + 'X-API-Key': apiKey, + Authorization: `Bearer ${token}` + } + + const data = request.data && request.method !== 'GET' ? request.data : undefined + + return { + ...request, + headers, + data + } + } + + parseEndpoint(url: string): string { + const regex = /(\/v\d+(?:\/.*)?)$/ + const match = url.match(regex) + + if (!match) { + throw new UrlParserException({ + message: 'No version pattern found in the URL', + url + }) + } + + return match[1] + } + + private validateRequest(request: AxiosRequestConfig): asserts request is AxiosRequestConfig & { + url: string + method: string + } { + if (!request.url) { + throw new BrokerException({ + message: 'Cannot sign a request without an URL', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY + }) + } + + if (!request.method) { + throw new BrokerException({ + message: 'Cannot sign a request without a method', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY + }) + } + } +} diff --git a/examples/unified-api/generate-key.ts b/examples/unified-api/generate-key.ts deleted file mode 100644 index aab055d8d..000000000 --- a/examples/unified-api/generate-key.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Alg, generateJwk } from '@narval-xyz/armory-sdk' -import { privateKeyToHex, publicKeyToHex } from '@narval-xyz/armory-sdk/signature' - -const main = async () => { - const key = await generateJwk(Alg.EDDSA) - const privateKeyHex = await privateKeyToHex(key) - const publicKeyHex = await publicKeyToHex(key) - - console.log({ - key, - privateKeyHex, - publicKeyHex - }) -} - -main() - .then(() => console.log('done')) - .catch(console.error) diff --git a/packages/armory-sdk/src/lib/vault/client.ts b/packages/armory-sdk/src/lib/vault/client.ts index 4d1e9b5e9..8385cc7e9 100644 --- a/packages/armory-sdk/src/lib/vault/client.ts +++ b/packages/armory-sdk/src/lib/vault/client.ts @@ -1,6 +1,6 @@ import { AccessToken, Request, SerializedSignableRequest } from '@narval/policy-engine-shared' import { RsaPublicKey, rsaEncrypt } from '@narval/signature' -import axios from 'axios' +import axios, { AxiosResponse } from 'axios' import { AccountApiFactory, AccountDto, @@ -710,15 +710,16 @@ export class VaultClient { }: { data: ProviderProxyApiDeleteRequest accessToken?: AccessToken - }): Promise { + }): Promise { const token = accessToken ? prefixGnapToken(accessToken) : undefined - await this.providerProxyHttp._delete({ + const ret = await this.providerProxyHttp._delete({ xClientId: this.config.clientId, authorization: token, endpoint: data.endpoint, xConnectionId: data.xConnectionId }) + return ret } async proxyOptions({ @@ -727,15 +728,16 @@ export class VaultClient { }: { data: ProviderProxyApiOptionsRequest accessToken?: AccessToken - }): Promise { + }): Promise { const token = accessToken ? prefixGnapToken(accessToken) : undefined - await this.providerProxyHttp._options({ + const ret = await this.providerProxyHttp._options({ xClientId: this.config.clientId, authorization: token, endpoint: data.endpoint, xConnectionId: data.xConnectionId }) + return ret } async proxyGet({ @@ -744,15 +746,16 @@ export class VaultClient { }: { data: ProviderProxyApiGetRequest accessToken?: AccessToken - }): Promise { + }): Promise { const token = accessToken ? prefixGnapToken(accessToken) : undefined - await this.providerProxyHttp.get({ + const ret = await this.providerProxyHttp.get({ xClientId: this.config.clientId, authorization: token, endpoint: data.endpoint, xConnectionId: data.xConnectionId }) + return ret } async proxyPost({ @@ -761,15 +764,16 @@ export class VaultClient { }: { data: ProviderProxyApiPostRequest accessToken?: AccessToken - }): Promise { + }): Promise { const token = accessToken ? prefixGnapToken(accessToken) : undefined - await this.providerProxyHttp.post({ + const ret = await this.providerProxyHttp.post({ xClientId: this.config.clientId, authorization: token, endpoint: data.endpoint, xConnectionId: data.xConnectionId }) + return ret } async proxyPut({ @@ -778,15 +782,16 @@ export class VaultClient { }: { data: ProviderProxyApiPutRequest accessToken?: AccessToken - }): Promise { + }): Promise { const token = accessToken ? prefixGnapToken(accessToken) : undefined - await this.providerProxyHttp.put({ + const ret = await this.providerProxyHttp.put({ xClientId: this.config.clientId, authorization: token, endpoint: data.endpoint, xConnectionId: data.xConnectionId }) + return ret } async proxyPatch({ @@ -795,15 +800,16 @@ export class VaultClient { }: { data: ProviderProxyApiPatchRequest accessToken?: AccessToken - }): Promise { + }): Promise { const token = accessToken ? prefixGnapToken(accessToken) : undefined - await this.providerProxyHttp.patch({ + const ret = await this.providerProxyHttp.patch({ xClientId: this.config.clientId, authorization: token, endpoint: data.endpoint, xConnectionId: data.xConnectionId }) + return ret } async proxyHead({ @@ -812,14 +818,15 @@ export class VaultClient { }: { data: ProviderProxyApiHeadRequest accessToken?: AccessToken - }): Promise { + }): Promise { const token = accessToken ? prefixGnapToken(accessToken) : undefined - await this.providerProxyHttp.head({ + const ret = await this.providerProxyHttp.head({ xClientId: this.config.clientId, authorization: token, endpoint: data.endpoint, xConnectionId: data.xConnectionId }) + return ret } } From 4cba5bacd5302e8b69744d5f06923fd1d4dd5a7d Mon Sep 17 00:00:00 2001 From: Ptroger <44851272+Ptroger@users.noreply.github.com> Date: Tue, 7 Jan 2025 10:20:48 +0100 Subject: [PATCH 074/120] SendTransfer requires a connectionId (#71) * removed customerRefId and added connectionId header * added test * make transfer clearer * always send an idempotentId to anchorage * added test over idempotentId generation and send * fixed tests assumption on idempotentId * make indempotenceId mandatory * bumped sdk * add required field in transfer spec --- .../src/broker/__test__/e2e/transfer.spec.ts | 37 +- .../anchorage-transfer.service.spec.ts | 11 +- .../anchorage/anchorage-transfer.service.ts | 7 +- .../broker/core/service/transfer.service.ts | 13 +- .../src/broker/core/type/transfer.type.ts | 2 +- .../rest/controller/transfer.controller.ts | 16 +- .../decorator/connection-id.decorator.ts | 4 +- package-lock.json | 2 +- packages/armory-sdk/package.json | 2 +- .../src/lib/http/client/vault/api.ts | 640 +++++++++++------- packages/armory-sdk/src/lib/vault/client.ts | 3 + 11 files changed, 459 insertions(+), 278 deletions(-) diff --git a/apps/vault/src/broker/__test__/e2e/transfer.spec.ts b/apps/vault/src/broker/__test__/e2e/transfer.spec.ts index fb88bc93c..33185a89c 100644 --- a/apps/vault/src/broker/__test__/e2e/transfer.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/transfer.spec.ts @@ -11,6 +11,7 @@ import { v4 as uuid } from 'uuid' import { ClientService } from '../../../client/core/service/client.service' import { MainModule } from '../../../main.module' import { ProvisionService } from '../../../provision.service' +import { REQUEST_HEADER_CONNECTION_ID } from '../../../shared/decorator/connection-id.decorator' import { KeyValueRepository } from '../../../shared/module/key-value/core/repository/key-value.repository' import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' @@ -125,7 +126,7 @@ describe('Transfer', () => { }, externalId: uuid(), grossAmount: '0.00001', - idempotenceId: null, + idempotenceId: uuid(), memo: 'Test transfer', networkFeeAttribution: NetworkFeeAttribution.DEDUCT, provider: Provider.ANCHORAGE, @@ -202,13 +203,15 @@ describe('Transfer', () => { id: accountTwo.accountId }, amount: '0.0001', - assetId: 'BTC_S' + assetId: 'BTC_S', + idempotenceId: uuid() } it('sends transfer to anchorage', async () => { const { status, body } = await request(app.getHttpServer()) .post(ENDPOINT) .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set(REQUEST_HEADER_CONNECTION_ID, connection.connectionId) .set( 'detached-jws', await getJwsd({ @@ -229,7 +232,7 @@ describe('Transfer', () => { customerRefId: null, destination: requiredPayload.destination, grossAmount: requiredPayload.amount, - idempotenceId: null, + idempotenceId: expect.any(String), memo: null, networkFeeAttribution: NetworkFeeAttribution.ON_TOP, provider: accountOne.provider, @@ -255,6 +258,7 @@ describe('Transfer', () => { const { body } = await request(app.getHttpServer()) .post(ENDPOINT) .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set(REQUEST_HEADER_CONNECTION_ID, connection.connectionId) .set( 'detached-jws', await getJwsd({ @@ -274,8 +278,9 @@ describe('Transfer', () => { expect(actualTransfer.networkFeeAttribution).toEqual(payload.networkFeeAttribution) expect(body.data.networkFeeAttribution).toEqual(payload.networkFeeAttribution) - expect(actualTransfer.customerRefId).toEqual(payload.customerRefId) - expect(body.data.customerRefId).toEqual(payload.customerRefId) + // Invalid fields should not be sent to the provider + expect(actualTransfer.customerRefId).toEqual(null) + expect(body.data.customerRefId).toEqual(null) expect(actualTransfer.idempotenceId).toEqual(payload.idempotenceId) expect(body.data.idempotenceId).toEqual(payload.idempotenceId) @@ -294,6 +299,7 @@ describe('Transfer', () => { const { status, body } = await request(app.getHttpServer()) .post(ENDPOINT) .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set(REQUEST_HEADER_CONNECTION_ID, connection.connectionId) .set( 'detached-jws', await getJwsd({ @@ -319,6 +325,27 @@ describe('Transfer', () => { expect(status).toEqual(HttpStatus.BAD_REQUEST) }) + + it('fails if connection header is missing', async () => { + const { body } = await request(app.getHttpServer()) + .post(ENDPOINT) + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + payload: requiredPayload, + userPrivateJwk: testUserPrivateJwk, + requestUrl: ENDPOINT, + htm: 'POST' + }) + ) + .send(requiredPayload) + + expect(body).toMatchObject({ + statusCode: HttpStatus.BAD_REQUEST, + message: 'Missing or invalid x-connection-id header' + }) + }) }) describe(`GET ${ENDPOINT}/:transferId`, () => { diff --git a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts index 1c831b41b..7b925c19a 100644 --- a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts +++ b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts @@ -274,7 +274,8 @@ describe(AnchorageTransferService.name, () => { id: accountTwo.accountId }, amount: '0.00005', - assetId: 'BTC' + assetId: 'BTC', + idempotenceId: uuid() } const transferAmlQuestionnaire = { @@ -305,7 +306,6 @@ describe(AnchorageTransferService.name, () => { ...requiredSendTransfer, memo: 'Integration test transfer', networkFeeAttribution: NetworkFeeAttribution.DEDUCT, - customerRefId: uuid(), idempotenceId: uuid() } @@ -314,7 +314,8 @@ describe(AnchorageTransferService.name, () => { expect(actualInternalTransfer.idempotenceId).toEqual(sendTransfer.idempotenceId) expect(actualInternalTransfer.memo).toEqual(sendTransfer.memo) - expect(actualInternalTransfer.customerRefId).toEqual(sendTransfer.customerRefId) + // Anchorage does not support customerRefId. + expect(actualInternalTransfer.customerRefId).toEqual(null) expect(actualInternalTransfer.networkFeeAttribution).toEqual(sendTransfer.networkFeeAttribution) }) @@ -329,7 +330,6 @@ describe(AnchorageTransferService.name, () => { const sendTransfer = { ...requiredSendTransfer, memo: 'Integration test transfer', - customerRefId: uuid(), idempotenceId: uuid() } @@ -348,7 +348,8 @@ describe(AnchorageTransferService.name, () => { }, assetType: sendTransfer.assetId, amount: sendTransfer.amount, - customerRefId: sendTransfer.customerRefId, + // !!CustomerRefId is not a field in Anchorage's API. + // customerRefId: sendTransfer.customerRefId, transferMemo: sendTransfer.memo, idempotentId: sendTransfer.idempotenceId, // Default `deductFeeFromAmountIfSameType` to false. diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts index 65ab6373e..21d6d0b89 100644 --- a/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts @@ -132,9 +132,8 @@ export class AnchorageTransferService implements ProviderTransferService { }, assetType: sendTransfer.assetId, amount: sendTransfer.amount, - customerRefId: sendTransfer.customerRefId || null, transferMemo: sendTransfer.memo || null, - idempotentId: sendTransfer.idempotenceId || null, + idempotentId: sendTransfer.idempotenceId, deductFeeFromAmountIfSameType: this.getDeductFeeFromAmountIfSameType(networkFeeAttribution), ...(isProviderSpecific(sendTransfer.providerSpecific) ? { ...sendTransfer.providerSpecific } : {}) } @@ -150,11 +149,11 @@ export class AnchorageTransferService implements ProviderTransferService { assetId: sendTransfer.assetId, clientId: connection.clientId, createdAt: new Date(), - customerRefId: sendTransfer.customerRefId || null, + customerRefId: null, destination: sendTransfer.destination, externalId: anchorageTransfer.transferId, grossAmount: sendTransfer.amount, - idempotenceId: sendTransfer.idempotenceId || null, + idempotenceId: sendTransfer.idempotenceId, memo: sendTransfer.memo || null, networkFeeAttribution, provider: Provider.ANCHORAGE, diff --git a/apps/vault/src/broker/core/service/transfer.service.ts b/apps/vault/src/broker/core/service/transfer.service.ts index e5cf3f7f3..6ef2065e2 100644 --- a/apps/vault/src/broker/core/service/transfer.service.ts +++ b/apps/vault/src/broker/core/service/transfer.service.ts @@ -5,7 +5,7 @@ import { TransferRepository } from '../../persistence/repository/transfer.reposi import { OTEL_ATTR_CONNECTION_PROVIDER } from '../../shared/constant' import { BrokerException } from '../exception/broker.exception' import { AnchorageTransferService } from '../provider/anchorage/anchorage-transfer.service' -import { ConnectionStatus, isActiveConnection } from '../type/connection.type' +import { isActiveConnection } from '../type/connection.type' import { Provider, ProviderTransferService } from '../type/provider.type' import { InternalTransfer, SendTransfer } from '../type/transfer.type' import { ConnectionService } from './connection.service' @@ -30,20 +30,15 @@ export class TransferService { return this.transferRepository.bulkCreate(transfers) } - async send(clientId: string, sendTransfer: SendTransfer): Promise { + async send(clientId: string, connectionId: string, sendTransfer: SendTransfer): Promise { this.logger.log('Send transfer', { clientId, sendTransfer }) const span = this.traceService.startSpan(`${TransferService.name}.sync`) const source = await this.transferPartyService.resolve(clientId, sendTransfer.source) - const { data: connections } = await this.connectionService.findAll(clientId, { - filters: { - status: ConnectionStatus.ACTIVE - } - }) + const connection = await this.connectionService.findById(clientId, connectionId) - if (connections.length && isActiveConnection(connections[0])) { - const [connection] = connections + if (isActiveConnection(connection)) { const credentials = await this.connectionService.findCredentials(connection) span.setAttribute(OTEL_ATTR_CONNECTION_PROVIDER, connection.provider) diff --git a/apps/vault/src/broker/core/type/transfer.type.ts b/apps/vault/src/broker/core/type/transfer.type.ts index 42f9d0c22..7ef7f5efb 100644 --- a/apps/vault/src/broker/core/type/transfer.type.ts +++ b/apps/vault/src/broker/core/type/transfer.type.ts @@ -40,7 +40,7 @@ export const SendTransfer = z.object({ // provider-specific transfer service. networkFeeAttribution: z.nativeEnum(NetworkFeeAttribution).optional(), customerRefId: z.string().optional(), - idempotenceId: z.string().optional(), + idempotenceId: z.string(), memo: z.string().optional(), provider: z.nativeEnum(Provider).optional(), // Requires `provider` to be set. diff --git a/apps/vault/src/broker/http/rest/controller/transfer.controller.ts b/apps/vault/src/broker/http/rest/controller/transfer.controller.ts index f97eef2c0..f3c328000 100644 --- a/apps/vault/src/broker/http/rest/controller/transfer.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/transfer.controller.ts @@ -1,7 +1,8 @@ import { ApiClientIdHeader } from '@narval/nestjs-shared' import { Body, Controller, Get, HttpStatus, Param, Post } from '@nestjs/common' -import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' +import { ApiHeader, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../shared/decorator/client-id.decorator' +import { ConnectionId } from '../../../../shared/decorator/connection-id.decorator' import { PermissionGuard } from '../../../../shared/decorator/permission-guard.decorator' import { VaultPermission } from '../../../../shared/type/domain.type' import { TransferService } from '../../../core/service/transfer.service' @@ -28,8 +29,17 @@ export class TransferController { description: 'The transfer was successfully sent.', type: TransferDto }) - async send(@ClientId() clientId: string, @Body() body: SendTransferDto): Promise { - const internalTransfer = await this.transferService.send(clientId, body) + @ApiHeader({ + name: 'x-connection-id', + required: true, + description: 'The connection ID used to forward request to provider' + }) + async send( + @ClientId() clientId: string, + @ConnectionId() connectionId: string, + @Body() body: SendTransferDto + ): Promise { + const internalTransfer = await this.transferService.send(clientId, connectionId, body) return TransferDto.create({ data: internalTransfer }) } diff --git a/apps/vault/src/shared/decorator/connection-id.decorator.ts b/apps/vault/src/shared/decorator/connection-id.decorator.ts index df7f8b3f4..65cae86dc 100644 --- a/apps/vault/src/shared/decorator/connection-id.decorator.ts +++ b/apps/vault/src/shared/decorator/connection-id.decorator.ts @@ -1,11 +1,11 @@ -import { createParamDecorator, ExecutionContext, UnprocessableEntityException } from '@nestjs/common' +import { BadRequestException, createParamDecorator, ExecutionContext } from '@nestjs/common' export const REQUEST_HEADER_CONNECTION_ID = 'x-connection-id' export const ConnectionId = createParamDecorator((_data: unknown, context: ExecutionContext): string => { const req = context.switchToHttp().getRequest() const connectionId = req.headers[REQUEST_HEADER_CONNECTION_ID] if (!connectionId || typeof connectionId !== 'string') { - throw new UnprocessableEntityException(`Missing or invalid ${REQUEST_HEADER_CONNECTION_ID} header`) + throw new BadRequestException(`Missing or invalid ${REQUEST_HEADER_CONNECTION_ID} header`) } return connectionId diff --git a/package-lock.json b/package-lock.json index 1bfb80e11..a4f8bfc41 100644 --- a/package-lock.json +++ b/package-lock.json @@ -46204,7 +46204,7 @@ }, "packages/armory-sdk": { "name": "@narval-xyz/armory-sdk", - "version": "0.15.0", + "version": "0.16.0", "license": "MPL-2.0", "dependencies": { "@noble/curves": "1.6.0", diff --git a/packages/armory-sdk/package.json b/packages/armory-sdk/package.json index f7f974458..e2c5e328d 100644 --- a/packages/armory-sdk/package.json +++ b/packages/armory-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@narval-xyz/armory-sdk", - "version": "0.15.0", + "version": "0.16.0", "license": "MPL-2.0", "publishConfig": { "access": "public" diff --git a/packages/armory-sdk/src/lib/http/client/vault/api.ts b/packages/armory-sdk/src/lib/http/client/vault/api.ts index 509d52c33..53865c47d 100644 --- a/packages/armory-sdk/src/lib/http/client/vault/api.ts +++ b/packages/armory-sdk/src/lib/http/client/vault/api.ts @@ -996,37 +996,19 @@ export interface CreateConnectionDto { 'url': string; /** * - * @type {CreateConnectionDtoCredentials} + * @type {any} * @memberof CreateConnectionDto */ - 'credentials'?: CreateConnectionDtoCredentials; + 'credentials'?: any; } export const CreateConnectionDtoProviderEnum = { - Anchorage: 'anchorage' + Anchorage: 'anchorage', + Fireblocks: 'fireblocks' } as const; export type CreateConnectionDtoProviderEnum = typeof CreateConnectionDtoProviderEnum[keyof typeof CreateConnectionDtoProviderEnum]; -/** - * - * @export - * @interface CreateConnectionDtoCredentials - */ -export interface CreateConnectionDtoCredentials { - /** - * - * @type {string} - * @memberof CreateConnectionDtoCredentials - */ - 'apiKey': string; - /** - * Ed25519 private key in hex format - * @type {any} - * @memberof CreateConnectionDtoCredentials - */ - 'privateKey'?: any; -} /** * * @export @@ -1279,7 +1261,8 @@ export interface InitiateConnectionDto { } export const InitiateConnectionDtoProviderEnum = { - Anchorage: 'anchorage' + Anchorage: 'anchorage', + Fireblocks: 'fireblocks' } as const; export type InitiateConnectionDtoProviderEnum = typeof InitiateConnectionDtoProviderEnum[keyof typeof InitiateConnectionDtoProviderEnum]; @@ -1305,165 +1288,16 @@ export interface KnownDestinationDto { export interface PaginatedAccountsDto { /** * - * @type {Array} + * @type {Array} * @memberof PaginatedAccountsDto */ - 'data': Array; + 'data': Array; /** * - * @type {PaginatedAccountsDtoPage} + * @type {PaginatedConnectionsDtoPage} * @memberof PaginatedAccountsDto */ - 'page'?: PaginatedAccountsDtoPage; -} -/** - * - * @export - * @interface PaginatedAccountsDtoDataInner - */ -export interface PaginatedAccountsDtoDataInner { - /** - * - * @type {string} - * @memberof PaginatedAccountsDtoDataInner - */ - 'accountId': string; - /** - * - * @type {Array} - * @memberof PaginatedAccountsDtoDataInner - */ - 'addresses'?: Array; - /** - * - * @type {string} - * @memberof PaginatedAccountsDtoDataInner - */ - 'clientId': string; - /** - * - * @type {any} - * @memberof PaginatedAccountsDtoDataInner - */ - 'createdAt': any; - /** - * - * @type {string} - * @memberof PaginatedAccountsDtoDataInner - */ - 'externalId': string; - /** - * - * @type {string} - * @memberof PaginatedAccountsDtoDataInner - */ - 'label'?: string | null; - /** - * - * @type {string} - * @memberof PaginatedAccountsDtoDataInner - */ - 'networkId': string; - /** - * - * @type {string} - * @memberof PaginatedAccountsDtoDataInner - */ - 'provider': PaginatedAccountsDtoDataInnerProviderEnum; - /** - * - * @type {any} - * @memberof PaginatedAccountsDtoDataInner - */ - 'updatedAt': any; - /** - * - * @type {string} - * @memberof PaginatedAccountsDtoDataInner - */ - 'walletId': string; -} - -export const PaginatedAccountsDtoDataInnerProviderEnum = { - Anchorage: 'anchorage' -} as const; - -export type PaginatedAccountsDtoDataInnerProviderEnum = typeof PaginatedAccountsDtoDataInnerProviderEnum[keyof typeof PaginatedAccountsDtoDataInnerProviderEnum]; - -/** - * - * @export - * @interface PaginatedAccountsDtoDataInnerAddressesInner - */ -export interface PaginatedAccountsDtoDataInnerAddressesInner { - /** - * - * @type {string} - * @memberof PaginatedAccountsDtoDataInnerAddressesInner - */ - 'accountId': string; - /** - * - * @type {string} - * @memberof PaginatedAccountsDtoDataInnerAddressesInner - */ - 'address': string; - /** - * - * @type {string} - * @memberof PaginatedAccountsDtoDataInnerAddressesInner - */ - 'addressId': string; - /** - * - * @type {string} - * @memberof PaginatedAccountsDtoDataInnerAddressesInner - */ - 'clientId': string; - /** - * - * @type {any} - * @memberof PaginatedAccountsDtoDataInnerAddressesInner - */ - 'createdAt': any; - /** - * - * @type {string} - * @memberof PaginatedAccountsDtoDataInnerAddressesInner - */ - 'externalId': string; - /** - * - * @type {string} - * @memberof PaginatedAccountsDtoDataInnerAddressesInner - */ - 'provider': PaginatedAccountsDtoDataInnerAddressesInnerProviderEnum; - /** - * - * @type {any} - * @memberof PaginatedAccountsDtoDataInnerAddressesInner - */ - 'updatedAt': any; -} - -export const PaginatedAccountsDtoDataInnerAddressesInnerProviderEnum = { - Anchorage: 'anchorage' -} as const; - -export type PaginatedAccountsDtoDataInnerAddressesInnerProviderEnum = typeof PaginatedAccountsDtoDataInnerAddressesInnerProviderEnum[keyof typeof PaginatedAccountsDtoDataInnerAddressesInnerProviderEnum]; - -/** - * - * @export - * @interface PaginatedAccountsDtoPage - */ -export interface PaginatedAccountsDtoPage { - /** - * - * @type {string} - * @memberof PaginatedAccountsDtoPage - */ - 'next': string | null; + 'page'?: PaginatedConnectionsDtoPage; } /** * @@ -1473,16 +1307,16 @@ export interface PaginatedAccountsDtoPage { export interface PaginatedAddressesDto { /** * - * @type {Array} + * @type {Array} * @memberof PaginatedAddressesDto */ - 'data': Array; + 'data': Array; /** * - * @type {PaginatedAccountsDtoPage} + * @type {PaginatedConnectionsDtoPage} * @memberof PaginatedAddressesDto */ - 'page'?: PaginatedAccountsDtoPage; + 'page'?: PaginatedConnectionsDtoPage; } /** * @@ -1498,10 +1332,23 @@ export interface PaginatedConnectionsDto { 'data': Array; /** * - * @type {PaginatedAccountsDtoPage} + * @type {PaginatedConnectionsDtoPage} * @memberof PaginatedConnectionsDto */ - 'page'?: PaginatedAccountsDtoPage; + 'page'?: PaginatedConnectionsDtoPage; +} +/** + * + * @export + * @interface PaginatedConnectionsDtoPage + */ +export interface PaginatedConnectionsDtoPage { + /** + * + * @type {string} + * @memberof PaginatedConnectionsDtoPage + */ + 'next': string | null; } /** * @@ -1517,10 +1364,10 @@ export interface PaginatedKnownDestinationsDto { 'data': Array; /** * - * @type {PaginatedAccountsDtoPage} + * @type {PaginatedConnectionsDtoPage} * @memberof PaginatedKnownDestinationsDto */ - 'page'?: PaginatedAccountsDtoPage; + 'page'?: PaginatedConnectionsDtoPage; } /** * @@ -1603,7 +1450,8 @@ export interface PaginatedKnownDestinationsDtoDataInner { } export const PaginatedKnownDestinationsDtoDataInnerProviderEnum = { - Anchorage: 'anchorage' + Anchorage: 'anchorage', + Fireblocks: 'fireblocks' } as const; export type PaginatedKnownDestinationsDtoDataInnerProviderEnum = typeof PaginatedKnownDestinationsDtoDataInnerProviderEnum[keyof typeof PaginatedKnownDestinationsDtoDataInnerProviderEnum]; @@ -1622,10 +1470,10 @@ export interface PaginatedSyncsDto { 'data': Array; /** * - * @type {PaginatedAccountsDtoPage} + * @type {PaginatedConnectionsDtoPage} * @memberof PaginatedSyncsDto */ - 'page'?: PaginatedAccountsDtoPage; + 'page'?: PaginatedConnectionsDtoPage; } /** * @@ -1641,10 +1489,10 @@ export interface PaginatedWalletsDto { 'data': Array; /** * - * @type {PaginatedAccountsDtoPage} + * @type {PaginatedConnectionsDtoPage} * @memberof PaginatedWalletsDto */ - 'page'?: PaginatedAccountsDtoPage; + 'page'?: PaginatedConnectionsDtoPage; } /** * @@ -1654,10 +1502,10 @@ export interface PaginatedWalletsDto { export interface PaginatedWalletsDtoDataInner { /** * - * @type {Array} + * @type {Array} * @memberof PaginatedWalletsDtoDataInner */ - 'accounts'?: Array; + 'accounts'?: Array; /** * * @type {string} @@ -1666,10 +1514,10 @@ export interface PaginatedWalletsDtoDataInner { 'clientId': string; /** * - * @type {Array} + * @type {Array} * @memberof PaginatedWalletsDtoDataInner */ - 'connections': Array; + 'connections': Array; /** * * @type {any} @@ -1709,7 +1557,8 @@ export interface PaginatedWalletsDtoDataInner { } export const PaginatedWalletsDtoDataInnerProviderEnum = { - Anchorage: 'anchorage' + Anchorage: 'anchorage', + Fireblocks: 'fireblocks' } as const; export type PaginatedWalletsDtoDataInnerProviderEnum = typeof PaginatedWalletsDtoDataInnerProviderEnum[keyof typeof PaginatedWalletsDtoDataInnerProviderEnum]; @@ -1717,47 +1566,140 @@ export type PaginatedWalletsDtoDataInnerProviderEnum = typeof PaginatedWalletsDt /** * * @export - * @interface PaginatedWalletsDtoDataInnerConnectionsInner + * @interface PaginatedWalletsDtoDataInnerAccountsInner */ -export interface PaginatedWalletsDtoDataInnerConnectionsInner { +export interface PaginatedWalletsDtoDataInnerAccountsInner { /** * * @type {string} - * @memberof PaginatedWalletsDtoDataInnerConnectionsInner + * @memberof PaginatedWalletsDtoDataInnerAccountsInner */ - 'connectionId': string; + 'accountId': string; + /** + * + * @type {Array} + * @memberof PaginatedWalletsDtoDataInnerAccountsInner + */ + 'addresses'?: Array; /** * * @type {string} - * @memberof PaginatedWalletsDtoDataInnerConnectionsInner + * @memberof PaginatedWalletsDtoDataInnerAccountsInner + */ + 'clientId': string; + /** + * + * @type {any} + * @memberof PaginatedWalletsDtoDataInnerAccountsInner */ - 'status'?: PaginatedWalletsDtoDataInnerConnectionsInnerStatusEnum; + 'createdAt': any; /** * * @type {string} - * @memberof PaginatedWalletsDtoDataInnerConnectionsInner + * @memberof PaginatedWalletsDtoDataInnerAccountsInner */ - 'label'?: string; + 'externalId': string; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoDataInnerAccountsInner + */ + 'label'?: string | null; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoDataInnerAccountsInner + */ + 'networkId': string; /** * * @type {string} - * @memberof PaginatedWalletsDtoDataInnerConnectionsInner + * @memberof PaginatedWalletsDtoDataInnerAccountsInner + */ + 'provider': PaginatedWalletsDtoDataInnerAccountsInnerProviderEnum; + /** + * + * @type {any} + * @memberof PaginatedWalletsDtoDataInnerAccountsInner */ - 'provider': PaginatedWalletsDtoDataInnerConnectionsInnerProviderEnum; + 'updatedAt': any; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoDataInnerAccountsInner + */ + 'walletId': string; } -export const PaginatedWalletsDtoDataInnerConnectionsInnerStatusEnum = { - Pending: 'pending', - Active: 'active', - Revoked: 'revoked' +export const PaginatedWalletsDtoDataInnerAccountsInnerProviderEnum = { + Anchorage: 'anchorage', + Fireblocks: 'fireblocks' } as const; -export type PaginatedWalletsDtoDataInnerConnectionsInnerStatusEnum = typeof PaginatedWalletsDtoDataInnerConnectionsInnerStatusEnum[keyof typeof PaginatedWalletsDtoDataInnerConnectionsInnerStatusEnum]; -export const PaginatedWalletsDtoDataInnerConnectionsInnerProviderEnum = { - Anchorage: 'anchorage' +export type PaginatedWalletsDtoDataInnerAccountsInnerProviderEnum = typeof PaginatedWalletsDtoDataInnerAccountsInnerProviderEnum[keyof typeof PaginatedWalletsDtoDataInnerAccountsInnerProviderEnum]; + +/** + * + * @export + * @interface PaginatedWalletsDtoDataInnerAccountsInnerAddressesInner + */ +export interface PaginatedWalletsDtoDataInnerAccountsInnerAddressesInner { + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoDataInnerAccountsInnerAddressesInner + */ + 'accountId': string; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoDataInnerAccountsInnerAddressesInner + */ + 'address': string; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoDataInnerAccountsInnerAddressesInner + */ + 'addressId': string; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoDataInnerAccountsInnerAddressesInner + */ + 'clientId': string; + /** + * + * @type {any} + * @memberof PaginatedWalletsDtoDataInnerAccountsInnerAddressesInner + */ + 'createdAt': any; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoDataInnerAccountsInnerAddressesInner + */ + 'externalId': string; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoDataInnerAccountsInnerAddressesInner + */ + 'provider': PaginatedWalletsDtoDataInnerAccountsInnerAddressesInnerProviderEnum; + /** + * + * @type {any} + * @memberof PaginatedWalletsDtoDataInnerAccountsInnerAddressesInner + */ + 'updatedAt': any; +} + +export const PaginatedWalletsDtoDataInnerAccountsInnerAddressesInnerProviderEnum = { + Anchorage: 'anchorage', + Fireblocks: 'fireblocks' } as const; -export type PaginatedWalletsDtoDataInnerConnectionsInnerProviderEnum = typeof PaginatedWalletsDtoDataInnerConnectionsInnerProviderEnum[keyof typeof PaginatedWalletsDtoDataInnerConnectionsInnerProviderEnum]; +export type PaginatedWalletsDtoDataInnerAccountsInnerAddressesInnerProviderEnum = typeof PaginatedWalletsDtoDataInnerAccountsInnerAddressesInnerProviderEnum[keyof typeof PaginatedWalletsDtoDataInnerAccountsInnerAddressesInnerProviderEnum]; /** * @@ -1780,10 +1722,10 @@ export interface PongDto { export interface ProviderAccountDto { /** * - * @type {PaginatedAccountsDtoDataInner} + * @type {PaginatedWalletsDtoDataInnerAccountsInner} * @memberof ProviderAccountDto */ - 'data': PaginatedAccountsDtoDataInner; + 'data': PaginatedWalletsDtoDataInnerAccountsInner; } /** * @@ -1798,80 +1740,239 @@ export interface ProviderConnectionDto { */ 'data': ProviderConnectionDtoData; } +/** + * @type ProviderConnectionDtoData + * @export + */ +export type ProviderConnectionDtoData = ProviderConnectionDtoDataOneOf | ProviderConnectionDtoDataOneOf1 | ProviderConnectionDtoDataOneOf2; + /** * * @export - * @interface ProviderConnectionDtoData + * @interface ProviderConnectionDtoDataOneOf */ -export interface ProviderConnectionDtoData { +export interface ProviderConnectionDtoDataOneOf { /** * * @type {string} - * @memberof ProviderConnectionDtoData + * @memberof ProviderConnectionDtoDataOneOf */ 'clientId': string; /** * * @type {string} - * @memberof ProviderConnectionDtoData + * @memberof ProviderConnectionDtoDataOneOf */ 'connectionId': string; /** * * @type {any} - * @memberof ProviderConnectionDtoData + * @memberof ProviderConnectionDtoDataOneOf */ 'createdAt': any; /** * * @type {string} - * @memberof ProviderConnectionDtoData + * @memberof ProviderConnectionDtoDataOneOf */ 'label'?: string; /** * * @type {string} - * @memberof ProviderConnectionDtoData + * @memberof ProviderConnectionDtoDataOneOf */ - 'provider': ProviderConnectionDtoDataProviderEnum; + 'provider': ProviderConnectionDtoDataOneOfProviderEnum; /** * * @type {any} - * @memberof ProviderConnectionDtoData + * @memberof ProviderConnectionDtoDataOneOf */ 'revokedAt'?: any; /** * * @type {string} - * @memberof ProviderConnectionDtoData + * @memberof ProviderConnectionDtoDataOneOf + */ + 'status': ProviderConnectionDtoDataOneOfStatusEnum; + /** + * + * @type {any} + * @memberof ProviderConnectionDtoDataOneOf + */ + 'updatedAt': any; + /** + * + * @type {string} + * @memberof ProviderConnectionDtoDataOneOf + */ + 'url': string; +} + +export const ProviderConnectionDtoDataOneOfProviderEnum = { + Anchorage: 'anchorage', + Fireblocks: 'fireblocks' +} as const; + +export type ProviderConnectionDtoDataOneOfProviderEnum = typeof ProviderConnectionDtoDataOneOfProviderEnum[keyof typeof ProviderConnectionDtoDataOneOfProviderEnum]; +export const ProviderConnectionDtoDataOneOfStatusEnum = { + Active: 'active' +} as const; + +export type ProviderConnectionDtoDataOneOfStatusEnum = typeof ProviderConnectionDtoDataOneOfStatusEnum[keyof typeof ProviderConnectionDtoDataOneOfStatusEnum]; + +/** + * + * @export + * @interface ProviderConnectionDtoDataOneOf1 + */ +export interface ProviderConnectionDtoDataOneOf1 { + /** + * + * @type {string} + * @memberof ProviderConnectionDtoDataOneOf1 + */ + 'clientId': string; + /** + * + * @type {string} + * @memberof ProviderConnectionDtoDataOneOf1 + */ + 'connectionId': string; + /** + * + * @type {any} + * @memberof ProviderConnectionDtoDataOneOf1 + */ + 'createdAt': any; + /** + * + * @type {string} + * @memberof ProviderConnectionDtoDataOneOf1 + */ + 'label'?: string; + /** + * + * @type {string} + * @memberof ProviderConnectionDtoDataOneOf1 + */ + 'provider': ProviderConnectionDtoDataOneOf1ProviderEnum; + /** + * + * @type {any} + * @memberof ProviderConnectionDtoDataOneOf1 + */ + 'revokedAt': any; + /** + * + * @type {string} + * @memberof ProviderConnectionDtoDataOneOf1 */ - 'status'?: ProviderConnectionDtoDataStatusEnum; + 'status': ProviderConnectionDtoDataOneOf1StatusEnum; /** * * @type {any} - * @memberof ProviderConnectionDtoData + * @memberof ProviderConnectionDtoDataOneOf1 */ 'updatedAt': any; /** * * @type {string} - * @memberof ProviderConnectionDtoData + * @memberof ProviderConnectionDtoDataOneOf1 */ 'url'?: string; } -export const ProviderConnectionDtoDataProviderEnum = { - Anchorage: 'anchorage' +export const ProviderConnectionDtoDataOneOf1ProviderEnum = { + Anchorage: 'anchorage', + Fireblocks: 'fireblocks' } as const; -export type ProviderConnectionDtoDataProviderEnum = typeof ProviderConnectionDtoDataProviderEnum[keyof typeof ProviderConnectionDtoDataProviderEnum]; -export const ProviderConnectionDtoDataStatusEnum = { - Pending: 'pending', - Active: 'active', +export type ProviderConnectionDtoDataOneOf1ProviderEnum = typeof ProviderConnectionDtoDataOneOf1ProviderEnum[keyof typeof ProviderConnectionDtoDataOneOf1ProviderEnum]; +export const ProviderConnectionDtoDataOneOf1StatusEnum = { Revoked: 'revoked' } as const; -export type ProviderConnectionDtoDataStatusEnum = typeof ProviderConnectionDtoDataStatusEnum[keyof typeof ProviderConnectionDtoDataStatusEnum]; +export type ProviderConnectionDtoDataOneOf1StatusEnum = typeof ProviderConnectionDtoDataOneOf1StatusEnum[keyof typeof ProviderConnectionDtoDataOneOf1StatusEnum]; + +/** + * + * @export + * @interface ProviderConnectionDtoDataOneOf2 + */ +export interface ProviderConnectionDtoDataOneOf2 { + /** + * + * @type {string} + * @memberof ProviderConnectionDtoDataOneOf2 + */ + 'clientId': string; + /** + * + * @type {string} + * @memberof ProviderConnectionDtoDataOneOf2 + */ + 'connectionId': string; + /** + * + * @type {any} + * @memberof ProviderConnectionDtoDataOneOf2 + */ + 'createdAt': any; + /** + * + * @type {string} + * @memberof ProviderConnectionDtoDataOneOf2 + */ + 'label'?: string; + /** + * + * @type {string} + * @memberof ProviderConnectionDtoDataOneOf2 + */ + 'provider': ProviderConnectionDtoDataOneOf2ProviderEnum; + /** + * + * @type {any} + * @memberof ProviderConnectionDtoDataOneOf2 + */ + 'revokedAt'?: any; + /** + * + * @type {string} + * @memberof ProviderConnectionDtoDataOneOf2 + */ + 'status': ProviderConnectionDtoDataOneOf2StatusEnum; + /** + * + * @type {any} + * @memberof ProviderConnectionDtoDataOneOf2 + */ + 'updatedAt': any; + /** + * + * @type {string} + * @memberof ProviderConnectionDtoDataOneOf2 + */ + 'url'?: string; + /** + * + * @type {CreateClientDtoBackupPublicKey} + * @memberof ProviderConnectionDtoDataOneOf2 + */ + 'encryptionPublicKey'?: CreateClientDtoBackupPublicKey; +} + +export const ProviderConnectionDtoDataOneOf2ProviderEnum = { + Anchorage: 'anchorage', + Fireblocks: 'fireblocks' +} as const; + +export type ProviderConnectionDtoDataOneOf2ProviderEnum = typeof ProviderConnectionDtoDataOneOf2ProviderEnum[keyof typeof ProviderConnectionDtoDataOneOf2ProviderEnum]; +export const ProviderConnectionDtoDataOneOf2StatusEnum = { + Pending: 'pending' +} as const; + +export type ProviderConnectionDtoDataOneOf2StatusEnum = typeof ProviderConnectionDtoDataOneOf2StatusEnum[keyof typeof ProviderConnectionDtoDataOneOf2StatusEnum]; /** * @@ -1937,7 +2038,8 @@ export interface ProviderPendingConnectionDtoData { } export const ProviderPendingConnectionDtoDataProviderEnum = { - Anchorage: 'anchorage' + Anchorage: 'anchorage', + Fireblocks: 'fireblocks' } as const; export type ProviderPendingConnectionDtoDataProviderEnum = typeof ProviderPendingConnectionDtoDataProviderEnum[keyof typeof ProviderPendingConnectionDtoDataProviderEnum]; @@ -2032,7 +2134,7 @@ export interface SendTransferDto { * @type {string} * @memberof SendTransferDto */ - 'idempotenceId'?: string; + 'idempotenceId': string; /** * * @type {string} @@ -2060,7 +2162,8 @@ export const SendTransferDtoNetworkFeeAttributionEnum = { export type SendTransferDtoNetworkFeeAttributionEnum = typeof SendTransferDtoNetworkFeeAttributionEnum[keyof typeof SendTransferDtoNetworkFeeAttributionEnum]; export const SendTransferDtoProviderEnum = { - Anchorage: 'anchorage' + Anchorage: 'anchorage', + Fireblocks: 'fireblocks' } as const; export type SendTransferDtoProviderEnum = typeof SendTransferDtoProviderEnum[keyof typeof SendTransferDtoProviderEnum]; @@ -2963,7 +3066,8 @@ export const TransferDtoDataNetworkFeeAttributionEnum = { export type TransferDtoDataNetworkFeeAttributionEnum = typeof TransferDtoDataNetworkFeeAttributionEnum[keyof typeof TransferDtoDataNetworkFeeAttributionEnum]; export const TransferDtoDataProviderEnum = { - Anchorage: 'anchorage' + Anchorage: 'anchorage', + Fireblocks: 'fireblocks' } as const; export type TransferDtoDataProviderEnum = typeof TransferDtoDataProviderEnum[keyof typeof TransferDtoDataProviderEnum]; @@ -2983,10 +3087,10 @@ export type TransferDtoDataStatusEnum = typeof TransferDtoDataStatusEnum[keyof t export interface UpdateConnectionDto { /** * - * @type {string} + * @type {any} * @memberof UpdateConnectionDto */ - 'label'?: string; + 'credentials'?: any | null; /** * RSA encrypted JSON string of the credentials * @type {string} @@ -2995,11 +3099,38 @@ export interface UpdateConnectionDto { 'encryptedCredentials'?: string; /** * - * @type {CreateConnectionDtoCredentials} + * @type {string} + * @memberof UpdateConnectionDto + */ + 'label'?: string; + /** + * + * @type {string} + * @memberof UpdateConnectionDto + */ + 'status'?: UpdateConnectionDtoStatusEnum; + /** + * + * @type {any} * @memberof UpdateConnectionDto */ - 'credentials'?: CreateConnectionDtoCredentials; + 'updatedAt'?: any; + /** + * + * @type {string} + * @memberof UpdateConnectionDto + */ + 'url'?: string; } + +export const UpdateConnectionDtoStatusEnum = { + Pending: 'pending', + Active: 'active', + Revoked: 'revoked' +} as const; + +export type UpdateConnectionDtoStatusEnum = typeof UpdateConnectionDtoStatusEnum[keyof typeof UpdateConnectionDtoStatusEnum]; + /** * * @export @@ -7592,14 +7723,17 @@ export const ProviderTransferApiAxiosParamCreator = function (configuration?: Co * This endpoint sends a transfer to the source\'s provider. * @summary Send a transfer * @param {string} xClientId + * @param {string} xConnectionId The connection ID used to forward request to provider * @param {SendTransferDto} sendTransferDto * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - send: async (xClientId: string, sendTransferDto: SendTransferDto, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + send: async (xClientId: string, xConnectionId: string, sendTransferDto: SendTransferDto, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'xClientId' is not null or undefined assertParamExists('send', 'xClientId', xClientId) + // verify required parameter 'xConnectionId' is not null or undefined + assertParamExists('send', 'xConnectionId', xConnectionId) // verify required parameter 'sendTransferDto' is not null or undefined assertParamExists('send', 'sendTransferDto', sendTransferDto) const localVarPath = `/v1/provider/transfers`; @@ -7623,6 +7757,10 @@ export const ProviderTransferApiAxiosParamCreator = function (configuration?: Co localVarHeaderParameter['x-client-id'] = String(xClientId); } + if (xConnectionId != null) { + localVarHeaderParameter['x-connection-id'] = String(xConnectionId); + } + if (authorization != null) { localVarHeaderParameter['Authorization'] = String(authorization); } @@ -7670,13 +7808,14 @@ export const ProviderTransferApiFp = function(configuration?: Configuration) { * This endpoint sends a transfer to the source\'s provider. * @summary Send a transfer * @param {string} xClientId + * @param {string} xConnectionId The connection ID used to forward request to provider * @param {SendTransferDto} sendTransferDto * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async send(xClientId: string, sendTransferDto: SendTransferDto, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.send(xClientId, sendTransferDto, authorization, options); + async send(xClientId: string, xConnectionId: string, sendTransferDto: SendTransferDto, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.send(xClientId, xConnectionId, sendTransferDto, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['ProviderTransferApi.send']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); @@ -7709,7 +7848,7 @@ export const ProviderTransferApiFactory = function (configuration?: Configuratio * @throws {RequiredError} */ send(requestParameters: ProviderTransferApiSendRequest, options?: RawAxiosRequestConfig): AxiosPromise { - return localVarFp.send(requestParameters.xClientId, requestParameters.sendTransferDto, requestParameters.authorization, options).then((request) => request(axios, basePath)); + return localVarFp.send(requestParameters.xClientId, requestParameters.xConnectionId, requestParameters.sendTransferDto, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, }; }; @@ -7755,6 +7894,13 @@ export interface ProviderTransferApiSendRequest { */ readonly xClientId: string + /** + * The connection ID used to forward request to provider + * @type {string} + * @memberof ProviderTransferApiSend + */ + readonly xConnectionId: string + /** * * @type {SendTransferDto} @@ -7798,7 +7944,7 @@ export class ProviderTransferApi extends BaseAPI { * @memberof ProviderTransferApi */ public send(requestParameters: ProviderTransferApiSendRequest, options?: RawAxiosRequestConfig) { - return ProviderTransferApiFp(this.configuration).send(requestParameters.xClientId, requestParameters.sendTransferDto, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + return ProviderTransferApiFp(this.configuration).send(requestParameters.xClientId, requestParameters.xConnectionId, requestParameters.sendTransferDto, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } } diff --git a/packages/armory-sdk/src/lib/vault/client.ts b/packages/armory-sdk/src/lib/vault/client.ts index 8385cc7e9..7ac75c304 100644 --- a/packages/armory-sdk/src/lib/vault/client.ts +++ b/packages/armory-sdk/src/lib/vault/client.ts @@ -666,15 +666,18 @@ export class VaultClient { async sendTransfer({ data, + connectionId, accessToken }: { data: SendTransferDto + connectionId: string accessToken?: AccessToken }): Promise { const token = accessToken ? prefixGnapToken(accessToken) : undefined const { data: transfer } = await this.providerTransferHttp.send({ xClientId: this.config.clientId, + xConnectionId: connectionId, authorization: token, sendTransferDto: data }) From da2673a31a63fb0ba16c6e23c9a72a928d632de8 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Tue, 7 Jan 2025 16:38:30 +0100 Subject: [PATCH 075/120] Transfer status by ID (#72) * Fetch transfer data from provider * Update Vault client and bump version --- .../src/broker/__test__/e2e/proxy.spec.ts | 2 +- .../src/broker/__test__/e2e/transfer.spec.ts | 32 +++++++++++++++++-- .../anchorage-transfer.service.spec.ts | 20 +++++++++--- .../anchorage/anchorage-transfer.service.ts | 1 + .../broker/core/service/transfer.service.ts | 23 +++++++------ .../src/broker/core/type/connection.type.ts | 12 +++++-- .../http/rest/controller/proxy.controller.ts | 5 +-- .../rest/controller/transfer.controller.ts | 24 +++++++++----- apps/vault/src/broker/shared/constant.ts | 6 ++++ .../decorator/connection-id.decorator.ts | 2 +- package-lock.json | 8 ++--- packages/armory-sdk/package.json | 2 +- .../src/lib/http/client/vault/api.ts | 31 +++++++++++++----- packages/armory-sdk/src/lib/vault/client.ts | 3 ++ 14 files changed, 124 insertions(+), 47 deletions(-) rename apps/vault/src/{ => broker}/shared/decorator/connection-id.decorator.ts (88%) diff --git a/apps/vault/src/broker/__test__/e2e/proxy.spec.ts b/apps/vault/src/broker/__test__/e2e/proxy.spec.ts index 86018ae02..0a39901e4 100644 --- a/apps/vault/src/broker/__test__/e2e/proxy.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/proxy.spec.ts @@ -10,13 +10,13 @@ import request from 'supertest' import { ClientService } from '../../../client/core/service/client.service' import { MainModule } from '../../../main.module' import { ProvisionService } from '../../../provision.service' -import { REQUEST_HEADER_CONNECTION_ID } from '../../../shared/decorator/connection-id.decorator' import { KeyValueRepository } from '../../../shared/module/key-value/core/repository/key-value.repository' import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' import { ConnectionService } from '../../core/service/connection.service' import { Provider } from '../../core/type/provider.type' +import { REQUEST_HEADER_CONNECTION_ID } from '../../shared/constant' import { getJwsd, testClient, testUserPrivateJwk } from '../util/mock-data' describe('Proxy', () => { diff --git a/apps/vault/src/broker/__test__/e2e/transfer.spec.ts b/apps/vault/src/broker/__test__/e2e/transfer.spec.ts index 33185a89c..1af58a0a6 100644 --- a/apps/vault/src/broker/__test__/e2e/transfer.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/transfer.spec.ts @@ -11,7 +11,6 @@ import { v4 as uuid } from 'uuid' import { ClientService } from '../../../client/core/service/client.service' import { MainModule } from '../../../main.module' import { ProvisionService } from '../../../provision.service' -import { REQUEST_HEADER_CONNECTION_ID } from '../../../shared/decorator/connection-id.decorator' import { KeyValueRepository } from '../../../shared/module/key-value/core/repository/key-value.repository' import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' @@ -32,6 +31,7 @@ import { ConnectionRepository } from '../../persistence/repository/connection.re import { TransferRepository } from '../../persistence/repository/transfer.repository' import { WalletRepository } from '../../persistence/repository/wallet.repository' import { setupMockServer } from '../../shared/__test__/mock-server' +import { REQUEST_HEADER_CONNECTION_ID } from '../../shared/constant' import { getJwsd, testClient, testUserPrivateJwk } from '../util/mock-data' const ENDPOINT = '/provider/transfers' @@ -359,7 +359,7 @@ describe('Transfer', () => { id: accountTwo.accountId }, externalId: uuid(), - grossAmount: '0.1', + grossAmount: '0.00001', idempotenceId: uuid(), memo: 'Test transfer', networkFeeAttribution: NetworkFeeAttribution.DEDUCT, @@ -381,6 +381,7 @@ describe('Transfer', () => { const { status, body } = await request(app.getHttpServer()) .get(`${ENDPOINT}/${transfer.transferId}`) .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set(REQUEST_HEADER_CONNECTION_ID, connection.connectionId) .set( 'detached-jws', await getJwsd({ @@ -395,11 +396,36 @@ describe('Transfer', () => { expect(body).toEqual({ data: { ...transfer, - createdAt: transfer.createdAt.toISOString() + // NOTE: The status is different from `transfer` because it's coming + // from the Anchorage API. The `findById` merges the state we have in + // the database with the API's. + status: TransferStatus.SUCCESS, + createdAt: expect.any(String) } }) expect(status).toEqual(HttpStatus.OK) }) + + it('fails if connection header is missing', async () => { + const { body } = await request(app.getHttpServer()) + .get(`${ENDPOINT}/${transfer.transferId}`) + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + payload: {}, + userPrivateJwk: testUserPrivateJwk, + requestUrl: `${ENDPOINT}/${transfer.transferId}`, + htm: 'GET' + }) + ) + .send() + + expect(body).toMatchObject({ + statusCode: HttpStatus.BAD_REQUEST, + message: 'Missing or invalid x-connection-id header' + }) + }) }) }) diff --git a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts index 7b925c19a..bf1e2da92 100644 --- a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts +++ b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts @@ -329,8 +329,7 @@ describe(AnchorageTransferService.name, () => { const [spy] = useRequestSpy(mockServer) const sendTransfer = { ...requiredSendTransfer, - memo: 'Integration test transfer', - idempotenceId: uuid() + memo: 'Integration test transfer' } await anchorageTransferService.send(connection, sendTransfer) @@ -348,8 +347,6 @@ describe(AnchorageTransferService.name, () => { }, assetType: sendTransfer.assetId, amount: sendTransfer.amount, - // !!CustomerRefId is not a field in Anchorage's API. - // customerRefId: sendTransfer.customerRefId, transferMemo: sendTransfer.memo, idempotentId: sendTransfer.idempotenceId, // Default `deductFeeFromAmountIfSameType` to false. @@ -359,6 +356,21 @@ describe(AnchorageTransferService.name, () => { ) }) + // IMPORTANT: We never send the customerRefId to Anchorage because they + // have deprecated it and it seems to get transfers stuck on their side. + it('does not send customerRefId', async () => { + const [spy] = useRequestSpy(mockServer) + const sendTransfer = { + ...requiredSendTransfer, + customerRefId: uuid() + } + + await anchorageTransferService.send(connection, sendTransfer) + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + expect('customerRefId' in (spy.mock.calls[0][0] as any)).toEqual(false) + }) + it('handles provider specific', async () => { const [spy] = useRequestSpy(mockServer) const sendTransfer = { diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts index 21d6d0b89..fe29d64e4 100644 --- a/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts @@ -64,6 +64,7 @@ export class AnchorageTransferService implements ProviderTransferService { memo: anchorageTransfer.transferMemo || internalTransfer.memo || null, networkFeeAttribution: internalTransfer.networkFeeAttribution, provider: internalTransfer.provider, + providerSpecific: internalTransfer.providerSpecific, source: internalTransfer.source, status: this.mapStatus(anchorageTransfer.status), transferId: internalTransfer.transferId, diff --git a/apps/vault/src/broker/core/service/transfer.service.ts b/apps/vault/src/broker/core/service/transfer.service.ts index 6ef2065e2..5c2e70c0e 100644 --- a/apps/vault/src/broker/core/service/transfer.service.ts +++ b/apps/vault/src/broker/core/service/transfer.service.ts @@ -22,8 +22,15 @@ export class TransferService { @Inject(TraceService) private readonly traceService: TraceService ) {} - async findById(clientId: string, transferId: string): Promise { - return this.transferRepository.findById(clientId, transferId) + async findById(clientId: string, connectionId: string, transferId: string): Promise { + const span = this.traceService.startSpan(`${TransferService.name}.findById`) + + const connection = await this.connectionService.findWithCredentialsById(clientId, connectionId) + const transfer = await this.getProviderTransferService(connection.provider).findById(connection, transferId) + + span.end() + + return transfer } async bulkCreate(transfers: InternalTransfer[]): Promise { @@ -36,20 +43,12 @@ export class TransferService { const span = this.traceService.startSpan(`${TransferService.name}.sync`) const source = await this.transferPartyService.resolve(clientId, sendTransfer.source) - const connection = await this.connectionService.findById(clientId, connectionId) + const connection = await this.connectionService.findWithCredentialsById(clientId, connectionId) if (isActiveConnection(connection)) { - const credentials = await this.connectionService.findCredentials(connection) - span.setAttribute(OTEL_ATTR_CONNECTION_PROVIDER, connection.provider) - const transfer = await this.getProviderTransferService(source.provider).send( - { - ...connection, - credentials - }, - sendTransfer - ) + const transfer = await this.getProviderTransferService(source.provider).send(connection, sendTransfer) span.end() diff --git a/apps/vault/src/broker/core/type/connection.type.ts b/apps/vault/src/broker/core/type/connection.type.ts index eb1273ea3..c7317e5ef 100644 --- a/apps/vault/src/broker/core/type/connection.type.ts +++ b/apps/vault/src/broker/core/type/connection.type.ts @@ -91,14 +91,20 @@ export type UpdateConnection = z.infer // Type Guard // -export const isPendingConnection = (connection: Connection): connection is PendingConnection => { +export const isPendingConnection = ( + connection: Connection | ConnectionWithCredentials +): connection is PendingConnection => { return connection.status === ConnectionStatus.PENDING } -export const isActiveConnection = (connection: Connection): connection is ActiveConnection => { +export const isActiveConnection = ( + connection: Connection | ConnectionWithCredentials +): connection is ActiveConnection => { return connection.status === ConnectionStatus.ACTIVE } -export const isRevokedConnection = (connection: Connection): connection is RevokedConnection => { +export const isRevokedConnection = ( + connection: Connection | ConnectionWithCredentials +): connection is RevokedConnection => { return connection.status === ConnectionStatus.REVOKED } diff --git a/apps/vault/src/broker/http/rest/controller/proxy.controller.ts b/apps/vault/src/broker/http/rest/controller/proxy.controller.ts index bd54edaaa..6fb60407d 100644 --- a/apps/vault/src/broker/http/rest/controller/proxy.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/proxy.controller.ts @@ -17,10 +17,11 @@ import { import { ApiHeader, ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger' import { Request, Response } from 'express' import { ClientId } from '../../../../shared/decorator/client-id.decorator' -import { ConnectionId } from '../../../../shared/decorator/connection-id.decorator' import { PermissionGuard } from '../../../../shared/decorator/permission-guard.decorator' import { VaultPermission } from '../../../../shared/type/domain.type' import { ProxyService } from '../../../core/service/proxy.service' +import { REQUEST_HEADER_CONNECTION_ID } from '../../../shared/constant' +import { ConnectionId } from '../../../shared/decorator/connection-id.decorator' const API_PARAM = ':endpoint(*)' @@ -31,7 +32,7 @@ const API_OPERATION = { } as const const CONNECTION_HEADER = { - name: 'x-connection-id', + name: REQUEST_HEADER_CONNECTION_ID, required: true, description: 'The connection ID used to forward request to provider' } as const diff --git a/apps/vault/src/broker/http/rest/controller/transfer.controller.ts b/apps/vault/src/broker/http/rest/controller/transfer.controller.ts index f3c328000..2cac5cdc1 100644 --- a/apps/vault/src/broker/http/rest/controller/transfer.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/transfer.controller.ts @@ -2,10 +2,11 @@ import { ApiClientIdHeader } from '@narval/nestjs-shared' import { Body, Controller, Get, HttpStatus, Param, Post } from '@nestjs/common' import { ApiHeader, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../shared/decorator/client-id.decorator' -import { ConnectionId } from '../../../../shared/decorator/connection-id.decorator' import { PermissionGuard } from '../../../../shared/decorator/permission-guard.decorator' import { VaultPermission } from '../../../../shared/type/domain.type' import { TransferService } from '../../../core/service/transfer.service' +import { REQUEST_HEADER_CONNECTION_ID } from '../../../shared/constant' +import { ConnectionId } from '../../../shared/decorator/connection-id.decorator' import { SendTransferDto } from '../dto/request/send-transfer.dto' import { TransferDto } from '../dto/response/transfer.dto' @@ -24,16 +25,15 @@ export class TransferController { summary: 'Send a transfer', description: "This endpoint sends a transfer to the source's provider." }) + @ApiHeader({ + name: REQUEST_HEADER_CONNECTION_ID, + required: true + }) @ApiResponse({ status: HttpStatus.CREATED, description: 'The transfer was successfully sent.', type: TransferDto }) - @ApiHeader({ - name: 'x-connection-id', - required: true, - description: 'The connection ID used to forward request to provider' - }) async send( @ClientId() clientId: string, @ConnectionId() connectionId: string, @@ -55,8 +55,16 @@ export class TransferController { description: 'The transfer details were successfully retrieved.', type: TransferDto }) - async getById(@ClientId() clientId: string, @Param('transferId') transferId: string) { - const internalTransfer = await this.transferService.findById(clientId, transferId) + @ApiHeader({ + name: REQUEST_HEADER_CONNECTION_ID, + required: true + }) + async getById( + @ClientId() clientId: string, + @ConnectionId() connectionId: string, + @Param('transferId') transferId: string + ) { + const internalTransfer = await this.transferService.findById(clientId, connectionId, transferId) return TransferDto.create({ data: internalTransfer }) } diff --git a/apps/vault/src/broker/shared/constant.ts b/apps/vault/src/broker/shared/constant.ts index bfcac904e..923531949 100644 --- a/apps/vault/src/broker/shared/constant.ts +++ b/apps/vault/src/broker/shared/constant.ts @@ -5,3 +5,9 @@ export const OTEL_ATTR_SYNC_ID = 'sync.id' export const OTEL_ATTR_CONNECTION_ID = 'connection.id' export const OTEL_ATTR_CONNECTION_PROVIDER = 'connection.provider' + +// +// HTTP Header +// + +export const REQUEST_HEADER_CONNECTION_ID = 'x-connection-id' diff --git a/apps/vault/src/shared/decorator/connection-id.decorator.ts b/apps/vault/src/broker/shared/decorator/connection-id.decorator.ts similarity index 88% rename from apps/vault/src/shared/decorator/connection-id.decorator.ts rename to apps/vault/src/broker/shared/decorator/connection-id.decorator.ts index 65cae86dc..3fb8dd791 100644 --- a/apps/vault/src/shared/decorator/connection-id.decorator.ts +++ b/apps/vault/src/broker/shared/decorator/connection-id.decorator.ts @@ -1,6 +1,6 @@ import { BadRequestException, createParamDecorator, ExecutionContext } from '@nestjs/common' +import { REQUEST_HEADER_CONNECTION_ID } from '../constant' -export const REQUEST_HEADER_CONNECTION_ID = 'x-connection-id' export const ConnectionId = createParamDecorator((_data: unknown, context: ExecutionContext): string => { const req = context.switchToHttp().getRequest() const connectionId = req.headers[REQUEST_HEADER_CONNECTION_ID] diff --git a/package-lock.json b/package-lock.json index a4f8bfc41..482e6df7f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27717,9 +27717,9 @@ "peer": true }, "node_modules/flow-parser": { - "version": "0.257.1", - "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.257.1.tgz", - "integrity": "sha512-7+KYDpAXyBPD/wODhbPYO6IGUx+WwtJcLLG/r3DvbNyxaDyuYaTBKbSqeCldWQzuFcj+MsOVx2bpkEwVPB9JRw==", + "version": "0.258.0", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.258.0.tgz", + "integrity": "sha512-/f3ui3WaPTRUtqnWaGzf/f352hn4VhqGOiuSVkgaW6SbHNp5EwdDoh6BF3zB9A6kcWhCpg/0x0A3aXU+KXugAA==", "license": "MIT", "peer": true, "engines": { @@ -46204,7 +46204,7 @@ }, "packages/armory-sdk": { "name": "@narval-xyz/armory-sdk", - "version": "0.16.0", + "version": "0.17.0", "license": "MPL-2.0", "dependencies": { "@noble/curves": "1.6.0", diff --git a/packages/armory-sdk/package.json b/packages/armory-sdk/package.json index e2c5e328d..0d4c2b55e 100644 --- a/packages/armory-sdk/package.json +++ b/packages/armory-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@narval-xyz/armory-sdk", - "version": "0.16.0", + "version": "0.17.0", "license": "MPL-2.0", "publishConfig": { "access": "public" diff --git a/packages/armory-sdk/src/lib/http/client/vault/api.ts b/packages/armory-sdk/src/lib/http/client/vault/api.ts index 53865c47d..7b0c6ba96 100644 --- a/packages/armory-sdk/src/lib/http/client/vault/api.ts +++ b/packages/armory-sdk/src/lib/http/client/vault/api.ts @@ -7673,15 +7673,18 @@ export const ProviderTransferApiAxiosParamCreator = function (configuration?: Co * @summary Retrieve transfer details * @param {string} xClientId * @param {string} transferId + * @param {string} xConnectionId * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getById: async (xClientId: string, transferId: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + getById: async (xClientId: string, transferId: string, xConnectionId: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'xClientId' is not null or undefined assertParamExists('getById', 'xClientId', xClientId) // verify required parameter 'transferId' is not null or undefined assertParamExists('getById', 'transferId', transferId) + // verify required parameter 'xConnectionId' is not null or undefined + assertParamExists('getById', 'xConnectionId', xConnectionId) const localVarPath = `/v1/provider/transfers/{transferId}` .replace(`{${"transferId"}}`, encodeURIComponent(String(transferId))); // use dummy base URL string because the URL constructor only accepts absolute URLs. @@ -7704,6 +7707,10 @@ export const ProviderTransferApiAxiosParamCreator = function (configuration?: Co localVarHeaderParameter['x-client-id'] = String(xClientId); } + if (xConnectionId != null) { + localVarHeaderParameter['x-connection-id'] = String(xConnectionId); + } + if (authorization != null) { localVarHeaderParameter['Authorization'] = String(authorization); } @@ -7723,7 +7730,7 @@ export const ProviderTransferApiAxiosParamCreator = function (configuration?: Co * This endpoint sends a transfer to the source\'s provider. * @summary Send a transfer * @param {string} xClientId - * @param {string} xConnectionId The connection ID used to forward request to provider + * @param {string} xConnectionId * @param {SendTransferDto} sendTransferDto * @param {string} [authorization] * @param {*} [options] Override http request option. @@ -7794,12 +7801,13 @@ export const ProviderTransferApiFp = function(configuration?: Configuration) { * @summary Retrieve transfer details * @param {string} xClientId * @param {string} transferId + * @param {string} xConnectionId * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async getById(xClientId: string, transferId: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.getById(xClientId, transferId, authorization, options); + async getById(xClientId: string, transferId: string, xConnectionId: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getById(xClientId, transferId, xConnectionId, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['ProviderTransferApi.getById']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); @@ -7808,7 +7816,7 @@ export const ProviderTransferApiFp = function(configuration?: Configuration) { * This endpoint sends a transfer to the source\'s provider. * @summary Send a transfer * @param {string} xClientId - * @param {string} xConnectionId The connection ID used to forward request to provider + * @param {string} xConnectionId * @param {SendTransferDto} sendTransferDto * @param {string} [authorization] * @param {*} [options] Override http request option. @@ -7838,7 +7846,7 @@ export const ProviderTransferApiFactory = function (configuration?: Configuratio * @throws {RequiredError} */ getById(requestParameters: ProviderTransferApiGetByIdRequest, options?: RawAxiosRequestConfig): AxiosPromise { - return localVarFp.getById(requestParameters.xClientId, requestParameters.transferId, requestParameters.authorization, options).then((request) => request(axios, basePath)); + return localVarFp.getById(requestParameters.xClientId, requestParameters.transferId, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, /** * This endpoint sends a transfer to the source\'s provider. @@ -7873,6 +7881,13 @@ export interface ProviderTransferApiGetByIdRequest { */ readonly transferId: string + /** + * + * @type {string} + * @memberof ProviderTransferApiGetById + */ + readonly xConnectionId: string + /** * * @type {string} @@ -7895,7 +7910,7 @@ export interface ProviderTransferApiSendRequest { readonly xClientId: string /** - * The connection ID used to forward request to provider + * * @type {string} * @memberof ProviderTransferApiSend */ @@ -7932,7 +7947,7 @@ export class ProviderTransferApi extends BaseAPI { * @memberof ProviderTransferApi */ public getById(requestParameters: ProviderTransferApiGetByIdRequest, options?: RawAxiosRequestConfig) { - return ProviderTransferApiFp(this.configuration).getById(requestParameters.xClientId, requestParameters.transferId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + return ProviderTransferApiFp(this.configuration).getById(requestParameters.xClientId, requestParameters.transferId, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } /** diff --git a/packages/armory-sdk/src/lib/vault/client.ts b/packages/armory-sdk/src/lib/vault/client.ts index 7ac75c304..d1639b436 100644 --- a/packages/armory-sdk/src/lib/vault/client.ts +++ b/packages/armory-sdk/src/lib/vault/client.ts @@ -687,15 +687,18 @@ export class VaultClient { async getTransfer({ transferId, + connectionId, accessToken }: { transferId: string + connectionId: string accessToken?: AccessToken }): Promise { const token = accessToken ? prefixGnapToken(accessToken) : undefined const { data: transfer } = await this.providerTransferHttp.getById({ xClientId: this.config.clientId, + xConnectionId: connectionId, transferId, authorization: token }) From 27a70d9e73e57219dfd0abb68e79c817dcb15d37 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Tue, 7 Jan 2025 17:57:28 +0100 Subject: [PATCH 076/120] Add network mapping endpoint (#73) * Add network mapping * Refactor network type * Remove duplicate check * Fix network index * Add missing DTO file --- apps/vault/src/broker/broker.module.ts | 6 +- .../anchorage/anchorage-sync.service.ts | 2 - .../src/broker/core/type/network.type.ts | 10 + .../src/broker/core/util/network.util.ts | 25 + .../rest/controller/network.controller.ts | 37 + .../http/rest/dto/response/network.dto.ts | 11 + .../repository/network.repository.ts | 660 ++++++++++++++++++ packages/policy-engine-shared/src/index.ts | 2 - .../src/lib/resource/networks.ts | 324 --------- 9 files changed, 748 insertions(+), 329 deletions(-) create mode 100644 apps/vault/src/broker/core/type/network.type.ts create mode 100644 apps/vault/src/broker/core/util/network.util.ts create mode 100644 apps/vault/src/broker/http/rest/controller/network.controller.ts create mode 100644 apps/vault/src/broker/http/rest/dto/response/network.dto.ts create mode 100644 apps/vault/src/broker/persistence/repository/network.repository.ts delete mode 100644 packages/policy-engine-shared/src/lib/resource/networks.ts diff --git a/apps/vault/src/broker/broker.module.ts b/apps/vault/src/broker/broker.module.ts index 6f11f837a..29d170361 100644 --- a/apps/vault/src/broker/broker.module.ts +++ b/apps/vault/src/broker/broker.module.ts @@ -31,6 +31,7 @@ import { ProviderAccountController } from './http/rest/controller/account.contro import { ProviderAddressController } from './http/rest/controller/address.controller' import { ConnectionController } from './http/rest/controller/connection.controller' import { KnownDestinationController } from './http/rest/controller/known-destination.controller' +import { NetworkController } from './http/rest/controller/network.controller' import { ProxyController } from './http/rest/controller/proxy.controller' import { SyncController } from './http/rest/controller/sync.controller' import { TransferController } from './http/rest/controller/transfer.controller' @@ -40,6 +41,7 @@ import { AccountRepository } from './persistence/repository/account.repository' import { AddressRepository } from './persistence/repository/address.repository' import { ConnectionRepository } from './persistence/repository/connection.repository' import { KnownDestinationRepository } from './persistence/repository/known-destination.repository' +import { NetworkRepository } from './persistence/repository/network.repository' import { SyncRepository } from './persistence/repository/sync.repository' import { TransferRepository } from './persistence/repository/transfer.repository' import { WalletRepository } from './persistence/repository/wallet.repository' @@ -56,6 +58,7 @@ import { WalletRepository } from './persistence/repository/wallet.repository' controllers: [ ConnectionController, KnownDestinationController, + NetworkController, ProviderAccountController, ProviderAddressController, ProviderWalletController, @@ -84,11 +87,12 @@ import { WalletRepository } from './persistence/repository/wallet.repository' ConnectionSyncEventHandler, EncryptionKeyRepository, EncryptionKeyService, - FireblocksCredentialService, FireblocksClient, + FireblocksCredentialService, FireblocksProxyService, KnownDestinationRepository, KnownDestinationService, + NetworkRepository, ProxyService, SyncRepository, SyncService, diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage-sync.service.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage-sync.service.ts index 4e9830f82..7ad111301 100644 --- a/apps/vault/src/broker/core/provider/anchorage/anchorage-sync.service.ts +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage-sync.service.ts @@ -18,7 +18,6 @@ import { isCreateOperation } from '../../type/provider.type' import { buildEmptyContext } from '../../util/provider-sync.util' -import { AnchorageCredentialService } from './anchorage-credential.service' import { validateConnection } from './anchorage.util' @Injectable() @@ -29,7 +28,6 @@ export class AnchorageSyncService implements ProviderSyncService { private readonly accountService: AccountService, private readonly addressService: AddressService, private readonly knownDestinationService: KnownDestinationService, - private readonly anchorageCredentialService: AnchorageCredentialService, private readonly logger: LoggerService ) {} diff --git a/apps/vault/src/broker/core/type/network.type.ts b/apps/vault/src/broker/core/type/network.type.ts new file mode 100644 index 000000000..e4a5007ab --- /dev/null +++ b/apps/vault/src/broker/core/type/network.type.ts @@ -0,0 +1,10 @@ +import { z } from 'zod' + +export const Network = z.object({ + networkId: z.string(), + coinType: z.number().nullable(), + name: z.string(), + anchorageId: z.string().optional(), + fireblocksId: z.string().optional() +}) +export type Network = z.infer diff --git a/apps/vault/src/broker/core/util/network.util.ts b/apps/vault/src/broker/core/util/network.util.ts new file mode 100644 index 000000000..2e5af2b17 --- /dev/null +++ b/apps/vault/src/broker/core/util/network.util.ts @@ -0,0 +1,25 @@ +import { Network } from '../type/network.type' + +export const isNetworkIdFromTestnet = (networkId: string): boolean => { + const id = networkId.toUpperCase() + + return ( + id.includes('TESTNET') || + id.includes('_T') || + id.includes('SEPOLIA') || + id.includes('KOVAN') || + id.includes('HOLESKY') || + id.includes('DEVNET') || + id.includes('BAKLAVA') + ) +} + +/** + * Checks if a network is a testnet based on its SLIP-44 coin type. Based on + * the standard, coin type 1 is reserved to all testnets. + * + * @see https://github.com/satoshilabs/slips/blob/master/slip-0044.md#registered-coin-types + */ +export const isTestnet = (network: Network): boolean => { + return Boolean(network.coinType && network.coinType === 1) +} diff --git a/apps/vault/src/broker/http/rest/controller/network.controller.ts b/apps/vault/src/broker/http/rest/controller/network.controller.ts new file mode 100644 index 000000000..dabc5fcf8 --- /dev/null +++ b/apps/vault/src/broker/http/rest/controller/network.controller.ts @@ -0,0 +1,37 @@ +import { ApiClientIdHeader } from '@narval/nestjs-shared' +import { Controller, Get, HttpStatus, Query } from '@nestjs/common' +import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' +import { PermissionGuard } from '../../../../shared/decorator/permission-guard.decorator' +import { VaultPermission } from '../../../../shared/type/domain.type' +import { Provider } from '../../../core/type/provider.type' +import { NetworkRepository } from '../../../persistence/repository/network.repository' +import { NetworkDto } from '../dto/response/network.dto' + +@Controller({ + path: 'networks', + version: '1' +}) +@ApiClientIdHeader() +@ApiTags('Provider Network') +export class NetworkController { + constructor(private readonly networkRepository: NetworkRepository) {} + + @Get() + @PermissionGuard(VaultPermission.CONNECTION_READ) + @ApiOperation({ + summary: 'Retrieve all networks', + description: 'This endpoint retrieves a list of all available networks.' + }) + @ApiResponse({ + status: HttpStatus.OK, + description: 'The networks were successfully retrieved.', + type: NetworkDto + }) + async list(@Query('provider') provider: Provider): Promise { + const networks = await this.networkRepository.findAll({ + filters: { provider } + }) + + return NetworkDto.create({ data: networks }) + } +} diff --git a/apps/vault/src/broker/http/rest/dto/response/network.dto.ts b/apps/vault/src/broker/http/rest/dto/response/network.dto.ts new file mode 100644 index 000000000..9ed29c787 --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/response/network.dto.ts @@ -0,0 +1,11 @@ +import { Page } from '@narval/nestjs-shared' +import { createZodDto } from 'nestjs-zod' +import { z } from 'zod' +import { Network } from '../../../../core/type/network.type' + +export class NetworkDto extends createZodDto( + z.object({ + data: z.array(Network), + page: Page + }) +) {} diff --git a/apps/vault/src/broker/persistence/repository/network.repository.ts b/apps/vault/src/broker/persistence/repository/network.repository.ts new file mode 100644 index 000000000..f480bf8a7 --- /dev/null +++ b/apps/vault/src/broker/persistence/repository/network.repository.ts @@ -0,0 +1,660 @@ +import { Injectable } from '@nestjs/common' +import { Network } from '../../core/type/network.type' +import { Provider } from '../../core/type/provider.type' + +type FindAllOptions = { + filters?: { + provider?: Provider + } +} + +const NETWORKS: Network[] = [ + { + networkId: 'AETH', + coinType: 514, + name: 'Aetherius', + fireblocksId: 'ETH-AETH' + }, + { + networkId: 'AEVO', + coinType: null, + name: 'Aevo', + fireblocksId: 'AEVO' + }, + { + networkId: 'AGORIC', + coinType: 564, + name: 'Agoric', + anchorageId: 'BLD' + }, + { + networkId: 'ALEPH_ZERO', + coinType: 643, + name: 'Aleph Zero', + fireblocksId: 'ALEPH_ZERO_EVM' + }, + { + networkId: 'ALGORAND', + coinType: 283, + name: 'Algorand', + fireblocksId: 'ALGO' + }, + { + networkId: 'ALGORAND_TESTNET', + coinType: 1, + name: 'Algorand Testnet', + fireblocksId: 'ALGO_TEST' + }, + { + networkId: 'ALLORA', + coinType: null, + name: 'Allora', + anchorageId: 'ALLO' + }, + { + networkId: 'ALLORA_TESTNET', + coinType: 1, + name: 'Allora Testnet', + anchorageId: 'ALLO_T' + }, + { + networkId: 'APTOS', + coinType: 637, + name: 'Aptos', + anchorageId: 'APT' + }, + { + networkId: 'APTOS_TESTNET', + coinType: 1, + name: 'Aptos Testnet', + anchorageId: 'APT_T' + }, + { + networkId: 'ARBITRUM_SEPOLIA', + coinType: 1, + name: 'Arbitrum Sepolia Testnet', + anchorageId: 'ETH_ARBITRUM_T' + }, + { + networkId: 'ASTAR', + coinType: 810, + name: 'Astar', + fireblocksId: 'ASTR_ASTR' + }, + { + networkId: 'ASTAR_TESTNET', + coinType: 1, + name: 'Astar Testnet', + fireblocksId: 'ASTR_TEST' + }, + { + networkId: 'ATOM', + coinType: 118, + name: 'Atom', + anchorageId: 'ATOM', + fireblocksId: 'ATOM_COS' + }, + { + networkId: 'ATOM_TESTNET', + coinType: 1, + name: 'Atom Testnet', + fireblocksId: 'ATOM_COS_TEST' + }, + { + networkId: 'AURORA', + coinType: 2570, + name: 'Aurora', + fireblocksId: 'AURORA_DEV' + }, + { + networkId: 'AVAX', + coinType: 9000, + name: 'Avalanche', + fireblocksId: 'AVAX' + }, + { + networkId: 'AVAX_TESTNET', + coinType: 1, + name: 'Avalanche Testnet', + fireblocksId: 'AVAXTEST' + }, + { + networkId: 'AXELAR', + coinType: null, + name: 'Axelar', + anchorageId: 'AXL' + }, + { + networkId: 'AXELAR_TESTNET', + coinType: 1, + name: 'Axelar Testnet', + anchorageId: 'AXL_T' + }, + { + networkId: 'BABYLON', + coinType: null, + name: 'Babylon', + anchorageId: 'BBN' + }, + { + networkId: 'BASE', + coinType: 8453, + name: 'Base', + fireblocksId: 'BASECHAIN_ETH' + }, + { + networkId: 'BASE_TESTNET', + coinType: 1, + name: 'Base Testnet', + fireblocksId: 'BASECHAIN_ETH_TEST5' + }, + { + networkId: 'BINANCE_SMART_CHAIN', + coinType: 9006, + name: 'Binance Smart Chain', + fireblocksId: 'BNB_BSC' + }, + { + networkId: 'BINANCE_SMART_CHAIN_TESTNET', + coinType: 1, + name: 'Binance Smart Chain Testnet', + fireblocksId: 'BNB_TEST' + }, + { + networkId: 'BITCOIN', + coinType: 0, + name: 'Bitcoin', + anchorageId: 'BTC', + fireblocksId: 'BTC' + }, + { + networkId: 'BITCOIN_CASH', + coinType: 145, + name: 'Bitcoin Cash', + anchorageId: 'BCH', + fireblocksId: 'BCH' + }, + { + networkId: 'BITCOIN_CASH_TESTNET', + coinType: 1, + name: 'Bitcoin Cash Testnet', + fireblocksId: 'BCH_TEST' + }, + { + networkId: 'BITCOIN_SIGNET', + coinType: 1, + name: 'Bitcoin Signet', + anchorageId: 'BTC_S' + }, + { + networkId: 'BITCOIN_SV', + coinType: 236, + name: 'BitcoinSV', + fireblocksId: 'BSV' + }, + { + networkId: 'BITCOIN_SV_TESTNET', + coinType: 1, + name: 'BitcoinSV Testnet', + fireblocksId: 'BSV_TEST' + }, + { + networkId: 'BITCOIN_TESTNET', + coinType: 1, + name: 'Bitcoin Testnet', + fireblocksId: 'BTC_TEST' + }, + { + networkId: 'CARDANO', + coinType: 1815, + name: 'Cardano', + fireblocksId: 'ADA' + }, + { + networkId: 'CARDANO_TESTNET', + coinType: 1, + name: 'Cardano Testnet', + fireblocksId: 'ADA_TEST' + }, + { + networkId: 'CELESTIA', + coinType: null, + name: 'Celestia', + anchorageId: 'TIA' + }, + { + networkId: 'CELO', + coinType: 52752, + name: 'Celo', + fireblocksId: 'CELO' + }, + { + networkId: 'CELO_ALFAJORES', + coinType: null, + name: 'Celo Alfajores', + fireblocksId: 'CELO_ALF' + }, + { + networkId: 'CELO_BAKLAVA', + coinType: 1, + name: 'Celo Baklava', + anchorageId: 'CGLD_TB', + fireblocksId: 'CELO_BAK' + }, + { + networkId: 'CHILIZ', + coinType: null, + name: 'Chiliz', + fireblocksId: 'CHZ_$CHZ' + }, + { + networkId: 'DABACUS', + coinType: 521, + name: 'Dabacus', + fireblocksId: 'ABA' + }, + { + networkId: 'DOGECOIN', + coinType: 3, + name: 'Dogecoin', + anchorageId: 'DOGE', + fireblocksId: 'DOGE' + }, + { + networkId: 'DOGECOIN_TESTNET', + coinType: 1, + name: 'Dogecoin Testnet', + fireblocksId: 'DOGE_TEST' + }, + { + networkId: 'DYDX_CHAIN', + coinType: null, + name: 'Dydx Chain', + anchorageId: 'DYDX_CHAIN' + }, + { + networkId: 'DYDX_CHAIN_TESTNET', + coinType: 1, + name: 'Dydx Testnet', + anchorageId: 'DYDX_CHAIN_T' + }, + { + networkId: 'ETHEREUM', + coinType: 60, + name: 'Ethereum', + anchorageId: 'ETH', + fireblocksId: 'ETH' + }, + { + networkId: 'ETHEREUM_HOLESKY', + coinType: 1, + name: 'Ethereum Holešky', + anchorageId: 'ETHHOL' + }, + { + networkId: 'ETHEREUM_SEPOLIA', + coinType: 1, + name: 'Ethereum Sepolia', + anchorageId: 'ETHSEP' + }, + { + networkId: 'EVMOS', + coinType: null, + name: 'Evmos', + anchorageId: 'EVMOS' + }, + { + networkId: 'EVMOS_TESTNET', + coinType: 1, + name: 'Evmos Testnet', + anchorageId: 'EVMOS_T' + }, + { + networkId: 'FILECOIN', + coinType: 461, + name: 'Filecoin', + anchorageId: 'FIL' + }, + { + networkId: 'FLOW_TESTNET', + coinType: 1, + name: 'Flow Testnet', + anchorageId: 'FLOW_T' + }, + { + networkId: 'LITECOIN', + coinType: 2, + name: 'Litecoin', + anchorageId: 'LTC', + fireblocksId: 'LTC' + }, + { + networkId: 'LITECOIN_TESTNET', + coinType: 1, + name: 'Litecoin Testnet', + fireblocksId: 'LTC_TEST' + }, + { + networkId: 'NEUTRON', + coinType: null, + name: 'Neutron', + anchorageId: 'NTRN' + }, + { + networkId: 'OASIS', + coinType: 474, + name: 'Oasis', + anchorageId: 'ROSE' + }, + { + networkId: 'OM_MANTRA', + coinType: null, + name: 'OM Mantra', + anchorageId: 'OM_MANTRA' + }, + { + networkId: 'OM_MANTRA_TESTNET', + coinType: 1, + name: 'OM Mantra Testnet', + anchorageId: 'OM_MANTRA_T' + }, + { + networkId: 'OSMOSIS', + coinType: 10000118, + name: 'Osmosis', + anchorageId: 'OSMO', + fireblocksId: 'OSMO' + }, + { + networkId: 'PLUME_SEPOLIA', + coinType: 1, + name: 'Plume Sepolia Testnet', + anchorageId: 'ETH_PLUME_T' + }, + { + networkId: 'POLYGON', + coinType: 966, + name: 'Polygon', + anchorageId: 'MATIC_POLYGON', + fireblocksId: 'MATIC_POLYGON' + }, + { + networkId: 'PROVENANCE', + coinType: 505, + name: 'Provenance', + anchorageId: 'HASH' + }, + { + networkId: 'RARIMO', + coinType: null, + name: 'Rarimo', + anchorageId: 'RMO' + }, + { + networkId: 'RIPPLE', + coinType: 144, + name: 'Ripple', + anchorageId: 'XRP', + fireblocksId: 'XRP' + }, + { + networkId: 'RIPPLE_TESTNET', + coinType: 1, + name: 'Ripple Testnet', + fireblocksId: 'XRP_TEST' + }, + { + networkId: 'SEI', + coinType: 19000118, + name: 'Sei', + anchorageId: 'SEI', + fireblocksId: 'SEI' + }, + { + networkId: 'SEI_TESTNET', + coinType: 1, + name: 'Sei Testnet', + anchorageId: 'SEI_T', + fireblocksId: 'SEI_TEST' + }, + { + networkId: 'SOLANA', + coinType: 501, + name: 'Solana', + fireblocksId: 'SOL' + }, + { + networkId: 'SOLANA_TESTNET', + coinType: 1, + name: 'Solana Testnet', + anchorageId: 'SOL_TD', + fireblocksId: 'SOL_TEST' + }, + { + networkId: 'STARKNET', + coinType: 9004, + name: 'Starknet', + anchorageId: 'STRK_STARKNET' + }, + { + networkId: 'STARKNET_TESTNET', + coinType: 1, + name: 'Starknet Testnet', + anchorageId: 'STRK_STARKNET_T' + }, + { + networkId: 'STELLAR_LUMENS', + coinType: 148, + name: 'Stellar Lumens', + fireblocksId: 'XLM' + }, + { + networkId: 'STELLAR_LUMENS_TESTNET', + coinType: 1, + name: 'Stellar Lumens Testnet', + fireblocksId: 'XLM_TEST' + }, + { + networkId: 'STRIDE', + coinType: null, + name: 'Stride', + anchorageId: 'STRD' + }, + { + networkId: 'SUI_TESTNET', + coinType: 1, + name: 'Sui Testnet', + anchorageId: 'SUI_T' + }, + { + networkId: 'TRON', + coinType: 195, + name: 'Tron', + fireblocksId: 'TRX' + }, + { + networkId: 'TRON_TESTNET', + coinType: 1, + name: 'Tron Testnet', + fireblocksId: 'TRX_TEST' + }, + { + networkId: 'VANA', + coinType: null, + name: 'Vana', + anchorageId: 'VANA_VANA' + }, + { + networkId: 'VANA_MOKSHA_TESTNET', + coinType: 1, + name: 'Vana Moksha Testnet', + anchorageId: 'VANA_VANA_MOKSHA_T' + }, + { + networkId: 'ZKSYNC_SEPOLIA', + coinType: 1, + name: 'ZKsync Sepolia Testnet', + anchorageId: 'ETH_ZKSYNC_T' + }, + { + networkId: 'POLKADOT', + coinType: 354, + name: 'Polkadot', + fireblocksId: 'DOT' + }, + { + networkId: 'EOS', + coinType: 194, + name: 'EOS', + fireblocksId: 'EOS' + }, + { + networkId: 'EOS_TESTNET', + coinType: 1, + name: 'EOS Testnet', + fireblocksId: 'EOS_TEST' + }, + { + networkId: 'OASYS', + coinType: 685, + name: 'Oasys', + fireblocksId: 'OAS' + }, + { + networkId: 'OASYS_TESTNET', + coinType: 1, + name: 'Oasys Testnet', + fireblocksId: 'OAS_TEST' + }, + { + networkId: 'OSMOSIS_TESTNET', + coinType: 1, + name: 'Osmosis Testnet', + fireblocksId: 'OSMO_TEST' + }, + { + networkId: 'TELOS', + coinType: 424, + name: 'Telos', + fireblocksId: 'TELOS' + }, + { + networkId: 'TELOS_TESTNET', + coinType: 1, + name: 'Telos Testnet', + fireblocksId: 'TELOS_TEST' + }, + { + networkId: 'TEZOS', + coinType: 1729, + name: 'Tezos', + fireblocksId: 'XTZ' + }, + { + networkId: 'TEZOS_TESTNET', + coinType: 1, + name: 'Tezos Testnet', + fireblocksId: 'XTZ_TEST' + }, + { + networkId: 'DASH', + coinType: 5, + name: 'Dash', + fireblocksId: 'DASH' + }, + { + networkId: 'DASH_TESTNET', + coinType: 1, + name: 'Dash Testnet', + fireblocksId: 'DASH_TEST' + }, + { + networkId: 'OPTIMISM', + coinType: 614, + name: 'Optimism', + fireblocksId: 'ETH-OPT' + }, + { + networkId: 'OPTIMISM_SEPOLIA', + coinType: 1, + name: 'Optimism Sepolia', + fireblocksId: 'ETH-OPT_SEPOLIA' + }, + { + networkId: 'OPTIMISM_KOVAN', + coinType: 1, + name: 'Optimism Kovan', + fireblocksId: 'ETH-OPT_KOV' + } +] + +@Injectable() +export class NetworkRepository { + private networkById: Map + private networkByProviderAndExternalId: Map + private networksByProvider: Map + + constructor() { + this.index() + } + + /** + * Builds index structures for O(1) lookups of networks. + * + * Creates three indexes: + * - networkById: Maps networkId -> Network for direct lookups + * - networkByProviderAndExternalId: Maps "provider:externalId" -> Network for external ID lookups + * - networksByProvider: Maps provider -> Network[] for provider-specific filtering + * + * This is a one-time O(n) operation at initialization to avoid O(n) + * array traversals on subsequent queries. All lookups become O(1) + * after indexing at the cost of O(n) additional memory. + */ + private index(): void { + this.networkById = new Map() + this.networkByProviderAndExternalId = new Map() + this.networksByProvider = new Map() + + for (const network of NETWORKS) { + this.networkById.set(network.networkId, network) + + if (network.anchorageId) { + const key = `${Provider.ANCHORAGE}:${network.anchorageId}` + this.networkByProviderAndExternalId.set(key, network) + + const providerNetworks = this.networksByProvider.get(Provider.ANCHORAGE) || [] + providerNetworks.push(network) + + this.networksByProvider.set(Provider.ANCHORAGE, providerNetworks) + } + + if (network.fireblocksId) { + const key = `${Provider.FIREBLOCKS}:${network.fireblocksId}` + this.networkByProviderAndExternalId.set(key, network) + + const providerNetworks = this.networksByProvider.get(Provider.FIREBLOCKS) || [] + providerNetworks.push(network) + + this.networksByProvider.set(Provider.FIREBLOCKS, providerNetworks) + } + } + } + + async findAll(options?: FindAllOptions): Promise { + if (!options?.filters?.provider) { + return NETWORKS + } + + return this.networksByProvider.get(options.filters.provider) || [] + } + + async findById(networkId: string): Promise { + return this.networkById.get(networkId) || null + } + + async findByExternalId(provider: Provider, externalId: string): Promise { + const key = `${provider}:${externalId}` + + return this.networkByProviderAndExternalId.get(key) || null + } +} diff --git a/packages/policy-engine-shared/src/index.ts b/packages/policy-engine-shared/src/index.ts index b9c27e8fb..b64777d9b 100644 --- a/packages/policy-engine-shared/src/index.ts +++ b/packages/policy-engine-shared/src/index.ts @@ -22,6 +22,4 @@ export * from './lib/util/json.util' export * from './lib/util/transaction.util' export * from './lib/util/typeguards' -export * from './lib/resource/networks' - export * as FIXTURE from './lib/dev.fixture' diff --git a/packages/policy-engine-shared/src/lib/resource/networks.ts b/packages/policy-engine-shared/src/lib/resource/networks.ts deleted file mode 100644 index 4569e1094..000000000 --- a/packages/policy-engine-shared/src/lib/resource/networks.ts +++ /dev/null @@ -1,324 +0,0 @@ -export const NETWORK_INFO = [ - { - networkId: 'AGORIC_MAINNET', - anchorageId: 'BLD', - coinType: 564, - name: 'Agoric', - addressValidationRegex: '^agoric(valoper)?1[ac-hj-np-z02-9]{7,88}$|^AGORIC(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' - }, - { - networkId: 'ALLORA_MAINNET', - anchorageId: 'ALLO', - coinType: null, - name: 'Allora', - addressValidationRegex: '^allo(valoper)?1[ac-hj-np-z02-9]{7,88}$|^ALLO(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' - }, - { - networkId: 'ALLORA_TESTNET', - anchorageId: 'ALLO_T', - coinType: 1, - name: 'Allora Testnet', - addressValidationRegex: '^allo(valoper)?1[ac-hj-np-z02-9]{7,88}$|^ALLO(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' - }, - { - networkId: 'APTOS_MAINNET', - anchorageId: 'APT', - coinType: 637, - name: 'Aptos', - addressValidationRegex: '^(0x)?[0-9a-fA-F]{1,64}$' - }, - { - networkId: 'APTOS_TESTNET', - anchorageId: 'APT_T', - coinType: 1, - name: 'Aptos Testnet', - addressValidationRegex: '^(0x)?[0-9a-fA-F]{1,64}$' - }, - { - networkId: 'AXELAR_MAINNET', - anchorageId: 'AXL', - coinType: null, - name: 'Axelar', - addressValidationRegex: '^axelar(valoper)?1[ac-hj-np-z02-9]{7,88}$|^AXELAR(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' - }, - { - networkId: 'AXELAR_TESTNET', - anchorageId: 'AXL_T', - coinType: 1, - name: 'Axelar Testnet', - addressValidationRegex: '^axelar(valoper)?1[ac-hj-np-z02-9]{7,88}$|^AXELAR(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' - }, - { - networkId: 'BABYLON_MAINNET', - anchorageId: 'BBN', - coinType: null, - name: 'Babylon', - addressValidationRegex: '^bbn(valoper)?1[ac-hj-np-z02-9]{7,88}$|^BBN(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' - }, - { - networkId: 'BITCOIN_MAINNET', - anchorageId: 'BTC', - coinType: 0, - name: 'Bitcoin', - addressValidationRegex: '^[13][a-km-zA-HJ-NP-Z1-9]{25,40}$|^bc1q[ac-hj-np-z02-9]{38,38}$|^BC1Q[AC-HJ-NP-Z02-9]{38,38}$|^bc1q[ac-hj-np-z02-9]{58,58}$|^BC1Q[AC-HJ-NP-Z02-9]{58,58}$|^bc1p[ac-hj-np-z02-9]{58,58}$|^BC1P[AC-HJ-NP-Z02-9]{58,58}$' - }, - { - networkId: 'BITCOIN_CASH_MAINNET', - anchorageId: 'BCH', - coinType: 145, - name: 'Bitcoin Cash', - addressValidationRegex: '^[13][a-km-zA-HJ-NP-Z1-9]{25,40}$|^(bitcoincash:)?[ac-hj-np-z02-9]{11,78}$|^(BITCOINCASH:)?[AC-HJ-NP-Z02-9]{11,78}$' - }, - { - networkId: 'BITCOIN_SIGNET', - anchorageId: 'BTC_S', - coinType: null, - name: 'Bitcoin Signet', - addressValidationRegex: '^[2nm][a-km-zA-HJ-NP-Z1-9]{25,40}$|^tb1q[ac-hj-np-z02-9]{38,38}$|^TB1Q[AC-HJ-NP-Z02-9]{38,38}$|^tb1q[ac-hj-np-z02-9]{58,58}$|^TB1Q[AC-HJ-NP-Z02-9]{58,58}$|^tb1p[ac-hj-np-z02-9]{58,58}$|^TB1P[AC-HJ-NP-Z02-9]{58,58}$' - }, - { - networkId: 'CELESTIA_MAINNET', - anchorageId: 'TIA', - coinType: null, - name: 'Celestia', - addressValidationRegex: '^celestia(valoper)?1[ac-hj-np-z02-9]{7,88}$|^CELESTIA(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' - }, - { - networkId: 'CELO_BAKLAVA', - anchorageId: 'CGLD_TB', - coinType: 1, - name: 'Celo Baklava', - addressValidationRegex: '^(0x)?[0-9a-fA-F]{40}$' - }, - { - networkId: 'COSMOS_MAINNET', - anchorageId: 'ATOM', - coinType: 118, - name: 'Cosmos', - addressValidationRegex: '^cosmos(valoper)?1[ac-hj-np-z02-9]{7,88}$|^COSMOS(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' - }, - { - networkId: 'DOGECOIN_MAINNET', - anchorageId: 'DOGE', - coinType: 3, - name: 'Dogecoin', - addressValidationRegex: '^[AD9][a-km-zA-HJ-NP-Z1-9]{25,40}$' - }, - { - networkId: 'DYDX_CHAIN_MAINNET', - anchorageId: 'DYDX_CHAIN', - coinType: null, - name: 'Dydx Chain', - addressValidationRegex: '^dydx(valoper)?1[ac-hj-np-z02-9]{7,88}$|^DYDX(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' - }, - { - networkId: 'DYDX_CHAIN_TESTNET', - anchorageId: 'DYDX_CHAIN_T', - coinType: 1, - name: 'Dydx Testnet', - addressValidationRegex: '^dydx(valoper)?1[ac-hj-np-z02-9]{7,88}$|^DYDX(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' - }, - { - networkId: 'ETHEREUM_MAINNET', - anchorageId: 'ETH', - coinType: 60, - name: 'Ethereum', - addressValidationRegex: '^(0x)?[0-9a-fA-F]{40}$' - }, - { - networkId: 'ETHEREUM_HOLESKY', - anchorageId: 'ETHHOL', - coinType: 1, - name: 'Ethereum Holešky', - addressValidationRegex: '^(0x)?[0-9a-fA-F]{40}$' - }, - { - networkId: 'ETHEREUM_SEPOLIA', - anchorageId: 'ETHSEP', - coinType: 1, - name: 'Ethereum Sepolia', - addressValidationRegex: '^(0x)?[0-9a-fA-F]{40}$' - }, - { - networkId: 'ARBITRUM_SEPOLIA', - anchorageId: 'ETH_ARBITRUM_T', - coinType: 1, - name: 'Arbitrum Sepolia Testnet', - addressValidationRegex: '^(0x)?[0-9a-fA-F]{40}$' - }, - { - networkId: 'PLUME_SEPOLIA', - anchorageId: 'ETH_PLUME_T', - coinType: 1, - name: 'Plume Sepolia Testnet', - addressValidationRegex: '^(0x)?[0-9a-fA-F]{40}$' - }, - { - networkId: 'ZKSYNC_SEPOLIA', - anchorageId: 'ETH_ZKSYNC_T', - coinType: 1, - name: 'ZKsync Sepolia Testnet', - addressValidationRegex: '^(0x)?[0-9a-fA-F]{40}$' - }, - { - networkId: 'EVMOS_MAINNET', - anchorageId: 'EVMOS', - coinType: null, - name: 'Evmos', - addressValidationRegex: '^evmos(valoper)?1[ac-hj-np-z02-9]{7,88}$|^EVMOS(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' - }, - { - networkId: 'EVMOS_TESTNET', - anchorageId: 'EVMOS_T', - coinType: 1, - name: 'Evmos Testnet', - addressValidationRegex: '^evmos(valoper)?1[ac-hj-np-z02-9]{7,88}$|^EVMOS(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' - }, - { - networkId: 'FILECOIN_MAINNET', - anchorageId: 'FIL', - coinType: 461, - name: 'Filecoin', - addressValidationRegex: '^[ft](0[0-9]{1,20}|[12][a-z2-7]{39}|3[a-z2-7]{84})$' - }, - { - networkId: 'FLOW_TESTNET', - anchorageId: 'FLOW_T', - coinType: 1, - name: 'Flow Testnet', - addressValidationRegex: '^(0x)?[0-9a-fA-F]{16}$' - }, - { - networkId: 'LITECOIN_MAINNET', - anchorageId: 'LTC', - coinType: 2, - name: 'Litecoin', - addressValidationRegex: '^[LM][a-km-zA-HJ-NP-Z1-9]{25,40}$|^ltc1q[ac-hj-np-z02-9]{38,38}$|^LTC1Q[AC-HJ-NP-Z02-9]{38,38}$|^ltc1q[ac-hj-np-z02-9]{58,58}$|^LTC1Q[AC-HJ-NP-Z02-9]{58,58}$' - }, - { - networkId: 'NEUTRON_MAINNET', - anchorageId: 'NTRN', - coinType: null, - name: 'Neutron', - addressValidationRegex: '^neutron(valoper)?1[ac-hj-np-z02-9]{7,88}$|^NEUTRON(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' - }, - { - networkId: 'OM_MANTRA_MAINNET', - anchorageId: 'OM_MANTRA', - coinType: null, - name: 'OM Mantra', - addressValidationRegex: '^mantra(valoper)?1[ac-hj-np-z02-9]{7,88}$|^MANTRA(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' - }, - { - networkId: 'OM_MANTRA_TESTNET', - anchorageId: 'OM_MANTRA_T', - coinType: 1, - name: 'OM Mantra Testnet', - addressValidationRegex: '^mantra(valoper)?1[ac-hj-np-z02-9]{7,88}$|^MANTRA(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' - }, - { - networkId: 'OASIS_MAINNET', - anchorageId: 'ROSE', - coinType: 474, - name: 'Oasis', - addressValidationRegex: '^oasis1[ac-hj-np-z02-9]{39,59}$|^OASIS1[AC-HJ-NP-Z02-9]{39,59}$' - }, - { - networkId: 'OSMOSIS_MAINNET', - anchorageId: 'OSMO', - coinType: 10000118, - name: 'Osmosis', - addressValidationRegex: '^osmo(valoper)?1[ac-hj-np-z02-9]{7,88}$|^OSMO(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' - }, - { - networkId: 'POLYGON_MAINNET', - anchorageId: 'MATIC_POLYGON', - coinType: 966, - name: 'Polygon', - addressValidationRegex: '^(0x)?[0-9a-fA-F]{40}$' - }, - { - networkId: 'PROVENANCE_MAINNET', - anchorageId: 'HASH', - coinType: 505, - name: 'Provenance', - addressValidationRegex: '^pb(valoper)?1[ac-hj-np-z02-9]{7,88}$|^PB(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' - }, - { - networkId: 'RARIMO_MAINNET', - anchorageId: 'RMO', - coinType: null, - name: 'Rarimo', - addressValidationRegex: '^rarimo(valoper)?1[ac-hj-np-z02-9]{7,88}$|^RARIMO(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' - }, - { - networkId: 'RIPPLE_MAINNET', - anchorageId: 'XRP', - coinType: 144, - name: 'Ripple', - addressValidationRegex: '^r[a-km-zA-HJ-NP-Z1-9]{24,34}$' - }, - { - networkId: 'SEI_MAINNET', - anchorageId: 'SEI', - coinType: 19000118, - name: 'Sei', - addressValidationRegex: '^sei(valoper)?1[ac-hj-np-z02-9]{7,88}$|^SEI(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' - }, - { - networkId: 'SEI_TESTNET', - anchorageId: 'SEI_T', - coinType: 1, - name: 'Sei Testnet', - addressValidationRegex: '^sei(valoper)?1[ac-hj-np-z02-9]{7,88}$|^SEI(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' - }, - { - networkId: 'SOLANA_DEVNET', - anchorageId: 'SOL_TD', - coinType: 1, - name: 'Solana Devnet', - addressValidationRegex: '^[a-km-zA-HJ-NP-Z1-9]{32,44}$' - }, - { - networkId: 'STARKNET_MAINNET', - anchorageId: 'STRK_STARKNET', - coinType: 9004, - name: 'Starknet', - addressValidationRegex: '^(0x)?[0-9a-fA-F]{1,64}$' - }, - { - networkId: 'STARKNET_TESTNET', - anchorageId: 'STRK_STARKNET_T', - coinType: 1, - name: 'Starknet Testnet', - addressValidationRegex: '^(0x)?[0-9a-fA-F]{1,64}$' - }, - { - networkId: 'STRIDE_MAINNET', - anchorageId: 'STRD', - coinType: null, - name: 'Stride', - addressValidationRegex: '^stride(valoper)?1[ac-hj-np-z02-9]{7,88}$|^STRIDE(VALOPER)?1[AC-HJ-NP-Z02-9]{7,88}$' - }, - { - networkId: 'SUI_TESTNET', - anchorageId: 'SUI_T', - coinType: 1, - name: 'Sui Testnet', - addressValidationRegex: '^0x[a-fA-F0-9]{64}$' - }, - { - networkId: 'VANA_MOKSHA_TESTNET', - anchorageId: 'VANA_VANA_MOKSHA_T', - coinType: 1, - name: 'Vana Moksha Testnet', - addressValidationRegex: '^(0x)?[0-9a-fA-F]{40}$' - }, - { - networkId: 'VANA_MAINNET', - anchorageId: 'VANA_VANA', - coinType: null, - name: 'Vana', - addressValidationRegex: '^(0x)?[0-9a-fA-F]{40}$' - } -] \ No newline at end of file From 27529d1e4fed41825a3677d1d61085eba2b447bf Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Tue, 7 Jan 2025 18:19:28 +0100 Subject: [PATCH 077/120] Map Anchorage network ID during the sync (#74) --- .../anchorage-sync.service.spec.ts | 8 +- .../anchorage/anchorage-sync.service.ts | 104 ++++++++++++------ .../src/broker/core/service/sync.service.ts | 41 ++++++- .../src/broker/core/type/provider.type.ts | 17 ++- .../repository/network.repository.ts | 2 +- 5 files changed, 134 insertions(+), 38 deletions(-) diff --git a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-sync.service.spec.ts b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-sync.service.spec.ts index 736016f91..f1ed2229b 100644 --- a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-sync.service.spec.ts +++ b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-sync.service.spec.ts @@ -29,6 +29,7 @@ import { isCreateOperation, isDeleteOperation, isFailedOperation, + isSkipOperation, isUpdateOperation } from '../../../../type/provider.type' import { buildEmptyContext } from '../../../../util/provider-sync.util' @@ -219,6 +220,7 @@ describe(AnchorageSyncService.name, () => { expect(secondSync.wallets.filter(isCreateOperation)).toHaveLength(0) expect(secondSync.wallets.filter(isUpdateOperation)).toHaveLength(1) expect(secondSync.wallets.filter(isDeleteOperation)).toHaveLength(0) + expect(secondSync.wallets.filter(isSkipOperation)).toHaveLength(0) expect(secondSync.wallets.filter(isFailedOperation)).toHaveLength(0) expect(secondSync.wallets.filter(isUpdateOperation)[0]).toEqual({ @@ -270,6 +272,7 @@ describe(AnchorageSyncService.name, () => { expect(result.accounts.filter(isCreateOperation)).toHaveLength(18) expect(result.accounts.filter(isUpdateOperation)).toHaveLength(0) expect(result.accounts.filter(isDeleteOperation)).toHaveLength(0) + expect(result.accounts.filter(isSkipOperation)).toHaveLength(0) expect(result.accounts.filter(isFailedOperation)).toHaveLength(0) expect(result.accounts.filter(isCreateOperation)[0]).toEqual({ @@ -284,7 +287,7 @@ describe(AnchorageSyncService.name, () => { externalId: '145ff5b10e0e208b9c3adab0a9531f0c', createdAt: now, updatedAt: now, - networkId: 'BTC' + networkId: 'BITCOIN' } }) }) @@ -354,6 +357,7 @@ describe(AnchorageSyncService.name, () => { expect(result.addresses.filter(isCreateOperation)).toHaveLength(1) expect(result.addresses.filter(isUpdateOperation)).toHaveLength(0) expect(result.addresses.filter(isDeleteOperation)).toHaveLength(0) + expect(result.addresses.filter(isSkipOperation)).toHaveLength(0) expect(result.addresses.filter(isFailedOperation)).toHaveLength(0) expect(result.addresses.filter(isCreateOperation)[0]).toEqual({ @@ -407,6 +411,7 @@ describe(AnchorageSyncService.name, () => { expect(result.knownDestinations.filter(isCreateOperation)).toHaveLength(4) expect(result.knownDestinations.filter(isUpdateOperation)).toHaveLength(0) expect(result.knownDestinations.filter(isDeleteOperation)).toHaveLength(0) + expect(result.knownDestinations.filter(isSkipOperation)).toHaveLength(0) expect(result.knownDestinations.filter(isFailedOperation)).toHaveLength(0) expect(result.knownDestinations.filter(isCreateOperation)[0]).toEqual({ @@ -503,6 +508,7 @@ describe(AnchorageSyncService.name, () => { expect(secondSync.knownDestinations.filter(isCreateOperation)).toHaveLength(0) expect(secondSync.knownDestinations.filter(isUpdateOperation)).toHaveLength(1) expect(secondSync.knownDestinations.filter(isDeleteOperation)).toHaveLength(3) + expect(secondSync.knownDestinations.filter(isSkipOperation)).toHaveLength(0) expect(secondSync.knownDestinations.filter(isFailedOperation)).toHaveLength(0) expect(secondSync.knownDestinations.filter(isUpdateOperation)[0]).toEqual({ diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage-sync.service.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage-sync.service.ts index 7ad111301..b839d50d9 100644 --- a/apps/vault/src/broker/core/provider/anchorage/anchorage-sync.service.ts +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage-sync.service.ts @@ -3,16 +3,19 @@ import { Injectable } from '@nestjs/common' import { randomUUID } from 'crypto' import { uniq } from 'lodash' import { AnchorageClient } from '../../../http/client/anchorage.client' +import { UpdateAccount } from '../../../persistence/repository/account.repository' +import { NetworkRepository } from '../../../persistence/repository/network.repository' import { AccountService } from '../../service/account.service' import { AddressService } from '../../service/address.service' import { KnownDestinationService } from '../../service/known-destination.service' import { WalletService } from '../../service/wallet.service' import { Connection, ConnectionWithCredentials } from '../../type/connection.type' -import { Address, KnownDestination, Wallet } from '../../type/indexed-resources.type' +import { Account, Address, KnownDestination, Wallet } from '../../type/indexed-resources.type' import { Provider, ProviderSyncService, SyncContext, + SyncOperation, SyncOperationType, SyncResult, isCreateOperation @@ -28,6 +31,7 @@ export class AnchorageSyncService implements ProviderSyncService { private readonly accountService: AccountService, private readonly addressService: AddressService, private readonly knownDestinationService: KnownDestinationService, + private readonly networkRepository: NetworkRepository, private readonly logger: LoggerService ) {} @@ -169,7 +173,9 @@ export class AnchorageSyncService implements ProviderSyncService { const now = context.now ?? new Date() - const operations = missingAnchorageWallets.map((anchorageWallet) => { + const operations: SyncOperation[] = [] + + for (const anchorageWallet of missingAnchorageWallets) { const externalId = anchorageWallet.walletId const parentExternalId = anchorageWallet.vaultId // Either look up the existing wallets in the database or in the sync context. @@ -177,31 +183,44 @@ export class AnchorageSyncService implements ProviderSyncService { contextWalletsIndexedByExternalId.get(parentExternalId) || walletsIndexedByExternalId.get(parentExternalId) if (wallet) { - return { - type: SyncOperationType.CREATE, - create: { - accountId: randomUUID(), - walletId: wallet.walletId, - label: anchorageWallet.walletName, - clientId: connection.clientId, - provider: Provider.ANCHORAGE, - addresses: [], + const network = await this.networkRepository.findByExternalId(Provider.ANCHORAGE, anchorageWallet.networkId) + + if (network) { + operations.push({ + type: SyncOperationType.CREATE, + create: { + externalId, + accountId: randomUUID(), + addresses: [], + clientId: connection.clientId, + createdAt: now, + label: anchorageWallet.walletName, + networkId: network.networkId, + provider: Provider.ANCHORAGE, + updatedAt: now, + walletId: wallet.walletId + } + }) + } else { + operations.push({ + type: SyncOperationType.SKIP, externalId, - createdAt: now, - updatedAt: now, - // TODO: Map their networkId to SLIP 44 format. - networkId: anchorageWallet.networkId - } + message: 'Unknown Anchorage wallet network ID', + context: { + externalId, + anchorageNetworkId: anchorageWallet.networkId + } + }) } + } else { + operations.push({ + type: SyncOperationType.FAILED, + externalId, + message: 'Parent wallet for account not found', + context: { anchorageWalletId: parentExternalId } + }) } - - return { - type: SyncOperationType.FAILED, - externalId, - message: 'Parent wallet for account not found', - context: { anchorageWalletId: parentExternalId } - } - }) + } return { ...context, @@ -362,14 +381,25 @@ export class AnchorageSyncService implements ProviderSyncService { }, []) .map((update) => ({ type: SyncOperationType.UPDATE, update })) - const createOperations = anchorageTrustedDestinations - .filter((anchorageTrustedAddress) => !existingMap.has(anchorageTrustedAddress.id)) - .map((anchorageTrustedAddress) => - KnownDestination.parse({ + const missingDestinations = anchorageTrustedDestinations.filter( + (anchorageTrustedAddress) => !existingMap.has(anchorageTrustedAddress.id) + ) + + const createOperations: SyncOperation[] = [] + + for (const anchorageTrustedAddress of missingDestinations) { + const externalId = anchorageTrustedAddress.id + const network = await this.networkRepository.findByExternalId( + Provider.ANCHORAGE, + anchorageTrustedAddress.crypto.networkId + ) + + if (network) { + const knownDestination = KnownDestination.parse({ + externalId, knownDestinationId: randomUUID(), address: anchorageTrustedAddress.crypto.address, clientId: connection.clientId, - externalId: anchorageTrustedAddress.id, label: anchorageTrustedAddress.crypto.memo, assetId: anchorageTrustedAddress.crypto.assetType, provider: Provider.ANCHORAGE, @@ -378,8 +408,20 @@ export class AnchorageSyncService implements ProviderSyncService { updatedAt: now, connections: [connection] }) - ) - .map((kd) => ({ type: SyncOperationType.CREATE, create: kd })) + + createOperations.push({ type: SyncOperationType.CREATE, create: knownDestination }) + } else { + createOperations.push({ + type: SyncOperationType.SKIP, + externalId, + message: 'Unknown Anchorage trusted address network ID', + context: { + externalId, + anchorageNetworkId: anchorageTrustedAddress.crypto.networkId + } + }) + } + } const deleteOperations = existingKnownDestinations .filter((dest) => !incomingMap.has(dest.externalId)) diff --git a/apps/vault/src/broker/core/service/sync.service.ts b/apps/vault/src/broker/core/service/sync.service.ts index b9650fad9..d11fa1283 100644 --- a/apps/vault/src/broker/core/service/sync.service.ts +++ b/apps/vault/src/broker/core/service/sync.service.ts @@ -17,6 +17,7 @@ import { isCreateOperation, isDeleteOperation, isFailedOperation, + isSkipOperation, isUpdateOperation } from '../type/provider.type' import { StartSync, Sync, SyncStarted, SyncStatus } from '../type/sync.type' @@ -156,16 +157,19 @@ export class SyncService { const walletCreateOperations = result.wallets.filter(isCreateOperation).map(({ create }) => create) const walletUpdateOperations = result.wallets.filter(isUpdateOperation).map(({ update }) => update) const walletDeleteOperations = result.wallets.filter(isDeleteOperation).map(({ entityId }) => entityId) + const walletSkipOperations = result.wallets.filter(isSkipOperation) const walletFailedOperations = result.wallets.filter(isFailedOperation) const accountCreateOperations = result.accounts.filter(isCreateOperation).map(({ create }) => create) const accountUpdateOperations = result.accounts.filter(isUpdateOperation).map(({ update }) => update) const accountDeleteOperations = result.accounts.filter(isDeleteOperation).map(({ entityId }) => entityId) + const accountSkipOperations = result.accounts.filter(isSkipOperation) const accountFailedOperations = result.accounts.filter(isFailedOperation) const addressCreateOperations = result.addresses.filter(isCreateOperation).map(({ create }) => create) const addressUpdateOperations = result.addresses.filter(isUpdateOperation).map(({ update }) => update) const addressDeleteOperations = result.addresses.filter(isDeleteOperation).map(({ entityId }) => entityId) + const addressSkipOperations = result.addresses.filter(isSkipOperation) const addressFailedOperations = result.addresses.filter(isFailedOperation) const knownDestinationCreateOperations = result.knownDestinations @@ -177,6 +181,7 @@ export class SyncService { const knownDestinationDeleteOperations = result.knownDestinations .filter(isDeleteOperation) .map(({ entityId }) => entityId) + const knownDestinationSkipOperations = result.knownDestinations.filter(isSkipOperation) const knownDestinationFailedOperations = result.knownDestinations.filter(isFailedOperation) this.logger.log('Execute sync operations', { @@ -187,53 +192,81 @@ export class SyncService { create: walletCreateOperations.length, update: walletUpdateOperations.length, delete: walletDeleteOperations.length, + skip: walletSkipOperations.length, failed: walletFailedOperations.length }, account: { create: accountCreateOperations.length, update: accountUpdateOperations.length, delete: accountDeleteOperations.length, + skip: accountSkipOperations.length, failed: accountFailedOperations.length }, address: { create: addressCreateOperations.length, update: addressUpdateOperations.length, delete: addressDeleteOperations.length, + skip: addressSkipOperations.length, failed: addressFailedOperations.length }, knownDestination: { create: knownDestinationCreateOperations.length, update: knownDestinationUpdateOperations.length, delete: knownDestinationDeleteOperations.length, + skip: knownDestinationSkipOperations.length, failed: knownDestinationFailedOperations.length } } }) if (walletFailedOperations.length) { - this.logger.warn('Sync operations contains failures for wallets', { + this.logger.error('Sync operations contains failures for wallets', { operations: walletFailedOperations }) } + if (walletSkipOperations.length) { + this.logger.error('Sync operations contains skips for wallets', { + operations: walletSkipOperations + }) + } + if (accountFailedOperations.length) { - this.logger.warn('Sync operations contains failures for accounts', { + this.logger.error('Sync operations contains failures for accounts', { operations: accountFailedOperations }) } + if (accountSkipOperations.length) { + this.logger.error('Sync operations contains skips for accounts', { + operations: accountSkipOperations + }) + } + if (addressFailedOperations.length) { - this.logger.warn('Sync operations contains failures for addresses', { + this.logger.error('Sync operations contains failures for addresses', { operations: addressFailedOperations }) } + if (addressSkipOperations.length) { + this.logger.error('Sync operations contains skips for addresses', { + operations: addressSkipOperations + }) + } + if (knownDestinationFailedOperations.length) { - this.logger.warn('Sync operations contains failures for known destinations', { + this.logger.error('Sync operations contains failures for known destinations', { operations: knownDestinationFailedOperations }) } + if (knownDestinationSkipOperations.length) { + this.logger.error('Sync operations contains skips for known destinations', { + operations: knownDestinationSkipOperations + }) + } + try { this.logger.log('Execute wallet create operations', { syncId, clientId }) await this.walletService.bulkCreate(walletCreateOperations) diff --git a/apps/vault/src/broker/core/type/provider.type.ts b/apps/vault/src/broker/core/type/provider.type.ts index 7dc67e8f8..807c07afe 100644 --- a/apps/vault/src/broker/core/type/provider.type.ts +++ b/apps/vault/src/broker/core/type/provider.type.ts @@ -20,7 +20,8 @@ export const SyncOperationType = { CREATE: 'create', UPDATE: 'update', DELETE: 'delete', - FAILED: 'failed' + FAILED: 'failed', + SKIP: 'skip' } as const export type SyncOperationType = (typeof SyncOperationType)[keyof typeof SyncOperationType] @@ -46,6 +47,13 @@ export type FailedSyncOperation = { context?: unknown } +export type SkipSyncOperation = { + type: typeof SyncOperationType.SKIP + externalId: string + message: string + context?: unknown +} + /** * Represents a synchronization operation for a resource, which can be a * creation, update, or deletion. Each operation type is associated with @@ -59,6 +67,7 @@ export type SyncOperation = | UpdateSyncOperation | DeleteSyncOperation | FailedSyncOperation + | SkipSyncOperation export const isCreateOperation = ( operation: SyncOperation @@ -84,6 +93,12 @@ export const isFailedOperation = ( return operation.type === SyncOperationType.FAILED } +export const isSkipOperation = ( + operation: SyncOperation +): operation is SkipSyncOperation => { + return operation.type === SyncOperationType.SKIP +} + /** * Represents the context used during synchronization, containing the active * connection and maps of synchronization operations for various resource diff --git a/apps/vault/src/broker/persistence/repository/network.repository.ts b/apps/vault/src/broker/persistence/repository/network.repository.ts index f480bf8a7..3c8e64954 100644 --- a/apps/vault/src/broker/persistence/repository/network.repository.ts +++ b/apps/vault/src/broker/persistence/repository/network.repository.ts @@ -375,7 +375,7 @@ const NETWORKS: Network[] = [ networkId: 'POLYGON', coinType: 966, name: 'Polygon', - anchorageId: 'MATIC_POLYGON', + anchorageId: 'POL_POLYGON', fireblocksId: 'MATIC_POLYGON' }, { From 75d1ebc3d64f808d3090a053a7ddcb23bd73f8e0 Mon Sep 17 00:00:00 2001 From: Matt Schoch Date: Tue, 7 Jan 2025 18:22:52 +0100 Subject: [PATCH 078/120] Adding transfer.asset field & resolving Destination address based on network (#75) --- .../src/broker/__test__/e2e/transfer.spec.ts | 6 +- .../anchorage-transfer.service.spec.ts | 12 +- .../provider/anchorage/anchorage-assets.ts | 2618 +++++++++++++++++ .../anchorage/anchorage-transfer.service.ts | 65 +- .../core/service/transfer-party.service.ts | 37 +- .../broker/core/service/transfer.service.ts | 7 +- .../src/broker/core/type/transfer.type.ts | 24 +- .../repository/address.repository.ts | 28 +- .../known-destination.repository.ts | 8 + .../src/lib/http/client/vault/api.ts | 41 +- packages/armory-sdk/src/lib/vault/client.ts | 14 + 11 files changed, 2816 insertions(+), 44 deletions(-) create mode 100644 apps/vault/src/broker/core/provider/anchorage/anchorage-assets.ts diff --git a/apps/vault/src/broker/__test__/e2e/transfer.spec.ts b/apps/vault/src/broker/__test__/e2e/transfer.spec.ts index 1af58a0a6..4244c8a66 100644 --- a/apps/vault/src/broker/__test__/e2e/transfer.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/transfer.spec.ts @@ -203,7 +203,9 @@ describe('Transfer', () => { id: accountTwo.accountId }, amount: '0.0001', - assetId: 'BTC_S', + asset: { + assetId: 'BTC_S' + }, idempotenceId: uuid() } @@ -227,7 +229,7 @@ describe('Transfer', () => { data: { clientId, externalId, - assetId: requiredPayload.assetId, + assetId: requiredPayload.asset.assetId, createdAt: expect.any(String), customerRefId: null, destination: requiredPayload.destination, diff --git a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts index bf1e2da92..35d4a9fd7 100644 --- a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts +++ b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts @@ -85,7 +85,7 @@ describe(AnchorageTransferService.name, () => { createdAt: new Date(), externalId: uuid(), label: 'Account 1', - networkId: 'BTC', + networkId: 'BITCOIN', provider: Provider.ANCHORAGE, updatedAt: new Date(), walletId @@ -98,7 +98,7 @@ describe(AnchorageTransferService.name, () => { createdAt: new Date(), externalId: uuid(), label: 'Account 2', - networkId: 'BTC', + networkId: 'BITCOIN', provider: Provider.ANCHORAGE, updatedAt: new Date(), walletId @@ -133,7 +133,7 @@ describe(AnchorageTransferService.name, () => { createdAt: new Date(), externalId: uuid(), knownDestinationId: uuid(), - networkId: 'BTC', + networkId: 'BITCOIN', provider: Provider.ANCHORAGE, updatedAt: new Date() } @@ -274,7 +274,9 @@ describe(AnchorageTransferService.name, () => { id: accountTwo.accountId }, amount: '0.00005', - assetId: 'BTC', + asset: { + assetId: 'BTC' + }, idempotenceId: uuid() } @@ -345,7 +347,7 @@ describe(AnchorageTransferService.name, () => { type: 'WALLET', id: accountTwo.externalId }, - assetType: sendTransfer.assetId, + assetType: sendTransfer.asset.assetId, amount: sendTransfer.amount, transferMemo: sendTransfer.memo, idempotentId: sendTransfer.idempotenceId, diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage-assets.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage-assets.ts new file mode 100644 index 000000000..3aa426ab2 --- /dev/null +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage-assets.ts @@ -0,0 +1,2618 @@ +export type AnchorageAsset = { + assetType: string + decimals: number + name: string + networkId: string + onchainIdentifier?: string +} + +// TODO: move this into a Repository, map w/ other providers +export const ANCHORAGE_ASSETS: AnchorageAsset[] = [ + { + assetType: '1INCH', + decimals: 18, + name: '1inch', + networkId: 'ETH', + onchainIdentifier: '0x111111111117dc0aa78b770fa6a738034120c302' + }, + { + assetType: 'A8', + decimals: 18, + name: 'Ancient8', + networkId: 'ETH', + onchainIdentifier: '0x3e5a19c91266ad8ce2477b91585d1856b84062df' + }, + { + assetType: 'AAVE', + decimals: 18, + name: 'Aave', + networkId: 'ETH', + onchainIdentifier: '0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9' + }, + { + assetType: 'ACX', + decimals: 18, + name: 'Across Protocol Token', + networkId: 'ETH', + onchainIdentifier: '0x44108f0223a3c3028f5fe7aec7f9bb2e66bef82f' + }, + { + assetType: 'AJNA', + decimals: 18, + name: 'AjnaToken', + networkId: 'ETH', + onchainIdentifier: '0x9a96ec9b57fb64fbc60b423d1f4da7691bd35079' + }, + { + assetType: 'ALD', + decimals: 18, + name: 'Aladdin Token', + networkId: 'ETH', + onchainIdentifier: '0xb26c4b3ca601136daf98593feaeff9e0ca702a8d' + }, + { + assetType: 'ALICE', + decimals: 6, + name: 'My Neighbor Alice', + networkId: 'ETH', + onchainIdentifier: '0xac51066d7bec65dc4589368da368b212745d63e8' + }, + { + assetType: 'ALLO', + decimals: 18, + name: 'Allora', + networkId: 'ALLO' + }, + { + assetType: 'ALLO_T', + decimals: 18, + name: 'Allora Testnet', + networkId: 'ALLO_T' + }, + { + assetType: 'ALPHA', + decimals: 18, + name: 'Alpha Finance Lab', + networkId: 'ETH', + onchainIdentifier: '0xa1faa113cbe53436df28ff0aee54275c13b40975' + }, + { + assetType: 'ALT', + decimals: 18, + name: 'AltLayer Token', + networkId: 'ETH', + onchainIdentifier: '0x8457ca5040ad67fdebbcc8edce889a335bc0fbfb' + }, + { + assetType: 'AMP', + decimals: 18, + name: 'Amp', + networkId: 'ETH', + onchainIdentifier: '0xff20817765cb7f73d4bde2e66e067e58d11095c2' + }, + { + assetType: 'ANGLE', + decimals: 18, + name: 'Angle', + networkId: 'ETH', + onchainIdentifier: '0x31429d1856ad1377a8a0079410b297e1a9e214c2' + }, + { + assetType: 'ANKR', + decimals: 18, + name: 'Ankr Network', + networkId: 'ETH', + onchainIdentifier: '0x8290333cef9e6d528dd5618fb97a76f268f3edd4' + }, + { + assetType: 'ANT', + decimals: 18, + name: 'Aragon', + networkId: 'ETH', + onchainIdentifier: '0xa117000000f279d81a1d3cc75430faa017fa5a2e' + }, + { + assetType: 'APE', + decimals: 18, + name: 'ApeCoin', + networkId: 'ETH', + onchainIdentifier: '0x4d224452801aced8b2f0aebe155379bb5d594381' + }, + { + assetType: 'API3', + decimals: 18, + name: 'API3', + networkId: 'ETH', + onchainIdentifier: '0x0b38210ea11411557c13457d4da7dc6ea731b88a' + }, + { + assetType: 'APT', + decimals: 8, + name: 'Aptos', + networkId: 'APT' + }, + { + assetType: 'APT_T', + decimals: 8, + name: 'Aptos Testnet', + networkId: 'APT_T' + }, + { + assetType: 'ARB', + decimals: 18, + name: 'Arbitrum', + networkId: 'ETH', + onchainIdentifier: '0xb50721bcf8d664c30412cfbc6cf7a15145234ad1' + }, + { + assetType: 'ARB_ARBITRUM_T', + decimals: 18, + name: 'ARB on Arbitrum Sepolia', + networkId: 'ARBITRUM_SEPOLIA', + onchainIdentifier: '0xf0114170db316047e508ce4714142cfad49f767d' + }, + { + assetType: 'ARCD', + decimals: 18, + name: 'Arcade', + networkId: 'ETH', + onchainIdentifier: '0xe020b01b6fbd83066aa2e8ee0ccd1eb8d9cc70bf' + }, + { + assetType: 'ARKM', + decimals: 18, + name: 'Arkham', + networkId: 'ETH', + onchainIdentifier: '0x6e2a43be0b1d33b726f0ca3b8de60b3482b8b050' + }, + { + assetType: 'ASTO', + decimals: 18, + name: 'Altered State Token', + networkId: 'ETH', + onchainIdentifier: '0x823556202e86763853b40e9cde725f412e294689' + }, + { + assetType: 'ATA', + decimals: 18, + name: 'Automata', + networkId: 'ETH', + onchainIdentifier: '0xa2120b9e674d3fc3875f415a7df52e382f141225' + }, + { + assetType: 'ATOM', + decimals: 6, + name: 'Cosmos', + networkId: 'COSMOS' + }, + { + assetType: 'AUCTION', + decimals: 18, + name: 'Bounce', + networkId: 'ETH', + onchainIdentifier: '0xa9b1eb5908cfc3cdf91f9b8b3a74108598009096' + }, + { + assetType: 'AUDIO', + decimals: 18, + name: 'Audius', + networkId: 'ETH', + onchainIdentifier: '0x18aaa7115705e8be94bffebde57af9bfc265b998' + }, + { + assetType: 'AURORA', + decimals: 18, + name: 'Aurora', + networkId: 'ETH', + onchainIdentifier: '0xaaaaaa20d9e0e2461697782ef11675f668207961' + }, + { + assetType: 'AUSD', + decimals: 6, + name: 'AUSD', + networkId: 'ETH', + onchainIdentifier: '0x00000000efe302beaa2b3e6e1b18d08d69a9012a' + }, + { + assetType: 'AVA', + decimals: 18, + name: 'Jadu AVA', + networkId: 'ETH', + onchainIdentifier: '0x86fc6f6c6702cef7d3bae87ef41256715416db71' + }, + { + assetType: 'AVAIL', + decimals: 18, + name: 'Avail', + networkId: 'ETH', + onchainIdentifier: '0xeeb4d8400aeefafc1b2953e0094134a887c76bd8' + }, + { + assetType: 'AVG', + decimals: 18, + name: 'Avocado DAO Token', + networkId: 'ETH', + onchainIdentifier: '0xa41f142b6eb2b164f8164cae0716892ce02f311f' + }, + { + assetType: 'AXL', + decimals: 6, + name: 'Axelar', + networkId: 'AXL' + }, + { + assetType: 'AXL_T', + decimals: 6, + name: 'Axelar Testnet', + networkId: 'AXL_T' + }, + { + assetType: 'AXS', + decimals: 18, + name: 'Axie Infinity', + networkId: 'ETH', + onchainIdentifier: '0xbb0e17ef65f82ab018d8edd776e8dd940327b28b' + }, + { + assetType: 'AXS_OLD', + decimals: 18, + name: 'Axie Infinity Shard', + networkId: 'ETH', + onchainIdentifier: '0xf5d669627376ebd411e34b98f19c868c8aba5ada' + }, + { + assetType: 'AZIMUTH', + decimals: 18, + name: 'Azimuth Points', + networkId: 'ETH', + onchainIdentifier: '0x33eecbf908478c10614626a9d304bfe18b78dd73' + }, + { + assetType: 'BADGER', + decimals: 18, + name: 'Badger DAO', + networkId: 'ETH', + onchainIdentifier: '0x3472a5a71965499acd81997a54bba8d852c6e53d' + }, + { + assetType: 'BAL', + decimals: 18, + name: 'Balancer', + networkId: 'ETH', + onchainIdentifier: '0xba100000625a3754423978a60c9317c58a424e3d' + }, + { + assetType: 'BANANA', + decimals: 18, + name: 'Banana', + networkId: 'ETH', + onchainIdentifier: '0x38e68a37e401f7271568cecaac63c6b1e19130b4' + }, + { + assetType: 'BAND', + decimals: 18, + name: 'BandToken', + networkId: 'ETH', + onchainIdentifier: '0xba11d00c5f74255f56a5e366f4f77f5a186d7f55' + }, + { + assetType: 'BAT', + decimals: 18, + name: 'Basic Attention', + networkId: 'ETH', + onchainIdentifier: '0x0d8775f648430679a709e98d2b0cb6250d2887ef' + }, + { + assetType: 'BAYC', + decimals: 18, + name: 'Bored Ape Yacht Club', + networkId: 'ETH', + onchainIdentifier: '0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d' + }, + { + assetType: 'BBN', + decimals: 6, + name: 'Babylon', + networkId: 'BBN' + }, + { + assetType: 'BCH', + decimals: 8, + name: 'Bitcoin Cash', + networkId: 'BCH' + }, + { + assetType: 'BEAM', + decimals: 18, + name: 'Beam', + networkId: 'ETH', + onchainIdentifier: '0x62d0a8458ed7719fdaf978fe5929c6d342b0bfce' + }, + { + assetType: 'BETA', + decimals: 18, + name: 'Beta Finance', + networkId: 'ETH', + onchainIdentifier: '0xbe1a001fe942f96eea22ba08783140b9dcc09d28' + }, + { + assetType: 'BGB_OLD', + decimals: 18, + name: 'BitgetToken', + networkId: 'ETH', + onchainIdentifier: '0x19de6b897ed14a376dda0fe53a5420d2ac828a28' + }, + { + assetType: 'BICO', + decimals: 18, + name: 'Biconomy Token', + networkId: 'ETH', + onchainIdentifier: '0xf17e65822b568b3903685a7c9f496cf7656cc6c2' + }, + { + assetType: 'BLD', + decimals: 6, + name: 'Agoric', + networkId: 'BLD' + }, + { + assetType: 'BLUR', + decimals: 18, + name: 'Blur', + networkId: 'ETH', + onchainIdentifier: '0x5283d291dbcf85356a21ba090e6db59121208b44' + }, + { + assetType: 'BNT', + decimals: 18, + name: 'Bancor', + networkId: 'ETH', + onchainIdentifier: '0x1f573d6fb3f13d689ff844b4ce37794d79a7ff1c' + }, + { + assetType: 'BOTTO', + decimals: 18, + name: 'Botto', + networkId: 'ETH', + onchainIdentifier: '0x9dfad1b7102d46b1b197b90095b5c4e9f5845bba' + }, + { + assetType: 'BREED', + decimals: 18, + name: 'BreederDAO', + networkId: 'ETH', + onchainIdentifier: '0x94e9eb8b5ab9fd6b9ea3169d55ffade62a01702e' + }, + { + assetType: 'BTC', + decimals: 8, + name: 'Bitcoin', + networkId: 'BTC' + }, + { + assetType: 'BTC_S', + decimals: 8, + name: 'Bitcoin Signet', + networkId: 'BTC_S' + }, + { + assetType: 'BTRST', + decimals: 18, + name: 'Braintrust', + networkId: 'ETH', + onchainIdentifier: '0x799ebfabe77a6e34311eeee9825190b9ece32824' + }, + { + assetType: 'BUIDL', + decimals: 6, + name: 'BlackRock USD Institutional Digital Liquidity Fund', + networkId: 'ETH', + onchainIdentifier: '0x7712c34205737192402172409a8f7ccef8aa2aec' + }, + { + assetType: 'BUIDLSEP', + decimals: 6, + name: 'BlackRock USD Institutional Digital Liquidity Fund (Sepolia Network)', + networkId: 'ETHSEP', + onchainIdentifier: '0xeb0609d3e6312f20bc82b6f500e0d266d6c3d8b5' + }, + { + assetType: 'BUIDL_APTOS', + decimals: 6, + name: 'Buidl on Aptos', + networkId: 'APT' + }, + { + assetType: 'BUSD', + decimals: 18, + name: 'Binance USD', + networkId: 'ETH', + onchainIdentifier: '0x4fabb145d64652a948d72533023f6e7a623c7c53' + }, + { + assetType: 'CBETH', + decimals: 18, + name: 'Coinbase Wrapped Staked ETH', + networkId: 'ETH', + onchainIdentifier: '0xbe9895146f7af43049ca1c1ae358b0541ea49704' + }, + { + assetType: 'CELLANA_APTOS', + decimals: 8, + name: 'CELLANA', + networkId: 'APT' + }, + { + assetType: 'CELO_TB', + decimals: 18, + name: 'Celo Testnet (Baklava)', + networkId: 'CELO_TB', + onchainIdentifier: '0xddc9be57f553fe75752d61606b94cbd7e0264ef8' + }, + { + assetType: 'CHZ', + decimals: 18, + name: 'Chiliz', + networkId: 'ETH', + onchainIdentifier: '0x3506424f91fd33084466f402d5d97f05f8e3b4af' + }, + { + assetType: 'CLONEX', + decimals: 18, + name: 'Clone X', + networkId: 'ETH', + onchainIdentifier: '0x49cf6f5d44e70224e2e23fdcdd2c053f30ada28b' + }, + { + assetType: 'COMP', + decimals: 18, + name: 'Compound', + networkId: 'ETH', + onchainIdentifier: '0xc00e94cb662c3520282e6f5717214004a7f26888' + }, + { + assetType: 'COW', + decimals: 18, + name: 'Cow Protocol Token', + networkId: 'ETH', + onchainIdentifier: '0xdef1ca1fb7fbcdc777520aa7f396b4e015f497ab' + }, + { + assetType: 'CPOOL', + decimals: 18, + name: 'Clearpool', + networkId: 'ETH', + onchainIdentifier: '0x66761fa41377003622aee3c7675fc7b5c1c2fac5' + }, + { + assetType: 'CQT', + decimals: 18, + name: 'Covalent Query Token', + networkId: 'ETH', + onchainIdentifier: '0xd417144312dbf50465b1c641d016962017ef6240' + }, + { + assetType: 'CREAM', + decimals: 18, + name: 'Cream Finance', + networkId: 'ETH', + onchainIdentifier: '0x2ba592f78db6436527729929aaf6c908497cb200' + }, + { + assetType: 'CRO', + decimals: 8, + name: 'Cronos', + networkId: 'ETH', + onchainIdentifier: '0xa0b73e1ff0b80914ab6fe0444e65848c4c34450b' + }, + { + assetType: 'CRV', + decimals: 18, + name: 'Curve DAO', + networkId: 'ETH', + onchainIdentifier: '0xd533a949740bb3306d119cc777fa900ba034cd52' + }, + { + assetType: 'CUSDC', + decimals: 8, + name: 'Compound USD Coin', + networkId: 'ETH', + onchainIdentifier: '0x39aa39c021dfbae8fac545936693ac917d5e7563' + }, + { + assetType: 'CVC', + decimals: 8, + name: 'Civic', + networkId: 'ETH', + onchainIdentifier: '0x41e5560054824ea6b0732e656e3ad64e20e94e45' + }, + { + assetType: 'CVX', + decimals: 18, + name: 'Convex Finance', + networkId: 'ETH', + onchainIdentifier: '0x4e3fbd56cd56c3e72c1403e103b45db9da5b9d2b' + }, + { + assetType: 'CYBER', + decimals: 18, + name: 'CyberConnect', + networkId: 'ETH', + onchainIdentifier: '0x14778860e937f509e651192a90589de711fb88a9' + }, + { + assetType: 'DAI', + decimals: 18, + name: 'Dai', + networkId: 'ETH', + onchainIdentifier: '0x6b175474e89094c44da98b954eedeac495271d0f' + }, + { + assetType: 'DAR', + decimals: 6, + name: 'Mines of Dalarnia', + networkId: 'ETH', + onchainIdentifier: '0x081131434f93063751813c619ecca9c4dc7862a3' + }, + { + assetType: 'DIMO', + decimals: 18, + name: 'Dimo', + networkId: 'ETH', + onchainIdentifier: '0x5fab9761d60419c9eeebe3915a8fa1ed7e8d2e1b' + }, + { + assetType: 'DODO', + decimals: 18, + name: 'DODO', + networkId: 'ETH', + onchainIdentifier: '0x43dfc4159d86f3a37a5a4b3d4580b888ad7d4ddd' + }, + { + assetType: 'DOGE', + decimals: 8, + name: 'Dogecoin', + networkId: 'DOGE' + }, + { + assetType: 'DPI', + decimals: 18, + name: 'DefiPulse Index', + networkId: 'ETH', + onchainIdentifier: '0x1494ca1f11d487c2bbe4543e90080aeba4ba3c2b' + }, + { + assetType: 'DYDX', + decimals: 18, + name: 'dYdX', + networkId: 'ETH', + onchainIdentifier: '0x92d6c1e31e14520e676a687f0a93788b716beff5' + }, + { + assetType: 'DYDX_CHAIN', + decimals: 18, + name: 'Dydx Chain', + networkId: 'DYDX_CHAIN' + }, + { + assetType: 'DYDX_CHAIN_T', + decimals: 18, + name: 'Dydx Chain Testnet', + networkId: 'DYDX_CHAIN_T' + }, + { + assetType: 'ECO', + decimals: 18, + name: 'Eco Fi Token', + networkId: 'ETH', + onchainIdentifier: '0xc242eb8e4e27eae6a2a728a41201152f19595c83' + }, + { + assetType: 'ECOX', + decimals: 18, + name: 'ECOx', + networkId: 'ETH', + onchainIdentifier: '0xcccd1ba9f7acd6117834e0d28f25645decb1736a' + }, + { + assetType: 'EIGEN', + decimals: 18, + name: 'Eigen', + networkId: 'ETH', + onchainIdentifier: '0xec53bf9167f50cdeb3ae105f56099aaab9061f83' + }, + { + assetType: 'EINUHOL', + decimals: 18, + name: 'EigenInu (Holesky Network)', + networkId: 'ETHHOL', + onchainIdentifier: '0xdeeeee2b48c121e6728ed95c860e296177849932' + }, + { + assetType: 'ELFI', + decimals: 18, + name: 'Element Fi', + networkId: 'ETH', + onchainIdentifier: '0x5c6d51ecba4d8e4f20373e3ce96a62342b125d6d' + }, + { + assetType: 'ELS', + decimals: 18, + name: 'Ethlas', + networkId: 'ETH', + onchainIdentifier: '0xeb575c45004bd7b61c6a8d3446a62a05a6ce18d8' + }, + { + assetType: 'ENA', + decimals: 18, + name: 'ENA', + networkId: 'ETH', + onchainIdentifier: '0x57e114b691db790c35207b2e685d4a43181e6061' + }, + { + assetType: 'ENFD', + decimals: 0, + name: 'EnergyFunders Yield FD I LLC', + networkId: 'ETH', + onchainIdentifier: '0x997bb865f307dbe0f979fd2864ae72c93b983d25' + }, + { + assetType: 'ENJ', + decimals: 18, + name: 'Enjin Coin', + networkId: 'ETH', + onchainIdentifier: '0xf629cbd94d3791c9250152bd8dfbdf380e2a3b9c' + }, + { + assetType: 'ENS', + decimals: 18, + name: 'ENS', + networkId: 'ETH', + onchainIdentifier: '0xc18360217d8f7ab5e7c516566761ea12ce7f9d72' + }, + { + assetType: 'ES', + decimals: 6, + name: 'Eclipse', + networkId: 'ETH', + onchainIdentifier: '0x6055dc6ff1077eebe5e6d2ba1a1f53d7ef8430de' + }, + { + assetType: 'ETH', + decimals: 18, + name: 'Ethereum', + networkId: 'ETH' + }, + { + assetType: 'ETHFI', + decimals: 18, + name: 'etherfi governance token', + networkId: 'ETH', + onchainIdentifier: '0xfe0c30065b384f05761f15d0cc899d4f9f9cc0eb' + }, + { + assetType: 'ETHHOL', + decimals: 18, + name: 'Ethereum Test (Holešky)', + networkId: 'ETHHOL' + }, + { + assetType: 'ETHSEP', + decimals: 18, + name: 'Ethereum Test (Sepolia)', + networkId: 'ETHSEP' + }, + { + assetType: 'ETHX', + decimals: 18, + name: 'ETHx', + networkId: 'ETH', + onchainIdentifier: '0xa35b1b31ce002fbf2058d22f30f95d405200a15b' + }, + { + assetType: 'ETH_ARBITRUM_T', + decimals: 18, + name: 'Ethereum on Arbitrum Sepolia Testnet', + networkId: 'ARBITRUM_SEPOLIA' + }, + { + assetType: 'ETH_PLUME_T', + decimals: 18, + name: 'Ethereum on Plume Sepolia Testnet', + networkId: 'PLUME_SEPOLIA' + }, + { + assetType: 'ETH_ZKSYNC_T', + decimals: 18, + name: 'Ethereum on ZKsync Sepolia Testnet', + networkId: 'ZKSYNC_SEPOLIA' + }, + { + assetType: 'EUL', + decimals: 18, + name: 'Euler', + networkId: 'ETH', + onchainIdentifier: '0xd9fcd98c322942075a5c3860693e9f4f03aae07b' + }, + { + assetType: 'EUROC', + decimals: 6, + name: 'Euro Coin', + networkId: 'ETH', + onchainIdentifier: '0x1abaea1f7c830bd89acc67ec4af516284b1bc33c' + }, + { + assetType: 'EVERY', + decimals: 18, + name: 'Everyworld', + networkId: 'ETH', + onchainIdentifier: '0x9afa9999e45484adf5d8eed8d9dfe0693bacd838' + }, + { + assetType: 'EVMOS', + decimals: 18, + name: 'Evmos', + networkId: 'EVMOS' + }, + { + assetType: 'EVMOS_T', + decimals: 18, + name: 'Evmos Testnet', + networkId: 'EVMOS_T' + }, + { + assetType: 'FEI', + decimals: 18, + name: 'Fei USD', + networkId: 'ETH', + onchainIdentifier: '0x956f47f50a910163d8bf957cf5846d573e7f87ca' + }, + { + assetType: 'FET', + decimals: 18, + name: 'Fetch', + networkId: 'ETH', + onchainIdentifier: '0xaea46a60368a7bd060eec7df8cba43b7ef41ad85' + }, + { + assetType: 'FIL', + decimals: 18, + name: 'Filecoin', + networkId: 'FIL' + }, + { + assetType: 'FIRE', + decimals: 18, + name: 'Ceramic Fire', + networkId: 'ETH', + onchainIdentifier: '0x2033e559cddff6dd36ec204e3014faa75a01052e' + }, + { + assetType: 'FLIP', + decimals: 18, + name: 'Chainflip', + networkId: 'ETH', + onchainIdentifier: '0x826180541412d574cf1336d22c0c0a287822678a' + }, + { + assetType: 'FLOW_T', + decimals: 8, + name: 'Flow Testnet', + networkId: 'FLOW_T' + }, + { + assetType: 'FLT', + decimals: 18, + name: 'Fluence', + networkId: 'ETH', + onchainIdentifier: '0x236501327e701692a281934230af0b6be8df3353' + }, + { + assetType: 'FLX', + decimals: 18, + name: 'Flex Ungovernance Token', + networkId: 'ETH', + onchainIdentifier: '0x6243d8cea23066d098a15582d81a598b4e8391f4' + }, + { + assetType: 'FLY', + decimals: 18, + name: 'FlyCoin', + networkId: 'ETH', + onchainIdentifier: '0x4e568ab95f029e8df1e39b30c9d6d076eaa15945' + }, + { + assetType: 'FOAM', + decimals: 18, + name: 'Foam', + networkId: 'ETH', + onchainIdentifier: '0x4946fcea7c692606e8908002e55a582af44ac121' + }, + { + assetType: 'FORT', + decimals: 18, + name: 'Forta', + networkId: 'ETH', + onchainIdentifier: '0x41545f8b9472d758bb669ed8eaeeecd7a9c4ec29' + }, + { + assetType: 'FOX', + decimals: 18, + name: 'Shapeshift FOX Token', + networkId: 'ETH', + onchainIdentifier: '0xc770eefad204b5180df6a14ee197d99d808ee52d' + }, + { + assetType: 'FRAX', + decimals: 18, + name: 'Frax', + networkId: 'ETH', + onchainIdentifier: '0x853d955acef822db058eb8505911ed77f175b99e' + }, + { + assetType: 'FST', + decimals: 18, + name: 'Futureswap', + networkId: 'ETH', + onchainIdentifier: '0x0e192d382a36de7011f795acc4391cd302003606' + }, + { + assetType: 'FTM', + decimals: 18, + name: 'Fantom', + networkId: 'ETH', + onchainIdentifier: '0x4e15361fd6b4bb609fa63c81a2be19d873717870' + }, + { + assetType: 'FTT', + decimals: 18, + name: 'FTX Token', + networkId: 'ETH', + onchainIdentifier: '0x50d1c9771902476076ecfc8b2a83ad6b9355a4c9' + }, + { + assetType: 'FUEL', + decimals: 18, + name: 'Fuel', + networkId: 'ETH', + onchainIdentifier: '0x56ebdae96d179549f279ea0cfea3b3432b8cd2bc' + }, + { + assetType: 'FWB', + decimals: 18, + name: 'Friends With Benefits Pro', + networkId: 'ETH', + onchainIdentifier: '0x35bd01fc9d6d5d81ca9e055db88dc49aa2c699a8' + }, + { + assetType: 'FXS', + decimals: 18, + name: 'Frax Share', + networkId: 'ETH', + onchainIdentifier: '0x3432b6a60d23ca0dfca7761b7ab56459d9c964d0' + }, + { + assetType: 'GEAR', + decimals: 18, + name: 'Gearbox', + networkId: 'ETH', + onchainIdentifier: '0xba3335588d9403515223f109edc4eb7269a9ab5d' + }, + { + assetType: 'GEL', + decimals: 18, + name: 'Gelato Network Token', + networkId: 'ETH', + onchainIdentifier: '0x15b7c0c907e4c6b9adaaaabc300c08991d6cea05' + }, + { + assetType: 'GF', + decimals: 18, + name: 'GuildFi Token', + networkId: 'ETH', + onchainIdentifier: '0xaaef88cea01475125522e117bfe45cf32044e238' + }, + { + assetType: 'GFI', + decimals: 18, + name: 'Goldfinch', + networkId: 'ETH', + onchainIdentifier: '0xdab396ccf3d84cf2d07c4454e10c8a6f5b008d2b' + }, + { + assetType: 'GLM', + decimals: 18, + name: 'Golem Network Token', + networkId: 'ETH', + onchainIdentifier: '0x7dd9c5cba05e151c895fde1cf355c9a1d5da6429' + }, + { + assetType: 'GMEE', + decimals: 18, + name: 'GAMEE', + networkId: 'ETH', + onchainIdentifier: '0xd9016a907dc0ecfa3ca425ab20b6b785b42f2373' + }, + { + assetType: 'GMT', + decimals: 8, + name: 'GreenMetaverseToken', + networkId: 'ETH', + onchainIdentifier: '0xe3c408bd53c31c085a1746af401a4042954ff740' + }, + { + assetType: 'GNO', + decimals: 18, + name: 'Gnosis', + networkId: 'ETH', + onchainIdentifier: '0x6810e776880c02933d47db1b9fc05908e5386b96' + }, + { + assetType: 'GNT', + decimals: 18, + name: 'Golem', + networkId: 'ETH', + onchainIdentifier: '0xa74476443119a942de498590fe1f2454d7d4ac0d' + }, + { + assetType: 'GRT', + decimals: 18, + name: 'Graph Token', + networkId: 'ETH', + onchainIdentifier: '0xc944e90c64b2c07662a292be6244bdf05cda44a7' + }, + { + assetType: 'GYEN', + decimals: 6, + name: 'GMO JPY', + networkId: 'ETH', + onchainIdentifier: '0xc08512927d12348f6620a698105e1baac6ecd911' + }, + { + assetType: 'HAIR', + decimals: 18, + name: 'HairDAO Token', + networkId: 'ETH', + onchainIdentifier: '0x9ce115f0341ae5dabc8b477b74e83db2018a6f42' + }, + { + assetType: 'HASH', + decimals: 9, + name: 'Provenance Hash', + networkId: 'HASH' + }, + { + assetType: 'HBOT', + decimals: 18, + name: 'Hummingbot Governance Token', + networkId: 'ETH', + onchainIdentifier: '0xe5097d9baeafb89f9bcb78c9290d545db5f9e9cb' + }, + { + assetType: 'HBTC', + decimals: 18, + name: 'Huobi BTC', + networkId: 'ETH', + onchainIdentifier: '0x0316eb71485b0ab14103307bf65a021042c6d380' + }, + { + assetType: 'HEGIC', + decimals: 18, + name: 'Hegic', + networkId: 'ETH', + onchainIdentifier: '0x584bc13c7d411c00c01a62e8019472de68768430' + }, + { + assetType: 'HFT', + decimals: 18, + name: 'Hashflow', + networkId: 'ETH', + onchainIdentifier: '0xb3999f658c0391d94a37f7ff328f3fec942bcadc' + }, + { + assetType: 'IDK', + decimals: 8, + name: 'IDKToken', + networkId: 'ETH', + onchainIdentifier: '0x61fd1c62551850d0c04c76fce614cbced0094498' + }, + { + assetType: 'ILV', + decimals: 18, + name: 'Illuvium', + networkId: 'ETH', + onchainIdentifier: '0x767fe9edc9e0df98e07454847909b5e959d7ca0e' + }, + { + assetType: 'IMX', + decimals: 18, + name: 'Immutable X', + networkId: 'ETH', + onchainIdentifier: '0xf57e7e7c23978c3caec3c3548e3d615c346e79ff' + }, + { + assetType: 'INDEX', + decimals: 18, + name: 'Index', + networkId: 'ETH', + onchainIdentifier: '0x0954906da0bf32d5479e25f46056d22f08464cab' + }, + { + assetType: 'INDI', + decimals: 18, + name: 'IndiGG', + networkId: 'ETH', + onchainIdentifier: '0x3392d8a60b77f8d3eaa4fb58f09d835bd31add29' + }, + { + assetType: 'IOTX', + decimals: 18, + name: 'IoTeX Network', + networkId: 'ETH', + onchainIdentifier: '0x6fb3e0a217407efff7ca062d46c26e5d60a14d69' + }, + { + assetType: 'KARATE', + decimals: 18, + name: 'Karate', + networkId: 'ETH', + onchainIdentifier: '0x80008bcd713c38af90a9930288d446bc3bd2e684' + }, + { + assetType: 'KARRAT', + decimals: 18, + name: 'KarratCoin', + networkId: 'ETH', + onchainIdentifier: '0xacd2c239012d17beb128b0944d49015104113650' + }, + { + assetType: 'KEEP', + decimals: 18, + name: 'Keep Network', + networkId: 'ETH', + onchainIdentifier: '0x85eee30c52b0b379b046fb0f85f4f3dc3009afec' + }, + { + assetType: 'KEYS', + decimals: 18, + name: 'KEYS Token', + networkId: 'ETH', + onchainIdentifier: '0xf24603654f1150926314badf00420d6a71ee343e' + }, + { + assetType: 'KINE', + decimals: 18, + name: 'Kine Governance Token', + networkId: 'ETH', + onchainIdentifier: '0xcbfef8fdd706cde6f208460f2bf39aa9c785f05d' + }, + { + assetType: 'KNC', + decimals: 18, + name: 'Kyber Network Crystal v2', + networkId: 'ETH', + onchainIdentifier: '0xdefa4e8a7bcba345f687a2f1456f5edd9ce97202' + }, + { + assetType: 'KNCL', + decimals: 18, + name: 'Kyber Network Legacy', + networkId: 'ETH', + onchainIdentifier: '0xdd974d5c2e2928dea5f71b9825b8b646686bd200' + }, + { + assetType: 'L3', + decimals: 18, + name: 'Layer3', + networkId: 'ETH', + onchainIdentifier: '0x88909d489678dd17aa6d9609f89b0419bf78fd9a' + }, + { + assetType: 'LAND', + decimals: 18, + name: "The Sandbox's LANDs", + networkId: 'ETH', + onchainIdentifier: '0x5cc5b05a8a13e3fbdb0bb9fccd98d38e50f90c38' + }, + { + assetType: 'LBTC', + decimals: 8, + name: 'Lombard Staked Bitcoin', + networkId: 'ETH', + onchainIdentifier: '0x8236a87084f8b84306f72007f36f2618a5634494' + }, + { + assetType: 'LDO', + decimals: 18, + name: 'Lido DAO', + networkId: 'ETH', + onchainIdentifier: '0x5a98fcbea516cf06857215779fd812ca3bef1b32' + }, + { + assetType: 'LINK', + decimals: 18, + name: 'Chainlink', + networkId: 'ETH', + onchainIdentifier: '0x514910771af9ca656af840dff83e8264ecf986ca' + }, + { + assetType: 'LINKSEP', + decimals: 18, + name: 'Chainlink Token Test', + networkId: 'ETHSEP', + onchainIdentifier: '0x779877a7b0d9e8603169ddbd7836e478b4624789' + }, + { + assetType: 'LINK_ARBITRUM_T', + decimals: 18, + name: 'Chainlink Token on Arbitrum Sepolia', + networkId: 'ARBITRUM_SEPOLIA', + onchainIdentifier: '0xb1d4538b4571d411f07960ef2838ce337fe1e80e' + }, + { + assetType: 'LINK_ZKSYNC_T', + decimals: 18, + name: 'Chainlink Token on ZKsync Sepolia', + networkId: 'ZKSYNC_SEPOLIA', + onchainIdentifier: '0x23a1afd896c8c8876af46adc38521f4432658d1e' + }, + { + assetType: 'LMWR', + decimals: 18, + name: 'LimeWire Token', + networkId: 'ETH', + onchainIdentifier: '0x628a3b2e302c7e896acc432d2d0dd22b6cb9bc88' + }, + { + assetType: 'LOKA', + decimals: 18, + name: 'League Of Kingdoms Arena', + networkId: 'ETH', + onchainIdentifier: '0x61e90a50137e1f645c9ef4a0d3a4f01477738406' + }, + { + assetType: 'LPT', + decimals: 18, + name: 'Livepeer Token', + networkId: 'ETH', + onchainIdentifier: '0x58b6a8a3302369daec383334672404ee733ab239' + }, + { + assetType: 'LRC', + decimals: 18, + name: 'Loopring', + networkId: 'ETH', + onchainIdentifier: '0xbbbbca6a901c926f240b89eacb641d8aec7aeafd' + }, + { + assetType: 'LRDS', + decimals: 18, + name: 'BLOCKLORDS', + networkId: 'ETH', + onchainIdentifier: '0xd0a6053f087e87a25dc60701ba6e663b1a548e85' + }, + { + assetType: 'LSETH', + decimals: 18, + name: 'Liquid Staked ETH', + networkId: 'ETH', + onchainIdentifier: '0x8c1bed5b9a0928467c9b1341da1d7bd5e10b6549' + }, + { + assetType: 'LSETHHOL', + decimals: 18, + name: 'Liquid Staked ETH (Holesky Network)', + networkId: 'ETHHOL', + onchainIdentifier: '0x1d8b30cc38dba8abce1ac29ea27d9cfd05379a09' + }, + { + assetType: 'LTC', + decimals: 8, + name: 'Litecoin', + networkId: 'LTC' + }, + { + assetType: 'M', + decimals: 6, + name: 'M by M^0', + networkId: 'ETH', + onchainIdentifier: '0x866a2bf4e572cbcf37d5071a7a58503bfb36be1b' + }, + { + assetType: 'MAGIC', + decimals: 18, + name: 'MAGIC', + networkId: 'ETH', + onchainIdentifier: '0xb0c7a3ba49c7a6eaba6cd4a96c55a1391070ac9a' + }, + { + assetType: 'MANA', + decimals: 18, + name: 'Decentraland', + networkId: 'ETH', + onchainIdentifier: '0x0f5d2fb29fb7d3cfee444a200298f468908cc942' + }, + { + assetType: 'MASK', + decimals: 18, + name: 'Mask Network', + networkId: 'ETH', + onchainIdentifier: '0x69af81e73a73b40adf4f3d4223cd9b1ece623074' + }, + { + assetType: 'MATIC', + decimals: 18, + name: 'Matic Token', + networkId: 'ETH', + onchainIdentifier: '0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0' + }, + { + assetType: 'MATICX', + decimals: 18, + name: 'Liquid Staking Matic', + networkId: 'ETH', + onchainIdentifier: '0xf03a7eb46d01d9ecaa104558c732cf82f6b6b645' + }, + { + assetType: 'MAV', + decimals: 18, + name: 'Maverick Token', + networkId: 'ETH', + onchainIdentifier: '0x7448c7456a97769f6cd04f1e83a4a23ccdc46abd' + }, + { + assetType: 'MAYC', + decimals: 18, + name: 'Mutant Ape Yacht Club', + networkId: 'ETH', + onchainIdentifier: '0x60e4d786628fea6478f785a6d7e704777c86a7c6' + }, + { + assetType: 'MIR', + decimals: 18, + name: 'Mirror Protocol', + networkId: 'ETH', + onchainIdentifier: '0x09a3ecafa817268f77be1283176b946c4ff2e608' + }, + { + assetType: 'MKR', + decimals: 18, + name: 'Maker', + networkId: 'ETH', + onchainIdentifier: '0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2' + }, + { + assetType: 'MLBCB', + decimals: 18, + name: 'LucidSight-MLB-NFT', + networkId: 'ETH', + onchainIdentifier: '0x8c9b261faef3b3c2e64ab5e58e04615f8c788099' + }, + { + assetType: 'MNT', + decimals: 18, + name: 'Mantle', + networkId: 'ETH', + onchainIdentifier: '0x3c3a81e81dc49a522a592e7622a7e711c06bf354' + }, + { + assetType: 'MOG', + decimals: 18, + name: 'Mog Coin', + networkId: 'ETH', + onchainIdentifier: '0xaaee1a9723aadb7afa2810263653a34ba2c21c7a' + }, + { + assetType: 'MOONBIRD', + decimals: 18, + name: 'Moonbirds', + networkId: 'ETH', + onchainIdentifier: '0x23581767a106ae21c074b2276d25e5c3e136a68b' + }, + { + assetType: 'MORPHO', + decimals: 18, + name: 'Morpho Token', + networkId: 'ETH', + onchainIdentifier: '0x9994e35db50125e0df82e4c2dde62496ce330999' + }, + { + assetType: 'MOVE', + decimals: 8, + name: 'Movement', + networkId: 'ETH', + onchainIdentifier: '0x3073f7aaa4db83f95e9fff17424f71d4751a3073' + }, + { + assetType: 'MPL', + decimals: 18, + name: 'Maple', + networkId: 'ETH', + onchainIdentifier: '0x33349b282065b0284d756f0577fb39c158f935e6' + }, + { + assetType: 'MPOND', + decimals: 18, + name: 'MPond', + networkId: 'ETH', + onchainIdentifier: '0x1c77d15857646687005dbbafff5873f4495a9731' + }, + { + assetType: 'MYC', + decimals: 18, + name: 'Mycelium', + networkId: 'ETH', + onchainIdentifier: '0x4b13006980acb09645131b91d259eaa111eaf5ba' + }, + { + assetType: 'MYTH', + decimals: 18, + name: 'Mythos', + networkId: 'ETH', + onchainIdentifier: '0xba41ddf06b7ffd89d1267b5a93bfef2424eb2003' + }, + { + assetType: 'NEXT', + decimals: 18, + name: 'Connext', + networkId: 'ETH', + onchainIdentifier: '0xfe67a4450907459c3e1fff623aa927dd4e28c67a' + }, + { + assetType: 'NFTX', + decimals: 18, + name: 'NFTX', + networkId: 'ETH', + onchainIdentifier: '0x87d73e916d7057945c9bcd8cdd94e42a6f47f776' + }, + { + assetType: 'NIGHT_APTOS', + decimals: 8, + name: 'Midnight Evergreen on Aptos', + networkId: 'APT' + }, + { + assetType: 'NII', + decimals: 15, + name: 'Nahmii', + networkId: 'ETH', + onchainIdentifier: '0x7c8155909cd385f120a56ef90728dd50f9ccbe52' + }, + { + assetType: 'NMR', + decimals: 18, + name: 'Numeraire', + networkId: 'ETH', + onchainIdentifier: '0x1776e1f26f98b1a5df9cd347953a26dd3cb46671' + }, + { + assetType: 'NMT', + decimals: 18, + name: 'NetMind Token', + networkId: 'ETH', + onchainIdentifier: '0x03aa6298f1370642642415edc0db8b957783e8d6' + }, + { + assetType: 'NOTE', + decimals: 8, + name: 'Notional', + networkId: 'ETH', + onchainIdentifier: '0xcfeaead4947f0705a14ec42ac3d44129e1ef3ed5' + }, + { + assetType: 'NOUN', + decimals: 18, + name: 'Nouns', + networkId: 'ETH', + onchainIdentifier: '0x9c8ff314c9bc7f6e59a9d9225fb22946427edc03' + }, + { + assetType: 'NSTR', + decimals: 18, + name: 'Nostra', + networkId: 'ETH', + onchainIdentifier: '0x610dbd98a28ebba525e9926b6aaf88f9159edbfd' + }, + { + assetType: 'NTRN', + decimals: 6, + name: 'Neutron', + networkId: 'NTRN' + }, + { + assetType: 'NXM', + decimals: 18, + name: 'NXM', + networkId: 'ETH', + onchainIdentifier: '0xd7c49cee7e9188cca6ad8ff264c1da2e69d4cf3b' + }, + { + assetType: 'NYM', + decimals: 6, + name: 'Nym', + networkId: 'ETH', + onchainIdentifier: '0x525a8f6f3ba4752868cde25164382bfbae3990e1' + }, + { + assetType: 'OBOL', + decimals: 18, + name: 'Obol Network Token', + networkId: 'ETH', + onchainIdentifier: '0x0b010000b7624eb9b3dfbc279673c76e9d29d5f7' + }, + { + assetType: 'OM', + decimals: 18, + name: 'MANTRA DAO', + networkId: 'ETH', + onchainIdentifier: '0x3593d125a4f7849a1b059e64f4517a86dd60c95d' + }, + { + assetType: 'OMG', + decimals: 18, + name: 'OMG Network', + networkId: 'ETH', + onchainIdentifier: '0xd26114cd6ee289accf82350c8d8487fedb8a0c07' + }, + { + assetType: 'OM_MANTRA', + decimals: 6, + name: 'OM Mantra', + networkId: 'OM_MANTRA' + }, + { + assetType: 'OM_MANTRA_T', + decimals: 6, + name: 'OM Mantra Testnet', + networkId: 'OM_MANTRA_T' + }, + { + assetType: 'ONDO', + decimals: 18, + name: 'Ondo', + networkId: 'ETH', + onchainIdentifier: '0xfaba6f8e4a5e8ab82f62fe7c39859fa577269be3' + }, + { + assetType: 'OP', + decimals: 18, + name: 'Oasis', + networkId: 'ETH', + onchainIdentifier: '0x898157afb3e158cc835d19b9ecd37c69bf460f8c' + }, + { + assetType: 'ORDER', + decimals: 18, + name: 'Orderly Network', + networkId: 'ETH', + onchainIdentifier: '0xabd4c63d2616a5201454168269031355f4764337' + }, + { + assetType: 'OSMO', + decimals: 6, + name: 'Osmosis', + networkId: 'OSMO' + }, + { + assetType: 'OTHR', + decimals: 18, + name: 'Otherdeed', + networkId: 'ETH', + onchainIdentifier: '0x34d85c9cdeb23fa97cb08333b511ac86e1c4e258' + }, + { + assetType: 'OUSG', + decimals: 18, + name: 'Ondo Short-Term U.S. Government Bond Fund', + networkId: 'ETH', + onchainIdentifier: '0x1b19c19393e2d034d8ff31ff34c81252fcbbee92' + }, + { + assetType: 'OXT', + decimals: 18, + name: 'Orchid', + networkId: 'ETH', + onchainIdentifier: '0x4575f41308ec1483f3d399aa9a2826d74da13deb' + }, + { + assetType: 'PARTY', + decimals: 18, + name: 'PartyDAO', + networkId: 'ETH', + onchainIdentifier: '0x381b31b3905b6d1175da9d216a7581023f1d6145' + }, + { + assetType: 'PATH', + decimals: 18, + name: 'PathDao', + networkId: 'ETH', + onchainIdentifier: '0x2a2550e0a75acec6d811ae3930732f7f3ad67588' + }, + { + assetType: 'PAXG', + decimals: 18, + name: 'Paxos Gold', + networkId: 'ETH', + onchainIdentifier: '0x45804880de22913dafe09f4980848ece6ecbaf78' + }, + { + assetType: 'PDT', + decimals: 18, + name: 'Paragons DAO', + networkId: 'ETH', + onchainIdentifier: '0x375abb85c329753b1ba849a601438ae77eec9893' + }, + { + assetType: 'PEEPS', + decimals: 18, + name: 'PleasrDAO', + networkId: 'ETH', + onchainIdentifier: '0xba962a81f78837751be8a177378d582f337084e6' + }, + { + assetType: 'PENDLE', + decimals: 18, + name: 'Pendle', + networkId: 'ETH', + onchainIdentifier: '0x808507121b80c02388fad14726482e061b8da827' + }, + { + assetType: 'PEPE', + decimals: 18, + name: 'PEPE', + networkId: 'ETH', + onchainIdentifier: '0x6982508145454ce325ddbe47a25d4ec3d2311933' + }, + { + assetType: 'PERP', + decimals: 18, + name: 'Perpetual', + networkId: 'ETH', + onchainIdentifier: '0xbc396689893d065f41bc2c6ecbee5e0085233447' + }, + { + assetType: 'PIRATE', + decimals: 18, + name: 'Pirate Nation Token', + networkId: 'ETH', + onchainIdentifier: '0x7613c48e0cd50e42dd9bf0f6c235063145f6f8dc' + }, + { + assetType: 'PIXEL', + decimals: 18, + name: 'PIXEL', + networkId: 'ETH', + onchainIdentifier: '0x3429d03c6f7521aec737a0bbf2e5ddcef2c3ae31' + }, + { + assetType: 'PIXFI', + decimals: 18, + name: 'Pixelverse', + networkId: 'ETH', + onchainIdentifier: '0xd795eb12034c2b77d787a22292c26fab5f5c70aa' + }, + { + assetType: 'POL', + decimals: 18, + name: 'Polygon Ecosystem Token', + networkId: 'ETH', + onchainIdentifier: '0x455e53cbb86018ac2b8092fdcd39d8444affc3f6' + }, + { + assetType: 'POLY', + decimals: 18, + name: 'Polymath', + networkId: 'ETH', + onchainIdentifier: '0x9992ec3cf6a55b00978cddf2b27bc6882d88d1ec' + }, + { + assetType: 'POL_POLYGON', + decimals: 18, + name: 'Polygon Ecosystem Token on Polygon', + networkId: 'POLYGON' + }, + { + assetType: 'POND', + decimals: 18, + name: 'Pond', + networkId: 'ETH', + onchainIdentifier: '0x57b946008913b82e4df85f501cbaed910e58d26c' + }, + { + assetType: 'PORTAL', + decimals: 18, + name: 'PORTAL', + networkId: 'ETH', + onchainIdentifier: '0x1bbe973bef3a977fc51cbed703e8ffdefe001fed' + }, + { + assetType: 'POWR', + decimals: 6, + name: 'PowerLedger', + networkId: 'ETH', + onchainIdentifier: '0x595832f8fc6bf59c85c527fec3740a1b7a361269' + }, + { + assetType: 'PRIME', + decimals: 18, + name: 'Prime', + networkId: 'ETH', + onchainIdentifier: '0xb23d80f5fefcddaa212212f028021b41ded428cf' + }, + { + assetType: 'PRINTS', + decimals: 18, + name: 'FingerprintsDAO', + networkId: 'ETH', + onchainIdentifier: '0x4dd28568d05f09b02220b09c2cb307bfd837cb95' + }, + { + assetType: 'PSP', + decimals: 18, + name: 'ParaSwap', + networkId: 'ETH', + onchainIdentifier: '0xcafe001067cdef266afb7eb5a286dcfd277f3de5' + }, + { + assetType: 'PSTAKE', + decimals: 18, + name: 'pSTAKE Finance', + networkId: 'ETH', + onchainIdentifier: '0xfb5c6815ca3ac72ce9f5006869ae67f18bf77006' + }, + { + assetType: 'PUFFER', + decimals: 18, + name: 'PUFFER', + networkId: 'ETH', + onchainIdentifier: '0x4d1c297d39c5c1277964d0e3f8aa901493664530' + }, + { + assetType: 'PYUSD', + decimals: 6, + name: 'PayPal USD', + networkId: 'ETH', + onchainIdentifier: '0x6c3ea9036406852006290770bedfcaba0e23a0e8' + }, + { + assetType: 'QF', + decimals: 18, + name: 'quasar fighter', + networkId: 'ETH', + onchainIdentifier: '0x9c9560a06de70df3d8e97c7364f7508ef92b0f83' + }, + { + assetType: 'QNT', + decimals: 18, + name: 'Quant', + networkId: 'ETH', + onchainIdentifier: '0x4a220e6096b25eadb88358cb44068a3248254675' + }, + { + assetType: 'RAD', + decimals: 18, + name: 'Radicle', + networkId: 'ETH', + onchainIdentifier: '0x31c8eacbffdd875c74b94b077895bd78cf1e64a3' + }, + { + assetType: 'RARE', + decimals: 18, + name: 'SuperRare', + networkId: 'ETH', + onchainIdentifier: '0xba5bde662c17e2adff1075610382b9b691296350' + }, + { + assetType: 'RARI', + decimals: 18, + name: 'Rarible', + networkId: 'ETH', + onchainIdentifier: '0xfca59cd816ab1ead66534d82bc21e7515ce441cf' + }, + { + assetType: 'RBN', + decimals: 18, + name: 'Ribbon Finance', + networkId: 'ETH', + onchainIdentifier: '0x6123b0049f904d730db3c36a31167d9d4121fa6b' + }, + { + assetType: 'RCOIN', + decimals: 8, + name: 'ArCoin', + networkId: 'ETH', + onchainIdentifier: '0x252739487c1fa66eaeae7ced41d6358ab2a6bca9' + }, + { + assetType: 'REN', + decimals: 18, + name: 'Ren', + networkId: 'ETH', + onchainIdentifier: '0x408e41876cccdc0f92210600ef50372656052a38' + }, + { + assetType: 'RENBTC', + decimals: 8, + name: 'renBTC', + networkId: 'ETH', + onchainIdentifier: '0xeb4c2781e4eba804ce9a9803c67d0893436bb27d' + }, + { + assetType: 'REP', + decimals: 18, + name: 'Augur', + networkId: 'ETH', + onchainIdentifier: '0x221657776846890989a759ba2973e427dff5c9bb' + }, + { + assetType: 'REZ', + decimals: 18, + name: 'Renzo', + networkId: 'ETH', + onchainIdentifier: '0x3b50805453023a91a8bf641e279401a0b23fa6f9' + }, + { + assetType: 'RLS', + decimals: 18, + name: 'Rayls', + networkId: 'ETH', + onchainIdentifier: '0xb5f7b021a78f470d31d762c1dda05ea549904fbd' + }, + { + assetType: 'RLY', + decimals: 18, + name: 'Rally', + networkId: 'ETH', + onchainIdentifier: '0xf1f955016ecbcd7321c7266bccfb96c68ea5e49b' + }, + { + assetType: 'RMO', + decimals: 6, + name: 'Rarimo', + networkId: 'RMO' + }, + { + assetType: 'RN', + decimals: 18, + name: 'Rio Network', + networkId: 'ETH', + onchainIdentifier: '0x3c61297e71e9bb04b9fbfead72a6d3c70e4f1e4a' + }, + { + assetType: 'RNDR', + decimals: 18, + name: 'Render Token', + networkId: 'ETH', + onchainIdentifier: '0x6de037ef9ad2725eb40118bb1702ebb27e4aeb24' + }, + { + assetType: 'ROSE', + decimals: 9, + name: 'Oasis Network', + networkId: 'OAC' + }, + { + assetType: 'RPL', + decimals: 18, + name: 'Rocket Pool Protocol', + networkId: 'ETH', + onchainIdentifier: '0xd33526068d116ce69f19a9ee46f0bd304f21a51f' + }, + { + assetType: 'RSC', + decimals: 18, + name: 'ResearchCoin', + networkId: 'ETH', + onchainIdentifier: '0xd101dcc414f310268c37eeb4cd376ccfa507f571' + }, + { + assetType: 'RSETH', + decimals: 18, + name: 'rsETH', + networkId: 'ETH', + onchainIdentifier: '0xa1290d69c65a6fe4df752f95823fae25cb99e5a7' + }, + { + assetType: 'RSR', + decimals: 18, + name: 'Reserve Rights', + networkId: 'ETH', + onchainIdentifier: '0x320623b8e4ff03373931769a31fc52a4e78b5d70' + }, + { + assetType: 'RST', + decimals: 18, + name: 'Realio Security Token', + networkId: 'ETH', + onchainIdentifier: '0x1a76bffd6d1fc1660e1d0e0552fde51ddbb120cf' + }, + { + assetType: 'RSV', + decimals: 18, + name: 'Reserve', + networkId: 'ETH', + onchainIdentifier: '0x196f4727526ea7fb1e17b2071b3d8eaa38486988' + }, + { + assetType: 'RVR', + decimals: 18, + name: 'River', + networkId: 'ETH', + onchainIdentifier: '0x53319181e003e7f86fb79f794649a2ab680db244' + }, + { + assetType: 'SAFE', + decimals: 18, + name: 'Safe Token', + networkId: 'ETH', + onchainIdentifier: '0x5afe3855358e112b5647b952709e6165e1c1eeee' + }, + { + assetType: 'SALD', + decimals: 18, + name: 'Salad', + networkId: 'ETH', + onchainIdentifier: '0x5582a479f0c403e207d2578963ccef5d03ba636f' + }, + { + assetType: 'SAND', + decimals: 18, + name: 'Sandbox', + networkId: 'ETH', + onchainIdentifier: '0x3845badade8e6dff049820680d1f14bd3903a5d0' + }, + { + assetType: 'SBTC', + decimals: 18, + name: 'Synth sBTC', + networkId: 'ETH', + onchainIdentifier: '0xfe18be6b3bd88a2d2a7f928d00292e7a9963cfc6' + }, + { + assetType: 'SD', + decimals: 18, + name: 'Stader', + networkId: 'ETH', + onchainIdentifier: '0x30d20208d987713f46dfd34ef128bb16c404d10f' + }, + { + assetType: 'SDL', + decimals: 18, + name: 'Saddle', + networkId: 'ETH', + onchainIdentifier: '0xf1dc500fde233a4055e25e5bbf516372bc4f6871' + }, + { + assetType: 'SEI', + decimals: 6, + name: 'Sei', + networkId: 'SEI' + }, + { + assetType: 'SEI_T', + decimals: 6, + name: 'Sei Testnet', + networkId: 'SEI_T' + }, + { + assetType: 'SFRXETHHOL', + decimals: 18, + name: 'Staked Frax Ether (Holesky Network)', + networkId: 'ETHHOL', + onchainIdentifier: '0xa63f56985f9c7f3bc9ffc5685535649e0c1a55f3' + }, + { + assetType: 'SHIB', + decimals: 18, + name: 'SHIBA INU', + networkId: 'ETH', + onchainIdentifier: '0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce' + }, + { + assetType: 'SHRAP', + decimals: 18, + name: 'SHRAPToken', + networkId: 'ETH', + onchainIdentifier: '0x31e4efe290973ebe91b3a875a7994f650942d28f' + }, + { + assetType: 'SIPHER', + decimals: 18, + name: 'Sipher Token', + networkId: 'ETH', + onchainIdentifier: '0x9f52c8ecbee10e00d9faaac5ee9ba0ff6550f511' + }, + { + assetType: 'SKY', + decimals: 18, + name: 'SKY Governance Token', + networkId: 'ETH', + onchainIdentifier: '0x56072c95faa701256059aa122697b133aded9279' + }, + { + assetType: 'SNX', + decimals: 18, + name: 'Synthetix', + networkId: 'ETH', + onchainIdentifier: '0xc011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f' + }, + { + assetType: 'SOL_TD', + decimals: 9, + name: 'Solana Devnet', + networkId: 'SOL_TD' + }, + { + assetType: 'SPEC', + decimals: 18, + name: 'Spectral Token', + networkId: 'ETH', + onchainIdentifier: '0xadf7c35560035944e805d98ff17d58cde2449389' + }, + { + assetType: 'SRM', + decimals: 6, + name: 'Serum', + networkId: 'ETH', + onchainIdentifier: '0x476c5e26a75bd202a9683ffd34359c0cc15be0ff' + }, + { + assetType: 'SSV', + decimals: 18, + name: 'ssv.network', + networkId: 'ETH', + onchainIdentifier: '0x9d65ff81a3c488d585bbfb0bfe3c7707c7917f54' + }, + { + assetType: 'STG', + decimals: 18, + name: 'Stargate Finance', + networkId: 'ETH', + onchainIdentifier: '0xaf5191b0de278c7286d6c7cc6ab6bb8a73ba2cd6' + }, + { + assetType: 'STKAAVE', + decimals: 18, + name: 'Staked AAVE', + networkId: 'ETH', + onchainIdentifier: '0x4da27a545c0c5b758a6ba100e3a049001de870f5' + }, + { + assetType: 'STORJ', + decimals: 8, + name: 'StorjToken', + networkId: 'ETH', + onchainIdentifier: '0xb64ef51c888972c908cfacf59b47c1afbc0ab8ac' + }, + { + assetType: 'STRD', + decimals: 6, + name: 'Stride', + networkId: 'STRD' + }, + { + assetType: 'STRDY', + decimals: 18, + name: 'Sturdy Token', + networkId: 'ETH', + onchainIdentifier: '0xaeb3607ec434454ceb308f5cd540875efb54309a' + }, + { + assetType: 'STRK', + decimals: 18, + name: 'StarkNet Token', + networkId: 'ETH', + onchainIdentifier: '0xca14007eff0db1f8135f4c25b34de49ab0d42766' + }, + { + assetType: 'STRK_STARKNET', + decimals: 18, + name: 'Starknet', + networkId: 'STARK_STARKNET' + }, + { + assetType: 'STRK_STARKNET_T', + decimals: 18, + name: 'Starknet Testnet', + networkId: 'STRK_STARKNET_T' + }, + { + assetType: 'STRP', + decimals: 18, + name: 'Strips', + networkId: 'ETH', + onchainIdentifier: '0x97872eafd79940c7b24f7bcc1eadb1457347adc9' + }, + { + assetType: 'SUDO', + decimals: 18, + name: 'SUDO GOVERNANCE TOKEN', + networkId: 'ETH', + onchainIdentifier: '0x3446dd70b2d52a6bf4a5a192d9b0a161295ab7f9' + }, + { + assetType: 'SUI_T', + decimals: 9, + name: 'Sui Testnet', + networkId: 'SUI_T' + }, + { + assetType: 'SUSDCSEP', + decimals: 6, + name: 'Sec USD Coin (Sepolia Network)', + networkId: 'ETHSEP', + onchainIdentifier: '0x6612394ea7cfa53ed6522a5ff0fad091a89aaef6' + }, + { + assetType: 'SUSDE', + decimals: 18, + name: 'Staked USDe', + networkId: 'ETH', + onchainIdentifier: '0x9d39a5de30e57443bff2a8307a4256c8797a3497' + }, + { + assetType: 'SUSHI', + decimals: 18, + name: 'SushiSwap', + networkId: 'ETH', + onchainIdentifier: '0x6b3595068778dd592e39a122f4f5a5cf09c90fe2' + }, + { + assetType: 'SWISE', + decimals: 18, + name: 'StakeWise', + networkId: 'ETH', + onchainIdentifier: '0x48c3399719b582dd63eb5aadf12a40b4c3f52fa2' + }, + { + assetType: 'SYN', + decimals: 18, + name: 'Synapse', + networkId: 'ETH', + onchainIdentifier: '0x0f2d719407fdbeff09d87557abb7232601fd9f29' + }, + { + assetType: 'T', + decimals: 18, + name: 'Threshold Network Token', + networkId: 'ETH', + onchainIdentifier: '0xcdf7028ceab81fa0c6971208e83fa7872994bee5' + }, + { + assetType: 'TAIKO', + decimals: 18, + name: 'Taiko Token', + networkId: 'ETH', + onchainIdentifier: '0x10dea67478c5f8c5e2d90e5e9b26dbe60c54d800' + }, + { + assetType: 'TBILL', + decimals: 6, + name: 'OpenEden T-Bills', + networkId: 'ETH', + onchainIdentifier: '0xdd50c053c096cb04a3e3362e2b622529ec5f2e8a' + }, + { + assetType: 'TBTC', + decimals: 18, + name: 'tBTC v2', + networkId: 'ETH', + onchainIdentifier: '0x18084fba666a33d37592fa2633fd49a74dd93a88' + }, + { + assetType: 'TEN', + decimals: 18, + name: 'Tokenomy', + networkId: 'ETH', + onchainIdentifier: '0xdd16ec0f66e54d453e6756713e533355989040e4' + }, + { + assetType: 'THOU', + decimals: 18, + name: 'Thousands', + networkId: 'ETH', + onchainIdentifier: '0x370e83ca976c1deb98803fbccf64c6f0948705ea' + }, + { + assetType: 'TIA', + decimals: 6, + name: 'Celestia', + networkId: 'TIA' + }, + { + assetType: 'TLC', + decimals: 18, + name: 'Liquid Collective', + networkId: 'ETH', + onchainIdentifier: '0xb5fe6946836d687848b5abd42dabf531d5819632' + }, + { + assetType: 'TLM', + decimals: 4, + name: 'Alien Worlds Trilium', + networkId: 'ETH', + onchainIdentifier: '0x888888848b652b3e3a0f34c96e00eec0f3a23f72' + }, + { + assetType: 'TOKE', + decimals: 18, + name: 'Tokemak', + networkId: 'ETH', + onchainIdentifier: '0x2e9d63788249371f1dfc918a52f8d799f4a38c94' + }, + { + assetType: 'TRIBE', + decimals: 18, + name: 'TRIBE Governance', + networkId: 'ETH', + onchainIdentifier: '0xc7283b66eb1eb5fb86327f08e1b5816b0720212b' + }, + { + assetType: 'TRIBL', + decimals: 18, + name: 'Tribal Token', + networkId: 'ETH', + onchainIdentifier: '0x6988a804c74fd04f37da1ea4781cea68c9c00f86' + }, + { + assetType: 'TRU', + decimals: 8, + name: 'TrueFi', + networkId: 'ETH', + onchainIdentifier: '0x4c19596f5aaff459fa38b0f7ed92f11ae6543784' + }, + { + assetType: 'TUSD', + decimals: 18, + name: 'TrueUSD', + networkId: 'ETH', + onchainIdentifier: '0x0000000000085d4780b73119b644ae5ecd22b376' + }, + { + assetType: 'UMA', + decimals: 18, + name: 'UMA', + networkId: 'ETH', + onchainIdentifier: '0x04fa0d235c4abf4bcf4787af4cf447de572ef828' + }, + { + assetType: 'UNI', + decimals: 18, + name: 'Uniswap', + networkId: 'ETH', + onchainIdentifier: '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984' + }, + { + assetType: 'UNIBOT', + decimals: 18, + name: 'Unibot', + networkId: 'ETH', + onchainIdentifier: '0xf819d9cb1c2a819fd991781a822de3ca8607c3c9' + }, + { + assetType: 'USCC', + decimals: 6, + name: 'Superstate Crypto Carry Fund', + networkId: 'ETH', + onchainIdentifier: '0x14d60e7fdc0d71d8611742720e4c50e7a974020c' + }, + { + assetType: 'USD', + decimals: 2, + name: 'US Dollars', + networkId: 'USD' + }, + { + assetType: 'USDANCHOL', + decimals: 6, + name: 'USDAnchor (Holesky Network)', + networkId: 'ETHHOL', + onchainIdentifier: '0xfe246cff3dfed50e032904ac1fbd0da32de6873e' + }, + { + assetType: 'USDC', + decimals: 6, + name: 'USD Coin', + networkId: 'ETH', + onchainIdentifier: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' + }, + { + assetType: 'USDCNOBLEDYDX', + decimals: 6, + name: 'USDC Noble dYdX', + networkId: 'DYDX_CHAIN' + }, + { + assetType: 'USDE', + decimals: 18, + name: 'USDe', + networkId: 'ETH', + onchainIdentifier: '0x4c9edd5852cd905f086c759e8383e09bff1e68b3' + }, + { + assetType: 'USDG', + decimals: 6, + name: 'Global Dollar', + networkId: 'ETH', + onchainIdentifier: '0xe343167631d89b6ffc58b88d6b7fb0228795491d' + }, + { + assetType: 'USDP', + decimals: 18, + name: 'Pax Dollar', + networkId: 'ETH', + onchainIdentifier: '0x8e870d67f660d95d5be530380d0ec0bd388289e1' + }, + { + assetType: 'USDS', + decimals: 18, + name: 'USDS Stablecoin', + networkId: 'ETH', + onchainIdentifier: '0xdc035d45d973e3ec169d2276ddab16f1e407384f' + }, + { + assetType: 'USDT', + decimals: 6, + name: 'Tether', + networkId: 'ETH', + onchainIdentifier: '0xdac17f958d2ee523a2206206994597c13d831ec7' + }, + { + assetType: 'USDT_APTOS', + decimals: 6, + name: 'Tether USD on Aptos', + networkId: 'APT' + }, + { + assetType: 'USDY', + decimals: 18, + name: 'Ondo U.S. Dollar Yield', + networkId: 'ETH', + onchainIdentifier: '0x96f6ef951840721adbf46ac996b59e0235cb985c' + }, + { + assetType: 'USDY_APTOS', + decimals: 6, + name: 'Ondo US Dollar Yield on Aptos', + networkId: 'APT' + }, + { + assetType: 'USD_R', + decimals: 2, + name: 'US dollars test', + networkId: 'USD_R' + }, + { + assetType: 'USTB', + decimals: 6, + name: 'Superstate Short Duration US Government Securities Fund', + networkId: 'ETH', + onchainIdentifier: '0x43415eb6ff9db7e26a15b704e7a3edce97d31c4e' + }, + { + assetType: 'USYC', + decimals: 6, + name: 'US Yield Coin', + networkId: 'ETH', + onchainIdentifier: '0x136471a34f6ef19fe571effc1ca711fdb8e49f2b' + }, + { + assetType: 'VANA_VANA', + decimals: 18, + name: 'Vana', + networkId: 'VANA' + }, + { + assetType: 'VANA_VANA_MOKSHA_T', + decimals: 18, + name: 'VANA Token on Vana Moksha Testnet', + networkId: 'VANA_MOKSHA_TESTNET' + }, + { + assetType: 'VFORT_POLYGON', + decimals: 18, + name: 'FORT Staking Vault', + networkId: 'POLYGON', + onchainIdentifier: '0xf22f690a41d22496496d4959acfff0f3bacc24f1' + }, + { + assetType: 'VIRTUAL', + decimals: 18, + name: 'Virtual Protocol', + networkId: 'ETH', + onchainIdentifier: '0x44ff8620b8ca30902395a7bd3f2407e1a091bf73' + }, + { + assetType: 'VITA', + decimals: 18, + name: 'VitaDAO Token', + networkId: 'ETH', + onchainIdentifier: '0x81f8f0bb1cb2a06649e51913a151f0e7ef6fa321' + }, + { + assetType: 'VRA', + decimals: 18, + name: 'VERA', + networkId: 'ETH', + onchainIdentifier: '0xf411903cbc70a74d22900a5de66a2dda66507255' + }, + { + assetType: 'W', + decimals: 18, + name: 'Wormhole Token', + networkId: 'ETH', + onchainIdentifier: '0xb0ffa8000886e57f86dd5264b9582b2ad87b2b91' + }, + { + assetType: 'WAXL', + decimals: 6, + name: 'Wrapped Axelar', + networkId: 'ETH', + onchainIdentifier: '0x467719ad09025fcc6cf6f8311755809d45a5e5f3' + }, + { + assetType: 'WBTC', + decimals: 8, + name: 'Wrapped Bitcoin', + networkId: 'ETH', + onchainIdentifier: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599' + }, + { + assetType: 'WCELO', + decimals: 18, + name: 'Wrapped Celo', + networkId: 'ETH', + onchainIdentifier: '0xe452e6ea2ddeb012e20db73bf5d3863a3ac8d77a' + }, + { + assetType: 'WCUSD', + decimals: 18, + name: 'Wrapped Celo Dollar', + networkId: 'ETH', + onchainIdentifier: '0xad3e3fc59dff318beceaab7d00eb4f68b1ecf195' + }, + { + assetType: 'WEETH', + decimals: 18, + name: 'Wrapped eETH', + networkId: 'ETH', + onchainIdentifier: '0xcd5fe23c85820f7b72d0926fc9b05b43e359b7ee' + }, + { + assetType: 'WETH', + decimals: 18, + name: 'Wrapped Ether', + networkId: 'ETH', + onchainIdentifier: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2' + }, + { + assetType: 'WETHDYDX', + decimals: 18, + name: 'Wrapped Ethereum DYDX', + networkId: 'ETH', + onchainIdentifier: '0x46b2deae6eff3011008ea27ea36b7c27255ddfa9' + }, + { + assetType: 'WEVMOS', + decimals: 18, + name: 'Wrapped Evmos', + networkId: 'ETH', + onchainIdentifier: '0x93581991f68dbae1ea105233b67f7fa0d6bdee7b' + }, + { + assetType: 'WEXIT', + decimals: 8, + name: 'Wrapped Exit', + networkId: 'ETH', + onchainIdentifier: '0xc12799bf6c139f269439675454267644d5c7aca3' + }, + { + assetType: 'WEXOD', + decimals: 8, + name: 'Wrapped EXOD', + networkId: 'ETH', + onchainIdentifier: '0x10ef8b469f47a3167505e2f46b57aa3c708ec3c8' + }, + { + assetType: 'WFIL', + decimals: 18, + name: 'Wrapped Filecoin', + networkId: 'ETH', + onchainIdentifier: '0x6e1a19f235be7ed8e3369ef73b196c07257494de' + }, + { + assetType: 'WFLOW', + decimals: 18, + name: 'Wrapped Flow', + networkId: 'ETH', + onchainIdentifier: '0x5c147e74d63b1d31aa3fd78eb229b65161983b2b' + }, + { + assetType: 'WLD', + decimals: 18, + name: 'Worldcoin', + networkId: 'ETH', + onchainIdentifier: '0x163f8c2467924be0ae7b5347228cabf260318753' + }, + { + assetType: 'WM', + decimals: 6, + name: 'WrappedM by M^0', + networkId: 'ETH', + onchainIdentifier: '0x437cc33344a0b27a429f795ff6b469c72698b291' + }, + { + assetType: 'WNXM', + decimals: 18, + name: 'Wrapped NXM', + networkId: 'ETH', + onchainIdentifier: '0x0d438f3b5175bebc262bf23753c1e53d03432bde' + }, + { + assetType: 'WOO', + decimals: 18, + name: 'Woo Network', + networkId: 'ETH', + onchainIdentifier: '0x4691937a7508860f876c9c0a2a617e7d9e945d4b' + }, + { + assetType: 'WOW', + decimals: 18, + name: 'World of Women', + networkId: 'ETH', + onchainIdentifier: '0xe785e82358879f061bc3dcac6f0444462d4b5330' + }, + { + assetType: 'WPUNKS', + decimals: 18, + name: 'Wrapped CryptoPunks', + networkId: 'ETH', + onchainIdentifier: '0xb7f7f6c52f2e2fdb1963eab30438024864c313f6' + }, + { + assetType: 'WQUIL', + decimals: 8, + name: 'Wrapped QUIL', + networkId: 'ETH', + onchainIdentifier: '0x8143182a775c54578c8b7b3ef77982498866945d' + }, + { + assetType: 'WSTETH', + decimals: 18, + name: 'Wrapped Staked ETH', + networkId: 'ETH', + onchainIdentifier: '0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0' + }, + { + assetType: 'WSTR', + decimals: 18, + name: 'WrappedStar', + networkId: 'ETH', + onchainIdentifier: '0xf0dc76c22139ab22618ddfb498be1283254612b1' + }, + { + assetType: 'WTAO', + decimals: 9, + name: 'Wrapped TAO', + networkId: 'ETH', + onchainIdentifier: '0x77e06c9eccf2e797fd462a92b6d7642ef85b0a44' + }, + { + assetType: 'WUSDM', + decimals: 18, + name: 'Wrapped Mountain Protocol USD', + networkId: 'ETH', + onchainIdentifier: '0x57f5e098cad7a3d1eed53991d4d66c45c9af7812' + }, + { + assetType: 'WZEC', + decimals: 18, + name: 'Wrapped Zcash', + networkId: 'ETH', + onchainIdentifier: '0x4a64515e5e1d1073e83f30cb97bed20400b66e10' + }, + { + assetType: 'XAV', + decimals: 18, + name: 'Xave Token', + networkId: 'ETH', + onchainIdentifier: '0x40370aed88933021e20cf7c4d67e00417cda2202' + }, + { + assetType: 'XJ_ZKSYNC_T', + decimals: 18, + name: 'xjToken', + networkId: 'ZKSYNC_SEPOLIA', + onchainIdentifier: '0x69e5dc39e2bcb1c17053d2a4ee7caeaac5d36f96' + }, + { + assetType: 'XMPL', + decimals: 18, + name: 'XMPL', + networkId: 'ETH', + onchainIdentifier: '0x4937a209d4cdbd3ecd48857277cfd4da4d82914c' + }, + { + assetType: 'XRP', + decimals: 6, + name: 'Ripple', + networkId: 'XRP' + }, + { + assetType: 'XSUSHI', + decimals: 18, + name: 'SushiBar', + networkId: 'ETH', + onchainIdentifier: '0x8798249c2e607446efb7ad49ec89dd1865ff4272' + }, + { + assetType: 'XYLB', + decimals: 0, + name: 'XY Labs', + networkId: 'ETH', + onchainIdentifier: '0x00d61c23ba36001603f1fcb4981e2d13ef9f0923' + }, + { + assetType: 'YFI', + decimals: 18, + name: 'yearn.finance', + networkId: 'ETH', + onchainIdentifier: '0x0bc529c00c6401aef6d220be8c6ea1667f6ad93e' + }, + { + assetType: 'YGG', + decimals: 18, + name: 'Yield Guild Games', + networkId: 'ETH', + onchainIdentifier: '0x25f8087ead173b73d6e8b84329989a8eea16cf73' + }, + { + assetType: 'ZBU', + decimals: 18, + name: 'ZEEBU', + networkId: 'ETH', + onchainIdentifier: '0x8f9b4525681f3ea6e43b8e0a57bfff86c0a1dd2e' + }, + { + assetType: 'ZENT', + decimals: 18, + name: 'Zentry', + networkId: 'ETH', + onchainIdentifier: '0xdbb7a34bf10169d6d2d0d02a6cbb436cf4381bfa' + }, + { + assetType: 'ZERO', + decimals: 6, + name: 'Zero by M^0', + networkId: 'ETH', + onchainIdentifier: '0x988567fe094570cce1ffda29d1f2d842b70492be' + }, + { + assetType: 'ZRO', + decimals: 18, + name: 'LayerZero', + networkId: 'ETH', + onchainIdentifier: '0x6985884c4392d348587b19cb9eaaf157f13271cd' + }, + { + assetType: 'ZRX', + decimals: 18, + name: '0x', + networkId: 'ETH', + onchainIdentifier: '0xe41d2489571d322189246dafa5ebde1f4699f498' + }, + { + assetType: 'cEUR_TB', + decimals: 18, + name: 'Celo EUR Testnet (baklava)', + networkId: 'CELO_TB', + onchainIdentifier: '0xf9ece301247ad2ce21894941830a2470f4e774ca' + }, + { + assetType: 'cUSD_TB', + decimals: 18, + name: 'Celo USD Testnet (baklava)', + networkId: 'CELO_TB', + onchainIdentifier: '0x62492a644a588fd904270bed06ad52b9abfea1ae' + } +] diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts index fe29d64e4..57afc1c98 100644 --- a/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts @@ -2,12 +2,14 @@ import { LoggerService } from '@narval/nestjs-shared' import { HttpStatus, Injectable } from '@nestjs/common' import { v4 as uuid } from 'uuid' import { AnchorageClient } from '../../../http/client/anchorage.client' +import { NetworkRepository } from '../../../persistence/repository/network.repository' import { TransferRepository } from '../../../persistence/repository/transfer.repository' import { BrokerException } from '../../exception/broker.exception' import { TransferPartyService } from '../../service/transfer-party.service' import { ConnectionWithCredentials } from '../../type/connection.type' import { Provider, ProviderTransferService } from '../../type/provider.type' import { + Asset, Destination, InternalTransfer, NetworkFeeAttribution, @@ -19,6 +21,7 @@ import { isAddressDestination, isProviderSpecific } from '../../type/transfer.type' +import { ANCHORAGE_ASSETS, AnchorageAsset } from './anchorage-assets' import { validateConnection } from './anchorage.util' @Injectable() @@ -27,6 +30,7 @@ export class AnchorageTransferService implements ProviderTransferService { private readonly anchorageClient: AnchorageClient, private readonly transferPartyService: TransferPartyService, private readonly transferRepository: TransferRepository, + private readonly networkRepository: NetworkRepository, private readonly logger: LoggerService ) {} @@ -105,6 +109,34 @@ export class AnchorageTransferService implements ProviderTransferService { }) } + private async resolveAsset(asset: Asset): Promise { + if (asset.externalAssetId) { + return ANCHORAGE_ASSETS.find((a) => a.assetType === asset.externalAssetId) + } + + if (asset.assetId) { + // TODO: Look up by the narval assetId; for now we just treat it as the same as the anchorage one. + return ANCHORAGE_ASSETS.find((a) => a.assetType === asset.assetId) + } + + if (!asset.networkId) { + throw new BrokerException({ + message: 'Cannot resolve asset without networkId', + suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, + context: { asset } + }) + } + if (!asset.address) { + // This is the base asset of the network + return ANCHORAGE_ASSETS.find((a) => a.networkId === asset.networkId && !a.onchainIdentifier) + } + + // This is a chain-specific asset + return ANCHORAGE_ASSETS.find( + (a) => a.networkId === asset.networkId && a.onchainIdentifier?.toLowerCase() === asset.address?.toLowerCase() + ) + } + async send(connection: ConnectionWithCredentials, sendTransfer: SendTransfer): Promise { this.logger.log('Send Anchorage transfer', { clientId: connection.clientId, @@ -114,10 +146,33 @@ export class AnchorageTransferService implements ProviderTransferService { validateConnection(connection) - const source = await this.transferPartyService.resolve(connection.clientId, sendTransfer.source) - const destination = await this.transferPartyService.resolve(connection.clientId, sendTransfer.destination) + // Get the Network from the Asset. + const asset = await this.resolveAsset(sendTransfer.asset) + if (!asset) { + throw new BrokerException({ + message: 'Cannot resolve asset', + suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, + context: { asset: sendTransfer.asset } + }) + } + // Get the narval networkId from the anchorage asset networkId + const network = await this.networkRepository.findByExternalId(Provider.ANCHORAGE, asset.networkId) + if (!network) { + throw new BrokerException({ + message: 'Cannot resolve Narval networkId from Anchorage networkId', + suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, + context: { asset } + }) + } + + const source = await this.transferPartyService.resolve(connection.clientId, sendTransfer.source, network.networkId) + const destination = await this.transferPartyService.resolve( + connection.clientId, + sendTransfer.destination, + network.networkId + ) - this.logger.log('Resolved source and destination', { source, destination }) + this.logger.log('Resolved source and destination', { source, destination, networkId: network.networkId }) // NOTE: Because Anchorage defaults `deductFeeFromAmountIfSameType` to false, we // default the fee attribution to ON_TOP to match their API's behaviour. @@ -131,7 +186,7 @@ export class AnchorageTransferService implements ProviderTransferService { type: this.getResourceType(sendTransfer.destination), id: destination.externalId }, - assetType: sendTransfer.assetId, + assetType: asset.assetType, amount: sendTransfer.amount, transferMemo: sendTransfer.memo || null, idempotentId: sendTransfer.idempotenceId, @@ -147,7 +202,7 @@ export class AnchorageTransferService implements ProviderTransferService { }) const internalTransfer: InternalTransfer = { - assetId: sendTransfer.assetId, + assetId: asset.assetType, // TODO: switch this to the Narval assetId once that is a real thing. clientId: connection.clientId, createdAt: new Date(), customerRefId: null, diff --git a/apps/vault/src/broker/core/service/transfer-party.service.ts b/apps/vault/src/broker/core/service/transfer-party.service.ts index 36882313f..d0c034e58 100644 --- a/apps/vault/src/broker/core/service/transfer-party.service.ts +++ b/apps/vault/src/broker/core/service/transfer-party.service.ts @@ -22,12 +22,13 @@ export class TransferPartyService { async resolve( clientId: string, - transferParty: Source | Destination + transferParty: Source | Destination, + networkId: string ): Promise { const span = this.traceService.startSpan(`${TransferPartyService.name}.resolve`) try { - return this.findTransferParty(clientId, transferParty) + return this.findTransferParty(clientId, transferParty, networkId) } catch (error) { this.logger.error('Unable to resolve transfer party', { clientId, transferParty, error }) @@ -43,46 +44,34 @@ export class TransferPartyService { private async findTransferParty( clientId: string, - transferParty: Source | Destination + transferParty: Source | Destination, + networkId: string ): Promise { this.logger.log('Find transfer party', { clientId, transferParty }) + // TODO: Need Network. if (isAddressDestination(transferParty)) { const rawAddress = transferParty.address this.logger.log('Starting search address destination by raw address', { clientId, rawAddress }) - const { data: addresses } = await this.addressRepository.findAll(clientId, { - filters: { - addresses: [transferParty.address] - } - }) - - if (addresses.length) { - if (addresses.length > 1) { - throw new BrokerException({ - message: 'Cannot resolve the right address due to ambiguity', - suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, - context: { - clientId, - addresses: addresses.map(({ address, addressId }) => ({ addressId, address })) - } - }) - } + const providerAddress = await this.addressRepository.findByAddress(clientId, transferParty.address, networkId) - this.logger.log('Successfully found address destination for raw address', { + if (providerAddress) { + this.logger.log('Successfully found account address destination for raw address', { clientId, - address: addresses[0] + address: providerAddress }) - return addresses[0] + return providerAddress } this.logger.log('Starting search known destination by raw address', { clientId, rawAddress }) const { data: knownDestinations } = await this.knownDestinationRepository.findAll(clientId, { filters: { - addresses: [transferParty.address] + addresses: [transferParty.address], + networksIds: [networkId] } }) diff --git a/apps/vault/src/broker/core/service/transfer.service.ts b/apps/vault/src/broker/core/service/transfer.service.ts index 5c2e70c0e..0a1fe7af5 100644 --- a/apps/vault/src/broker/core/service/transfer.service.ts +++ b/apps/vault/src/broker/core/service/transfer.service.ts @@ -40,15 +40,14 @@ export class TransferService { async send(clientId: string, connectionId: string, sendTransfer: SendTransfer): Promise { this.logger.log('Send transfer', { clientId, sendTransfer }) - const span = this.traceService.startSpan(`${TransferService.name}.sync`) + const span = this.traceService.startSpan(`${TransferService.name}.send`) - const source = await this.transferPartyService.resolve(clientId, sendTransfer.source) const connection = await this.connectionService.findWithCredentialsById(clientId, connectionId) if (isActiveConnection(connection)) { span.setAttribute(OTEL_ATTR_CONNECTION_PROVIDER, connection.provider) - const transfer = await this.getProviderTransferService(source.provider).send(connection, sendTransfer) + const transfer = await this.getProviderTransferService(connection.provider).send(connection, sendTransfer) span.end() @@ -64,7 +63,7 @@ export class TransferService { throw new BrokerException({ message: 'Cannot find an active connection for the source', suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, - context: { source } + context: { connection, connectionId, clientId } }) } diff --git a/apps/vault/src/broker/core/type/transfer.type.ts b/apps/vault/src/broker/core/type/transfer.type.ts index 7ef7f5efb..b11d9cde3 100644 --- a/apps/vault/src/broker/core/type/transfer.type.ts +++ b/apps/vault/src/broker/core/type/transfer.type.ts @@ -31,11 +31,33 @@ export type AddressDestination = z.infer export const Destination = z.union([TransferParty, AddressDestination]) export type Destination = z.infer +export const Asset = z + .object({ + assetId: z.string().optional().describe('ID of the asset. Can be used instead of address+networkId.'), + externalAssetId: z + .string() + .optional() + .describe( + 'ID of the asset on the provider. Can be used to directly specify the asset of the underlying provider.' + ), + address: z + .string() + .optional() + .describe( + 'On-chain address of the asset. If assetId is null, then an empty address means the network Base Asset (e.g. BTC)' + ), + networkId: z.string().optional().describe('Network of the asset. Required if address is provided.') + }) + .describe('The asset being transferred') +export type Asset = z.infer + export const SendTransfer = z.object({ source: Source, destination: Destination, amount: z.string(), - assetId: z.string(), + + assetId: z.string().optional().describe('@deprecated use asset instead'), // @deprecated use asset instead + asset: Asset, // This is optional on the base transfer and always default on the // provider-specific transfer service. networkFeeAttribution: z.nativeEnum(NetworkFeeAttribution).optional(), diff --git a/apps/vault/src/broker/persistence/repository/address.repository.ts b/apps/vault/src/broker/persistence/repository/address.repository.ts index cba5ed4b9..cd8126346 100644 --- a/apps/vault/src/broker/persistence/repository/address.repository.ts +++ b/apps/vault/src/broker/persistence/repository/address.repository.ts @@ -1,8 +1,9 @@ import { PaginatedResult, PaginationOptions, applyPagination, getPaginatedResult } from '@narval/nestjs-shared' -import { Injectable } from '@nestjs/common' +import { HttpStatus, Injectable } from '@nestjs/common' import { ProviderAddress } from '@prisma/client/vault' import { z } from 'zod' import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' +import { BrokerException } from '../../core/exception/broker.exception' import { NotFoundException } from '../../core/exception/not-found.exception' import { Address } from '../../core/type/indexed-resources.type' import { Provider } from '../../core/type/provider.type' @@ -74,6 +75,31 @@ export class AddressRepository { return AddressRepository.parseModel(address) } + async findByAddress(clientId: string, address: string, networkId: string): Promise

{ + const providerAddresses = await this.prismaService.providerAddress.findMany({ + where: { + clientId, + address, + account: { + networkId + } + } + }) + + if (providerAddresses.length > 1) { + throw new BrokerException({ + message: 'Cannot resolve the right address due to ambiguity', + suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, + context: { + clientId, + addresses: providerAddresses.map(({ address, id }) => ({ addressId: id, address })) + } + }) + } + + return providerAddresses.length ? AddressRepository.parseModel(providerAddresses[0]) : null + } + async findAll(clientId: string, opts?: FindAllOptions): Promise> { const pagination = applyPagination(opts?.pagination) diff --git a/apps/vault/src/broker/persistence/repository/known-destination.repository.ts b/apps/vault/src/broker/persistence/repository/known-destination.repository.ts index ef1ac211f..f69259671 100644 --- a/apps/vault/src/broker/persistence/repository/known-destination.repository.ts +++ b/apps/vault/src/broker/persistence/repository/known-destination.repository.ts @@ -14,6 +14,7 @@ type FindAllFilters = { addresses?: string[] providers?: Provider[] connections?: string[] + networksIds?: string[] } } @@ -153,6 +154,13 @@ export class KnownDestinationRepository { } } } + : {}), + ...(opts?.filters?.networksIds + ? { + networkId: { + in: opts.filters.networksIds + } + } : {}) }, include: { diff --git a/packages/armory-sdk/src/lib/http/client/vault/api.ts b/packages/armory-sdk/src/lib/http/client/vault/api.ts index 7b0c6ba96..5640bea20 100644 --- a/packages/armory-sdk/src/lib/http/client/vault/api.ts +++ b/packages/armory-sdk/src/lib/http/client/vault/api.ts @@ -2112,11 +2112,17 @@ export interface SendTransferDto { */ 'amount': string; /** - * + * @deprecated use asset instead * @type {string} * @memberof SendTransferDto */ - 'assetId': string; + 'assetId'?: string; + /** + * + * @type {SendTransferDtoAsset} + * @memberof SendTransferDto + */ + 'asset': SendTransferDtoAsset; /** * * @type {string} @@ -2168,6 +2174,37 @@ export const SendTransferDtoProviderEnum = { export type SendTransferDtoProviderEnum = typeof SendTransferDtoProviderEnum[keyof typeof SendTransferDtoProviderEnum]; +/** + * The asset being transferred + * @export + * @interface SendTransferDtoAsset + */ +export interface SendTransferDtoAsset { + /** + * ID of the asset. Can be used instead of address+networkId. + * @type {string} + * @memberof SendTransferDtoAsset + */ + 'assetId'?: string; + /** + * ID of the asset on the provider. Can be used to directly specify the asset of the underlying provider. + * @type {string} + * @memberof SendTransferDtoAsset + */ + 'externalAssetId'?: string; + /** + * On-chain address of the asset. If assetId is null, then an empty address means the network Base Asset (e.g. BTC) + * @type {string} + * @memberof SendTransferDtoAsset + */ + 'address'?: string; + /** + * Network of the asset. Required if address is provided. + * @type {string} + * @memberof SendTransferDtoAsset + */ + 'networkId'?: string; +} /** * @type SendTransferDtoDestination * @export diff --git a/packages/armory-sdk/src/lib/vault/client.ts b/packages/armory-sdk/src/lib/vault/client.ts index d1639b436..f40694ffd 100644 --- a/packages/armory-sdk/src/lib/vault/client.ts +++ b/packages/armory-sdk/src/lib/vault/client.ts @@ -518,14 +518,28 @@ export class VaultClient { } async listProviderWallets({ + connectionId, accessToken, pagination }: { + connectionId?: string accessToken?: AccessToken pagination?: RequestPagination } = {}): Promise { const token = accessToken ? prefixGnapToken(accessToken) : undefined + if (connectionId) { + const { data: wallets } = await this.providerConnectionHttp.listWallets({ + xClientId: this.config.clientId, + connectionId, + authorization: token, + cursor: pagination?.cursor, + limit: pagination?.limit, + desc: pagination?.desc + }) + return wallets + } + const { data: wallets } = await this.providerWalletHttp.list({ xClientId: this.config.clientId, authorization: token, From 698943ae359f7a63e65105abca27ea4e1992369e Mon Sep 17 00:00:00 2001 From: Matt Schoch Date: Tue, 7 Jan 2025 18:58:19 +0100 Subject: [PATCH 079/120] Fixing asset network lookup --- .../anchorage/anchorage-transfer.service.ts | 12 ++++++++++-- apps/vault/src/main.ts | 2 +- examples/unified-api/5-create-transfer.ts | 14 +++++++++++++- examples/unified-api/package-lock.json | 9 +++++---- examples/unified-api/package.json | 2 +- 5 files changed, 30 insertions(+), 9 deletions(-) diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts index 57afc1c98..2c5f78286 100644 --- a/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts @@ -126,14 +126,22 @@ export class AnchorageTransferService implements ProviderTransferService { context: { asset } }) } + const network = await this.networkRepository.findById(asset.networkId) + if (!network) { + throw new BrokerException({ + message: 'Cannot resolve asset without valid network', + suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, + context: { asset } + }) + } if (!asset.address) { // This is the base asset of the network - return ANCHORAGE_ASSETS.find((a) => a.networkId === asset.networkId && !a.onchainIdentifier) + return ANCHORAGE_ASSETS.find((a) => a.networkId === network.anchorageId && !a.onchainIdentifier) } // This is a chain-specific asset return ANCHORAGE_ASSETS.find( - (a) => a.networkId === asset.networkId && a.onchainIdentifier?.toLowerCase() === asset.address?.toLowerCase() + (a) => a.networkId === network.anchorageId && a.onchainIdentifier?.toLowerCase() === asset.address?.toLowerCase() ) } diff --git a/apps/vault/src/main.ts b/apps/vault/src/main.ts index db62856cf..46669d4c7 100644 --- a/apps/vault/src/main.ts +++ b/apps/vault/src/main.ts @@ -63,7 +63,7 @@ async function bootstrap() { withSwagger({ title: 'Vault', description: - 'Secure storage for private keys and sensitive data, designed to protect your most critical assets in web3.0', + 'Secure Enclave-backed authorization proxy for web3 secrets. Holds encrypted credentials and proxies API requests to custodians and wallet tech providers. Can also generate evm wallet private keys & sign transactions.', version: '1.0', security: [securityOptions.gnap, securityOptions.adminApiKey, securityOptions.detachedJws], server: { diff --git a/examples/unified-api/5-create-transfer.ts b/examples/unified-api/5-create-transfer.ts index 9d8c04a0c..ad277b865 100644 --- a/examples/unified-api/5-create-transfer.ts +++ b/examples/unified-api/5-create-transfer.ts @@ -1,13 +1,23 @@ +import { v4 } from 'uuid' import { vaultClient } from './vault.client' const fromId = '11904d17-f621-4cbe-bdcb-d587e7bc8045' const toId = '3b102898-5468-445b-99ac-f672033d6f37' const assetType = 'BTC_S' const amount = '0.00001' +const connectionId = process.env.CONNECTION_ID +const url = process.env.CONNECTION_URL + +if (!connectionId) { + console.error('Please provide CONNECTION_ID in your .env file') + process.exit(1) +} const main = async () => { const transfer = await vaultClient.sendTransfer({ + connectionId, data: { + idempotenceId: v4(), source: { type: 'account', id: fromId @@ -16,7 +26,9 @@ const main = async () => { type: 'account', id: toId }, - assetId: assetType, + asset: { + assetId: assetType + }, amount } }) diff --git a/examples/unified-api/package-lock.json b/examples/unified-api/package-lock.json index e1754c39e..763011c04 100644 --- a/examples/unified-api/package-lock.json +++ b/examples/unified-api/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "@narval-xyz/armory-sdk": "0.15.0", + "@narval-xyz/armory-sdk": "0.17.0", "dotenv": "16.4.5", "tsx": "4.19.2" } @@ -380,9 +380,10 @@ } }, "node_modules/@narval-xyz/armory-sdk": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@narval-xyz/armory-sdk/-/armory-sdk-0.15.0.tgz", - "integrity": "sha512-WB58ecz/1nozojAvn8F42HpuFa7FKIYW8U0pAcFi9gPxq4iK+0bKvRfiqf7I3geE3yGimAMLQBAUuN5DpgdMRg==", + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@narval-xyz/armory-sdk/-/armory-sdk-0.17.0.tgz", + "integrity": "sha512-94AxgbSddeghixiP7fgL/13ECJMezwJti6bvAAxEZscNNK9D9r6BSQdY52dgMGJ8Yu/hSxcrfa1OkWjzTCdZZA==", + "license": "MPL-2.0", "dependencies": { "@noble/curves": "1.6.0", "@noble/ed25519": "1.7.1", diff --git a/examples/unified-api/package.json b/examples/unified-api/package.json index b079e2dc1..33a90467c 100644 --- a/examples/unified-api/package.json +++ b/examples/unified-api/package.json @@ -9,7 +9,7 @@ "author": "", "license": "ISC", "dependencies": { - "@narval-xyz/armory-sdk": "0.15.0", + "@narval-xyz/armory-sdk": "0.17.0", "dotenv": "16.4.5", "tsx": "4.19.2" } From e2d08142f6c6b8f5f547769ba82a2834b0a1773e Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Tue, 7 Jan 2025 19:10:03 +0100 Subject: [PATCH 080/120] Data migration to fix network ID in staging (#76) --- .../migration.sql | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 apps/vault/src/shared/module/persistence/schema/migrations/20250107175743_fix_staging_network_id_data/migration.sql diff --git a/apps/vault/src/shared/module/persistence/schema/migrations/20250107175743_fix_staging_network_id_data/migration.sql b/apps/vault/src/shared/module/persistence/schema/migrations/20250107175743_fix_staging_network_id_data/migration.sql new file mode 100644 index 000000000..e62501150 --- /dev/null +++ b/apps/vault/src/shared/module/persistence/schema/migrations/20250107175743_fix_staging_network_id_data/migration.sql @@ -0,0 +1,17 @@ +UPDATE provider_account SET network_id = 'BITCOIN' WHERE network_id = 'BTC'; +UPDATE provider_account SET network_id = 'BITCOIN_SIGNET' WHERE network_id = 'BTC_S'; +UPDATE provider_account SET network_id = 'BITCOIN_CASH' WHERE network_id = 'BCH'; +UPDATE provider_account SET network_id = 'ARBITRUM_SEPOLIA' WHERE network_id = 'ETH_ARBITRUM_T'; +UPDATE provider_account SET network_id = 'ETHEREUM' WHERE network_id = 'ETH'; +UPDATE provider_account SET network_id = 'ETHEREUM_HOLESKY' WHERE network_id = 'ETHHOL'; +UPDATE provider_account SET network_id = 'ETHEREUM_SEPOLIA' WHERE network_id = 'ETHSEP'; +UPDATE provider_account SET network_id = 'POLYGON' WHERE network_id = 'POL_POLYGON'; + +UPDATE provider_known_destination SET network_id = 'BITCOIN' WHERE network_id = 'BTC'; +UPDATE provider_known_destination SET network_id = 'BITCOIN_SIGNET' WHERE network_id = 'BTC_S'; +UPDATE provider_known_destination SET network_id = 'BITCOIN_CASH' WHERE network_id = 'BCH'; +UPDATE provider_known_destination SET network_id = 'ARBITRUM_SEPOLIA' WHERE network_id = 'ETH_ARBITRUM_T'; +UPDATE provider_known_destination SET network_id = 'ETHEREUM' WHERE network_id = 'ETH'; +UPDATE provider_known_destination SET network_id = 'ETHEREUM_HOLESKY' WHERE network_id = 'ETHHOL'; +UPDATE provider_known_destination SET network_id = 'ETHEREUM_SEPOLIA' WHERE network_id = 'ETHSEP'; +UPDATE provider_known_destination SET network_id = 'POLYGON' WHERE network_id = 'POL_POLYGON'; From d4fe06f108866e7415074c134cca3098c4b115f5 Mon Sep 17 00:00:00 2001 From: Matt Schoch Date: Wed, 8 Jan 2025 18:21:58 +0100 Subject: [PATCH 081/120] HOTFIX - actually using the Narval networkId in the known destination sync --- .../broker/core/provider/anchorage/anchorage-sync.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage-sync.service.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage-sync.service.ts index b839d50d9..7bd239e90 100644 --- a/apps/vault/src/broker/core/provider/anchorage/anchorage-sync.service.ts +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage-sync.service.ts @@ -403,7 +403,7 @@ export class AnchorageSyncService implements ProviderSyncService { label: anchorageTrustedAddress.crypto.memo, assetId: anchorageTrustedAddress.crypto.assetType, provider: Provider.ANCHORAGE, - networkId: anchorageTrustedAddress.crypto.networkId, + networkId: network.networkId, createdAt: now, updatedAt: now, connections: [connection] From 4f6f98e6cce2edcd192bdc11fbc53a905a16fc9a Mon Sep 17 00:00:00 2001 From: Matt Schoch Date: Wed, 8 Jan 2025 18:30:12 +0100 Subject: [PATCH 082/120] fixing test --- .../__test__/integration/anchorage-sync.service.spec.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-sync.service.spec.ts b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-sync.service.spec.ts index f1ed2229b..923557997 100644 --- a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-sync.service.spec.ts +++ b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-sync.service.spec.ts @@ -425,7 +425,7 @@ describe(AnchorageSyncService.name, () => { externalId: 'toBeConnected', knownDestinationId: expect.any(String), label: undefined, - networkId: 'ETH', + networkId: 'ETHEREUM', provider: Provider.ANCHORAGE, updatedAt: now } @@ -465,7 +465,7 @@ describe(AnchorageSyncService.name, () => { externalId: 'toBeUpdated', knownDestinationId: expect.any(String), label: 'new memo', - networkId: 'ETH', + networkId: 'ETHEREUM', provider: Provider.ANCHORAGE, updatedAt: now } @@ -523,7 +523,7 @@ describe(AnchorageSyncService.name, () => { externalId: 'toBeConnected', knownDestinationId: expect.any(String), label: undefined, - networkId: 'ETH', + networkId: 'ETHEREUM', provider: Provider.ANCHORAGE, updatedAt: now } From 829bf72d33ba382df9ced15f271eacab8ad6c1f4 Mon Sep 17 00:00:00 2001 From: Ptroger <44851272+Ptroger@users.noreply.github.com> Date: Fri, 10 Jan 2025 16:14:29 +0100 Subject: [PATCH 083/120] Feat/fb client (#78) * methods to fetch fb API for sync * client test with dependencies * use string type for fireblocks expected constants --- .../__test__/unit/fireblocks.client.spec.ts | 9 +- .../broker/http/client/fireblocks.client.ts | 433 +++++++++++++++++- 2 files changed, 433 insertions(+), 9 deletions(-) diff --git a/apps/vault/src/broker/http/client/__test__/unit/fireblocks.client.spec.ts b/apps/vault/src/broker/http/client/__test__/unit/fireblocks.client.spec.ts index 4231c5f96..2a1ade16e 100644 --- a/apps/vault/src/broker/http/client/__test__/unit/fireblocks.client.spec.ts +++ b/apps/vault/src/broker/http/client/__test__/unit/fireblocks.client.spec.ts @@ -1,6 +1,8 @@ +import { LoggerService } from '@narval/nestjs-shared' import { RsaPrivateKey } from '@narval/signature' +import { HttpService } from '@nestjs/axios' import axios from 'axios' -import { mockReset } from 'jest-mock-extended' +import { mock, mockReset } from 'jest-mock-extended' import { BrokerException } from '../../../../core/exception/broker.exception' import { UrlParserException } from '../../../../core/exception/url-parser.exception' import { FireblocksClient } from '../../fireblocks.client' @@ -26,7 +28,10 @@ describe(FireblocksClient.name, () => { } beforeEach(() => { - client = new FireblocksClient() + const httpServiceMock = mock() + const loggerServiceMock = mock() + + client = new FireblocksClient(httpServiceMock, loggerServiceMock) mockReset(mockedAxios) }) diff --git a/apps/vault/src/broker/http/client/fireblocks.client.ts b/apps/vault/src/broker/http/client/fireblocks.client.ts index e1be7fd5c..0d0422273 100644 --- a/apps/vault/src/broker/http/client/fireblocks.client.ts +++ b/apps/vault/src/broker/http/client/fireblocks.client.ts @@ -1,9 +1,12 @@ +import { LoggerService } from '@narval/nestjs-shared' import { RsaPrivateKey, hash, signJwt } from '@narval/signature' +import { HttpService } from '@nestjs/axios' import { HttpStatus, Injectable } from '@nestjs/common' import axios, { AxiosRequestConfig, AxiosResponse } from 'axios' import { isNil, omitBy } from 'lodash' +import { EMPTY, Observable, catchError, expand, from, lastValueFrom, map, reduce, switchMap, tap } from 'rxjs' import { v4 } from 'uuid' -import { z } from 'zod' +import { ZodType, z } from 'zod' import { BrokerException } from '../../core/exception/broker.exception' import { UrlParserException } from '../../core/exception/url-parser.exception' @@ -33,7 +36,7 @@ const Asset = z.object({ blockHeight: z.string().optional(), blockHash: z.string().optional(), rewardsInfo: RewardsInfo.optional(), - hiddenOnUI: z.boolean(), + hiddenOnUI: z.boolean().optional(), customerRefId: z.string().optional(), autoFuel: z.boolean().optional() }) @@ -43,15 +46,15 @@ const VaultAccount = z.object({ id: z.string(), name: z.string().optional(), assets: z.array(Asset), - hiddenOnUI: z.boolean(), - customerRefId: z.string(), + hiddenOnUI: z.boolean().optional(), + customerRefId: z.string().optional(), autoFuel: z.boolean() }) type VaultAccount = z.infer const Paging = z.object({ - before: z.string(), - after: z.string() + before: z.string().optional(), + after: z.string().optional() }) type Paging = z.infer @@ -79,7 +82,7 @@ const AssetWallet = z.object({ lockedAmount: z.string(), blockHeight: z.string().nullable(), blockHash: z.string().nullable(), - creationTimestamp: z.string() + creationTimestamp: z.string().optional() }) type AssetWallet = z.infer @@ -89,8 +92,84 @@ const GetVaultWalletsResponse = z.object({ }) type GetVaultWalletsResponse = z.infer +const AssetAddress = z.object({ + assetId: z.string(), + address: z.string(), + description: z.string().optional(), + tag: z.string().optional(), + type: z.string(), + customerRefId: z.string().optional(), + addressFormat: z.string().optional(), + legacyAddress: z.string(), + enterpriseAddress: z.string(), + bip44AddressIndex: z.number(), + userDefined: z.boolean() +}) +type AssetAddress = z.infer + +const GetAddressListResponse = z.object({ + addresses: z.array(AssetAddress), + paging: Paging.optional() +}) +type GetAddressListResponse = z.infer + +const InternalWhitelistedAddressAsset = z.object({ + id: z.string(), + balance: z.string(), + lockedAmount: z.string().optional(), + status: z.string(), + address: z.string(), + tag: z.string().optional(), + activationTime: z.string().optional() +}) +type InternalWhitelistedAddressAsset = z.infer + +const InternalWhitelistedWallet = z.object({ + id: z.string(), + name: z.string(), + customerRefId: z.string().optional(), + assets: z.array(InternalWhitelistedAddressAsset) +}) +type InternalWhitelistedWallet = z.infer + +const ExternalWhitelistedAddressAsset = z.object({ + id: z.string(), + lockedAmount: z.string().optional(), + status: z.string(), + address: z.string(), + tag: z.string(), + activationTime: z.string().optional() +}) +type ExternalWhitelistedAddressAsset = z.infer + +const ExternalWhitelistedAddress = z + .object({ + id: z.string(), + name: z.string(), + customerRefId: z.string().optional(), + assets: z.array(ExternalWhitelistedAddressAsset) + }) + .strict() +type ExternalWhitelistedAddress = z.infer + +const WhitelistedContract = ExternalWhitelistedAddress +type WhitelistedContract = z.infer + +const GetWhitelistedInternalWalletsResponse = z.array(InternalWhitelistedWallet) +type GetWhitelistedInternalWalletsResponse = z.infer + +const GetWhitelistedExternalWalletsResponse = z.array(ExternalWhitelistedAddress) +type GetWhitelistedExternalWalletsResponse = z.infer + +const GetWhitelistedContractsResponse = z.array(WhitelistedContract) +type GetWhitelistedContractsResponse = z.infer @Injectable() export class FireblocksClient { + constructor( + private readonly httpService: HttpService, + private readonly logger: LoggerService + ) {} + async forward({ url, method, data, apiKey, signKey, nonce }: ForwardRequestOptions): Promise { const signedRequest = await this.authorize({ request: { @@ -173,6 +252,16 @@ export class FireblocksClient { return match[1] } + private serializeError(error: any) { + return { + message: error.message, + name: error.name, + stack: error.stack, + status: error.response?.status, + statusText: error.response?.statusText + } + } + private validateRequest(request: AxiosRequestConfig): asserts request is AxiosRequestConfig & { url: string method: string @@ -191,4 +280,334 @@ export class FireblocksClient { }) } } + + private sendSignedRequest(opts: { + schema: ZodType + request: AxiosRequestConfig + signKey: RsaPrivateKey + apiKey: string + }): Observable { + return from( + this.authorize({ + request: opts.request, + apiKey: opts.apiKey, + signKey: opts.signKey + }) + ).pipe( + switchMap((signedRequest) => + this.httpService.request(signedRequest).pipe( + tap((response) => { + this.logger.log('Received response', { + url: opts.request.url, + method: opts.request.method, + nextPage: response.data?.paging?.after + }) + }), + map((response) => opts.schema.parse(response.data)) + ) + ) + ) + } + + async getVaultAccounts(opts: { apiKey: string; signKey: RsaPrivateKey; url: string }): Promise { + this.logger.log('Requesting Fireblocks vault accounts page', { + url: opts.url + }) + + return lastValueFrom( + this.sendSignedRequest({ + schema: GetVaultAccountsResponse, + request: { + url: `${opts.url}/v1/vault/accounts_paged`, + params: { + limit: 500 + }, + method: 'GET' + }, + apiKey: opts.apiKey, + signKey: opts.signKey + }).pipe( + expand((response) => { + if (response.paging.after) { + return this.sendSignedRequest({ + schema: GetVaultAccountsResponse, + request: { + url: `${opts.url}/v1/vault/accounts_paged`, + method: 'GET', + params: { + limit: 500, + after: response.paging.after + } + }, + apiKey: opts.apiKey, + signKey: opts.signKey + }) + } + return EMPTY + }), + tap((response) => { + if (response.paging.after) { + this.logger.log('Requesting Fireblocks vault accounts next page', { + url: opts.url + }) + } else { + this.logger.log('Reached Fireblocks vault accounts last page') + } + }), + reduce((accounts: VaultAccount[], response) => [...accounts, ...response.accounts], []), + tap((accounts) => { + this.logger.log('Completed fetching all vault accounts', { + accountsCount: accounts.length, + url: opts.url + }) + }), + catchError((error) => { + this.logger.error('Failed to get Fireblocks vault accounts', this.serializeError(error)) + throw error + }) + ) + ) + } + + async getAssetWallets(opts: { apiKey: string; signKey: RsaPrivateKey; url: string }): Promise { + this.logger.log('Requesting Fireblocks asset wallets page', { + url: opts.url + }) + + return lastValueFrom( + this.sendSignedRequest({ + schema: GetVaultWalletsResponse, + request: { + url: `${opts.url}/v1/vault/asset_wallets`, + method: 'GET', + params: { + limit: 1000 + } + }, + apiKey: opts.apiKey, + signKey: opts.signKey + }).pipe( + expand((response) => { + if (response.paging.after) { + return this.sendSignedRequest({ + schema: GetVaultWalletsResponse, + request: { + url: `${opts.url}/v1/vault/asset_wallets`, + method: 'GET', + params: { + after: response.paging.after, + limit: 1000 + } + }, + apiKey: opts.apiKey, + signKey: opts.signKey + }) + } + return EMPTY + }), + tap((response) => { + if (response.paging.after) { + this.logger.log('Requesting Fireblocks asset wallets next page', { + url: opts.url + }) + } else { + this.logger.log('Reached Fireblocks asset wallets last page') + } + }), + reduce((wallets: AssetWallet[], response) => [...wallets, ...response.assetWallets], []), + tap((wallets) => { + this.logger.log('Completed fetching all asset wallets', { + walletsCount: wallets.length, + url: opts.url + }) + }), + catchError((error) => { + this.logger.error('Failed to get Fireblocks asset wallets', this.serializeError(error)) + throw error + }) + ) + ) + } + + async getAddresses(opts: { + apiKey: string + signKey: RsaPrivateKey + url: string + vaultAccountId: string + assetId: string + }): Promise { + this.logger.log(`Requesting Fireblocks vault ${opts.vaultAccountId} asset ${opts.assetId} addresses page`, { + url: opts.url, + vaultAccountId: opts.vaultAccountId, + assetId: opts.assetId + }) + + return lastValueFrom( + this.sendSignedRequest({ + schema: GetAddressListResponse, + request: { + url: `${opts.url}/v1/vault/accounts/${opts.vaultAccountId}/${opts.assetId}/addresses_paginated`, + method: 'GET', + params: { + limit: 1000 + } + }, + apiKey: opts.apiKey, + signKey: opts.signKey + }).pipe( + expand((response) => { + if (response.paging?.after) { + return this.sendSignedRequest({ + schema: GetAddressListResponse, + request: { + url: `${opts.url}/v1/vault/accounts/${opts.vaultAccountId}/${opts.assetId}/addresses_paginated`, + method: 'GET', + params: { + after: response.paging.after, + limit: 1000 + } + }, + apiKey: opts.apiKey, + signKey: opts.signKey + }) + } + return EMPTY + }), + tap((response) => { + if (response.paging?.after) { + this.logger.log( + `Requesting Fireblocks vault ${opts.vaultAccountId} asset ${opts.assetId} addresses next page`, + { + url: opts.url, + vaultAccountId: opts.vaultAccountId, + assetId: opts.assetId + } + ) + } else { + this.logger.log(`Reached Fireblocks vault ${opts.vaultAccountId} asset ${opts.assetId} addresses last page`) + } + }), + reduce((addresses: AssetAddress[], response) => [...addresses, ...response.addresses], []), + tap((addresses) => { + this.logger.log(`Completed fetching all ${opts.assetId} addresses`, { + addressesCount: addresses.length, + url: opts.url, + vaultAccountId: opts.vaultAccountId, + assetId: opts.assetId + }) + }), + catchError((error) => { + this.logger.error(`Failed to get Fireblocks vault ${opts.vaultAccountId} asset ${opts.assetId} addresses`, { + error: error.message, + status: error.response?.status, + vaultAccountId: opts.vaultAccountId, + assetId: opts.assetId + }) + throw error + }) + ) + ) + } + + async getWhitelistedInternalWallets(opts: { + apiKey: string + signKey: RsaPrivateKey + url: string + }): Promise { + this.logger.log('Requesting Fireblocks whitelisted internal wallets page', { + url: opts.url + }) + + return lastValueFrom( + this.sendSignedRequest({ + schema: GetWhitelistedInternalWalletsResponse, + request: { + url: `${opts.url}/v1/internal_wallets`, + method: 'GET' + }, + apiKey: opts.apiKey, + signKey: opts.signKey + }).pipe( + reduce((wallets: InternalWhitelistedWallet[], response) => [...wallets, ...response], []), + tap((addresses) => { + this.logger.log('Completed fetching all whitelisted internal addresses', { + addressesCount: addresses.length, + url: opts.url + }) + }), + catchError((error) => { + this.logger.error('Failed to get Fireblocks whitelisted internal addresses', this.serializeError(error)) + throw error + }) + ) + ) + } + + async getWhitelistedExternalWallets(opts: { + apiKey: string + signKey: RsaPrivateKey + url: string + }): Promise { + this.logger.log('Requesting Fireblocks whitelisted external wallets page', { + url: opts.url + }) + + return lastValueFrom( + this.sendSignedRequest({ + schema: GetWhitelistedExternalWalletsResponse, + request: { + url: `${opts.url}/v1/external_wallets`, + method: 'GET' + }, + apiKey: opts.apiKey, + signKey: opts.signKey + }).pipe( + reduce((wallets: ExternalWhitelistedAddress[], response) => [...wallets, ...response], []), + tap((addresses) => { + this.logger.log('Completed fetching all whitelisted external addresses', { + addressesCount: addresses.length, + url: opts.url + }) + }), + catchError((error) => { + this.logger.error('Failed to get Fireblocks whitelisted external addresses', this.serializeError(error)) + throw error + }) + ) + ) + } + + async getWhitelistedContracts(opts: { + apiKey: string + signKey: RsaPrivateKey + url: string + }): Promise { + this.logger.log('Requesting Fireblocks whitelisted contracts page', { + url: opts.url + }) + + return lastValueFrom( + this.sendSignedRequest({ + schema: GetWhitelistedContractsResponse, + request: { + url: `${opts.url}/v1/contracts`, + method: 'GET' + }, + apiKey: opts.apiKey, + signKey: opts.signKey + }).pipe( + reduce((contracts: WhitelistedContract[], response) => [...contracts, ...response], []), + tap((contracts) => { + this.logger.log('Completed fetching all whitelisted contracts', { + contractsCount: contracts.length, + url: opts.url + }) + }), + catchError((error) => { + this.logger.error('Failed to get Fireblocks whitelisted contracts', this.serializeError(error)) + throw error + }) + ) + ) + } } From 12b94019f963f386967a2e5ee175c36ef5f12cae Mon Sep 17 00:00:00 2001 From: Matt Schoch Date: Mon, 13 Jan 2025 16:40:29 +0100 Subject: [PATCH 084/120] Fixing network mapping --- .../provider/anchorage/anchorage-assets.ts | 17 +++++++++++++++++ .../repository/network.repository.ts | 18 +++++++++--------- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage-assets.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage-assets.ts index 3aa426ab2..67059fb63 100644 --- a/apps/vault/src/broker/core/provider/anchorage/anchorage-assets.ts +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage-assets.ts @@ -2616,3 +2616,20 @@ export const ANCHORAGE_ASSETS: AnchorageAsset[] = [ onchainIdentifier: '0x62492a644a588fd904270bed06ad52b9abfea1ae' } ] + +/** + * util to find anchorage networks that don't have a match in the networks list. + +const baseAssets = ANCHORAGE_ASSETS.filter((asset) => !asset.onchainIdentifier) + +// for each baseAsset, see if you can find a match for `networkId` against the `anchorageId` property of the networks list. +// Filter the baseAssets list to only the ones that do NOT have a match. +const baseAssetsWithoutMatch = baseAssets.filter((asset) => { + const match = NETWORKS.find((network) => network.anchorageId === asset.networkId) + return !match +}) + +// Write teh base assets out to base-assets.json +fs.writeFileSync('base-assets-no-match.json', JSON.stringify(baseAssetsWithoutMatch, null, 2)) + +*/ diff --git a/apps/vault/src/broker/persistence/repository/network.repository.ts b/apps/vault/src/broker/persistence/repository/network.repository.ts index 3c8e64954..ee1826fbb 100644 --- a/apps/vault/src/broker/persistence/repository/network.repository.ts +++ b/apps/vault/src/broker/persistence/repository/network.repository.ts @@ -73,7 +73,7 @@ const NETWORKS: Network[] = [ networkId: 'ARBITRUM_SEPOLIA', coinType: 1, name: 'Arbitrum Sepolia Testnet', - anchorageId: 'ETH_ARBITRUM_T' + anchorageId: 'ARBITRUM_SEPOLIA' }, { networkId: 'ASTAR', @@ -91,7 +91,7 @@ const NETWORKS: Network[] = [ networkId: 'ATOM', coinType: 118, name: 'Atom', - anchorageId: 'ATOM', + anchorageId: 'COSMOS', fireblocksId: 'ATOM_COS' }, { @@ -344,7 +344,7 @@ const NETWORKS: Network[] = [ networkId: 'OASIS', coinType: 474, name: 'Oasis', - anchorageId: 'ROSE' + anchorageId: 'OAC' }, { networkId: 'OM_MANTRA', @@ -369,13 +369,13 @@ const NETWORKS: Network[] = [ networkId: 'PLUME_SEPOLIA', coinType: 1, name: 'Plume Sepolia Testnet', - anchorageId: 'ETH_PLUME_T' + anchorageId: 'PLUME_SEPOLIA' }, { networkId: 'POLYGON', coinType: 966, name: 'Polygon', - anchorageId: 'POL_POLYGON', + anchorageId: 'POLYGON', fireblocksId: 'MATIC_POLYGON' }, { @@ -434,7 +434,7 @@ const NETWORKS: Network[] = [ networkId: 'STARKNET', coinType: 9004, name: 'Starknet', - anchorageId: 'STRK_STARKNET' + anchorageId: 'STARK_STARKNET' }, { networkId: 'STARKNET_TESTNET', @@ -482,19 +482,19 @@ const NETWORKS: Network[] = [ networkId: 'VANA', coinType: null, name: 'Vana', - anchorageId: 'VANA_VANA' + anchorageId: 'VANA' }, { networkId: 'VANA_MOKSHA_TESTNET', coinType: 1, name: 'Vana Moksha Testnet', - anchorageId: 'VANA_VANA_MOKSHA_T' + anchorageId: 'VANA_MOKSHA_TESTNET' }, { networkId: 'ZKSYNC_SEPOLIA', coinType: 1, name: 'ZKsync Sepolia Testnet', - anchorageId: 'ETH_ZKSYNC_T' + anchorageId: 'ZKSYNC_SEPOLIA' }, { networkId: 'POLKADOT', From cecd1ddd46e409976ad469ab02189f3f59bae165 Mon Sep 17 00:00:00 2001 From: Matt Schoch Date: Mon, 13 Jan 2025 16:48:05 +0100 Subject: [PATCH 085/120] Updating mock data for anchorageId in network mapping --- .../__test__/server-mock/response/get-wallets-200.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/response/get-wallets-200.json b/apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/response/get-wallets-200.json index 3e1faa25d..cabc8d153 100644 --- a/apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/response/get-wallets-200.json +++ b/apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/response/get-wallets-200.json @@ -29,7 +29,7 @@ }, "isArchived": false, "isDefault": true, - "networkId": "ETH_ZKSYNC_T", + "networkId": "ZKSYNC_SEPOLIA", "type": "WALLET", "vaultId": "084ff57c0984420efac31723579c94fc", "vaultName": "Vault 1", @@ -65,7 +65,7 @@ }, "isArchived": false, "isDefault": true, - "networkId": "ETH_ARBITRUM_T", + "networkId": "ARBITRUM_SEPOLIA", "type": "WALLET", "vaultId": "084ff57c0984420efac31723579c94fc", "vaultName": "Vault 1", @@ -153,7 +153,7 @@ }, "isArchived": false, "isDefault": true, - "networkId": "POL_POLYGON", + "networkId": "POLYGON", "type": "WALLET", "vaultId": "084ff57c0984420efac31723579c94fc", "vaultName": "Vault 1", @@ -225,7 +225,7 @@ }, "isArchived": false, "isDefault": false, - "networkId": "POL_POLYGON", + "networkId": "POLYGON", "type": "WALLET", "vaultId": "084ff57c0984420efac31723579c94fc", "vaultName": "Vault 1", From 4279685c53efe70ea8c50e0db2d868ecbf7ab649 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Mon, 13 Jan 2025 18:42:46 +0100 Subject: [PATCH 086/120] Fix Anchorage trusted addresses transfer destination --- .../anchorage/anchorage-transfer.service.ts | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts index 2c5f78286..6a6e16faf 100644 --- a/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts @@ -7,6 +7,7 @@ import { TransferRepository } from '../../../persistence/repository/transfer.rep import { BrokerException } from '../../exception/broker.exception' import { TransferPartyService } from '../../service/transfer-party.service' import { ConnectionWithCredentials } from '../../type/connection.type' +import { Network } from '../../type/network.type' import { Provider, ProviderTransferService } from '../../type/provider.type' import { Asset, @@ -190,10 +191,7 @@ export class AnchorageTransferService implements ProviderTransferService { type: this.getResourceType(sendTransfer.source), id: source.externalId }, - destination: { - type: this.getResourceType(sendTransfer.destination), - id: destination.externalId - }, + destination: await this.getDestination(connection.clientId, network, sendTransfer), assetType: asset.assetType, amount: sendTransfer.amount, transferMemo: sendTransfer.memo || null, @@ -259,6 +257,27 @@ export class AnchorageTransferService implements ProviderTransferService { return false } + private async getDestination(clientId: string, network: Network, sendTransfer: SendTransfer) { + const destination = await this.transferPartyService.resolve(clientId, sendTransfer.destination, network.networkId) + const type = this.getResourceType(sendTransfer.destination) + + // TODO: Automate test this. It's an important biz rule. + if (type === 'ADDRESS' && 'knownDestinationId' in destination) { + return { + type, + id: destination.address + } + } + + // TODO: When we send to an internal address, do we must pass and ID or the + // address as well? + + return { + type, + id: destination.externalId + } + } + private getResourceType(transferParty: Source | Destination) { if (isAddressDestination(transferParty)) { return 'ADDRESS' From 33290c35f93f6c68121c7d7e4950a8051cdb61e5 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Mon, 13 Jan 2025 19:05:10 +0100 Subject: [PATCH 087/120] Remove the extra call destination --- .../anchorage/anchorage-transfer.service.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts index 6a6e16faf..e9233a159 100644 --- a/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts @@ -175,13 +175,8 @@ export class AnchorageTransferService implements ProviderTransferService { } const source = await this.transferPartyService.resolve(connection.clientId, sendTransfer.source, network.networkId) - const destination = await this.transferPartyService.resolve( - connection.clientId, - sendTransfer.destination, - network.networkId - ) - this.logger.log('Resolved source and destination', { source, destination, networkId: network.networkId }) + this.logger.log('Resolved Anchorage source', { source, networkId: network.networkId }) // NOTE: Because Anchorage defaults `deductFeeFromAmountIfSameType` to false, we // default the fee attribution to ON_TOP to match their API's behaviour. @@ -261,8 +256,15 @@ export class AnchorageTransferService implements ProviderTransferService { const destination = await this.transferPartyService.resolve(clientId, sendTransfer.destination, network.networkId) const type = this.getResourceType(sendTransfer.destination) + this.logger.log('Resolved Anchorage destination', { + network: network.networkId, + type, + destination + }) + // TODO: Automate test this. It's an important biz rule. - if (type === 'ADDRESS' && 'knownDestinationId' in destination) { + // If it's an Address or Known Destination + if (type === 'ADDRESS' && 'address' in destination) { return { type, id: destination.address From 0e4f720075a6a8aab92987123182a20e979034bd Mon Sep 17 00:00:00 2001 From: Ptroger <44851272+Ptroger@users.noreply.github.com> Date: Tue, 14 Jan 2025 09:16:33 +0100 Subject: [PATCH 088/120] Feature/nar 1985 sync fireblocks (#79) * syncing wallets and accounts. Addresses takes ages * add a passthrough to query with no pagination limit * sync from wallets to known-dests * Moved composed externalId in a util, fixed queries * naming and filter correctly for fireblocks * throw a correct error for anchorage knownDestination failed sync * removed unused test suite * add external classification to fireblocks's wallets * re-deleted unused test file --- apps/vault/src/broker/broker.module.ts | 2 + .../anchorage/anchorage-sync.service.ts | 15 +- .../response/get-asset-wallets-200.json | 31 ++ .../response/get-transfer-200.json | 28 + .../get-trusted-destinations-200-second.json | 35 ++ .../get-trusted-destinations-200-third.json | 16 + .../get-trusted-destinations-200.json | 44 ++ .../response/get-vault-accounts-200.json | 35 ++ .../get-wallet-addresses-matic-200.json | 16 + .../get-wallet-addresses-optimism-200.json | 16 + .../response/post-transfer-201.json | 6 + .../response/post-transfer-400.json | 4 + .../fireblocks/__test__/server-mock/server.ts | 37 ++ .../fireblocks/fireblocks-sync.service.ts | 497 ++++++++++++++++++ .../provider/fireblocks/fireblocks.type.ts | 7 + .../provider/fireblocks/fireblocks.util.ts | 24 + .../src/broker/core/service/sync.service.ts | 4 + .../broker/http/client/anchorage.client.ts | 5 +- .../broker/http/client/fireblocks.client.ts | 147 +++--- .../src/lib/type/pagination.type.ts | 1 + .../src/lib/util/pagination.util.ts | 7 +- 21 files changed, 880 insertions(+), 97 deletions(-) create mode 100644 apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-asset-wallets-200.json create mode 100644 apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-transfer-200.json create mode 100644 apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-trusted-destinations-200-second.json create mode 100644 apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-trusted-destinations-200-third.json create mode 100644 apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-trusted-destinations-200.json create mode 100644 apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-vault-accounts-200.json create mode 100644 apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-wallet-addresses-matic-200.json create mode 100644 apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-wallet-addresses-optimism-200.json create mode 100644 apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/post-transfer-201.json create mode 100644 apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/post-transfer-400.json create mode 100644 apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/server.ts create mode 100644 apps/vault/src/broker/core/provider/fireblocks/fireblocks-sync.service.ts diff --git a/apps/vault/src/broker/broker.module.ts b/apps/vault/src/broker/broker.module.ts index 29d170361..a4df1613f 100644 --- a/apps/vault/src/broker/broker.module.ts +++ b/apps/vault/src/broker/broker.module.ts @@ -15,6 +15,7 @@ import { AnchorageSyncService } from './core/provider/anchorage/anchorage-sync.s import { AnchorageTransferService } from './core/provider/anchorage/anchorage-transfer.service' import { FireblocksCredentialService } from './core/provider/fireblocks/fireblocks-credential.service' import { FireblocksProxyService } from './core/provider/fireblocks/fireblocks-proxy.service' +import { FireblocksSyncService } from './core/provider/fireblocks/fireblocks-sync.service' import { AccountService } from './core/service/account.service' import { AddressService } from './core/service/address.service' import { ConnectionService } from './core/service/connection.service' @@ -90,6 +91,7 @@ import { WalletRepository } from './persistence/repository/wallet.repository' FireblocksClient, FireblocksCredentialService, FireblocksProxyService, + FireblocksSyncService, KnownDestinationRepository, KnownDestinationService, NetworkRepository, diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage-sync.service.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage-sync.service.ts index 7bd239e90..f2f09c955 100644 --- a/apps/vault/src/broker/core/provider/anchorage/anchorage-sync.service.ts +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage-sync.service.ts @@ -52,7 +52,7 @@ export class AnchorageSyncService implements ProviderSyncService { const { connection } = context this.logger.log('Sync Anchorage wallets', { - connectionId: connection.credentials, + connectionId: connection.connectionId, clientId: connection.clientId, url: connection.url }) @@ -68,7 +68,8 @@ export class AnchorageSyncService implements ProviderSyncService { const { data: existingWallets } = await this.walletService.findAll(connection.clientId, { filters: { externalIds: anchorageVaults.map((vault) => vault.vaultId) - } + }, + pagination: { disabled: true } }) const existingWalletByExternalId = new Map( @@ -147,13 +148,15 @@ export class AnchorageSyncService implements ProviderSyncService { const { data: existingWallets } = await this.walletService.findAll(connection.clientId, { filters: { externalIds: walletExternalIds - } + }, + pagination: { disabled: true } }) const { data: existingAccounts } = await this.accountService.findAll(connection.clientId, { filters: { externalIds: uniq(anchorageWallets.map((wallet) => wallet.walletId)) - } + }, + pagination: { disabled: true } }) const existingAccountsByExternalId = new Map(existingAccounts.map((account) => [account.externalId, account])) @@ -347,7 +350,9 @@ export class AnchorageSyncService implements ProviderSyncService { const now = context.now || new Date() - const { data: existingKnownDestinations } = await this.knownDestinationService.findAll(connection.clientId) + const { data: existingKnownDestinations } = await this.knownDestinationService.findAll(connection.clientId, { + pagination: { disabled: true } + }) const incomingMap = new Map(anchorageTrustedDestinations.map((dest) => [dest.id, dest])) const existingMap = new Map(existingKnownDestinations.map((dest) => [dest.externalId, dest])) diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-asset-wallets-200.json b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-asset-wallets-200.json new file mode 100644 index 000000000..464701eac --- /dev/null +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-asset-wallets-200.json @@ -0,0 +1,31 @@ +{ + "assetWallets": [ + { + "vaultId": "3483", + "assetId": "MATIC_POLYGON", + "total": "1065.275813068575650415", + "available": "1065.275813068575650415", + "pending": "0", + "staked": "0", + "frozen": "0", + "lockedAmount": "0", + "blockHeight": "65405786", + "blockHash": "0xa25d8a09a0fb05b3a417a8668b6044ab3d87d4e359aee1c339ad5763c163dea3", + "creationTime": "1716233725000" + }, + { + "vaultId": "3483", + "assetId": "ETH-OPT", + "total": "0.001942589115042143", + "available": "0.001942589115042143", + "pending": "0", + "staked": "0", + "frozen": "0", + "lockedAmount": "0", + "blockHeight": "124638003", + "blockHash": "0x6cdcecb4c1190ad0ffbc6ba51d4c9115caf1622fd1b32685165fd3abe247de3e", + "creationTime": "1723119346000" + } + ], + "paging": {} +} diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-transfer-200.json b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-transfer-200.json new file mode 100644 index 000000000..1ba192755 --- /dev/null +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-transfer-200.json @@ -0,0 +1,28 @@ +{ + "data": { + "amount": { + "assetType": "BTC_S", + "currentPrice": "104576.34", + "currentUSDValue": "1.05", + "quantity": "0.00001" + }, + "assetType": "BTC_S", + "blockchainTxId": "71ffe98ce4f51b4d12c77626dc455c9223f68b215c631f45ff05958623761e23", + "createdAt": "2024-12-18T14:04:10.519Z", + "destination": { + "id": "afb308d207a76f029257ea6d9d7d58ab", + "type": "WALLET" + }, + "endedAt": "2024-12-18T14:08:13.618Z", + "fee": { + "assetType": "BTC_S", + "quantity": "0.00001771" + }, + "source": { + "id": "6a46a1977959e0529f567e8e927e3895", + "type": "WALLET" + }, + "status": "COMPLETED", + "transferId": "60a0676772fdbd7a041e9451c61c3cb6b28ee901186e40ac99433308604e2e20" + } +} diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-trusted-destinations-200-second.json b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-trusted-destinations-200-second.json new file mode 100644 index 000000000..cd627749f --- /dev/null +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-trusted-destinations-200-second.json @@ -0,0 +1,35 @@ +{ + "data": [ + { + "id": "toBeConnected", + "type": "crypto", + "crypto": { + "address": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", + "networkId": "ETH", + "assetType": "ETH" + } + }, + { + "id": "neverChanges", + "type": "crypto", + "crypto": { + "address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh", + "networkId": "BTC", + "assetType": "BTC" + } + }, + { + "id": "toBeUpdated", + "type": "crypto", + "crypto": { + "address": "0x8Bc2B8F33e5AeF847B8973Fa669B948A3028D6bd", + "networkId": "ETH", + "assetType": "USDC", + "memo": "new memo" + } + } + ], + "page": { + "next": null + } +} diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-trusted-destinations-200-third.json b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-trusted-destinations-200-third.json new file mode 100644 index 000000000..5985e2f1b --- /dev/null +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-trusted-destinations-200-third.json @@ -0,0 +1,16 @@ +{ + "data": [ + { + "id": "toBeConnected", + "type": "crypto", + "crypto": { + "address": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", + "networkId": "ETH", + "assetType": "ETH" + } + } + ], + "page": { + "next": null + } +} diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-trusted-destinations-200.json b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-trusted-destinations-200.json new file mode 100644 index 000000000..51dc594bd --- /dev/null +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-trusted-destinations-200.json @@ -0,0 +1,44 @@ +{ + "data": [ + { + "id": "toBeConnected", + "type": "crypto", + "crypto": { + "address": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", + "networkId": "ETH", + "assetType": "ETH" + } + }, + { + "id": "neverChanges", + "type": "crypto", + "crypto": { + "address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh", + "networkId": "BTC", + "assetType": "BTC" + } + }, + { + "id": "toBeUpdated", + "type": "crypto", + "crypto": { + "address": "0x8Bc2B8F33e5AeF847B8973Fa669B948A3028D6bd", + "networkId": "ETH", + "assetType": "USDC" + } + }, + { + "id": "toBeDeleted", + "type": "crypto", + "crypto": { + "address": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", + "networkId": "XRP", + "assetType": "XRP", + "memo": "123456" + } + } + ], + "page": { + "next": null + } +} diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-vault-accounts-200.json b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-vault-accounts-200.json new file mode 100644 index 000000000..c94ac9682 --- /dev/null +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-vault-accounts-200.json @@ -0,0 +1,35 @@ +{ + "accounts": { + "id": "3483", + "name": "prod-50-3085", + "hiddenOnUI": false, + "autoFuel": false, + "assets": [ + { + "id": "MATIC_POLYGON", + "total": "1065.275813068575650415", + "balance": "1065.275813068575650415", + "lockedAmount": "0", + "available": "1065.275813068575650415", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "65405786", + "blockHash": "0xa25d8a09a0fb05b3a417a8668b6044ab3d87d4e359aee1c339ad5763c163dea3" + }, + { + "id": "ETH-OPT", + "total": "0.001942589115042143", + "balance": "0.001942589115042143", + "lockedAmount": "0", + "available": "0.001942589115042143", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "124638003", + "blockHash": "0x6cdcecb4c1190ad0ffbc6ba51d4c9115caf1622fd1b32685165fd3abe247de3e" + } + ] + }, + "paging": {} +} diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-wallet-addresses-matic-200.json b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-wallet-addresses-matic-200.json new file mode 100644 index 000000000..0167e0b52 --- /dev/null +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-wallet-addresses-matic-200.json @@ -0,0 +1,16 @@ +{ + "addresses": [ + { + "assetId": "MATIC_POLYGON", + "address": "0x5748EA5ca075734bc7ADc9D8046e897c24829A80", + "description": "", + "tag": "", + "type": "Permanent", + "legacyAddress": "", + "enterpriseAddress": "", + "bip44AddressIndex": 0, + "userDefined": false + } + ], + "paging": {} +} diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-wallet-addresses-optimism-200.json b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-wallet-addresses-optimism-200.json new file mode 100644 index 000000000..c02b95088 --- /dev/null +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-wallet-addresses-optimism-200.json @@ -0,0 +1,16 @@ +{ + "addresses": [ + { + "assetId": "ETH-OPT", + "address": "0x5748EA5ca075734bc7ADc9D8046e897c24829A80", + "description": "", + "tag": "", + "type": "Permanent", + "legacyAddress": "", + "enterpriseAddress": "", + "bip44AddressIndex": 0, + "userDefined": false + } + ], + "paging": {} +} diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/post-transfer-201.json b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/post-transfer-201.json new file mode 100644 index 000000000..d99d733ea --- /dev/null +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/post-transfer-201.json @@ -0,0 +1,6 @@ +{ + "data": { + "transferId": "008d3ec72558ce907571886df63ef51594b5bd8cf106a0b7fa8f12a30dfc867f", + "status": "IN_PROGRESS" + } +} diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/post-transfer-400.json b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/post-transfer-400.json new file mode 100644 index 000000000..56891b250 --- /dev/null +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/post-transfer-400.json @@ -0,0 +1,4 @@ +{ + "errorType": "InternalError", + "message": "Missing required field 'amount'." +} diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/server.ts b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/server.ts new file mode 100644 index 000000000..99a119034 --- /dev/null +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/server.ts @@ -0,0 +1,37 @@ +import { HttpResponse, http } from 'msw' +import getAssetWalletsOk from './response/get-asset-wallets-200.json' +import getTransferOk from './response/get-transfer-200.json' +import getWalletAddressesMaticOk from './response/get-wallet-addresses-matic-200.json' +import getWalletAddressesOptOk from './response/get-wallet-addresses-optimism-200.json' +import postTransferCreated from './response/post-transfer-201.json' + +export const FIREBLOCKS_TEST_API_BASE_URL = 'https://test-mock-api.fireblocks.com' + +export const getAddressesHandlers = (baseUrl = FIREBLOCKS_TEST_API_BASE_URL) => { + return { + getMatic: http.get( + `${baseUrl}vault/accounts/:vaultAccountId/:assetId/addresses_paginated`, + () => new HttpResponse(JSON.stringify(getWalletAddressesMaticOk)) + ), + getOptimism: http.get( + `${baseUrl}vault/accounts/:vaultAccountId/:assetId/addresses_paginated`, + () => new HttpResponse(JSON.stringify(getWalletAddressesOptOk)) + ) + } +} + +export const getHandlers = (baseUrl = FIREBLOCKS_TEST_API_BASE_URL) => [ + http.get(`${baseUrl}/v2/wallets`, () => { + return new HttpResponse(JSON.stringify(getAssetWalletsOk)) + }), + + http.get(`${baseUrl}/v2/transfers/:transferId`, () => { + return new HttpResponse(JSON.stringify(getTransferOk)) + }), + + http.post(`${baseUrl}/v2/transfers`, () => { + return new HttpResponse(JSON.stringify(postTransferCreated)) + }), + + getAddressesHandlers(baseUrl).getMatic +] diff --git a/apps/vault/src/broker/core/provider/fireblocks/fireblocks-sync.service.ts b/apps/vault/src/broker/core/provider/fireblocks/fireblocks-sync.service.ts new file mode 100644 index 000000000..45c42e968 --- /dev/null +++ b/apps/vault/src/broker/core/provider/fireblocks/fireblocks-sync.service.ts @@ -0,0 +1,497 @@ +import { LoggerService } from '@narval/nestjs-shared' +import { Injectable } from '@nestjs/common' +import { randomUUID } from 'crypto' +import { uniq } from 'lodash/fp' +import { FireblocksClient, WhitelistedWallet } from '../../../http/client/fireblocks.client' +import { UpdateAccount } from '../../../persistence/repository/account.repository' +import { NetworkRepository } from '../../../persistence/repository/network.repository' +import { AccountService } from '../../service/account.service' +import { KnownDestinationService } from '../../service/known-destination.service' +import { WalletService } from '../../service/wallet.service' +import { Connection, ConnectionWithCredentials } from '../../type/connection.type' +import { Account, Address, KnownDestination, UpdateWallet, Wallet } from '../../type/indexed-resources.type' +import { + Provider, + ProviderSyncService, + SyncContext, + SyncOperation, + SyncOperationType, + SyncResult, + isCreateOperation +} from '../../type/provider.type' +import { buildEmptyContext } from '../../util/provider-sync.util' +import { WhitelistClassification } from './fireblocks.type' +import { getFireblocksAssetWalletExternalId, validateConnection } from './fireblocks.util' + +@Injectable() +export class FireblocksSyncService implements ProviderSyncService { + constructor( + private readonly fireblocksClient: FireblocksClient, + private readonly walletService: WalletService, + private readonly accountService: AccountService, + private readonly knownDestinationService: KnownDestinationService, + private readonly networkRepository: NetworkRepository, + private readonly logger: LoggerService + ) {} + + async sync(connection: ConnectionWithCredentials): Promise { + const initialContext = buildEmptyContext({ connection, now: new Date() }) + const syncWalletContext = await this.syncWallets(initialContext) + const syncAccountContext = await this.syncAccounts(syncWalletContext) + // const syncAddressContext = await this.syncAddresses(syncAccountContext) + const lastSyncContext = await this.syncKnownDestinations(syncAccountContext) + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { connection: _conn, ...result } = lastSyncContext + + return result + } + + async syncWallets(context: SyncContext): Promise { + const { connection } = context + + this.logger.log('Sync Fireblocks wallets', { + connectionId: connection.connectionId, + clientId: connection.clientId, + url: connection.url + }) + + validateConnection(connection) + + const now = context.now ?? new Date() + + const fireblocksVaultAccounts = await this.fireblocksClient.getVaultAccounts({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey + }) + + const { data: existingWallets } = await this.walletService.findAll(connection.clientId, { + filters: { + externalIds: uniq(fireblocksVaultAccounts.map((account) => account.id)) + }, + pagination: { disabled: true } + }) + + const operations: SyncOperation[] = [] + + for (const account of fireblocksVaultAccounts) { + const existingAccount = existingWallets.find((w) => w.externalId === account.id) + if (!existingAccount) { + operations.push({ + type: SyncOperationType.CREATE, + create: { + externalId: account.id, + clientId: connection.clientId, + createdAt: now, + accounts: [], + label: account.name, + connections: [Connection.parse(connection)], + provider: Provider.FIREBLOCKS, + updatedAt: now, + walletId: randomUUID() + } + }) + continue + } + + const hasConnection = existingAccount.connections.some((conn) => conn.connectionId === connection.connectionId) + const hasDataChanges = existingAccount.label !== account.name + + if (hasConnection || hasDataChanges) { + operations.push({ + type: SyncOperationType.UPDATE, + update: { + ...existingAccount, + label: account.name, + updatedAt: now + } + }) + } + } + + return { + ...context, + wallets: operations + } + } + + async syncAccounts(context: SyncContext): Promise { + const { connection } = context + + this.logger.log('Sync Fireblocks accounts', { + connectionId: connection.connectionId, + clientId: connection.clientId, + url: connection.url + }) + + validateConnection(connection) + + const fireblocksAssetWallets = await this.fireblocksClient.getAssetWallets({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey + }) + + const walletExternalIds = uniq(fireblocksAssetWallets.map(({ vaultId }) => vaultId)) + + const { data: existingWallets } = await this.walletService.findAll(connection.clientId, { + filters: { + externalIds: walletExternalIds + }, + pagination: { disabled: true } + }) + + const { data: existingAccounts } = await this.accountService.findAll(connection.clientId, { + filters: { + externalIds: uniq( + fireblocksAssetWallets.map((wallet) => + getFireblocksAssetWalletExternalId({ + vaultId: wallet.vaultId, + assetId: wallet.assetId + }) + ) + ) + }, + pagination: { disabled: true } + }) + + const existingAccountsByExternalId = new Map(existingAccounts.map((account) => [account.externalId, account])) + + const missingFireblocksWallets = fireblocksAssetWallets.filter( + (fireblocksVault) => + !existingAccountsByExternalId.has( + getFireblocksAssetWalletExternalId({ + vaultId: fireblocksVault.vaultId, + assetId: fireblocksVault.assetId + }) + ) + ) + + const walletsIndexedByExternalId = new Map(existingWallets.map((wallet) => [wallet.externalId, wallet])) + + const contextWalletsIndexedByExternalId = new Map( + context.wallets.filter(isCreateOperation).map(({ create }) => [create.externalId, create]) + ) + + const now = context.now ?? new Date() + + const operations: SyncOperation[] = [] + + for (const fireblocksAssetWallet of missingFireblocksWallets) { + const externalId = getFireblocksAssetWalletExternalId({ + vaultId: fireblocksAssetWallet.vaultId, + assetId: fireblocksAssetWallet.assetId + }) + const parentExternalId = fireblocksAssetWallet.vaultId + + // Either look up the existing wallets in the database or in the sync context. + const contextWallet = contextWalletsIndexedByExternalId.get(parentExternalId) + const indexedWallet = walletsIndexedByExternalId.get(parentExternalId) + + const wallet = contextWallet || indexedWallet + + if (wallet) { + const network = await this.networkRepository.findByExternalId( + Provider.FIREBLOCKS, + fireblocksAssetWallet.assetId + ) + + if (network) { + operations.push({ + type: SyncOperationType.CREATE, + create: { + // Fireblocks 'assetWallet' ID is not unique. It's the networkID used per vault Account + // In our system, each provider account has a unique external ID per client. + // This is a specific problem from Fireblocks, so we need to be aware of the way we store the externalID in order to know how to query per ID + externalId, + accountId: randomUUID(), + addresses: [], + clientId: connection.clientId, + createdAt: now, + networkId: network.networkId, + provider: Provider.FIREBLOCKS, + updatedAt: now, + walletId: wallet.walletId + } + }) + } else { + operations.push({ + type: SyncOperationType.SKIP, + externalId, + message: 'Unknown Fireblocks wallet network ID', + context: { + externalId, + fireblocksNetworkId: fireblocksAssetWallet.assetId + } + }) + } + } else { + operations.push({ + type: SyncOperationType.FAILED, + externalId, + + message: 'Parent wallet for account not found', + context: { + fireblocksWalletId: parentExternalId, + totalLength: existingWallets.length, + contextWallet, + indexedWallet + } + }) + } + } + + return { + ...context, + accounts: operations + } + } + + async syncAddresses(context: SyncContext): Promise { + const { connection } = context + + this.logger.log('Sync Fireblocks addresses', { + connectionId: connection.connectionId, + clientId: connection.clientId, + url: connection.url + }) + + validateConnection(connection) + + const vaultAccounts = await this.fireblocksClient.getVaultAccounts({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey + }) + + const now = context.now ?? new Date() + + const accountOperations = await Promise.all( + vaultAccounts.map(async (account) => { + this.logger.log('Sync Fireblocks addresses for account', { + clientId: connection.clientId, + url: connection.url, + accountId: account.id + }) + + const assetOperations = await Promise.all( + account.assets.map(async (asset) => { + try { + const addresses = await this.fireblocksClient.getAddresses({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey, + vaultAccountId: account.id, + assetId: asset.id + }) + + return addresses.map( + (fireblocksAddress): SyncOperation => ({ + type: SyncOperationType.CREATE, + create: { + externalId: fireblocksAddress.address, + addressId: fireblocksAddress.address, + accountId: account.id, + address: fireblocksAddress.address, + clientId: connection.clientId, + createdAt: now, + provider: Provider.FIREBLOCKS, + updatedAt: now + } + }) + ) + } catch (error) { + const failedOperation: SyncOperation = { + type: SyncOperationType.FAILED, + externalId: `${account.id}:${asset.id}`, + message: `Failed to fetch addresses for account/asset: ${error.message}`, + context: { + accountId: account.id, + assetId: asset.id, + error: error.message + } + } + + this.logger.error('Failed to fetch addresses for account/asset', { + accountId: account.id, + assetId: asset.id, + error: error.message + }) + + return [failedOperation] + } + }) + ) + + return assetOperations.flat() + }) + ) + const operations = accountOperations.flat() + + return { + ...context, + addresses: operations + } + } + + async syncKnownDestinations(context: SyncContext): Promise { + const { connection } = context + + this.logger.log('Sync Fireblocks known destinations', { + connectionId: connection.connectionId, + clientId: connection.clientId, + url: connection.url + }) + + validateConnection(connection) + + const fireblocksWhitelistedInternalsWallets = await this.fireblocksClient.getWhitelistedInternalWallets({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey + }) + + const fireblocksWhitelistedExternals = await this.fireblocksClient.getWhitelistedExternalWallets({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey + }) + + const fireblocksWhitelistedContracts = await this.fireblocksClient.getWhitelistedContracts({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey + }) + + const fireblocksKnownDestinations = [ + ...this.transformWhitelistedAddresses({ + whitelistedWallets: fireblocksWhitelistedContracts, + classification: WhitelistClassification.CONTRACT + }), + ...this.transformWhitelistedAddresses({ + whitelistedWallets: fireblocksWhitelistedExternals, + classification: WhitelistClassification.EXTERNAL + }), + ...this.transformWhitelistedAddresses({ + whitelistedWallets: fireblocksWhitelistedInternalsWallets, + classification: WhitelistClassification.INTERNAL + }) + ] + + const { data: existingKnownDestinations } = await this.knownDestinationService.findAll(connection.clientId, { + filters: { + providers: [Provider.FIREBLOCKS] + }, + pagination: { disabled: true } + }) + + const now = context.now ?? new Date() + + const incomingMap = new Map(fireblocksKnownDestinations.map((dest) => [dest.externalId, dest])) + const existingMap = new Map(existingKnownDestinations.map((dest) => [dest.externalId, dest])) + + const updateOperations = fireblocksKnownDestinations + .reduce((acc, incoming) => { + const existing = existingMap.get(incoming.externalId) + if (!existing) return acc + + const hasConnection = existing.connections.some((conn) => conn.connectionId === connection.connectionId) + const hasDataChanges = (existing.label || undefined) !== incoming.label + + if (hasDataChanges || !hasConnection) { + acc.push( + KnownDestination.parse({ + ...existing, + label: incoming.label, + updatedAt: now, + connections: [...existing.connections, connection] + }) + ) + } + + return acc + }, []) + .map((update) => ({ type: SyncOperationType.UPDATE, update })) + + const missingDestinations = fireblocksKnownDestinations.filter( + (fireblocksTrustedAddress) => !existingMap.has(fireblocksTrustedAddress.externalId) + ) + + const createOperations: SyncOperation[] = [] + + for (const fireblocksTrustedAddress of missingDestinations) { + const externalId = fireblocksTrustedAddress.externalId + const network = await this.networkRepository.findByExternalId( + Provider.FIREBLOCKS, + fireblocksTrustedAddress.assetId + ) + + if (network) { + const knownDestination = KnownDestination.parse({ + externalId, + knownDestinationId: randomUUID(), + address: fireblocksTrustedAddress.address, + externalClassification: fireblocksTrustedAddress.externalClassification, + clientId: connection.clientId, + label: fireblocksTrustedAddress.label, + assetId: fireblocksTrustedAddress.assetId, + provider: Provider.FIREBLOCKS, + networkId: fireblocksTrustedAddress.assetId, + createdAt: now, + updatedAt: now, + connections: [connection] + }) + + createOperations.push({ type: SyncOperationType.CREATE, create: knownDestination }) + } else { + createOperations.push({ + type: SyncOperationType.SKIP, + externalId, + message: 'Unknown Fireblocks trusted address network ID', + context: { + externalId, + fireblocksNetworkId: fireblocksTrustedAddress.assetId + } + }) + } + } + + const deleteOperations = existingKnownDestinations + .filter((dest) => !incomingMap.has(dest.externalId)) + .map((kd) => ({ type: SyncOperationType.DELETE, entityId: kd.knownDestinationId })) + + return { + ...context, + knownDestinations: [...createOperations, ...updateOperations, ...deleteOperations] + } + } + + private transformWhitelistedAddresses(opts: { + whitelistedWallets: WhitelistedWallet[] + classification: WhitelistClassification + }) { + const now = new Date() + const destinations = [] + + for (const wallet of opts.whitelistedWallets) { + for (const asset of wallet.assets) { + destinations.push({ + provider: Provider.FIREBLOCKS, + externalId: getFireblocksAssetWalletExternalId({ + vaultId: wallet.id, + assetId: asset.id + }), + externalClassification: opts.classification, + address: asset.address, + label: wallet.name, + assetId: asset.id, + createdAt: now, + updatedAt: now + }) + } + } + + return destinations + } +} diff --git a/apps/vault/src/broker/core/provider/fireblocks/fireblocks.type.ts b/apps/vault/src/broker/core/provider/fireblocks/fireblocks.type.ts index 5c1318b57..6ca5d92c7 100644 --- a/apps/vault/src/broker/core/provider/fireblocks/fireblocks.type.ts +++ b/apps/vault/src/broker/core/provider/fireblocks/fireblocks.type.ts @@ -1,6 +1,13 @@ import { rsaPrivateKeySchema, rsaPublicKeySchema } from '@narval/signature' import { z } from 'zod' +export const WhitelistClassification = { + CONTRACT: 'contract', + INTERNAL: 'internal', + EXTERNAL: 'external' +} as const +export type WhitelistClassification = (typeof WhitelistClassification)[keyof typeof WhitelistClassification] + export const FireblocksInputCredentials = z.object({ apiKey: z.string(), privateKey: z.string().optional().describe('RSA private key pem base64 encoded') diff --git a/apps/vault/src/broker/core/provider/fireblocks/fireblocks.util.ts b/apps/vault/src/broker/core/provider/fireblocks/fireblocks.util.ts index 160494940..abe9f01fb 100644 --- a/apps/vault/src/broker/core/provider/fireblocks/fireblocks.util.ts +++ b/apps/vault/src/broker/core/provider/fireblocks/fireblocks.util.ts @@ -1,4 +1,6 @@ import { RsaPrivateKey } from '@narval/signature' +import { HttpStatus } from '@nestjs/common' +import { BrokerException } from '../../exception/broker.exception' import { ConnectionInvalidException } from '../../exception/connection-invalid.exception' import { ConnectionWithCredentials } from '../../type/connection.type' import { Provider } from '../../type/provider.type' @@ -51,3 +53,25 @@ export function validateConnection( }) } } + +export type FireblocksAccountExternalId = `fireblocks/vaults/${string}/wallets/${string}` +export function getFireblocksAssetWalletExternalId({ vaultId, assetId }: { vaultId: string; assetId: string }): string { + return `fireblocks/vaults/${vaultId}/wallets/${assetId}` +} + +export type FireblocksAssetWalletId = { vaultId: string; assetId: string } +export function toFireblocksAssetWalletExternalId(externalId: string): FireblocksAssetWalletId { + const matches = externalId.match(/^fireblocks\/vaults\/([^/]+)\/wallets\/([^/]+)$/) + if (!matches) { + throw new BrokerException({ + message: 'The external ID does not match composed standard for fireblocks', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY + }) + } + + const [, vaultId, assetId] = matches + return { + vaultId, + assetId + } +} diff --git a/apps/vault/src/broker/core/service/sync.service.ts b/apps/vault/src/broker/core/service/sync.service.ts index d11fa1283..c4406a1a4 100644 --- a/apps/vault/src/broker/core/service/sync.service.ts +++ b/apps/vault/src/broker/core/service/sync.service.ts @@ -9,6 +9,7 @@ import { FindAllOptions, SyncRepository } from '../../persistence/repository/syn import { OTEL_ATTR_CONNECTION_ID, OTEL_ATTR_CONNECTION_PROVIDER, OTEL_ATTR_SYNC_ID } from '../../shared/constant' import { SyncStartedEvent } from '../../shared/event/sync-started.event' import { AnchorageSyncService } from '../provider/anchorage/anchorage-sync.service' +import { FireblocksSyncService } from '../provider/fireblocks/fireblocks-sync.service' import { ConnectionWithCredentials } from '../type/connection.type' import { Provider, @@ -31,6 +32,7 @@ export class SyncService { constructor( private readonly syncRepository: SyncRepository, private readonly anchorageSyncService: AnchorageSyncService, + private readonly fireblocksSyncService: FireblocksSyncService, private readonly walletService: WalletService, private readonly accountService: AccountService, private readonly addressService: AddressService, @@ -356,6 +358,8 @@ export class SyncService { switch (provider) { case Provider.ANCHORAGE: return this.anchorageSyncService + case Provider.FIREBLOCKS: + return this.fireblocksSyncService default: throw new NotImplementedException(`Unsupported sync for provider ${provider}`) } diff --git a/apps/vault/src/broker/http/client/anchorage.client.ts b/apps/vault/src/broker/http/client/anchorage.client.ts index 4064a4c17..c0984512d 100644 --- a/apps/vault/src/broker/http/client/anchorage.client.ts +++ b/apps/vault/src/broker/http/client/anchorage.client.ts @@ -510,10 +510,7 @@ export class AnchorageClient { url: opts.url }) }), - catchError((error) => { - this.logger.error('Failed to get Anchorage trusted-destinations', { error }) - throw error - }) + this.handleError('Failed to get Anchorage trusted-destinations') ) ) } diff --git a/apps/vault/src/broker/http/client/fireblocks.client.ts b/apps/vault/src/broker/http/client/fireblocks.client.ts index 0d0422273..3cddadb37 100644 --- a/apps/vault/src/broker/http/client/fireblocks.client.ts +++ b/apps/vault/src/broker/http/client/fireblocks.client.ts @@ -1,14 +1,30 @@ import { LoggerService } from '@narval/nestjs-shared' -import { RsaPrivateKey, hash, signJwt } from '@narval/signature' +import { RsaPrivateKey, signJwt } from '@narval/signature' import { HttpService } from '@nestjs/axios' import { HttpStatus, Injectable } from '@nestjs/common' -import axios, { AxiosRequestConfig, AxiosResponse } from 'axios' +import { sha256 } from '@noble/hashes/sha256' +import axios, { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios' import { isNil, omitBy } from 'lodash' -import { EMPTY, Observable, catchError, expand, from, lastValueFrom, map, reduce, switchMap, tap } from 'rxjs' +import { + EMPTY, + Observable, + OperatorFunction, + catchError, + expand, + from, + lastValueFrom, + map, + reduce, + switchMap, + tap +} from 'rxjs' import { v4 } from 'uuid' +import { toHex } from 'viem' import { ZodType, z } from 'zod' import { BrokerException } from '../../core/exception/broker.exception' +import { ProviderHttpException } from '../../core/exception/provider-http.exception' import { UrlParserException } from '../../core/exception/url-parser.exception' +import { Provider } from '../../core/type/provider.type' interface ForwardRequestOptions { url: string @@ -113,56 +129,28 @@ const GetAddressListResponse = z.object({ }) type GetAddressListResponse = z.infer -const InternalWhitelistedAddressAsset = z.object({ +const WhitelistedAddressAsset = z.object({ id: z.string(), - balance: z.string(), + balance: z.string().optional(), lockedAmount: z.string().optional(), status: z.string(), address: z.string(), tag: z.string().optional(), activationTime: z.string().optional() }) -type InternalWhitelistedAddressAsset = z.infer +type WhitelistedAddressAsset = z.infer -const InternalWhitelistedWallet = z.object({ +const WhitelistedWallet = z.object({ id: z.string(), name: z.string(), customerRefId: z.string().optional(), - assets: z.array(InternalWhitelistedAddressAsset) + assets: z.array(WhitelistedAddressAsset) }) -type InternalWhitelistedWallet = z.infer +export type WhitelistedWallet = z.infer -const ExternalWhitelistedAddressAsset = z.object({ - id: z.string(), - lockedAmount: z.string().optional(), - status: z.string(), - address: z.string(), - tag: z.string(), - activationTime: z.string().optional() -}) -type ExternalWhitelistedAddressAsset = z.infer - -const ExternalWhitelistedAddress = z - .object({ - id: z.string(), - name: z.string(), - customerRefId: z.string().optional(), - assets: z.array(ExternalWhitelistedAddressAsset) - }) - .strict() -type ExternalWhitelistedAddress = z.infer +const GetWhitelistedWalletsResponse = z.array(WhitelistedWallet) +type GetWhitelistedWalletsResponse = z.infer -const WhitelistedContract = ExternalWhitelistedAddress -type WhitelistedContract = z.infer - -const GetWhitelistedInternalWalletsResponse = z.array(InternalWhitelistedWallet) -type GetWhitelistedInternalWalletsResponse = z.infer - -const GetWhitelistedExternalWalletsResponse = z.array(ExternalWhitelistedAddress) -type GetWhitelistedExternalWalletsResponse = z.infer - -const GetWhitelistedContractsResponse = z.array(WhitelistedContract) -type GetWhitelistedContractsResponse = z.infer @Injectable() export class FireblocksClient { constructor( @@ -211,8 +199,7 @@ export class FireblocksClient { const exp = now + 30 - const bodyHash = request.data ? hash(request.data) : '' - + const bodyHash = request.data ? toHex(sha256(JSON.stringify(request.data))).slice(2) : undefined const payload = { uri, nonce: opts.nonce || v4(), @@ -252,14 +239,23 @@ export class FireblocksClient { return match[1] } - private serializeError(error: any) { - return { - message: error.message, - name: error.name, - stack: error.stack, - status: error.response?.status, - statusText: error.response?.statusText - } + private handleError(logMessage: string): OperatorFunction { + return catchError((error: unknown): Observable => { + this.logger.error(logMessage, { error }) + + if (error instanceof AxiosError) { + throw new ProviderHttpException({ + provider: Provider.ANCHORAGE, + origin: error, + response: { + status: error.response?.status ?? HttpStatus.INTERNAL_SERVER_ERROR, + body: error.response?.data + } + }) + } + + throw error + }) } private validateRequest(request: AxiosRequestConfig): asserts request is AxiosRequestConfig & { @@ -361,10 +357,7 @@ export class FireblocksClient { url: opts.url }) }), - catchError((error) => { - this.logger.error('Failed to get Fireblocks vault accounts', this.serializeError(error)) - throw error - }) + this.handleError('Failed to get Fireblocks vault accounts') ) ) } @@ -421,10 +414,7 @@ export class FireblocksClient { url: opts.url }) }), - catchError((error) => { - this.logger.error('Failed to get Fireblocks asset wallets', this.serializeError(error)) - throw error - }) + this.handleError('Failed to get Fireblocks asset wallets') ) ) } @@ -496,15 +486,7 @@ export class FireblocksClient { assetId: opts.assetId }) }), - catchError((error) => { - this.logger.error(`Failed to get Fireblocks vault ${opts.vaultAccountId} asset ${opts.assetId} addresses`, { - error: error.message, - status: error.response?.status, - vaultAccountId: opts.vaultAccountId, - assetId: opts.assetId - }) - throw error - }) + this.handleError(`Failed to get Fireblocks vault ${opts.vaultAccountId} asset ${opts.assetId} addresses`) ) ) } @@ -513,14 +495,14 @@ export class FireblocksClient { apiKey: string signKey: RsaPrivateKey url: string - }): Promise { + }): Promise { this.logger.log('Requesting Fireblocks whitelisted internal wallets page', { url: opts.url }) return lastValueFrom( this.sendSignedRequest({ - schema: GetWhitelistedInternalWalletsResponse, + schema: GetWhitelistedWalletsResponse, request: { url: `${opts.url}/v1/internal_wallets`, method: 'GET' @@ -528,17 +510,14 @@ export class FireblocksClient { apiKey: opts.apiKey, signKey: opts.signKey }).pipe( - reduce((wallets: InternalWhitelistedWallet[], response) => [...wallets, ...response], []), + reduce((wallets: WhitelistedWallet[], response) => [...wallets, ...response], []), tap((addresses) => { this.logger.log('Completed fetching all whitelisted internal addresses', { addressesCount: addresses.length, url: opts.url }) }), - catchError((error) => { - this.logger.error('Failed to get Fireblocks whitelisted internal addresses', this.serializeError(error)) - throw error - }) + this.handleError('Failed to get Fireblocks whitelisted internal addresses') ) ) } @@ -547,14 +526,14 @@ export class FireblocksClient { apiKey: string signKey: RsaPrivateKey url: string - }): Promise { + }): Promise { this.logger.log('Requesting Fireblocks whitelisted external wallets page', { url: opts.url }) return lastValueFrom( this.sendSignedRequest({ - schema: GetWhitelistedExternalWalletsResponse, + schema: GetWhitelistedWalletsResponse, request: { url: `${opts.url}/v1/external_wallets`, method: 'GET' @@ -562,17 +541,14 @@ export class FireblocksClient { apiKey: opts.apiKey, signKey: opts.signKey }).pipe( - reduce((wallets: ExternalWhitelistedAddress[], response) => [...wallets, ...response], []), + reduce((wallets: WhitelistedWallet[], response) => [...wallets, ...response], []), tap((addresses) => { this.logger.log('Completed fetching all whitelisted external addresses', { addressesCount: addresses.length, url: opts.url }) }), - catchError((error) => { - this.logger.error('Failed to get Fireblocks whitelisted external addresses', this.serializeError(error)) - throw error - }) + this.handleError('Failed to get Fireblocks whitelisted external addresses') ) ) } @@ -581,14 +557,14 @@ export class FireblocksClient { apiKey: string signKey: RsaPrivateKey url: string - }): Promise { + }): Promise { this.logger.log('Requesting Fireblocks whitelisted contracts page', { url: opts.url }) return lastValueFrom( this.sendSignedRequest({ - schema: GetWhitelistedContractsResponse, + schema: GetWhitelistedWalletsResponse, request: { url: `${opts.url}/v1/contracts`, method: 'GET' @@ -596,17 +572,14 @@ export class FireblocksClient { apiKey: opts.apiKey, signKey: opts.signKey }).pipe( - reduce((contracts: WhitelistedContract[], response) => [...contracts, ...response], []), + reduce((contracts: WhitelistedWallet[], response) => [...contracts, ...response], []), tap((contracts) => { this.logger.log('Completed fetching all whitelisted contracts', { contractsCount: contracts.length, url: opts.url }) }), - catchError((error) => { - this.logger.error('Failed to get Fireblocks whitelisted contracts', this.serializeError(error)) - throw error - }) + this.handleError('Failed to get Fireblocks whitelisted contracts') ) ) } diff --git a/packages/nestjs-shared/src/lib/type/pagination.type.ts b/packages/nestjs-shared/src/lib/type/pagination.type.ts index 8b738d9ee..a79a7185d 100644 --- a/packages/nestjs-shared/src/lib/type/pagination.type.ts +++ b/packages/nestjs-shared/src/lib/type/pagination.type.ts @@ -65,4 +65,5 @@ export type PaginationOptions = { skip?: number sortOrder?: 'asc' | 'desc' orderBy?: { [key: string]: 'asc' | 'desc' }[] + disabled?: boolean } diff --git a/packages/nestjs-shared/src/lib/util/pagination.util.ts b/packages/nestjs-shared/src/lib/util/pagination.util.ts index 4bf0eac65..092ec366f 100644 --- a/packages/nestjs-shared/src/lib/util/pagination.util.ts +++ b/packages/nestjs-shared/src/lib/util/pagination.util.ts @@ -80,9 +80,14 @@ export const applyPagination = ( ): { skip?: number cursor?: { id: string; createdAt: Date } - take: number + take?: number orderBy: { [key: string]: 'asc' | 'desc' }[] } => { + if (pagination?.disabled === true) { + return { + orderBy: DEFAULT_ORDER_BY + } + } const multiplier = pagination?.take && pagination?.take < 0 ? -1 : 1 const skip = pagination?.cursor ? 1 : undefined const take = (Math.abs(pagination?.take || DEFAULT_SERVICE_PAGINATION_LIMIT) + 1) * multiplier From fc1004566d0b9b8427e5af7d41b4a1d19f36764b Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Wed, 15 Jan 2025 11:36:15 +0100 Subject: [PATCH 089/120] Unified network list (#77) * Persist network unified list * Add asset list * Add findByOnchainId and findNativeAsset for Fireblocks * Remove asset indexes * Add network data migration * Rename network model Change uniqueness constraints in the network and provider network models. Address some minor request changes. --- .../src/shared/module/persistence/seed.ts | 2 +- apps/vault/Makefile | 3 + .../src/broker/__test__/e2e/asset.spec.ts | 158 + .../broker/__test__/e2e/connection.spec.ts | 3 +- .../src/broker/__test__/e2e/network.spec.ts | 88 + .../src/broker/__test__/e2e/transfer.spec.ts | 9 +- apps/vault/src/broker/broker.module.ts | 13 +- .../anchorage-sync.service.spec.ts | 5 + .../anchorage-transfer.service.spec.ts | 25 +- ...e-assets.ts => anchorage-asset.service.ts} | 101 +- .../anchorage/anchorage-transfer.service.ts | 46 +- .../fireblocks/fireblocks-asset.service.ts | 10720 ++++++++++++++++ apps/vault/src/broker/core/type/asset.type.ts | 10 + .../src/broker/core/type/network.type.ts | 11 +- .../src/broker/core/type/transfer.type.ts | 6 +- .../src/broker/core/util/network.util.ts | 7 +- .../http/rest/controller/asset.controller.ts | 51 + .../rest/controller/network.controller.ts | 12 +- .../rest/dto/response/provider-asset.dto.ts | 11 + ...network.dto.ts => provider-network.dto.ts} | 8 +- .../src/broker/persistence/connection.seed.ts | 16 - .../repository/network.repository.ts | 819 +- .../broker/persistence/seed/network.seed.ts | 626 + apps/vault/src/main.config.ts | 4 + .../module/persistence/persistence.module.ts | 5 +- .../migration.sql | 252 + .../module/persistence/schema/schema.prisma | 26 + .../src/shared/module/persistence/seed.ts | 316 +- .../persistence/service/seed.service.ts | 2 +- .../persistence/service/seeder.service.ts | 47 + 30 files changed, 12408 insertions(+), 994 deletions(-) create mode 100644 apps/vault/src/broker/__test__/e2e/asset.spec.ts create mode 100644 apps/vault/src/broker/__test__/e2e/network.spec.ts rename apps/vault/src/broker/core/provider/anchorage/{anchorage-assets.ts => anchorage-asset.service.ts} (95%) create mode 100644 apps/vault/src/broker/core/provider/fireblocks/fireblocks-asset.service.ts create mode 100644 apps/vault/src/broker/core/type/asset.type.ts create mode 100644 apps/vault/src/broker/http/rest/controller/asset.controller.ts create mode 100644 apps/vault/src/broker/http/rest/dto/response/provider-asset.dto.ts rename apps/vault/src/broker/http/rest/dto/response/{network.dto.ts => provider-network.dto.ts} (57%) delete mode 100644 apps/vault/src/broker/persistence/connection.seed.ts create mode 100644 apps/vault/src/broker/persistence/seed/network.seed.ts create mode 100644 apps/vault/src/shared/module/persistence/schema/migrations/20250115095035_add_network_table_and_data/migration.sql create mode 100644 apps/vault/src/shared/module/persistence/service/seeder.service.ts diff --git a/apps/armory/src/shared/module/persistence/seed.ts b/apps/armory/src/shared/module/persistence/seed.ts index efddde962..f61ce8c63 100644 --- a/apps/armory/src/shared/module/persistence/seed.ts +++ b/apps/armory/src/shared/module/persistence/seed.ts @@ -56,9 +56,9 @@ async function main() { } try { - logger.log('Database germinated 🌱') await seeder.seed() } finally { + logger.log('✅ Database seeded') await application.close() } } diff --git a/apps/vault/Makefile b/apps/vault/Makefile index c5db6932e..4974208aa 100644 --- a/apps/vault/Makefile +++ b/apps/vault/Makefile @@ -31,6 +31,9 @@ vault/build: vault/format: npx nx format:write --projects ${VAULT_PROJECT_NAME} + make vault/format/prisma + +vault/format/prisma: npx prisma format --schema ${VAULT_DATABASE_SCHEMA} vault/lint: diff --git a/apps/vault/src/broker/__test__/e2e/asset.spec.ts b/apps/vault/src/broker/__test__/e2e/asset.spec.ts new file mode 100644 index 000000000..86928d9b9 --- /dev/null +++ b/apps/vault/src/broker/__test__/e2e/asset.spec.ts @@ -0,0 +1,158 @@ +import { EncryptionModuleOptionProvider } from '@narval/encryption-module' +import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' +import { HttpStatus, INestApplication } from '@nestjs/common' +import { Test, TestingModule } from '@nestjs/testing' +import request from 'supertest' +import { ClientService } from '../../../client/core/service/client.service' +import { MainModule } from '../../../main.module' +import { ProvisionService } from '../../../provision.service' +import { KeyValueRepository } from '../../../shared/module/key-value/core/repository/key-value.repository' +import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' +import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' +import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' +import { Provider } from '../../core/type/provider.type' +import { NetworkSeed } from '../../persistence/seed/network.seed' +import { TEST_CLIENT_ID, getJwsd, testClient, testUserPrivateJwk } from '../util/mock-data' + +import { ProviderAssetDto } from '../../http/rest/dto/response/provider-asset.dto' +import '../../shared/__test__/matcher' + +describe('Asset', () => { + let app: INestApplication + let module: TestingModule + let testPrismaService: TestPrismaService + let provisionService: ProvisionService + let clientService: ClientService + let networkSeed: NetworkSeed + + beforeAll(async () => { + module = await Test.createTestingModule({ + imports: [MainModule] + }) + .overrideModule(LoggerModule) + .useModule(LoggerModule.forTest()) + .overrideProvider(KeyValueRepository) + .useValue(new InMemoryKeyValueRepository()) + .overrideProvider(EncryptionModuleOptionProvider) + .useValue({ + keyring: getTestRawAesKeyring() + }) + .compile() + + app = module.createNestApplication() + + clientService = module.get(ClientService) + networkSeed = module.get(NetworkSeed) + provisionService = module.get(ProvisionService) + testPrismaService = module.get(TestPrismaService) + + await testPrismaService.truncateAll() + }) + + afterAll(async () => { + await testPrismaService.truncateAll() + await module.close() + await app.close() + }) + + beforeEach(async () => { + await testPrismaService.truncateAll() + await provisionService.provision() + await clientService.save(testClient) + + await networkSeed.seed() + + await app.init() + }) + + describe('GET /assets', () => { + it('returns the list of assets for the specified provider', async () => { + const { status, body } = await request(app.getHttpServer()) + .get('/provider/assets') + .query({ provider: Provider.ANCHORAGE }) + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: `/provider/assets?provider=${Provider.ANCHORAGE}`, + payload: {}, + htm: 'GET' + }) + ) + + expect(body).toMatchZodSchema(ProviderAssetDto.schema) + expect(status).toEqual(HttpStatus.OK) + }) + + it('returns 400 when provider parameter is missing', async () => { + const { status } = await request(app.getHttpServer()) + .get('/provider/assets') + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/assets', + payload: {}, + htm: 'GET' + }) + ) + + expect(status).toEqual(HttpStatus.BAD_REQUEST) + }) + + it('returns 400 when provider is invalid', async () => { + const { status } = await request(app.getHttpServer()) + .get('/provider/assets') + .query({ provider: 'INVALID' }) + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/assets?provider=INVALID', + payload: {}, + htm: 'GET' + }) + ) + + expect(status).toEqual(HttpStatus.BAD_REQUEST) + }) + + it('returns different assets for different providers', async () => { + const anchorageResponse = await request(app.getHttpServer()) + .get('/provider/assets') + .query({ provider: Provider.ANCHORAGE }) + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: `/provider/assets?provider=${Provider.ANCHORAGE}`, + payload: {}, + htm: 'GET' + }) + ) + + const fireblocksResponse = await request(app.getHttpServer()) + .get('/provider/assets') + .query({ provider: Provider.FIREBLOCKS }) + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: `/provider/assets?provider=${Provider.FIREBLOCKS}`, + payload: {}, + htm: 'GET' + }) + ) + + expect(anchorageResponse.status).toEqual(HttpStatus.OK) + expect(fireblocksResponse.status).toEqual(HttpStatus.OK) + + expect(anchorageResponse.body.data).not.toEqual(fireblocksResponse.body.data) + }) + }) +}) diff --git a/apps/vault/src/broker/__test__/e2e/connection.spec.ts b/apps/vault/src/broker/__test__/e2e/connection.spec.ts index a7be0f17b..001da35e1 100644 --- a/apps/vault/src/broker/__test__/e2e/connection.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/connection.spec.ts @@ -35,7 +35,6 @@ import { ConnectionService } from '../../core/service/connection.service' import { SyncService } from '../../core/service/sync.service' import { ConnectionStatus } from '../../core/type/connection.type' import { Provider } from '../../core/type/provider.type' -import '../../shared/__test__/matcher' import { ConnectionActivatedEvent } from '../../shared/event/connection-activated.event' import { getExpectedAccount, getExpectedWallet } from '../util/map-db-to-returned' import { @@ -48,6 +47,8 @@ import { testUserPrivateJwk } from '../util/mock-data' +import '../../shared/__test__/matcher' + describe('Connection', () => { let app: INestApplication let module: TestingModule diff --git a/apps/vault/src/broker/__test__/e2e/network.spec.ts b/apps/vault/src/broker/__test__/e2e/network.spec.ts new file mode 100644 index 000000000..3f10fd55b --- /dev/null +++ b/apps/vault/src/broker/__test__/e2e/network.spec.ts @@ -0,0 +1,88 @@ +import { EncryptionModuleOptionProvider } from '@narval/encryption-module' +import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' +import { HttpStatus, INestApplication } from '@nestjs/common' +import { Test, TestingModule } from '@nestjs/testing' +import request from 'supertest' +import { ClientService } from '../../../client/core/service/client.service' +import { MainModule } from '../../../main.module' +import { ProvisionService } from '../../../provision.service' +import { KeyValueRepository } from '../../../shared/module/key-value/core/repository/key-value.repository' +import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' +import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' +import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' +import { NetworkSeed } from '../../persistence/seed/network.seed' +import { TEST_CLIENT_ID, getJwsd, testClient, testUserPrivateJwk } from '../util/mock-data' + +import { ProviderNetworkDto } from '../../http/rest/dto/response/provider-network.dto' +import '../../shared/__test__/matcher' + +describe('Network', () => { + let app: INestApplication + let module: TestingModule + + let testPrismaService: TestPrismaService + let provisionService: ProvisionService + let clientService: ClientService + let networkSeed: NetworkSeed + + beforeAll(async () => { + module = await Test.createTestingModule({ + imports: [MainModule] + }) + .overrideModule(LoggerModule) + .useModule(LoggerModule.forTest()) + .overrideProvider(KeyValueRepository) + .useValue(new InMemoryKeyValueRepository()) + .overrideProvider(EncryptionModuleOptionProvider) + .useValue({ + keyring: getTestRawAesKeyring() + }) + .compile() + + app = module.createNestApplication() + + clientService = module.get(ClientService) + networkSeed = module.get(NetworkSeed) + provisionService = module.get(ProvisionService) + testPrismaService = module.get(TestPrismaService) + + await testPrismaService.truncateAll() + }) + + afterAll(async () => { + await testPrismaService.truncateAll() + await module.close() + await app.close() + }) + + beforeEach(async () => { + await testPrismaService.truncateAll() + await provisionService.provision() + await clientService.save(testClient) + + await networkSeed.seed() + + await app.init() + }) + + describe('GET /networks', () => { + it('returns the list of networks', async () => { + const { status, body } = await request(app.getHttpServer()) + .get('/provider/networks') + .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk: testUserPrivateJwk, + requestUrl: '/provider/networks', + payload: {}, + htm: 'GET' + }) + ) + + expect(body).toMatchZodSchema(ProviderNetworkDto.schema) + expect(body.data).toHaveLength(networkSeed.getNetworks().length) + expect(status).toEqual(HttpStatus.OK) + }) + }) +}) diff --git a/apps/vault/src/broker/__test__/e2e/transfer.spec.ts b/apps/vault/src/broker/__test__/e2e/transfer.spec.ts index 4244c8a66..722d40194 100644 --- a/apps/vault/src/broker/__test__/e2e/transfer.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/transfer.spec.ts @@ -30,6 +30,7 @@ import { AccountRepository } from '../../persistence/repository/account.reposito import { ConnectionRepository } from '../../persistence/repository/connection.repository' import { TransferRepository } from '../../persistence/repository/transfer.repository' import { WalletRepository } from '../../persistence/repository/wallet.repository' +import { NetworkSeed } from '../../persistence/seed/network.seed' import { setupMockServer } from '../../shared/__test__/mock-server' import { REQUEST_HEADER_CONNECTION_ID } from '../../shared/constant' import { getJwsd, testClient, testUserPrivateJwk } from '../util/mock-data' @@ -43,9 +44,10 @@ describe('Transfer', () => { let provisionService: ProvisionService let clientService: ClientService - let transferRepository: TransferRepository - let connectionRepository: ConnectionRepository let accountRepository: AccountRepository + let connectionRepository: ConnectionRepository + let networkSeed: NetworkSeed + let transferRepository: TransferRepository let walletRepository: WalletRepository const clientId = testClient.clientId @@ -168,6 +170,7 @@ describe('Transfer', () => { connectionRepository = module.get(ConnectionRepository) walletRepository = module.get(WalletRepository) accountRepository = module.get(AccountRepository) + networkSeed = module.get(NetworkSeed) await testPrismaService.truncateAll() }) @@ -189,6 +192,8 @@ describe('Transfer', () => { await accountRepository.bulkCreate([accountOne, accountTwo]) await transferRepository.bulkCreate([internalTransfer]) + await networkSeed.seed() + await app.init() }) diff --git a/apps/vault/src/broker/broker.module.ts b/apps/vault/src/broker/broker.module.ts index a4df1613f..65a254bfe 100644 --- a/apps/vault/src/broker/broker.module.ts +++ b/apps/vault/src/broker/broker.module.ts @@ -3,16 +3,19 @@ import { Module } from '@nestjs/common' import { APP_FILTER } from '@nestjs/core' import { EventEmitterModule } from '@nestjs/event-emitter' import { ClientModule } from '../client/client.module' +import { Env, getEnv } from '../main.config' import { DEFAULT_HTTP_MODULE_PROVIDERS } from '../shared/constant' import { ProviderHttpExceptionFilter } from '../shared/filter/provider-http-exception.filter' import { PersistenceModule } from '../shared/module/persistence/persistence.module' import { EncryptionKeyService } from '../transit-encryption/core/service/encryption-key.service' import { EncryptionKeyRepository } from '../transit-encryption/persistence/encryption-key.repository' import { TransitEncryptionModule } from '../transit-encryption/transit-encryption.module' +import { AnchorageAssetService } from './core/provider/anchorage/anchorage-asset.service' import { AnchorageCredentialService } from './core/provider/anchorage/anchorage-credential.service' import { AnchorageProxyService } from './core/provider/anchorage/anchorage-proxy.service' import { AnchorageSyncService } from './core/provider/anchorage/anchorage-sync.service' import { AnchorageTransferService } from './core/provider/anchorage/anchorage-transfer.service' +import { FireblocksAssetService } from './core/provider/fireblocks/fireblocks-asset.service' import { FireblocksCredentialService } from './core/provider/fireblocks/fireblocks-credential.service' import { FireblocksProxyService } from './core/provider/fireblocks/fireblocks-proxy.service' import { FireblocksSyncService } from './core/provider/fireblocks/fireblocks-sync.service' @@ -30,6 +33,7 @@ import { AnchorageClient } from './http/client/anchorage.client' import { FireblocksClient } from './http/client/fireblocks.client' import { ProviderAccountController } from './http/rest/controller/account.controller' import { ProviderAddressController } from './http/rest/controller/address.controller' +import { AssetController } from './http/rest/controller/asset.controller' import { ConnectionController } from './http/rest/controller/connection.controller' import { KnownDestinationController } from './http/rest/controller/known-destination.controller' import { NetworkController } from './http/rest/controller/network.controller' @@ -37,7 +41,6 @@ import { ProxyController } from './http/rest/controller/proxy.controller' import { SyncController } from './http/rest/controller/sync.controller' import { TransferController } from './http/rest/controller/transfer.controller' import { ProviderWalletController } from './http/rest/controller/wallet.controller' -import { ConnectionSeedService } from './persistence/connection.seed' import { AccountRepository } from './persistence/repository/account.repository' import { AddressRepository } from './persistence/repository/address.repository' import { ConnectionRepository } from './persistence/repository/connection.repository' @@ -46,6 +49,9 @@ import { NetworkRepository } from './persistence/repository/network.repository' import { SyncRepository } from './persistence/repository/sync.repository' import { TransferRepository } from './persistence/repository/transfer.repository' import { WalletRepository } from './persistence/repository/wallet.repository' +import { NetworkSeed } from './persistence/seed/network.seed' + +const SEEDS = [NetworkSeed] @Module({ imports: [ @@ -57,6 +63,7 @@ import { WalletRepository } from './persistence/repository/wallet.repository' TransitEncryptionModule ], controllers: [ + AssetController, ConnectionController, KnownDestinationController, NetworkController, @@ -68,6 +75,7 @@ import { WalletRepository } from './persistence/repository/wallet.repository' TransferController ], providers: [ + ...(getEnv() !== Env.PRODUCTION ? SEEDS : []), ...DEFAULT_HTTP_MODULE_PROVIDERS, { provide: APP_FILTER, @@ -77,17 +85,18 @@ import { WalletRepository } from './persistence/repository/wallet.repository' AccountService, AddressRepository, AddressService, + AnchorageAssetService, AnchorageClient, AnchorageCredentialService, AnchorageProxyService, AnchorageSyncService, AnchorageTransferService, ConnectionRepository, - ConnectionSeedService, ConnectionService, ConnectionSyncEventHandler, EncryptionKeyRepository, EncryptionKeyService, + FireblocksAssetService, FireblocksClient, FireblocksCredentialService, FireblocksProxyService, diff --git a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-sync.service.spec.ts b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-sync.service.spec.ts index 923557997..e00d8277a 100644 --- a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-sync.service.spec.ts +++ b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-sync.service.spec.ts @@ -15,6 +15,7 @@ import { TestPrismaService } from '../../../../../../shared/module/persistence/s import { getTestRawAesKeyring } from '../../../../../../shared/testing/encryption.testing' import { testClient } from '../../../../../__test__/util/mock-data' import { WalletRepository } from '../../../../../persistence/repository/wallet.repository' +import { NetworkSeed } from '../../../../../persistence/seed/network.seed' import { setupMockServer } from '../../../../../shared/__test__/mock-server' import { AccountService } from '../../../../service/account.service' import { AddressService } from '../../../../service/address.service' @@ -64,6 +65,7 @@ describe(AnchorageSyncService.name, () => { let connection: ConnectionWithCredentials let connectionService: ConnectionService let knownDestinationService: KnownDestinationService + let networkSeed: NetworkSeed let provisionService: ProvisionService let testPrismaService: TestPrismaService let walletService: WalletRepository @@ -102,6 +104,7 @@ describe(AnchorageSyncService.name, () => { addressService = module.get(AddressService) knownDestinationService = module.get(KnownDestinationService) provisionService = module.get(ProvisionService) + networkSeed = module.get(NetworkSeed) clientService = module.get(ClientService) await testPrismaService.truncateAll() @@ -130,6 +133,8 @@ describe(AnchorageSyncService.name, () => { } }) + await networkSeed.seed() + await app.init() }) diff --git a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts index 35d4a9fd7..d2fdecb11 100644 --- a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts +++ b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts @@ -18,6 +18,7 @@ import { ConnectionRepository } from '../../../../../persistence/repository/conn import { KnownDestinationRepository } from '../../../../../persistence/repository/known-destination.repository' import { TransferRepository } from '../../../../../persistence/repository/transfer.repository' import { WalletRepository } from '../../../../../persistence/repository/wallet.repository' +import { NetworkSeed } from '../../../../../persistence/seed/network.seed' import { setupMockServer, useRequestSpy } from '../../../../../shared/__test__/mock-server' import { Connection, ConnectionStatus, ConnectionWithCredentials } from '../../../../type/connection.type' import { Account, Address, KnownDestination, Wallet } from '../../../../type/indexed-resources.type' @@ -28,6 +29,7 @@ import { TransferPartyType, TransferStatus } from '../../../../type/transfer.type' +import { AnchorageAssetService } from '../../anchorage-asset.service' import { AnchorageTransferService } from '../../anchorage-transfer.service' import { ANCHORAGE_TEST_API_BASE_URL, getHandlers } from '../server-mock/server' @@ -35,16 +37,18 @@ describe(AnchorageTransferService.name, () => { let app: INestApplication let module: TestingModule let testPrismaService: TestPrismaService - let anchorageTransferService: AnchorageTransferService - let provisionService: ProvisionService - let clientService: ClientService - let transferRepository: TransferRepository - let connectionRepository: ConnectionRepository - let walletRepository: WalletRepository let accountRepository: AccountRepository let addressRepository: AddressRepository + let anchorageAssetService: AnchorageAssetService + let anchorageTransferService: AnchorageTransferService + let clientService: ClientService + let connectionRepository: ConnectionRepository let knownDestinationRepository: KnownDestinationRepository + let networkSeed: NetworkSeed + let provisionService: ProvisionService + let transferRepository: TransferRepository + let walletRepository: WalletRepository const mockServer = setupMockServer(getHandlers()) @@ -181,12 +185,14 @@ describe(AnchorageTransferService.name, () => { provisionService = module.get(ProvisionService) clientService = module.get(ClientService) - transferRepository = module.get(TransferRepository) - connectionRepository = module.get(ConnectionRepository) - walletRepository = module.get(WalletRepository) accountRepository = module.get(AccountRepository) addressRepository = module.get(AddressRepository) + anchorageAssetService = module.get(AnchorageAssetService) + connectionRepository = module.get(ConnectionRepository) knownDestinationRepository = module.get(KnownDestinationRepository) + networkSeed = module.get(NetworkSeed) + transferRepository = module.get(TransferRepository) + walletRepository = module.get(WalletRepository) await testPrismaService.truncateAll() }) @@ -202,6 +208,7 @@ describe(AnchorageTransferService.name, () => { await provisionService.provision() await clientService.save(testClient) + await networkSeed.seed() await connectionRepository.create(connection) await walletRepository.bulkCreate([wallet]) diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage-assets.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage-asset.service.ts similarity index 95% rename from apps/vault/src/broker/core/provider/anchorage/anchorage-assets.ts rename to apps/vault/src/broker/core/provider/anchorage/anchorage-asset.service.ts index 67059fb63..b9fb37fa8 100644 --- a/apps/vault/src/broker/core/provider/anchorage/anchorage-assets.ts +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage-asset.service.ts @@ -1,4 +1,12 @@ -export type AnchorageAsset = { +import { LoggerService } from '@narval/nestjs-shared' +import { Injectable } from '@nestjs/common' +import { NetworkRepository } from '../../../persistence/repository/network.repository' +import { Asset } from '../../type/asset.type' +import { Network } from '../../type/network.type' +import { Provider } from '../../type/provider.type' +import { getExternalNetwork } from '../../util/network.util' + +type AnchorageAsset = { assetType: string decimals: number name: string @@ -6,8 +14,7 @@ export type AnchorageAsset = { onchainIdentifier?: string } -// TODO: move this into a Repository, map w/ other providers -export const ANCHORAGE_ASSETS: AnchorageAsset[] = [ +const ANCHORAGE_ASSETS: AnchorageAsset[] = [ { assetType: '1INCH', decimals: 18, @@ -2617,19 +2624,83 @@ export const ANCHORAGE_ASSETS: AnchorageAsset[] = [ } ] -/** - * util to find anchorage networks that don't have a match in the networks list. +@Injectable() +export class AnchorageAssetService { + constructor( + private readonly networkRepository: NetworkRepository, + private readonly logger: LoggerService + ) {} + + private mapAnchorageAsset(network: Network, anchorageAsset: AnchorageAsset): Asset { + return { + decimals: anchorageAsset.decimals, + externalId: anchorageAsset.assetType, + name: anchorageAsset.name, + networkId: network.networkId, + onchainId: anchorageAsset.onchainIdentifier + } + } + + async findByExternalId(externalId: string): Promise { + for (const anchorageAsset of ANCHORAGE_ASSETS) { + if (anchorageAsset.assetType === externalId) { + const network = await this.networkRepository.findByExternalId(Provider.ANCHORAGE, anchorageAsset.networkId) + + if (network) { + return this.mapAnchorageAsset(network, anchorageAsset) + } + } + } + + return null + } + + async findAll(): Promise { + const networkExternalIdIndex = await this.networkRepository.buildProviderExternalIdIndex(Provider.ANCHORAGE) + const assets: Asset[] = [] + + for (const anchorageAsset of ANCHORAGE_ASSETS) { + const network = networkExternalIdIndex.get(anchorageAsset.networkId) -const baseAssets = ANCHORAGE_ASSETS.filter((asset) => !asset.onchainIdentifier) + if (network) { + assets.push(this.mapAnchorageAsset(network, anchorageAsset)) + } else { + this.logger.warn('Anchorage asset network not found', { anchorageAsset }) + } + } -// for each baseAsset, see if you can find a match for `networkId` against the `anchorageId` property of the networks list. -// Filter the baseAssets list to only the ones that do NOT have a match. -const baseAssetsWithoutMatch = baseAssets.filter((asset) => { - const match = NETWORKS.find((network) => network.anchorageId === asset.networkId) - return !match -}) + return assets + } + + async findByOnchainId(networkId: string, onchainId: string): Promise { + for (const anchorageAsset of ANCHORAGE_ASSETS) { + if (anchorageAsset.onchainIdentifier?.toLowerCase() === onchainId.toLowerCase()) { + const network = await this.networkRepository.findByExternalId(Provider.ANCHORAGE, anchorageAsset.assetType) + + if (network?.networkId === networkId) { + return this.mapAnchorageAsset(network, anchorageAsset) + } + } + } + + return null + } -// Write teh base assets out to base-assets.json -fs.writeFileSync('base-assets-no-match.json', JSON.stringify(baseAssetsWithoutMatch, null, 2)) + async findNativeAsset(networkId: string): Promise { + const network = await this.networkRepository.findById(networkId) -*/ + if (network) { + const externalNetwork = getExternalNetwork(network, Provider.ANCHORAGE) + + for (const anchorageAsset of ANCHORAGE_ASSETS) { + // If network matches and asset doesn't has an address, it must be the + // native asset. + if (externalNetwork?.externalId === anchorageAsset.networkId && !anchorageAsset.onchainIdentifier) { + return this.mapAnchorageAsset(network, anchorageAsset) + } + } + } + + return null + } +} diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts index e9233a159..69ed81285 100644 --- a/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts @@ -6,32 +6,34 @@ import { NetworkRepository } from '../../../persistence/repository/network.repos import { TransferRepository } from '../../../persistence/repository/transfer.repository' import { BrokerException } from '../../exception/broker.exception' import { TransferPartyService } from '../../service/transfer-party.service' +import { Asset } from '../../type/asset.type' import { ConnectionWithCredentials } from '../../type/connection.type' import { Network } from '../../type/network.type' import { Provider, ProviderTransferService } from '../../type/provider.type' import { - Asset, Destination, InternalTransfer, NetworkFeeAttribution, SendTransfer, Source, Transfer, + TransferAsset, TransferPartyType, TransferStatus, isAddressDestination, isProviderSpecific } from '../../type/transfer.type' -import { ANCHORAGE_ASSETS, AnchorageAsset } from './anchorage-assets' +import { AnchorageAssetService } from './anchorage-asset.service' import { validateConnection } from './anchorage.util' @Injectable() export class AnchorageTransferService implements ProviderTransferService { constructor( + private readonly anchorageAssetService: AnchorageAssetService, private readonly anchorageClient: AnchorageClient, + private readonly networkRepository: NetworkRepository, private readonly transferPartyService: TransferPartyService, private readonly transferRepository: TransferRepository, - private readonly networkRepository: NetworkRepository, private readonly logger: LoggerService ) {} @@ -110,14 +112,15 @@ export class AnchorageTransferService implements ProviderTransferService { }) } - private async resolveAsset(asset: Asset): Promise { + private async resolveAsset(asset: TransferAsset): Promise { if (asset.externalAssetId) { - return ANCHORAGE_ASSETS.find((a) => a.assetType === asset.externalAssetId) + return this.anchorageAssetService.findByExternalId(asset.externalAssetId) } if (asset.assetId) { - // TODO: Look up by the narval assetId; for now we just treat it as the same as the anchorage one. - return ANCHORAGE_ASSETS.find((a) => a.assetType === asset.assetId) + // TODO: Look up by the narval assetId; for now we just treat it as the + // same as the anchorage one. + return this.anchorageAssetService.findByExternalId(asset.assetId) } if (!asset.networkId) { @@ -127,23 +130,12 @@ export class AnchorageTransferService implements ProviderTransferService { context: { asset } }) } - const network = await this.networkRepository.findById(asset.networkId) - if (!network) { - throw new BrokerException({ - message: 'Cannot resolve asset without valid network', - suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, - context: { asset } - }) - } - if (!asset.address) { - // This is the base asset of the network - return ANCHORAGE_ASSETS.find((a) => a.networkId === network.anchorageId && !a.onchainIdentifier) + + if (asset.address) { + return this.anchorageAssetService.findByOnchainId(asset.networkId, asset.address) } - // This is a chain-specific asset - return ANCHORAGE_ASSETS.find( - (a) => a.networkId === network.anchorageId && a.onchainIdentifier?.toLowerCase() === asset.address?.toLowerCase() - ) + return this.anchorageAssetService.findNativeAsset(asset.networkId) } async send(connection: ConnectionWithCredentials, sendTransfer: SendTransfer): Promise { @@ -155,7 +147,6 @@ export class AnchorageTransferService implements ProviderTransferService { validateConnection(connection) - // Get the Network from the Asset. const asset = await this.resolveAsset(sendTransfer.asset) if (!asset) { throw new BrokerException({ @@ -164,8 +155,8 @@ export class AnchorageTransferService implements ProviderTransferService { context: { asset: sendTransfer.asset } }) } - // Get the narval networkId from the anchorage asset networkId - const network = await this.networkRepository.findByExternalId(Provider.ANCHORAGE, asset.networkId) + + const network = await this.networkRepository.findById(asset.networkId) if (!network) { throw new BrokerException({ message: 'Cannot resolve Narval networkId from Anchorage networkId', @@ -187,7 +178,7 @@ export class AnchorageTransferService implements ProviderTransferService { id: source.externalId }, destination: await this.getDestination(connection.clientId, network, sendTransfer), - assetType: asset.assetType, + assetType: asset.externalId, amount: sendTransfer.amount, transferMemo: sendTransfer.memo || null, idempotentId: sendTransfer.idempotenceId, @@ -203,7 +194,8 @@ export class AnchorageTransferService implements ProviderTransferService { }) const internalTransfer: InternalTransfer = { - assetId: asset.assetType, // TODO: switch this to the Narval assetId once that is a real thing. + // TODO: switch this to the Narval assetId once that is a real thing. + assetId: asset.externalId, clientId: connection.clientId, createdAt: new Date(), customerRefId: null, diff --git a/apps/vault/src/broker/core/provider/fireblocks/fireblocks-asset.service.ts b/apps/vault/src/broker/core/provider/fireblocks/fireblocks-asset.service.ts new file mode 100644 index 000000000..f74b9d2e1 --- /dev/null +++ b/apps/vault/src/broker/core/provider/fireblocks/fireblocks-asset.service.ts @@ -0,0 +1,10720 @@ +import { LoggerService } from '@narval/nestjs-shared' +import { Injectable } from '@nestjs/common' +import { NetworkRepository } from '../../../persistence/repository/network.repository' +import { Asset } from '../../type/asset.type' +import { Network } from '../../type/network.type' +import { Provider } from '../../type/provider.type' +import { getExternalNetwork } from '../../util/network.util' + +type FireblocksAsset = { + contractAddress: string + decimals: number + id: string + issuerAddress?: string + name: string + nativeAsset: string + type: string +} + +const FIREBLOCKS_ASSETS: FireblocksAsset[] = [ + { + contractAddress: '0xEA6A3E367e96521fD9E8296425a44EFa6aee82da', + decimals: 0, + id: '$ACM_$CHZ', + name: 'AC Milan ($CHZ)', + nativeAsset: 'CHZ_$CHZ', + type: 'ERC20' + }, + { + contractAddress: '0x235639F72E127bBdd1509BFC9DC6e2caeb3FB741', + decimals: 0, + id: '$ASR_$CHZ', + name: 'AS Roma ($CHZ)', + nativeAsset: 'CHZ_$CHZ', + type: 'ERC20' + }, + { + contractAddress: '0x4c3E460b8e8285DE57c8B1B2B688847B995B71D6', + decimals: 0, + id: '$ATM_$CHZ', + name: 'Atlético de Madrid ($CHZ)', + nativeAsset: 'CHZ_$CHZ', + type: 'ERC20' + }, + { + contractAddress: '0xECc000EBd318bee2a052EB174A71fAF2C3c9e898', + decimals: 0, + id: '$BAR_$CHZ', + name: 'FC Barcelona ($CHZ)', + nativeAsset: 'CHZ_$CHZ', + type: 'ERC20' + }, + { + contractAddress: '0xf30D150250F5301ef34A0E4a64aaFa93F242d87A', + decimals: 0, + id: '$CITY_$CHZ', + name: 'Manchester City FC ($CHZ)', + nativeAsset: 'CHZ_$CHZ', + type: 'ERC20' + }, + { + contractAddress: '0xEE06A81a695750E71a662B51066F2c74CF4478a0', + decimals: 18, + id: '$DG', + name: 'Decentral.games', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x67e410B0e722ff2eec6dDCC7AefD3EdBC2B9078d', + decimals: 0, + id: '$INTER_$CHZ', + name: 'Inter Milan ($CHZ)', + nativeAsset: 'CHZ_$CHZ', + type: 'ERC20' + }, + { + contractAddress: '0x14A5750B0e54b57D12767B84A326C9fE59472Da5', + decimals: 0, + id: '$JUV_$CHZ', + name: 'Juventus ($CHZ)', + nativeAsset: 'CHZ_$CHZ', + type: 'ERC20' + }, + { + contractAddress: '0xd44fC47dBe5751ed36C3f549e217Dab749Aa4039', + decimals: 0, + id: '$LEG_$CHZ', + name: 'Legia Warsaw ($CHZ)', + nativeAsset: 'CHZ_$CHZ', + type: 'ERC20' + }, + { + contractAddress: '0xC7456e8f7CE7BDdBcbF719d0a90811a35dD3d363', + decimals: 0, + id: '$NAP_$CHZ', + name: 'Napoli ($CHZ)', + nativeAsset: 'CHZ_$CHZ', + type: 'ERC20' + }, + { + contractAddress: '0x6fc212cdE3b420733A88496CbdbB15d85beAb1Ca', + decimals: 0, + id: '$PSG_$CHZ', + name: 'Paris Saint-Germain ($CHZ)', + nativeAsset: 'CHZ_$CHZ', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: '$WIF_SOL', + issuerAddress: 'EKpQGSJtjMFqKZ9KQanSqYXRcF8fBopzLHYxdM65zcjm', + name: 'dogwifhat', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x111111111117dC0aa78b770fA6A738034120C302', + decimals: 18, + id: '1INCH', + name: '1INCH Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x111111111117dC0aa78b770fA6A738034120C302', + decimals: 18, + id: '1INCH_BSC', + name: '1INCH Token (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0xfDBc1aDc26F0F8f8606a5d63b7D3a3CD21c22B23', + decimals: 8, + id: '1WO', + name: '1World', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xC96c1609A1a45CcC667B2b7FA6508e29617f7b69', + decimals: 18, + id: '2GT', + name: '2GT_token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xde50da7f5966eFe1869349ff2242D7AD932Eb785', + decimals: 18, + id: '7UT', + name: '7EVEN Utility Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xe8272210954eA85DE6D2Ae739806Ab593B5d9c51', + decimals: 18, + id: 'A5T', + name: 'Alpha5Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xFFC97d72E13E01096502Cb8Eb52dEe56f74DAD7B', + decimals: 18, + id: 'AAAVE', + name: 'Aave interest bearing AAVE', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9', + decimals: 18, + id: 'AAVE', + name: 'Aave Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xfb6115445Bff7b52FeB98650C87f44907E58f802', + decimals: 18, + id: 'AAVE_BSC', + name: 'Binance-Peg Aave Token (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0x63a72806098Bd3D9520cC43356dD78afe5D386D9', + decimals: 18, + id: 'AAVE_E_AVAX', + name: 'Aave Token (Avalanche)', + nativeAsset: 'AVAX', + type: 'ERC20' + }, + { + contractAddress: '0xD6DF932A45C0f255f85145f286eA0b292B21C90B', + decimals: 18, + id: 'AAVE_POLYGON', + name: 'Aave (Polygon)', + nativeAsset: 'MATIC_POLYGON', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 2, + id: 'ABA_USD', + name: 'USD (ABA)', + nativeAsset: 'ABA_USD', + type: 'FIAT' + }, + { + contractAddress: '0xE1BA0FB44CCb0D11b80F92f4f8Ed94CA3fF51D00', + decimals: 18, + id: 'ABAT', + name: 'Aave BAT', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x0E8d6b471e332F140e7d9dbB99E5E3822F728DA6', + decimals: 18, + id: 'ABYSS', + name: 'The Abyss', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xEd04915c23f00A313a544955524EB7DBD823143d', + decimals: 8, + id: 'ACH', + name: 'Alchemy Pay', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 9, + id: 'ACM_SOL', + issuerAddress: 'ACUMENkbnxQPAsN8XrNA11sY3NmXDNKVCqS82EiDqMYB', + name: 'Acumen Governance Token (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '', + decimals: 6, + id: 'ADA', + name: 'ADA (Cardano)', + nativeAsset: 'ADA', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x3EE2200Efb3400fAbB9AacF31297cBdD1d435D47', + decimals: 18, + id: 'ADA_BSC', + name: 'Binance-Peg Cardano (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '', + decimals: 6, + id: 'ADA_TEST', + name: 'ADA Test', + nativeAsset: 'ADA_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x028171bCA77440897B824Ca71D1c56caC55b68A3', + decimals: 18, + id: 'ADAI', + name: 'Aave interest bearing DAI', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xfC1E690f61EFd961294b3e1Ce3313fBD8aa4f85d', + decimals: 18, + id: 'ADAI_OLD', + name: 'Aave Interest bearing DAI (Old)', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xc3FdbadC7c795EF1D6Ba111e06fF8F16A20Ea539', + decimals: 18, + id: 'ADDY_POLYGON', + name: 'Adamant', + nativeAsset: 'MATIC_POLYGON', + type: 'ERC20' + }, + { + contractAddress: '0xE69a353b3152Dd7b706ff7dD40fe1d18b7802d31', + decimals: 18, + id: 'ADH', + name: 'AdHive', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xADE00C28244d5CE17D72E40330B1c318cD12B7c3', + decimals: 18, + id: 'ADX', + name: 'AdEx Network', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x3a3A65aAb0dd2A17E3F1947bA16138cd37d08c04', + decimals: 18, + id: 'AETH', + name: 'Aave Interest bearing ETH', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'AEVO', + name: 'Aevo', + nativeAsset: 'AEVO', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x8eB24319393716668D768dCEC29356ae9CfFe285', + decimals: 8, + id: 'AGI', + name: 'SingularityNET', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x5B7533812759B45C2B44C19e320ba2cD2681b542', + decimals: 8, + id: 'AGIX', + name: 'SingularityNET Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x32353A6C91143bfd6C7d363B546e62a9A2489A20', + decimals: 18, + id: 'AGLD', + name: 'Adventure Gold', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'AGNG_TEST', + name: 'Agung (Testnet)', + nativeAsset: 'AGNG_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x69CF1e63090Acf1e1E16ec0066055f8973fc9Ec8', + decimals: 18, + id: 'AGX', + name: 'AGX Coin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x8Ab7404063Ec4DBcfd4598215992DC3F8EC853d7', + decimals: 18, + id: 'AKRO', + name: 'Akropolis', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xdBdb4d16EdA451D0503b854CF79D55697F90c8DF', + decimals: 18, + id: 'ALCX', + name: 'Alchemix', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xb26C4B3Ca601136Daf98593feAeff9E0CA702a8D', + decimals: 18, + id: 'ALD', + name: 'Aladdin Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xB5495A8D85EE18cfD0d2816993658D88aF08bEF4', + decimals: 0, + id: 'ALDDAO', + name: 'Aladdin DAO Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x27702a26126e0B3702af63Ee09aC4d1A084EF628', + decimals: 18, + id: 'ALEPH', + name: 'aleph.im v2', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'ALEPH_ZERO_EVM', + name: 'Aleph Zero EVM', + nativeAsset: 'ALEPH_ZERO_EVM', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x0100546F2cD4C9D97f798fFC9755E47865FF7Ee6', + decimals: 18, + id: 'ALETH', + name: 'Alchemix ETH', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x16B0a1a87ae8aF5C792faBC429C4FE248834842B', + decimals: 18, + id: 'ALG', + name: 'Algory', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'ALGO', + name: 'Algorand', + nativeAsset: 'ALGO', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 6, + id: 'ALGO_TEST', + name: 'Algorand Test', + nativeAsset: 'ALGO_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 6, + id: 'ALGO_USDC_2V6G', + issuerAddress: '10458941', + name: 'USDC Test on Algorand', + nativeAsset: 'ALGO_TEST', + type: 'ALGO_ASSET' + }, + { + contractAddress: '', + decimals: 6, + id: 'ALGO_USDC_UV4I', + issuerAddress: '31566704', + name: 'USDC on Algorand', + nativeAsset: 'ALGO', + type: 'ALGO_ASSET' + }, + { + contractAddress: '', + decimals: 6, + id: 'ALGO_USDT_I3ZH', + issuerAddress: '312769', + name: 'USDT on Algorand', + nativeAsset: 'ALGO', + type: 'ALGO_ASSET' + }, + { + contractAddress: '0x6B0b3a982b4634aC68dD83a4DBF02311cE324181', + decimals: 18, + id: 'ALI', + name: 'Artificial Liquid Intelligence Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xAC51066d7bEC65Dc4589368da368b212745d63E8', + decimals: 6, + id: 'ALICE', + name: 'ALICE', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xA64BD6C70Cb9051F6A9ba1F163Fdc07E0DfB5F84', + decimals: 18, + id: 'ALINK', + name: 'Aave Interest bearing LINK', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xa06bC25B5805d5F8d82847D191Cb4Af5A3e873E0', + decimals: 18, + id: 'ALINK_V2', + name: 'Aave interest bearing LINK v2', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x6C16119B20fa52600230F074b349dA3cb861a7e3', + decimals: 18, + id: 'ALK', + name: 'Alkemi_Network_DAO_Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x7cA4408137eb639570F8E647d9bD7B7E8717514A', + decimals: 18, + id: 'ALPA', + name: 'AlpaToken', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x8F0528cE5eF7B51152A59745bEfDD91D97091d2F', + decimals: 18, + id: 'ALPACA_BSC', + name: 'AlpacaToken (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0xa1faa113cbE53436Df28FF0aEe54275c13B40975', + decimals: 18, + id: 'ALPHA', + name: 'AlphaToken', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x8263CD1601FE73C066bf49cc09841f35348e3be0', + decimals: 18, + id: 'ALU_BSC', + name: 'Altura', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0xBC6DA0FE9aD5f3b0d58160288917AA56653660E9', + decimals: 18, + id: 'ALUSD', + name: 'Alchemix USD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x4DC3643DbC642b72C158E7F3d2ff232df61cb6CE', + decimals: 18, + id: 'AMB', + name: 'Ambrosus', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xCA0e7269600d353F70b14Ad118A49575455C0f2f', + decimals: 18, + id: 'AMLT', + name: 'AMLT', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x737F98AC8cA59f2C68aD658E3C3d8C8963E40a4c', + decimals: 18, + id: 'AMN', + name: 'Amon', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'AMOY_POLYGON_TEST', + name: 'Matic Gas Token (Polygon Test Amoy)', + nativeAsset: 'AMOY_POLYGON_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xfF20817765cB7f73d4bde2e66e067E58D11095C2', + decimals: 18, + id: 'AMP', + name: 'Amp', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xD46bA6D942050d489DBd938a2C909A5d5039A161', + decimals: 9, + id: 'AMPL', + name: 'Ampleforth', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x0F3ADC247E91c3c50bC08721355A41037E89Bc20', + decimals: 18, + id: 'ANC', + name: 'Wrapped ANC Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x8290333ceF9e6D528dD5618Fb97a76f268f3EDD4', + decimals: 18, + id: 'ANKR', + name: 'Ankr Network', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xa117000000f279D81A1D3cc75430fAA017FA5A2e', + decimals: 18, + id: 'ANT', + name: 'Aragon', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x9ab165D795019b6d8B3e971DdA91071421305e5a', + decimals: 18, + id: 'AOA', + name: 'Aurora.io (Ethereum)', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x4d224452801ACEd8B2F0aebE155379bb5D594381', + decimals: 18, + id: 'APE_ETH', + name: 'ApeCoin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x0b38210ea11411557c13457D4dA7dC6ea731B88a', + decimals: 18, + id: 'API3', + name: 'API3', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x4104b135DBC9609Fc1A9490E61369036497660c8', + decimals: 18, + id: 'APW', + name: 'APWine Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x95a4492F028aa1fd432Ea71146b433E7B4446611', + decimals: 18, + id: 'APY', + name: 'APY Governance Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x912CE59144191C1204E64559FE8253a0e49E6548', + decimals: 18, + id: 'ARB_ARB_FRK9', + name: 'Arbitrum', + nativeAsset: 'ETH-AETH', + type: 'ERC20' + }, + { + contractAddress: '0x319190E3Bbc595602A9E63B2bCfB61c6634355b1', + decimals: 18, + id: 'ARC_AETH', + name: 'Aave Arc Interest bearing ETH', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x89eFaC495C65d43619c661df654ec64fc10C0A75', + decimals: 18, + id: 'ARC-AAAVE', + name: 'Aave Arc Interest bearing AAVE', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x62A6738d887F47e297676FaB05b902709B106C64', + decimals: 18, + id: 'ARCA', + name: 'ARCA', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x1F3f9D3068568F8040775be2e8C03C103C61f3aF', + decimals: 18, + id: 'ARCH', + name: 'Archer DAO Governance Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xBA50933C268F567BDC86E1aC131BE072C6B0b71a', + decimals: 18, + id: 'ARPA', + name: 'ARPA Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x64D91f12Ece7362F91A6f8E7940Cd55F05060b92', + decimals: 18, + id: 'ASH', + name: 'Burn', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x2565ae0385659badCada1031DB704442E1b69982', + decimals: 18, + id: 'ASM', + name: 'ASSEMBLE', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x27054b13b1B798B345b591a4d22e6562d47eA75a', + decimals: 4, + id: 'AST', + name: 'AirSwap', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'ASTR_ASTR', + name: 'Astar', + nativeAsset: 'ASTR_ASTR', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'ASTR_TEST', + name: 'Shibuya (Astar Test)', + nativeAsset: 'ASTR_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xA2120b9e674d3fC3875f415A7DF52e382F141225', + decimals: 18, + id: 'ATA', + name: 'Automata', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xF69709C4c6F3F2b17978280dCe8b7b7a2CbcbA8b', + decimals: 18, + id: 'ATD', + name: 'ATD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 8, + id: 'ATLAS_SOL', + issuerAddress: 'ATLASXmbPQxBUYbxPsV97usA3fPQYEqzQBUHgiFCUsXx', + name: 'Star Atlas (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x0Eb3a705fc54725037CC9e008bDede697f62F335', + decimals: 18, + id: 'ATOM', + name: 'Cosmos Token (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '', + decimals: 6, + id: 'ATOM_COS', + name: 'Cosmos Hub', + nativeAsset: 'ATOM_COS', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 6, + id: 'ATOM_COS_TEST', + name: 'Cosmos Hub Test', + nativeAsset: 'ATOM_COS_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xdacD69347dE42baBfAEcD09dC88958378780FB62', + decimals: 0, + id: 'ATRI', + name: 'AtariToken', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x101cc05f4A51C0319f570d5E146a8C625198e636', + decimals: 18, + id: 'ATUSD', + name: 'Aave interest bearing TUSD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xA9B1Eb5908CfC3cdf91F9B8B3a74108598009096', + decimals: 18, + id: 'AUCTION', + name: 'Bounce Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x18aAA7115705e8be94bfFEBDE57Af9BFc265B998', + decimals: 18, + id: 'AUDIO', + name: 'Audius', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'AURORA_DEV', + name: 'Aurora.dev', + nativeAsset: 'AURORA_DEV', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x9bA00D6856a4eDF4665BcA2C2309936572473B7E', + decimals: 6, + id: 'AUSDC', + name: 'Aave Interest bearing USDC', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xd35f648C3C7f17cd1Ba92e5eac991E3EfcD4566d', + decimals: 6, + id: 'AUSDC_D35F6_ETH', + name: 'Aave Arc Interest bearing USDC', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xBcca60bB61934080951369a648Fb03DF4F96263C', + decimals: 6, + id: 'AUSDC_ETH', + name: 'Aave interest bearing USDC (V2)', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xab60CcAC0d4157c2b03e5D883bDbe60317992f58', + decimals: 18, + id: 'AUX', + name: 'AUX Coin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'AVAX', + name: 'Avalanche (C-Chain)', + nativeAsset: 'AVAX', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x1CE0c2827e2eF14D5C4f29a091d735A204794041', + decimals: 18, + id: 'AVAX_BSC', + name: 'Avalanche (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '', + decimals: 18, + id: 'AVAXTEST', + name: 'Avalanche Fuji', + nativeAsset: 'AVAXTEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x46A51127C3ce23fb7AB1DE06226147F446e4a857', + decimals: 6, + id: 'AVUSDC', + name: 'Aave Avalanche Market USDC', + nativeAsset: 'AVAX', + type: 'ERC20' + }, + { + contractAddress: '0x9ff58f4fFB29fA2266Ab25e75e2A8b3503311656', + decimals: 8, + id: 'AWBTC', + name: 'Aave interest bearing WBTC', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x030bA81f1c18d280636F32af80b9AAd02Cf0854e', + decimals: 18, + id: 'AWETH', + name: 'Aave interest bearing WETH', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x32950db2a7164aE833121501C797D79E7B79d74C', + decimals: 0, + id: 'AXIE_RON', + name: 'Axie (Ronin)', + nativeAsset: 'RON', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'AXL', + name: 'Axelar', + nativeAsset: 'AXL', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 6, + id: 'AXL_TEST', + name: 'Axelar Test', + nativeAsset: 'AXL_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xBB0E17EF65F82Ab018d8EDd776e8DD940327B28b', + decimals: 18, + id: 'AXS', + name: 'Axie Infinity Shard', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x715D400F88C167884bbCc41C5FeA407ed4D2f8A0', + decimals: 18, + id: 'AXS_BSC', + name: 'Axie Infinity Shard (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0xF5D669627376EBd411E34b98F19C868c8ABA5ADA', + decimals: 18, + id: 'AXS_L', + name: 'Axie Infinity Shard (Old)', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x97a9107C1793BC407d6F527b77e7fff4D812bece', + decimals: 18, + id: 'AXS_RON', + name: 'Axie Infinity Shard (Ronin)', + nativeAsset: 'RON', + type: 'ERC20' + }, + { + contractAddress: '0xd7c302fc3ac829C7E896a32c4Bd126f3e8Bd0a1f', + decimals: 18, + id: 'B2M_ERC20', + name: 'Bit2Me Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x6Faa826aF0568d1866Fca570dA79B318ef114dAb', + decimals: 18, + id: 'B21', + name: 'B21 Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x3472A5A71965499acd81997a54BBA8D852C6E53d', + decimals: 18, + id: 'BADGER', + name: 'Badger', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xe7Bf3aEE922367c10c8acEc3793fE7D809A38eef', + decimals: 18, + id: 'BAGS', + name: 'BAGS', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xE02dF9e3e622DeBdD69fb838bB799E3F168902c5', + decimals: 18, + id: 'BAKE', + name: 'BAKE', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0xba100000625a3754423978a60c9317c58a424e3D', + decimals: 18, + id: 'BAL', + name: 'Balancer', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x603c7f932ED1fc6575303D8Fb018fDCBb0f39a95', + decimals: 18, + id: 'BANANA_BSC', + name: 'ApeSwapFinance Banana', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0xBA11D00c5f74255f56a5E366F4F77f5A186d7f55', + decimals: 18, + id: 'BAND', + name: 'BandToken', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x24A6A37576377F63f194Caa5F518a60f45b42921', + decimals: 18, + id: 'BANK', + name: 'Float Bank', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'BASECHAIN_ETH', + name: 'Ethereum (Base)', + nativeAsset: 'BASECHAIN_ETH', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'BASECHAIN_ETH_TEST5', + name: 'Base Sepolia', + nativeAsset: 'BASECHAIN_ETH_TEST5', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x0D8775F648430679A709E98d2b0Cb6250d2887EF', + decimals: 18, + id: 'BAT', + name: 'Basic Attn.', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x19D97D8fA813EE2f51aD4B4e04EA08bAf4DFfC28', + decimals: 18, + id: 'BBADGER', + name: 'Badger Sett Badger', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xF4b5470523cCD314C6B9dA041076e7D79E0Df267', + decimals: 18, + id: 'BBANK', + name: 'BlockBank', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x9BE89D2a4cd102D8Fecc6BF9dA793be995C22541', + decimals: 8, + id: 'BBTC', + name: 'Binance Wrapped BTC', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x1f41E42D0a9e3c0Dd3BA15B527342783B43200A9', + decimals: 0, + id: 'BCAP', + name: 'BCAP', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 8, + id: 'BCH', + name: 'Bitcoin Cash', + nativeAsset: 'BCH', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x8fF795a6F4D97E7887C79beA79aba5cc76444aDf', + decimals: 18, + id: 'BCH_BSC', + name: 'Binance-Peg Bitcoin Cash Token (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '', + decimals: 8, + id: 'BCH_TEST', + name: 'Bitcoin Cash Test', + nativeAsset: 'BCH_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x72e203a17adD19A3099137c9d7015fD3e2b7DBa9', + decimals: 18, + id: 'BCP', + name: 'BlockchainPoland', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x1c4481750daa5Ff521A2a7490d9981eD46465Dbd', + decimals: 18, + id: 'BCPT', + name: 'BlackMason', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x8D717AB5eaC1016b64C2A7fD04720Fd2D27D1B86', + decimals: 18, + id: 'BCVT', + name: 'BitcoinVend', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x7e7E112A68d8D2E221E11047a72fFC1065c38e1a', + decimals: 18, + id: 'BDIGG', + name: 'Badger Sett Digg', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x7884F51dC1410387371ce61747CB6264E1dAeE0B', + decimals: 10, + id: 'BDOT', + name: 'Binance Wrapped DOT', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x593114f03A0A575aece9ED675e52Ed68D2172B8c', + decimals: 18, + id: 'BDP', + name: 'BidiPass', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xDC59ac4FeFa32293A95889Dc396682858d52e5Db', + decimals: 6, + id: 'BEAN', + name: 'Beanstalk', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xA91ac63D040dEB1b7A5E4d4134aD23eb0ba07e14', + decimals: 18, + id: 'BEL', + name: 'Bella', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xE0e514c71282b6f4e823703a39374Cf58dc3eA4f', + decimals: 18, + id: 'BELT_BSC', + name: 'BELT Token (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '', + decimals: 18, + id: 'BERACHAIN_ARTIO_TEST', + name: 'Berachain Artio Test', + nativeAsset: 'BERACHAIN_ARTIO_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x1B073382E63411E3BcfFE90aC1B9A43feFa1Ec6F', + decimals: 8, + id: 'BEST', + name: 'Bitpanda Ecosystem Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xBe1a001FE942f96Eea22bA08783140B9Dcc09D28', + decimals: 18, + id: 'BETA', + name: 'Beta Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x250632378E573c6Be1AC2f97Fcdf00515d0Aa91B', + decimals: 18, + id: 'BETH_BSC', + name: 'Binance Beacon ETH (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0x14C926F2290044B647e1Bf2072e67B495eff1905', + decimals: 18, + id: 'BETHER', + name: 'Bethereum', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x01fF50f8b7f74E4f00580d9596cd3D0d6d6E326f', + decimals: 18, + id: 'BFT', + name: 'Bnk to the future', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xF17e65822b568B3903685a7c9F496CF7656Cc6C2', + decimals: 18, + id: 'BICO', + name: 'Biconomy Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x25e1474170c4c0aA64fa98123bdc8dB49D7802fa', + decimals: 18, + id: 'BID', + name: 'Bidao', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x6e8908cfa881C9f6f2C64d3436E7b80b1bf0093F', + decimals: 18, + id: 'BIST', + name: 'Bistroo Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x1A4b46696b2bB4794Eb3D4c26f1c55F9170fa4C5', + decimals: 18, + id: 'BIT', + name: 'BitDAO', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xb3104b4B9Da82025E8b9F8Fb28b3553ce2f67069', + decimals: 18, + id: 'BIX', + name: 'Bibox Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xCa1bedEd9720289eb20D9449DE872d28ADa27476', + decimals: 10, + id: 'BK', + name: 'Blockkoin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x3AcF9680b5d57994B6570C0eA97bc4d8b25E3F5b', + decimals: 10, + id: 'BK_OLD', + name: 'Blockkoin (OLD)', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x45245bc59219eeaAF6cD3f382e078A461FF9De7B', + decimals: 18, + id: 'BKX', + name: 'BANKEX', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'BLAST', + name: 'Blast Ethereum', + nativeAsset: 'BLAST', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 2, + id: 'BLINC_CAD', + name: 'Blinc CAD', + nativeAsset: 'BLINC_CAD', + type: 'FIAT' + }, + { + contractAddress: '', + decimals: 2, + id: 'BLINC_CHF', + name: 'Blinc CHF', + nativeAsset: 'BLINC_CHF', + type: 'FIAT' + }, + { + contractAddress: '', + decimals: 2, + id: 'BLINC_EUR', + name: 'Blinc EUR', + nativeAsset: 'BLINC_EUR', + type: 'FIAT' + }, + { + contractAddress: '', + decimals: 2, + id: 'BLINC_GBP', + name: 'Blinc GBP', + nativeAsset: 'BLINC_GBP', + type: 'FIAT' + }, + { + contractAddress: '', + decimals: 2, + id: 'BLINC_JPY', + name: 'Blinc JPY', + nativeAsset: 'BLINC_JPY', + type: 'FIAT' + }, + { + contractAddress: '', + decimals: 2, + id: 'BLINC_SGD', + name: 'Blinc SGD', + nativeAsset: 'BLINC_SGD', + type: 'FIAT' + }, + { + contractAddress: '', + decimals: 2, + id: 'BLINC_TEST_CAD', + name: 'Blinc CAD Test', + nativeAsset: 'BLINC_TEST_CAD', + type: 'FIAT' + }, + { + contractAddress: '', + decimals: 2, + id: 'BLINC_TEST_CHF', + name: 'Blinc CHF Test', + nativeAsset: 'BLINC_TEST_CHF', + type: 'FIAT' + }, + { + contractAddress: '', + decimals: 2, + id: 'BLINC_TEST_EUR', + name: 'Blinc EUR Test', + nativeAsset: 'BLINC_TEST_EUR', + type: 'FIAT' + }, + { + contractAddress: '', + decimals: 2, + id: 'BLINC_TEST_GBP', + name: 'Blinc GBP Test', + nativeAsset: 'BLINC_TEST_GBP', + type: 'FIAT' + }, + { + contractAddress: '', + decimals: 2, + id: 'BLINC_TEST_JPY', + name: 'Blinc JPY Test', + nativeAsset: 'BLINC_TEST_JPY', + type: 'FIAT' + }, + { + contractAddress: '', + decimals: 2, + id: 'BLINC_TEST_SGD', + name: 'Blinc SGD Test', + nativeAsset: 'BLINC_TEST_SGD', + type: 'FIAT' + }, + { + contractAddress: '0x20d37E84Ad91436B0F4380D29c2bc192AA05920B', + decimals: 8, + id: 'BLL', + name: 'BELLCOIN', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 8, + id: 'BLT_SOL', + issuerAddress: 'BLT1noyNr3GttckEVrtcfC6oyK6yV1DpPgSyXbncMwef', + name: 'Blocto Token', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x5732046A883704404F284Ce41FfADd5b007FD668', + decimals: 18, + id: 'BLZ', + name: 'Bluzelle', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x725C263e32c72dDC3A19bEa12C5a0479a81eE688', + decimals: 18, + id: 'BMI', + name: 'Bridge Mutual', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'BNB_BSC', + name: 'BNB Smart Chain', + nativeAsset: 'BNB_BSC', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xB8c77482e45F1F44dE1745F52C74426C631bDD52', + decimals: 18, + id: 'BNB_ERC20', + name: 'BNB (Ethereum)', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'BNB_TEST', + name: 'BNB Smart Chain Testnet', + nativeAsset: 'BNB_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C', + decimals: 18, + id: 'BNT', + name: 'Bancor', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xDF347911910b6c9A4286bA8E2EE5ea4a39eB2134', + decimals: 18, + id: 'BOB', + name: 'BOB Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x0391D2021f89DC339F60Fff84546EA23E337750f', + decimals: 18, + id: 'BOND', + name: 'BarnBridge Governance Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xD2dDa223b2617cB616c1580db421e4cFAe6a8a85', + decimals: 18, + id: 'BONDLY', + name: 'Bondly Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x9813037ee2218799597d83D4a5B6F3b6778218d9', + decimals: 18, + id: 'BONE', + name: 'BONE SHIBASWAP', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 5, + id: 'BONK_SOL', + issuerAddress: 'DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263', + name: 'Bonk_Solana_', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x841FAD6EAe12c286d1Fd18d1d525DFfA75C7EFFE', + decimals: 18, + id: 'BOO_FANTOM', + name: 'SpookyToken (Fantom)', + nativeAsset: 'FTM_FANTOM', + type: 'ERC20' + }, + { + contractAddress: '0x3c9d6c1C73b31c837832c72E04D3152f051fc1A9', + decimals: 18, + id: 'BOR', + name: 'BoringDAO', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xC477D038d5420C6A9e0b031712f61c5120090de9', + decimals: 18, + id: 'BOSON', + name: 'Boson Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x68B55024aD32523c95aaA0A235e1d78E9191168e', + decimals: 8, + id: 'BOSSC', + name: 'BOSSC', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x5bEaBAEBB3146685Dd74176f68a0721F91297D37', + decimals: 18, + id: 'BOT', + name: 'Bounce Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 8, + id: 'BOT_SOL', + issuerAddress: 'AkhdZGVbJXPuQZ53u2LrimCjkRP6ZyxG1SoM85T98eE1', + name: 'Starbots Token', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x780116D91E5592E58a3b3c76A351571b39abCEc6', + decimals: 15, + id: 'BOXX', + name: 'BOXX Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x440CD83C160De5C96Ddb20246815eA44C7aBBCa8', + decimals: 18, + id: 'BPRO_RBTC', + name: 'BitPro (RSK)', + nativeAsset: 'RBTC', + type: 'ERC20' + }, + { + contractAddress: '0xe969991CE475bCF817e01E1AAd4687dA7e1d6F83', + decimals: 18, + id: 'BPT_ETHUSDC_7', + name: 'Balancer: ETH/USDC 50/50 #7', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x24D97EEd6E171E70c82bc60aFd37c7d1E549A0AD', + decimals: 18, + id: 'BPT_LPTETH_2', + name: 'Balancer: LPT/ETH 50/50 #2', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x558EC3152e2eb2174905cd19AeA4e34A23DE9aD6', + decimals: 18, + id: 'BRD', + name: 'Bread', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x420412E765BFa6d85aaaC94b4f7b708C89be2e2B', + decimals: 4, + id: 'BRZ', + name: 'BRZ Token (ETH)', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 8, + id: 'BSV', + name: 'Bitcoin SV', + nativeAsset: 'BSV', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 8, + id: 'BSV_TEST', + name: 'Bitcoin SV Test', + nativeAsset: 'BSV_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 8, + id: 'BTC', + name: 'Bitcoin', + nativeAsset: 'BTC', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x321162Cd933E2Be498Cd2267a90534A804051b11', + decimals: 8, + id: 'BTC_FTM', + name: 'Bitcoin (Fantom)', + nativeAsset: 'FTM_FANTOM', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 8, + id: 'BTC_TEST', + name: 'Bitcoin Test', + nativeAsset: 'BTC_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x7130d2A12B9BCbFAe4f2634d864A1Ee1Ce3Ead9c', + decimals: 18, + id: 'BTCB_BSC', + name: 'Binance-Peg BTCB Token (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0x78650B139471520656b9E7aA7A5e9276814a38e9', + decimals: 17, + id: 'BTCST_BSC', + name: 'StandardBTCHashrateToken (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0x799ebfABE77a6E34311eeEe9825190B9ECe32824', + decimals: 18, + id: 'BTRST', + name: 'BTRST token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x8595F9dA7b868b1822194fAEd312235E43007b49', + decimals: 18, + id: 'BTT_BSC', + name: 'BitTorrent (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0x7712c34205737192402172409a8F7ccef8aA2AEc', + decimals: 6, + id: 'BUIDL_ETH_X3N7', + name: 'BlackRock USD Institutional Digital Liquidity Fund', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xAe9269f27437f0fcBC232d39Ec814844a51d6b8f', + decimals: 18, + id: 'BURGER_BSC', + name: 'Burger Swap (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0x33f391F4c4fE802b70B77AE37670037A92114A7c', + decimals: 18, + id: 'BURP', + name: 'Burp', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x4Fabb145d64652a948d72533023f6E7A623C7C53', + decimals: 18, + id: 'BUSD', + name: 'Binance USD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56', + decimals: 18, + id: 'BUSD_BSC', + name: 'Binance-Peg BUSD (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0xeD24FC36d5Ee211Ea25A80239Fb8C4Cfd80f12Ee', + decimals: 18, + id: 'BUSD_BSC_TEST', + name: 'Binance USD (BSC Test)', + nativeAsset: 'BNB_TEST', + type: 'BEP20' + }, + { + contractAddress: '0x54F9b4B4485543A815c51c412a9E20436A06491d', + decimals: 18, + id: 'BXX', + name: 'Baanx', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x4Bb3205bf648B7F59EF90Dee0F1B62F6116Bc7ca', + decimals: 18, + id: 'BYN', + name: 'Beyond Finance (ERC-20)', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x56d811088235F11C8920698a204A5010a788f4b3', + decimals: 18, + id: 'BZRX', + name: 'bZx Protocol Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x19062190B1925b5b6689D7073fDfC8c2976EF8Cb', + decimals: 16, + id: 'BZZ', + name: 'BZZ', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x26E75307Fc0C021472fEb8F727839531F112f317', + decimals: 18, + id: 'C20', + name: 'Crypto20', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xe65cdB6479BaC1e22340E4E755fAE7E509EcD06c', + decimals: 8, + id: 'CAAVE', + name: 'Compound Aave Token', + nativeAsset: 'ETH', + type: 'COMPOUND' + }, + { + contractAddress: '0x7d4b8Cce0591C9044a22ee543533b72E976E36C3', + decimals: 18, + id: 'CAG', + name: 'ChangeBank', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82', + decimals: 18, + id: 'CAKE_BSC', + name: 'PancakeSwap Token (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '', + decimals: 18, + id: 'CAMINO', + name: 'Camino', + nativeAsset: 'CAMINO', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'CAMINO_COLUMBUS_TEST', + name: 'Camino Columbus Test', + nativeAsset: 'CAMINO_COLUMBUS_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'CANTO', + name: 'Canto', + nativeAsset: 'CANTO', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'CANTO_TEST', + name: 'Canto Test', + nativeAsset: 'CANTO_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x03Be5C903c727Ee2C8C4e9bc0AcC860Cca4715e2', + decimals: 18, + id: 'CAPS', + name: 'Capsule Coin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x6894CDe390a3f51155ea41Ed24a33A4827d3063D', + decimals: 18, + id: 'CAT_B71VABWJ_BY1A', + name: 'Simons Cat', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '', + decimals: 6, + id: 'CAVE_SOL', + issuerAddress: '4SZjjNABoqhbd4hnapbvoEPEqT8mnNkfbEoAwALf1V8t', + name: 'Crypto Cavemen (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x6C8c6b02E7b2BE14d4fA6022Dfd6d75921D90E4E', + decimals: 8, + id: 'CBAT', + name: 'cBAT', + nativeAsset: 'ETH', + type: 'COMPOUND' + }, + { + contractAddress: '0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf', + decimals: 8, + id: 'CBBTC_B6QT1TZK_9XC8', + name: 'Coinbase Wrapped BTC', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf', + decimals: 8, + id: 'CBBTC_B609K9QB_0N6V', + name: 'Coinbase Wrapped BTC', + nativeAsset: 'BASECHAIN_ETH', + type: 'ERC20' + }, + { + contractAddress: '0x0E2b41eA957624A314108cc4E33703e9d78f4b3C', + decimals: 18, + id: 'CBD_BSC', + name: 'Greenheart (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0xD85a6Ae55a7f33B0ee113C234d2EE308EdeAF7fD', + decimals: 18, + id: 'CBK', + name: 'Cobak Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xA6FA6531acDf1f9F96EDdD66a0F9481E35c2e42A', + decimals: 6, + id: 'CBRL', + name: 'Crypto BRL', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x70e36f6BF80a52b3B46b3aF8e106CC0ed743E8e4', + decimals: 8, + id: 'CCOMP', + name: 'Compound Collateral', + nativeAsset: 'ETH', + type: 'COMPOUND' + }, + { + contractAddress: '0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643', + decimals: 8, + id: 'CDAI', + name: 'cDAI', + nativeAsset: 'ETH', + type: 'COMPOUND' + }, + { + contractAddress: '0x177d39AC676ED1C67A2b268AD7F1E58826E5B0af', + decimals: 18, + id: 'CDT', + name: 'Blox', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xaaAEBE6Fe48E54f431b0C390CfaF0b017d09D42d', + decimals: 4, + id: 'CEL', + name: 'Celsius', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'CELESTIA', + name: 'Celestia', + nativeAsset: 'CELESTIA', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 6, + id: 'CELESTIA_TEST', + name: 'Celestia Test', + nativeAsset: 'CELESTIA_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xA2F26a3AF6a2C5Bc1d64e176F3BB42BF6e9c6c61', + decimals: 18, + id: 'CELLDOGE_CELO', + name: 'Cell Doge (Celo)', + nativeAsset: 'CELO', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'CELO', + name: 'Celo', + nativeAsset: 'CELO', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'CELO_ALF', + name: 'Celo Alfajores', + nativeAsset: 'CELO_ALF', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'CELO_BAK', + name: 'Celo Baklava', + nativeAsset: 'CELO_BAK', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x4F9254C83EB525f9FCf346490bbb3ed28a81C667', + decimals: 18, + id: 'CELR', + name: 'CelerToken', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x1122B6a0E00DCe0563082b6e2953f3A943855c1F', + decimals: 18, + id: 'CENNZ', + name: 'Centrality Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x2dA719DB753dFA10a62E140f436E1d67F2ddB0d6', + decimals: 10, + id: 'CERE_ERC20', + name: 'CERE Network', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x4Ddc2D193948926D02f9B1fE9e1daa0718270ED5', + decimals: 8, + id: 'CETH', + name: 'cEther', + nativeAsset: 'ETH', + type: 'COMPOUND' + }, + { + contractAddress: '0xD8763CBa276a3738E6DE85b4b3bF5FDed6D6cA73', + decimals: 18, + id: 'CEUR_CELO', + name: 'Celo Euro', + nativeAsset: 'CELO', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'CFG', + name: 'Centrifuge', + nativeAsset: 'CFG', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x12FEF5e57bF45873Cd9B62E9DBd7BFb99e32D73e', + decimals: 18, + id: 'CFI', + name: 'CFI', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xAdA0A1202462085999652Dc5310a7A9e2BF3eD42', + decimals: 18, + id: 'CGI', + name: 'CoinShares Gold and Cryptoassets Index Lite', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xC4C2614E694cF534D407Ee49F8E44D125E4681c4', + decimals: 18, + id: 'CHAIN', + name: 'Chain Games', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x20de22029ab63cf9A7Cf5fEB2b737Ca1eE4c82A6', + decimals: 18, + id: 'CHESS_BSC', + name: 'Tranchess (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0x0000000000004946c0e9F43F4Dee607b0eF1fA1c', + decimals: 0, + id: 'CHI', + name: 'Chi Gastoken by 1inch', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 9, + id: 'CHICKS_SOL', + issuerAddress: 'cxxShYRVcepDudXhe7U62QHvw8uBJoKFifmzggGKVC2', + name: 'SolChicks', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0xDF98E4306efF7E3d839f9Ca54C56959E578CEa04', + decimals: 18, + id: 'CHLI', + name: 'Chilli Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x8A2279d4A90B6fe1C4B30fa660cC9f926797bAA2', + decimals: 6, + id: 'CHR', + name: 'Chromia', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xf9CeC8d50f6c8ad3Fb6dcCEC577e05aA32B224FE', + decimals: 6, + id: 'CHR_BSC', + name: 'Chroma (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0xba9d4199faB4f26eFE3551D490E3821486f135Ba', + decimals: 8, + id: 'CHSB', + name: 'SwissBorg Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x159dC1C54D409BD694bC1e756d6e17a02D6BF167', + decimals: 7, + id: 'CHT', + name: 'CHATTY', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x3506424F91fD33084466F402d5D97f05F8e3b4AF', + decimals: 18, + id: 'CHZ', + name: 'Chiliz (ETH)', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'CHZ_$CHZ', + name: 'Chiliz ($CHZ)', + nativeAsset: 'CHZ_$CHZ', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'CHZ_CHZ2', + name: 'Chiliz', + nativeAsset: 'CHZ_CHZ2', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'CHZ_CHZ2_TEST', + name: 'Chiliz Test', + nativeAsset: 'CHZ_CHZ2_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xFAce851a4921ce59e912d19329929CE6da6EB0c7', + decimals: 8, + id: 'CLINK', + name: 'Compound ChainLink Token', + nativeAsset: 'ETH', + type: 'COMPOUND' + }, + { + contractAddress: '0x2001f2A0Cf801EcFda622f6C28fb6E10d803D969', + decimals: 8, + id: 'CLT', + name: 'CoinLoan', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x80C62FE4487E1351b47Ba49809EBD60ED085bf52', + decimals: 18, + id: 'CLV', + name: 'Clover', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x47bc01597798DCD7506DCCA36ac4302fc93a8cFb', + decimals: 8, + id: 'CMCT', + name: 'Crowd Machine Compute Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x95b4eF2869eBD94BEb4eEE400a99824BF5DC325b', + decimals: 8, + id: 'CMKR', + name: 'Compound Maker', + nativeAsset: 'ETH', + type: 'COMPOUND' + }, + { + contractAddress: '0xd4c435F5B09F855C3317c8524Cb1F586E42795fa', + decimals: 18, + id: 'CND', + name: 'Cindicator', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x6E109E9dD7Fa1a58BC3eff667e8e41fC3cc07AEF', + decimals: 6, + id: 'CNHT_ERC20', + name: 'Tether CNH (ERC20)', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xc00e94Cb662C3520282E6f5717214004A7f26888', + decimals: 18, + id: 'COMP', + name: 'Compound Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x52CE071Bd9b1C4B00A0b92D298c512478CaD67e8', + decimals: 18, + id: 'COMP_BSC', + name: 'Binance-Peg Compound Coin (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0xc834Fa996fA3BeC7aAD3693af486ae53D8aA8B50', + decimals: 18, + id: 'CONV_ETH', + name: 'Convergence', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x62359Ed7505Efc61FF1D56fEF82158CcaffA23D7', + decimals: 18, + id: 'CORE', + name: 'cVault.finance', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'CORE_COREDAO', + name: 'Core DAO', + nativeAsset: 'CORE_COREDAO', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'CORE_COREDAO_TEST', + name: 'Core DAO Test', + nativeAsset: 'CORE_COREDAO_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x589891a198195061Cb8ad1a75357A3b7DbaDD7Bc', + decimals: 18, + id: 'COS', + name: 'Contentos', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 2, + id: 'COS_TEST_USD', + name: 'Cross River USD Test', + nativeAsset: 'COS_TEST_USD', + type: 'FIAT' + }, + { + contractAddress: '', + decimals: 2, + id: 'COS_USD', + name: 'Cross River USD', + nativeAsset: 'COS_USD', + type: 'FIAT' + }, + { + contractAddress: '0xDDB3422497E61e13543BeA06989C0789117555c5', + decimals: 18, + id: 'COTI', + name: 'COTI Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xB37a769B37224449d92AAc57dE379E1267Cd3B00', + decimals: 18, + id: 'COVA', + name: 'Covalent', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x4688a8b1F292FDaB17E9a90c8Bc379dC1DBd8713', + decimals: 18, + id: 'COVER', + name: 'Cover Protocol', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x66761Fa41377003622aEE3c7675Fc7b5c1C2FaC5', + decimals: 18, + id: 'CPOOL', + name: 'Clearpool', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xD417144312DbF50465b1C641d016962017Ef6240', + decimals: 18, + id: 'CQT', + name: 'Covalent Query Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x115eC79F1de567eC68B7AE7eDA501b406626478e', + decimals: 18, + id: 'CRE', + name: 'CarryToken', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x2ba592F78dB6436527729929AAf6c908497cB200', + decimals: 18, + id: 'CREAM', + name: 'Cream', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x158079Ee67Fce2f58472A96584A73C7Ab9AC95c1', + decimals: 8, + id: 'CREP', + name: 'cAugur', + nativeAsset: 'ETH', + type: 'COMPOUND' + }, + { + contractAddress: '0xA0b73E1Ff0B80914AB6fe0444E65848C4C34450b', + decimals: 8, + id: 'CRO', + name: 'Crypto.com', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 9, + id: 'CRP_SOL', + issuerAddress: 'DubwWZNWiNGMMeeQHPnMATNj77YZPZSAz2WVR5WjLJqz', + name: 'CropperFinance (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x08389495D7456E1951ddF7c3a1314A4bfb646d8B', + decimals: 18, + id: 'CRPT', + name: 'Crypterium', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x80A7E048F37A50500351C204Cb407766fA3baE7f', + decimals: 18, + id: 'CRPT_OLD', + name: 'Crypterium (Old)', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x32a7C02e79c4ea1008dD6564b35F131428673c41', + decimals: 18, + id: 'CRU', + name: 'CRUST', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x44fbeBd2F576670a6C33f6Fc0B00aA8c5753b322', + decimals: 8, + id: 'CRUSDC', + name: 'Cream USD Coin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xD533a949740bb3306d119CC777fa900bA034cd52', + decimals: 18, + id: 'CRV', + name: 'Curve DAO Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xF5DCe57282A584D2746FaF1593d3121Fcac444dC', + decimals: 8, + id: 'CSAI', + name: 'cSAI', + nativeAsset: 'ETH', + type: 'COMPOUND' + }, + { + contractAddress: '', + decimals: 9, + id: 'CSOL_SOL', + issuerAddress: '5h6ssFpeDeRbzsEHDbTQNH7nVGgsKrZydxdSTnLm6QdV', + name: 'Solend SOL (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0xA6446D655a0c34bC4F05042EE88170D056CBAf45', + decimals: 18, + id: 'CSP', + name: 'Caspian', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x4B0181102A0112A2ef11AbEE5563bb4a3176c9d7', + decimals: 8, + id: 'CSUSHI', + name: 'Compound Sushi Token', + nativeAsset: 'ETH', + type: 'COMPOUND' + }, + { + contractAddress: '0xa3EE21C306A700E682AbCdfe9BaA6A08F3820419', + decimals: 18, + id: 'CTC', + name: 'Gluwa Creditcoin Vesting Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x8c18D6a985Ef69744b9d57248a45c0861874f244', + decimals: 18, + id: 'CTI', + name: 'ClinTex', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x96A65609a7B84E8842732DEB08f56C3E21aC6f8a', + decimals: 18, + id: 'CTR', + name: 'Centra', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x491604c0FDF08347Dd1fa4Ee062a822A5DD06B5D', + decimals: 18, + id: 'CTSI', + name: 'Cartesi Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x12392F67bdf24faE0AF363c24aC620a2f67DAd86', + decimals: 8, + id: 'CTUSD', + name: 'Compound TrueUSD', + nativeAsset: 'ETH', + type: 'COMPOUND' + }, + { + contractAddress: '0x321C2fE4446C7c963dc41Dd58879AF648838f98D', + decimals: 18, + id: 'CTX', + name: 'Cryptex', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xDf801468a808a32656D2eD2D2d80B72A129739f4', + decimals: 8, + id: 'CUBE', + name: 'Somnium Space Cubes', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x817bbDbC3e8A1204f3691d14bB44992841e3dB35', + decimals: 18, + id: 'CUDOS', + name: 'CudosToken', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x35A18000230DA775CAc24873d00Ff85BccdeD550', + decimals: 8, + id: 'CUNI', + name: 'Compound Uniswap', + nativeAsset: 'ETH', + type: 'COMPOUND' + }, + { + contractAddress: '0x1410d4eC3D276C0eBbf16ccBE88A4383aE734eD0', + decimals: 18, + id: 'CUSD', + name: 'CarbonUSD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x765DE816845861e75A25fCA122bb6898B8B1282a', + decimals: 18, + id: 'CUSD_CELO', + name: 'Celo Dollar', + nativeAsset: 'CELO', + type: 'ERC20' + }, + { + contractAddress: '0x39AA39c021dfbaE8faC545936693aC917d5E7563', + decimals: 8, + id: 'CUSDC', + name: 'Compound USD Coin', + nativeAsset: 'ETH', + type: 'COMPOUND' + }, + { + contractAddress: '0xf650C3d88D12dB855b8bf7D11Be6C55A4e07dCC9', + decimals: 8, + id: 'CUSDT_ERC20', + name: 'cTether', + nativeAsset: 'ETH', + type: 'COMPOUND' + }, + { + contractAddress: '0x41e5560054824eA6B0732E656E3Ad64E20e94E45', + decimals: 8, + id: 'CVC', + name: 'Civic', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B', + decimals: 18, + id: 'CVX', + name: 'CVX', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x62B9c7356A2Dc64a1969e19C23e4f579F9810Aa7', + decimals: 18, + id: 'CVXCRV', + name: 'cvxCRV', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 9, + id: 'CWAR_SOL', + issuerAddress: 'HfYFjMKNZygfMC8LsQ8LtpPsPxEJoXJx4M6tqi75Hajo', + name: 'Cryowar Token (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0xC11b1268C1A384e55C48c2391d8d480264A3A7F4', + decimals: 8, + id: 'CWBTC', + name: 'cWBTC', + nativeAsset: 'ETH', + type: 'COMPOUND' + }, + { + contractAddress: '0xaC0104Cca91D167873B8601d2e71EB3D4D8c33e0', + decimals: 18, + id: 'CWS', + name: 'Crowns', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x7ABc8A5768E6bE61A6c693a6e4EAcb5B60602C4D', + decimals: 18, + id: 'CXT_B6QT1TZK_3BEN', + name: 'Covalent X Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x80a2AE356fc9ef4305676f7a3E2Ed04e12C33946', + decimals: 8, + id: 'CYFI', + name: 'Compound yearn.finance', + nativeAsset: 'ETH', + type: 'COMPOUND' + }, + { + contractAddress: '', + decimals: 6, + id: 'CYS_SOL', + issuerAddress: 'BRLsMczKuaR5w9vSubF4j8HwEGGprVAyyVgS4EX7DKEg', + name: 'Cyclos', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0xB3319f5D18Bc0D84dD1b4825Dcde5d5f7266d407', + decimals: 8, + id: 'CZRX', + name: 'Compound 0x', + nativeAsset: 'ETH', + type: 'COMPOUND' + }, + { + contractAddress: '0xA31108E5BAB5494560Db34c95492658AF239357C', + decimals: 18, + id: 'DACS', + name: 'DACSEE', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x5B322514FF727253292637D9054301600c2C81e8', + decimals: 9, + id: 'DAD', + name: 'DAD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xFc979087305A826c2B2a0056cFAbA50aad3E6439', + decimals: 18, + id: 'DAFI', + name: 'DAFI Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x6B175474E89094C44Da98b954EedeAC495271d0F', + decimals: 18, + id: 'DAI', + name: 'Dai', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3', + decimals: 18, + id: 'DAI_BSC', + name: 'Dai BSC Token', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0xd586E7F844cEa2F87f50152665BCbc2C279D8d70', + decimals: 18, + id: 'DAI_E', + name: 'Dai Stablecoin (Avalanche)', + nativeAsset: 'AVAX', + type: 'ERC20' + }, + { + contractAddress: '0x8D11eC38a3EB5E956B052f67Da8Bdc9bef8Abf3E', + decimals: 18, + id: 'DAI_FANTOM', + name: 'Dai Stablecoin (Fantom)', + nativeAsset: 'FTM_FANTOM', + type: 'ERC20' + }, + { + contractAddress: '0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063', + decimals: 18, + id: 'DAI_POLYGON', + name: '(PoS) Dai Stablecoin (Polygon)', + nativeAsset: 'MATIC_POLYGON', + type: 'ERC20' + }, + { + contractAddress: '0x0f51bb10119727a7e5eA3538074fb341F56B09Ad', + decimals: 18, + id: 'DAO', + name: 'DAO Maker', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 8, + id: 'DASH', + name: 'Dash', + nativeAsset: 'DASH', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 8, + id: 'DASH_TEST', + name: 'Dash Test', + nativeAsset: 'DASH_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x0Cf0Ee63788A0849fE5297F3407f701E122cC023', + decimals: 18, + id: 'DATA', + name: 'Streamr Data', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x8f693ca8D21b157107184d29D398A8D082b38b76', + decimals: 18, + id: 'DATA_ERC20', + name: 'Streamr', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x0B4BdC478791897274652DC15eF5C135cae61E60', + decimals: 18, + id: 'DAX', + name: 'DAEX Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'DCFG_TEST', + name: 'Centrifuge Test', + nativeAsset: 'DCFG_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x88EF27e69108B2633F8E1C184CC37940A075cC02', + decimals: 18, + id: 'DEGO', + name: 'dego.finance', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x3597bfD533a99c9aa083587B074434E61Eb0A258', + decimals: 8, + id: 'DENT', + name: 'DENT', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x1A3496C18d558bd9C6C8f609E1B129f67AB08163', + decimals: 18, + id: 'DEP', + name: 'DEAPCOIN', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xaB93dF617F51E1E415b5b4f8111f122d6b48e55C', + decimals: 18, + id: 'DETO', + name: 'Delta Exchange Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xfB7B4564402E5500dB5bB6d63Ae671302777C75a', + decimals: 18, + id: 'DEXT', + name: 'DEXTools', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x431ad2ff6a9C365805eBaD47Ee021148d6f7DBe0', + decimals: 18, + id: 'DF', + name: 'dForce', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x20c36f062a31865bED8a5B1e512D9a1A20AA333A', + decimals: 18, + id: 'DFD', + name: 'DefiDollar DAO', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x7CCC863EcE2E15bC45ac0565D410da7A3340aD98', + decimals: 18, + id: 'DFY', + name: 'Dotify Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x9695e0114e12C0d3A3636fAb5A18e6b737529023', + decimals: 18, + id: 'DFYN', + name: 'DFYN Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xC168E40227E4ebD8C1caE80F7a55a4F0e6D66C97', + decimals: 18, + id: 'DFYN_POLYGON', + name: 'DFYN Token (Polygon)', + nativeAsset: 'MATIC_POLYGON', + type: 'ERC20' + }, + { + contractAddress: '0x1C83501478f1320977047008496DACBD60Bb15ef', + decimals: 18, + id: 'DGTX', + name: 'Digitex', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xc666081073E8DfF8D3d1c2292A29aE1A2153eC09', + decimals: 18, + id: 'DGTX_ETH', + name: 'DigitexFutures', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x4f3AfEC4E5a3F2A6a1A411DEF7D7dFe50eE057bF', + decimals: 9, + id: 'DGX', + name: 'Digix Gold Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xca1207647Ff814039530D7d35df0e1Dd2e91Fa84', + decimals: 18, + id: 'DHT', + name: 'dHedge DAO', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x84cA8bc7997272c7CfB4D0Cd3D55cd942B3c9419', + decimals: 18, + id: 'DIA', + name: 'DIAToken', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xefA64D3d5431dBcE85eBCb87e51a5625243d1A55', + decimals: 5, + id: 'DIFX', + name: 'DigitalFinancialExch', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x798D1bE841a82a273720CE31c822C61a67a601C3', + decimals: 9, + id: 'DIGG', + name: 'Digg', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xAa9654BECca45B5BDFA5ac646c939C62b527D394', + decimals: 18, + id: 'DINO_POLYGON', + name: 'DinoSwap (Polygon)', + nativeAsset: 'MATIC_POLYGON', + type: 'ERC20' + }, + { + contractAddress: '0xc1411567d2670e24d9C4DaAa7CdA95686e1250AA', + decimals: 18, + id: 'DLLR_RSK_OYHI', + name: 'Sovryn Dollar', + nativeAsset: 'RBTC', + type: 'ERC20' + }, + { + contractAddress: '0x07e3c70653548B04f0A75970C1F81B4CBbFB606f', + decimals: 18, + id: 'DLT', + name: 'Agrello', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x0000000DE40dfa9B17854cBC7869D80f9F98D823', + decimals: 18, + id: 'DLTA', + name: 'delta.theta', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xEd91879919B71bB6905f23af0A68d231EcF87b14', + decimals: 18, + id: 'DMG', + name: 'DMM: Governance', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x82b0E50478eeaFde392D45D1259Ed1071B6fDa81', + decimals: 18, + id: 'DNA', + name: 'DNA', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x0AbdAce70D3790235af448C88547603b945604ea', + decimals: 18, + id: 'DNT', + name: 'district0x', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xe700691dA7b9851F2F35f8b8182c69c53CcaD9Db', + decimals: 18, + id: 'DOC_RBTC', + name: 'Dollar on Chain (RSK)', + nativeAsset: 'RBTC', + type: 'ERC20' + }, + { + contractAddress: '0xE5Dada80Aa6477e85d09747f2842f7993D0Df71C', + decimals: 18, + id: 'DOCK', + name: 'Dock', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x43Dfc4159D86F3A37A5A4B3D4580b888ad7d4DDd', + decimals: 18, + id: 'DODO', + name: 'DODO bird', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x67ee3Cb086F8a16f34beE3ca72FAD36F7Db929e2', + decimals: 18, + id: 'DODO_BSC', + name: 'DODO bird (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '', + decimals: 8, + id: 'DOGE', + name: 'Doge Coin', + nativeAsset: 'DOGE', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xbA2aE424d960c26247Dd6c32edC70B295c744C43', + decimals: 8, + id: 'DOGE_BSC', + name: 'Binance-Peg Dogecoin (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '', + decimals: 8, + id: 'DOGE_TEST', + name: 'Doge Coin Test', + nativeAsset: 'DOGE_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 9, + id: 'DOGS_TON', + issuerAddress: 'EQCvxJy4eG8hyHBFsZ7eePxrRsUQSFE_jpptRAYBmcG_DOGS', + name: 'Dogs (Ton)', + nativeAsset: 'TON', + type: 'TON_ASSET' + }, + { + contractAddress: '0xa2b5C6d877Ae7eb964E5E7c79F721D1c0085Ec0F', + decimals: 18, + id: 'DOPEX', + name: 'Dopex Governance Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 10, + id: 'DOT', + name: 'Polkadot', + nativeAsset: 'DOT', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x7083609fCE4d1d8Dc0C979AAb8c869Ea2C873402', + decimals: 18, + id: 'DOT_BSC', + name: 'Binance-Peg Polkadot (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0x1494CA1F11D487c2bBe4543E90080AeBa4BA3C2b', + decimals: 18, + id: 'DPI', + name: 'DefiPulse Index', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x9d561d63375672ABd02119b9Bc4FB90EB9E307Ca', + decimals: 18, + id: 'DRCT_ERC20', + name: 'Ally Direct Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x9400Aa8eb5126d20CDE45C7822836BFB70F19878', + decimals: 18, + id: 'DRF_BSC', + name: 'DRIFE', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0x814F67fA286f7572B041D041b1D99b432c9155Ee', + decimals: 8, + id: 'DRG', + name: 'Dragon Coins', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xBD2F0Cd039E0BFcf88901C98c0bFAc5ab27566e3', + decimals: 18, + id: 'DSD', + name: 'Dynamic Set Dollar', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'DSETH_DEV', + name: 'dSETH (Dev)', + nativeAsset: 'DSETH_DEV', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x940a2dB1B7008B6C776d4faaCa729d6d4A4AA551', + decimals: 18, + id: 'DUSK', + name: 'Dusk Network', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'DV4TNT_TEST', + name: 'DYDX Test', + nativeAsset: 'DV4TNT_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xDDdddd4301A082e62E84e43F474f044423921918', + decimals: 18, + id: 'DVF', + name: 'DeversiFi Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x10633216E7E8281e33c86F02Bf8e565a635D9770', + decimals: 18, + id: 'DVI', + name: 'Dvision', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xa1d65E8fB6e87b60FECCBc582F7f97804B725521', + decimals: 18, + id: 'DXD', + name: 'DXdao', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'DXL_SOL', + issuerAddress: 'GsNzxJfFn6zQdJGeYsupJWzUAm57Ba7335mfhWvFiE9Z', + name: 'Dexlab (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x92D6C1e31e14520e676a687F0a93788B716BEff5', + decimals: 18, + id: 'DYDX', + name: 'dYdX', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'DYDX_DYDX', + name: 'DYDX', + nativeAsset: 'DYDX_DYDX', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 8, + id: 'DYDX_SOL', + issuerAddress: '4Hx6Bj56eGyw8EJrrheM6LBQAvVYRikYCWsALeTrwyRU', + name: 'dYdX (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x900b4449236a7bb26b286601dD14d2bDe7a6aC6c', + decimals: 8, + id: 'EARTH', + name: 'Earth Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x913D8ADf7CE6986a8CbFee5A54725D9Eea4F0729', + decimals: 18, + id: 'EASY', + name: 'EASY', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x9eaD0844ea0e890CD0eC6A01e4b65288E6FB20B3', + decimals: 2, + id: 'EAUD', + name: 'FX-T0 eAUD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x9872E14A43482098c400050D21293778AbA28EDf', + decimals: 2, + id: 'ECAD', + name: 'FX-T0 eCAD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xcEcB588AF34B1573e87ef66f612329d12BD3D902', + decimals: 2, + id: 'ECHF', + name: 'FX-T0 eCHF', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x1559FA1b8F28238FD5D76D9f434ad86FD20D1559', + decimals: 18, + id: 'EDEN', + name: 'Eden', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xc528c28FEC0A90C083328BC45f587eE215760A0F', + decimals: 18, + id: 'EDR', + name: 'Endor', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x847a5c271421d53872C559e37F525A73057eCA5e', + decimals: 2, + id: 'EEUR', + name: 'FX-T0 eEUR', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x656C00e1BcD96f256F224AD9112FF426Ef053733', + decimals: 18, + id: 'EFI', + name: 'Efinity Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x575990152169e1C1a4867E81C6AE662caEf068fd', + decimals: 18, + id: 'EFRONTIERUSD', + name: 'EfrontierUSD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x99445865D67B7F15Be5a7DA5D6461a4cbF7803CD', + decimals: 2, + id: 'EGBP', + name: 'FX-T0 eGBP', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xF29F7F4159AD97DEBDd4b187cA48966555e4A723', + decimals: 0, + id: 'EJPY', + name: 'FX-T0 eJPY', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xbf2179859fc6D5BEE9Bf9158632Dc51678a4100e', + decimals: 18, + id: 'ELF', + name: 'aelf', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x761D38e5ddf6ccf6Cf7c55759d5210750B5D60F3', + decimals: 18, + id: 'ELON_ETH', + name: 'Dogelon', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xd6A5aB46ead26f49b03bBB1F9EB1Ad5c1767974a', + decimals: 18, + id: 'EMON', + name: 'EthermonToken', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x95dAaaB98046846bF4B2853e23cba236fa394A31', + decimals: 8, + id: 'EMONT', + name: 'EtheremonToken', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xbdbC2a5B32F3a5141ACd18C39883066E4daB9774', + decimals: 8, + id: 'EMRX', + name: 'Emirex Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x074699497F924682229f2Beee64aaC6F6e05F5c4', + decimals: 2, + id: 'EMXN', + name: 'FX-T0 eMXN', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x6eCD91444f3570E28608B718c31bF3C111Ea5D8F', + decimals: 18, + id: 'ENDEREDGEUSD', + name: 'EnderEdgeUSD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xf0Ee6b27b759C9893Ce4f094b49ad28fd15A23e4', + decimals: 8, + id: 'ENG', + name: 'Enigma', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xF629cBd94d3791C9250152BD8dfBDF380E2a3B9c', + decimals: 18, + id: 'ENJ', + name: 'Enjin Coin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xC18360217D8F7Ab5e7c516566761Ea12Ce7F9D72', + decimals: 18, + id: 'ENS2', + name: 'Ethereum Name Service', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x9A24B8E8A6D4563c575A707b1275381119298E60', + decimals: 18, + id: 'ENVY', + name: 'EVNY Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x1067756c6d6292651B33ba9e4586f5d2893A08d4', + decimals: 2, + id: 'ENZD', + name: 'FX-T0 eNZD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 4, + id: 'EOS', + name: 'EOS', + nativeAsset: 'EOS', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 4, + id: 'EOS_TEST', + name: 'EOS Test', + nativeAsset: 'EOS_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xDaF88906aC1DE12bA2b1D2f7bfC94E9638Ac40c4', + decimals: 18, + id: 'EPK', + name: 'EpiK Protocol', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xA7f552078dcC247C2684336020c03648500C6d9F', + decimals: 18, + id: 'EPS_BSC', + name: 'Ellipsis (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0x8eCb1cA966b6804B129D3c0F9771e079cbF48EFe', + decimals: 18, + id: 'EPT', + name: 'e-Pocket', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xF9986D445ceD31882377b5D6a5F58EaEa72288c3', + decimals: 18, + id: 'ERD', + name: 'Elrond', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xBBc2AE13b23d715c30720F079fcd9B4a74093505', + decimals: 18, + id: 'ERN', + name: 'EthernityChain Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x92A5B04D0ED5D94D7a193d1d334D3D16996f4E13', + decimals: 18, + id: 'ERT', + name: 'Eristica', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xE4Cfc3259c678Cc4d69D18E90E9A52764D8725ea', + decimals: 2, + id: 'ERUB', + name: 'FX-T0 eRUB', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x36F3FD68E7325a35EB768F1AedaAe9EA0689d723', + decimals: 18, + id: 'ESD', + name: 'Empty Set Dollar', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'ETC', + name: 'Ethereum Classic', + nativeAsset: 'ETC', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'ETC_TEST', + name: 'Ethereum Classic Test', + nativeAsset: 'ETC_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'ETH', + name: 'Ethereum', + nativeAsset: 'ETH', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x2170Ed0880ac9A755fd29B2688956BD959F933F8', + decimals: 18, + id: 'ETH_BSC', + name: 'Binance-Peg Ethereum (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0x74b23882a30290451A17c44f4F05243b6b58C76d', + decimals: 18, + id: 'ETH_FTM', + name: 'Multichain Bridged WETH', + nativeAsset: 'FTM_FANTOM', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 8, + id: 'ETH_SOL', + issuerAddress: '7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs', + name: 'Ether (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'ETH_TEST5', + name: 'Ethereum Test (Sepolia)', + nativeAsset: 'ETH_TEST5', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'ETH_TEST6', + name: 'Ethereum Test (Holesky)', + nativeAsset: 'ETH_TEST6', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'ETH_ZKEVM', + name: 'Ethereum (zkEVM)', + nativeAsset: 'ETH_ZKEVM', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'ETH_ZKEVM_TEST', + name: 'Ethereum (zkEVM Test)', + nativeAsset: 'ETH_ZKEVM_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'ETH_ZKSYNC_ERA', + name: 'Ethereum (zkSync Era)', + nativeAsset: 'ETH_ZKSYNC_ERA', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'ETH_ZKSYNC_ERA_SEPOLIA', + name: 'Ethereum (zkSync Era Sepolia)', + nativeAsset: 'ETH_ZKSYNC_ERA_SEPOLIA', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'ETH_ZKSYNC_ERA_TEST', + name: 'Ethereum (zkSync Era Test)', + nativeAsset: 'ETH_ZKSYNC_ERA_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'ETH-AETH', + name: 'Ethereum (Arbitrum)', + nativeAsset: 'ETH-AETH', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'ETH-AETH_RIN', + name: 'Arbitrum Rinkeby', + nativeAsset: 'ETH-AETH_RIN', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'ETH-AETH_SEPOLIA', + name: 'Arbitrum Sepolia', + nativeAsset: 'ETH-AETH_SEPOLIA', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'ETH-OPT', + name: 'Optimistic Ethereum', + nativeAsset: 'ETH-OPT', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'ETH-OPT_KOV', + name: 'Optimistic Ethereum (Kovan)', + nativeAsset: 'ETH-OPT_KOV', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'ETH-OPT_SEPOLIA', + name: 'Optimistic Ethereum (Sepolia)', + nativeAsset: 'ETH-OPT_SEPOLIA', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'ETHW', + name: 'EthereumPoW', + nativeAsset: 'ETHW', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xdBd4d868854575867b9403e751837c9957A016ab', + decimals: 2, + id: 'ETRY', + name: 'FX-T0 eTRY', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x6aB4A7d75B0A42B6Bc83E852daB9E121F9C610Aa', + decimals: 18, + id: 'EUM', + name: 'Elitium', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 7, + id: 'EURC_XLM', + issuerAddress: 'GDHU6WRG4IEQXM5NZ4BMPKOXHW76MZM4Y2IEMFDVXBSDP6SJY4ITNPP2', + name: 'EURC (Stellar)', + nativeAsset: 'XLM', + type: 'XLM_ASSET' + }, + { + contractAddress: '0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c', + decimals: 6, + id: 'EUROC_ETH_F5NG', + name: 'EURC', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xdB25f211AB05b1c97D595516F45794528a807ad8', + decimals: 2, + id: 'EURS', + name: 'STASIS EURS Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xC581b735A1688071A1746c968e0798D642EDE491', + decimals: 6, + id: 'EURT_ERC20', + name: 'Tether EUR (ERC20)', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xf756b5A7209D905d3897A2efB41e2C94b60d1149', + decimals: 2, + id: 'EUSD', + name: 'FX-T0 eUSD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'EVMOS', + name: 'Evmos', + nativeAsset: 'EVMOS', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x9aF15D7B8776fa296019979E70a5BE53c714A7ec', + decimals: 18, + id: 'EVN', + name: 'Evn Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xf3Db5Fa2C66B7aF3Eb0C0b782510816cbe4813b8', + decimals: 4, + id: 'EVX', + name: 'Everex', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x1E8D772EC5085578bDA258b696453e323296e048', + decimals: 8, + id: 'EXD', + name: 'Escada', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x6468e79A80C0eaB0F9A2B574c8d5bC374Af59414', + decimals: 18, + id: 'EXRD', + name: 'E-RADIX', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x5512014efa6Cd57764Fa743756F7a6Ce3358cC83', + decimals: 18, + id: 'EZ_BSC', + name: 'EASY V2 (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0xED18EA36382838ED0039b3a197EB6BAa4B59BE7F', + decimals: 2, + id: 'EZAR', + name: 'FX-T0 eZAR', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x1D3E6CC37b930977dFF8452cEE7b5db870e71679', + decimals: 18, + id: 'FALCONXUSD', + name: 'FalconXUSD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'FANT_SOL', + issuerAddress: 'FANTafPFBAt93BNJVpdu25pGPmca3RfwdsDsRrT3LX1r', + name: 'Phantasia (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'FASTEX_BAHAMUT', + name: 'Fastex Bahamut', + nativeAsset: 'FASTEX_BAHAMUT', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 8, + id: 'FB_ATHENA_TEST', + name: 'FB Private Test', + nativeAsset: 'FB_ATHENA_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xF4d861575ecC9493420A3f5a14F85B13f0b50EB3', + decimals: 18, + id: 'FCL', + name: 'Fractal Protocol Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x956F47F50A910163D8BF957Cf5846D573E7f87CA', + decimals: 18, + id: 'FEI', + name: 'Fei USD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xaea46A60368A7bD060eec7DF8CBa43b7EF41Ad85', + decimals: 18, + id: 'FET', + name: 'Fetch', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x0D8Ce2A99Bb6e3B7Db580eD848240e4a0F9aE153', + decimals: 18, + id: 'FIL_BSC', + name: 'Binance-Peg Filecoin (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0xef3A930e1FfFFAcd2fc13434aC81bD278B0ecC8d', + decimals: 18, + id: 'FIS', + name: 'StaFi', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x3a3Df212b7AA91Aa0402B9035b098891d276572B', + decimals: 18, + id: 'FISH_POLYGON', + name: 'Polycat Finance (Polygon)', + nativeAsset: 'MATIC_POLYGON', + type: 'ERC20' + }, + { + contractAddress: '0xFcF8eda095e37A41e002E266DaAD7efC1579bc0A', + decimals: 18, + id: 'FLEX', + name: 'FLEX Coin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x98Dd7eC28FB43b3C4c770AE532417015fa939Dd3', + decimals: 18, + id: 'FLEX_SMARTBCH', + name: 'FLEX Coin (SmartBCH)', + nativeAsset: 'SMARTBCH', + type: 'ERC20' + }, + { + contractAddress: '0x2B93824ad1c8c2DD79351FaCaE9473eAEf062366', + decimals: 18, + id: 'FLEXBTC', + name: 'flexBTC', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x40fB4096E0ACbf97D0087C3b7e4c6794Aa24a32f', + decimals: 18, + id: 'FLEXETH', + name: 'flexETH', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xa774FFB4AF6B0A91331C084E1aebAE6Ad535e6F3', + decimals: 18, + id: 'FLEXUSD', + name: 'flexUSD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x7b2B3C5308ab5b2a1d9a94d20D35CCDf61e05b72', + decimals: 18, + id: 'FLEXUSD_SMARTBCH', + name: 'flexUSD (SmartBCH)', + nativeAsset: 'SMARTBCH', + type: 'ERC20' + }, + { + contractAddress: '0x43f11c02439e2736800433b4594994Bd43Cd066D', + decimals: 9, + id: 'FLOKI', + name: 'FLOKI old', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x2B3F34e9D4b127797CE6244Ea341a83733ddd6E4', + decimals: 9, + id: 'FLOKI_BSC', + name: 'FLOKI old (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '', + decimals: 18, + id: 'FLR', + name: 'Flare', + nativeAsset: 'FLR', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x6243d8CEA23066d098a15582d81a598b4e8391F4', + decimals: 18, + id: 'FLX', + name: 'Flex Ungovernance Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x7bf3B1922F00C106865fE97a9767b445975D0f71', + decimals: 18, + id: 'FLY', + name: 'Fly Coin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x85f6eB2BD5a062f5F8560BE93FB7147e16c81472', + decimals: 4, + id: 'FLY_1', + name: 'Franklin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x314f951d144b397a088EA9eAc5218bdC7db2Ed4a', + decimals: 18, + id: 'FLY_OLD', + name: 'Fly Coin (Old)', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x67c4729aD44201972E8Bf5Ad2addaBE9DFea4e37', + decimals: 18, + id: 'FLY_SMARTBCH', + name: 'Fly Coin (SmartBCH)', + nativeAsset: 'SMARTBCH', + type: 'ERC20' + }, + { + contractAddress: '0x4946Fcea7C692606e8908002e55A582af44AC121', + decimals: 18, + id: 'FOAM', + name: 'FOAM', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x4C2e59D098DF7b6cBaE0848d66DE2f8A4889b9C3', + decimals: 18, + id: 'FODL', + name: 'Fodl', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xe14026c2f4EdD463791DA1991c74Cf16975942f6', + decimals: 18, + id: 'FOLKVANGUSD', + name: 'FolkvangUSD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x1FCdcE58959f536621d76f5b7FfB955baa5A672F', + decimals: 18, + id: 'FOR', + name: 'The Force Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xDb298285FE4C5410B05390cA80e8Fbe9DE1F259B', + decimals: 18, + id: 'FOREX', + name: 'handleFOREX', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x77FbA179C79De5B7653F68b5039Af940AdA60ce0', + decimals: 18, + id: 'FORTH', + name: 'Ampleforth Governance', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d', + decimals: 18, + id: 'FOX', + name: 'FOX', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x853d955aCEf822Db058eb8505911ED77F175b99e', + decimals: 18, + id: 'FRAX', + name: 'Frax', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xD24C2Ad096400B6FBcd2ad8B24E7acBc21A1da64', + decimals: 18, + id: 'FRAX_AVAX', + name: 'Frax (Avalanche)', + nativeAsset: 'AVAX', + type: 'ERC20' + }, + { + contractAddress: '0xf8C3527CC04340b208C854E985240c02F7B7793f', + decimals: 18, + id: 'FRONT', + name: 'Frontier Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xD0352a019e9AB9d757776F532377aAEbd36Fd541', + decimals: 18, + id: 'FSN', + name: 'Fusion', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x0E192d382a36De7011F795Acc4391Cd302003606', + decimals: 18, + id: 'FST', + name: 'Futureswap Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x274AA8B58E8C57C4e347C8768ed853Eb6D375b48', + decimals: 18, + id: 'FSUSHI', + name: 'FARM_SUSHI', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x4E15361FD6b4BB609Fa63C81A2be19d873717870', + decimals: 18, + id: 'FTM', + name: 'Fantom Token (ERC20)', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xAD29AbB318791D579433D831ed122aFeAf29dcfe', + decimals: 18, + id: 'FTM_BSC', + name: 'Fantom (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '', + decimals: 18, + id: 'FTM_FANTOM', + name: 'Fantom', + nativeAsset: 'FTM_FANTOM', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x50D1c9771902476076eCFc8B2A83Ad6b9355a4c9', + decimals: 18, + id: 'FTT', + name: 'FTX Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 8, + id: 'FTT_SOL', + issuerAddress: 'EzfgjvkSwthhgHaceR3LnKXUoRkP6NUhfghdaHAj1tUv', + name: 'FTX Token (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', + decimals: 8, + id: 'FUN', + name: 'FunFair', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x35bD01FC9d6D5D81CA9E055Db88Dc49aa2c699A8', + decimals: 18, + id: 'FWB', + name: 'Friends With Benefits Pro', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x8a40c222996f9F3431f63Bf80244C36822060f12', + decimals: 18, + id: 'FXF', + name: 'Finxflo', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0', + decimals: 18, + id: 'FXS', + name: 'Frax Share', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x214DB107654fF987AD859F34125307783fC8e387', + decimals: 18, + id: 'FXS_AVAX', + name: 'Frax Share (Avalanche)', + nativeAsset: 'AVAX', + type: 'ERC20' + }, + { + contractAddress: '0xaaEfF6C96F952Fc67379dcFa1667fC32AF02069B', + decimals: 18, + id: 'FXTE', + name: 'FutureX Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x15D4c048F83bd7e37d49eA4C83a07267Ec4203dA', + decimals: 8, + id: 'GALA', + name: 'Gala V1', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xd1d2Eb1B1e90B638588728b4130137D262C87cae', + decimals: 8, + id: 'GALA2', + name: 'Gala V2', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x63f88A2298a5c4AEE3c216Aa6D926B184a4b2437', + decimals: 18, + id: 'GAME', + name: 'Game Credits', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 9, + id: 'GARI_SOL', + issuerAddress: 'CKaKtYvz6dKPyMvYq9Rh3UBrnNqYZAyd7iF4hJtjUvks', + name: 'Gari (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x9d7630aDF7ab0b0CB00Af747Db76864df0EC82E4', + decimals: 18, + id: 'GATE', + name: 'GATE', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x86B4dBE5D203e634a12364C0e428fa242A3FbA98', + decimals: 18, + id: 'GBPT_ETH_APNR', + name: 'poundtoken', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xc67B12049c2D0CF6e476BC64c7F82fc6C63cFFc5', + decimals: 8, + id: 'GDT', + name: 'Globe Derivative Exchange', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 9, + id: 'GENE_SOL', + issuerAddress: 'GENEtH5amGSi8kHAtQoezp1XEXwZJ8vcuePYnXdKrMYz', + name: 'Genopets (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x8a854288a5976036A725879164Ca3e91d30c6A1B', + decimals: 18, + id: 'GET', + name: 'GET Protocol', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xAaEf88cEa01475125522e117BFe45cF32044E238', + decimals: 18, + id: 'GF', + name: 'GuildFi Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x7F969C4D388Ca0AE39A4FdDB1A6f89878CA2fBf8', + decimals: 18, + id: 'GGC', + name: 'GGCOIN', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x3F382DbD960E3a9bbCeaE22651E88158d2791550', + decimals: 18, + id: 'GHST', + name: 'Aavegotchi GHST Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x038a68FF68c393373eC894015816e33Ad41BD564', + decimals: 18, + id: 'GLCH', + name: 'Glitch', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x7DD9c5Cba05E151C895FDe1CF355C9A1D5DA6429', + decimals: 18, + id: 'GLM', + name: 'Golem Network Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'GLMR_GLMR', + name: 'Moonbeam', + nativeAsset: 'GLMR_GLMR', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 9, + id: 'GMT_SOL', + issuerAddress: '7i5KKsX2weiTkry7jA4ZwSuXGhs5eJBEjY8vVxR4pfRx', + name: 'GMT _Solana_', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x6810e776880C02933D47DB1b9fc05908e5386b96', + decimals: 18, + id: 'GNO', + name: 'Gnosis', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xa74476443119A942dE498590Fe1f2454d7D4aC0d', + decimals: 18, + id: 'GNT', + name: 'Golem', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 9, + id: 'GOFX_SOL', + issuerAddress: 'GFX1ZjR2P15tmrSwow6FjyDYcEkoFb4p4gJCpLBjaxHD', + name: 'GooseFX', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x0ab87046fBb341D058F17CBC4c1133F25a20a52f', + decimals: 18, + id: 'GOHM', + name: 'Governance OHM', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xeEAA40B28A2d1b0B08f6f97bB1DD4B75316c6107', + decimals: 18, + id: 'GOVI', + name: 'GOVI', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x71dF9Dd3e658f0136c40E2E8eC3988a5226E9A67', + decimals: 18, + id: 'GRAPEFRUITUSD', + name: 'GrapefruitUSD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x09e64c2B61a5f1690Ee6fbeD9baf5D6990F8dFd0', + decimals: 18, + id: 'GRO', + name: 'Growth', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xc944E90C64B2c07662A292be6244BDf05Cda44a7', + decimals: 18, + id: 'GRT', + name: 'Graph Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x228ba514309FFDF03A81a205a6D040E429d6E80C', + decimals: 18, + id: 'GSC', + name: 'Global Social Chain', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xe530441f4f73bDB6DC2fA5aF7c3fC5fD551Ec838', + decimals: 4, + id: 'GSE', + name: 'GSENetwork', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xB70835D7822eBB9426B56543E391846C107bd32C', + decimals: 18, + id: 'GTC', + name: 'Game.com', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xDe30da39c46104798bB5aA3fe8B9e0e1F348163F', + decimals: 18, + id: 'GTC_ETH', + name: 'Gitcoin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'GUN_TEST', + name: 'GUN_TEST', + nativeAsset: 'GUN_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xf7B098298f7C69Fc14610bf71d5e02c60792894C', + decimals: 3, + id: 'GUP', + name: 'Matchpool', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x056Fd409E1d7A124BD7017459dFEa2F387b6d5Cd', + decimals: 2, + id: 'GUSD', + name: 'Gemini USD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xC08512927D12348F6620a698105e1BAac6EcD911', + decimals: 6, + id: 'GYEN', + name: 'GMO JPY', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x4AC00f287f36A6Aad655281fE1cA6798C9cb727b', + decimals: 18, + id: 'GZE', + name: 'GazeCoin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 8, + id: 'HBAR', + name: 'Hedera Hashgraph', + nativeAsset: 'HBAR', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 8, + id: 'HBAR_TEST', + name: 'Hedera Hashgraph Test', + nativeAsset: 'HBAR_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 6, + id: 'HBB_SPL', + issuerAddress: 'HBB111SCo9jkCejsZfz8Ec8nH7T6THF8KEKSnvwT6XK6', + name: 'Hubble Protocol Token (SPL)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x0316EB71485b0Ab14103307bf65a021042c6d380', + decimals: 18, + id: 'HBTC', + name: 'Huobi BTC', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xE34e1944E776f39B9252790a0527eBDa647aE668', + decimals: 18, + id: 'HBZ', + name: 'HBZ coin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xF1290473E210b2108A85237fbCd7b6eb42Cc654F', + decimals: 18, + id: 'HEDG', + name: 'HEDG', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x584bC13c7D411c00c01A62e8019472dE68768430', + decimals: 18, + id: 'HEGIC', + name: 'Hegic', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x49C7295ff86EaBf5bf58C6eBC858DB4805738c01', + decimals: 18, + id: 'HERA_BSC', + name: 'Hero Arena', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0x2b591e99afE9f32eAA6214f7B7629768c40Eeb39', + decimals: 8, + id: 'HEX', + name: 'HEX', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x77087aB5Df23cFB52449A188e80e9096201c2097', + decimals: 18, + id: 'HI_BSC', + name: 'hi Dollar (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0xd1ba9BAC957322D6e8c07a160a3A8dA11A0d2867', + decimals: 18, + id: 'HMT', + name: 'Human Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 8, + id: 'HNT_SOL', + issuerAddress: 'hntyVP6YFm1Hg25TN9WGLqM12b8TQmcknKrdu1oxWux', + name: 'Helium Network Token (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x6c6EE5e31d828De241282B9606C8e98Ea48526E2', + decimals: 18, + id: 'HOT1', + name: 'Holo', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x9AF839687F6C94542ac5ece2e317dAAE355493A1', + decimals: 18, + id: 'HOT2', + name: 'Hydro Protocol', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x554C20B7c486beeE439277b4540A434566dC4C02', + decimals: 18, + id: 'HST', + name: 'Decision Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x6f259637dcD74C767781E37Bc6133cd6A68aa161', + decimals: 18, + id: 'HT', + name: 'Huobi Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'HT_CHAIN', + name: 'HT Chain', + nativeAsset: 'HT_CHAIN', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'HT_CHAIN_TEST', + name: 'HT Chain Test', + nativeAsset: 'HT_CHAIN_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xdF574c24545E5FfEcb9a659c229253D4111d87e1', + decimals: 8, + id: 'HUSD', + name: 'Huobi USD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x4bD70556ae3F8a6eC6C4080A0C327B24325438f3', + decimals: 18, + id: 'HXRO', + name: 'Hxro', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 2, + id: 'IBAN_CHF', + name: 'CHF (IBAN)', + nativeAsset: 'IBAN_CHF', + type: 'FIAT' + }, + { + contractAddress: '', + decimals: 2, + id: 'IBAN_EUR', + name: 'EUR (IBAN)', + nativeAsset: 'IBAN_EUR', + type: 'FIAT' + }, + { + contractAddress: '', + decimals: 2, + id: 'IBAN_SGD', + name: 'SGD (IBAN)', + nativeAsset: 'IBAN_SGD', + type: 'FIAT' + }, + { + contractAddress: '', + decimals: 2, + id: 'IBAN_USD', + name: 'USD (IBAN)', + nativeAsset: 'IBAN_USD', + type: 'FIAT' + }, + { + contractAddress: '0xf16e81dce15B08F326220742020379B855B87DF9', + decimals: 18, + id: 'ICE', + name: 'Ice Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xB705268213D593B8FD88d3FDEFF93AFF5CbDcfAE', + decimals: 18, + id: 'IDEX', + name: 'IDEX Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x61fd1c62551850D0c04C76FcE614cBCeD0094498', + decimals: 8, + id: 'IDK', + name: 'IDKToken', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x12c5E73Ddb44cD70225669B9F6f0d9DE5455Bc31', + decimals: 18, + id: 'IDON', + name: 'Idoneus Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x998FFE1E43fAcffb941dc337dD0468d52bA5b48A', + decimals: 2, + id: 'IDRT', + name: 'Rupiah', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x66207E39bb77e6B99aaB56795C7c340C08520d83', + decimals: 2, + id: 'IDRTBEP_BSC', + name: 'Rupiah Token (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0x9f059eDcf1C111e9C5987f884abBfEc0F80acFbB', + decimals: 2, + id: 'IDRTBEP_BSC_TEST', + name: 'Rupiah Token (BSC TEST)', + nativeAsset: 'BNB_TEST', + type: 'BEP20' + }, + { + contractAddress: '0xF784682C82526e245F50975190EF0fff4E4fC077', + decimals: 8, + id: 'ILK', + name: 'Inlock Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x767FE9EDC9E0dF98E07454847909b5E959D7ca0E', + decimals: 18, + id: 'ILV', + name: 'Illuvium', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x13119E34E140097a507B07a5564bDe1bC375D9e6', + decimals: 18, + id: 'IMT', + name: 'Moneytoken', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xF57e7e7C23978C3cAEC3C3548E3D615c346e79fF', + decimals: 18, + id: 'IMX_ERC20', + name: 'Immutable X', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'IMX_ZKEVM', + name: 'Immutable zkEVM', + nativeAsset: 'IMX_ZKEVM', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'IMX_ZKEVM_TEST', + name: 'Immutable zkEVM Test', + nativeAsset: 'IMX_ZKEVM_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x17Aa18A4B64A55aBEd7FA543F2Ba4E91f2dcE482', + decimals: 18, + id: 'INB', + name: 'Insight Chain', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x0954906da0Bf32d5479e25f46056d22f08464cab', + decimals: 18, + id: 'INDEX', + name: 'Index', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xe28b3B32B6c345A34Ff64674606124Dd5Aceca30', + decimals: 18, + id: 'INJ', + name: 'Injective Token (Ethereum)', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'INJ_INJ', + name: 'Injective', + nativeAsset: 'INJ_INJ', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'INJ_TEST', + name: 'Injective Test', + nativeAsset: 'INJ_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x5B2e4a700dfBc560061e957edec8F6EeEb74a320', + decimals: 10, + id: 'INS', + name: 'Insolar', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x6f40d4A6237C257fff2dB00FA0510DeEECd303eb', + decimals: 18, + id: 'INST', + name: 'Instadapp', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x544c42fBB96B39B21DF61cf322b5EDC285EE7429', + decimals: 18, + id: 'INSUR', + name: 'InsurAce', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xBBC7f7A6AADAc103769C66CBC69AB720f7F9Eae3', + decimals: 18, + id: 'INX', + name: 'INX token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xa8006C4ca56F24d6836727D106349320dB7fEF82', + decimals: 8, + id: 'INXT', + name: 'Internxt', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x02D3A27Ac3f55d5D91Fb0f52759842696a864217', + decimals: 18, + id: 'IONX', + name: 'Charged Particles - IONX', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xFA1a856Cfa3409CFa145Fa4e20Eb270dF3EB21ab', + decimals: 18, + id: 'IOST', + name: 'IOST', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xd944f1D1e9d5f9Bb90b62f9D45e447D989580782', + decimals: 6, + id: 'IOTA_BSC', + name: 'MIOTAC (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '', + decimals: 18, + id: 'IOTA_EVM', + name: 'IOTA EVM', + nativeAsset: 'IOTA_EVM', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x6fB3e0A217407EFFf7Ca062D46c26E5d60a14d69', + decimals: 18, + id: 'IOTX', + name: 'IoTeX', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'IOTX_IOTEX', + name: 'IoTex', + nativeAsset: 'IOTX_IOTEX', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x001F0aA5dA15585e5b2305DbaB2bac425ea71007', + decimals: 18, + id: 'IPSX', + name: 'IP Exchange', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xF88b137cfa667065955ABD17525e89EDCF4D6426', + decimals: 18, + id: 'ITG', + name: 'iTrust Governance Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x585E7bC75089eD111b656faA7aeb1104F5b96c15', + decimals: 8, + id: 'JLINK_AVAX', + name: 'Banker Joe Link (Avalanche)', + nativeAsset: 'AVAX', + type: 'ERC20' + }, + { + contractAddress: '0xeD8CBD9F0cE3C6986b22002F03c6475CEb7a6256', + decimals: 18, + id: 'JLP_AVAX', + name: 'Joe LP Token (Avalanche)', + nativeAsset: 'AVAX', + type: 'ERC20' + }, + { + contractAddress: '0x6e84a6216eA6dACC71eE8E6b0a5B7322EEbC0fDd', + decimals: 18, + id: 'JOE_AVAX', + name: 'JoeToken (Avalanche)', + nativeAsset: 'AVAX', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 9, + id: 'JTO_SOL', + issuerAddress: 'jtojtomepa8beP8AuQc6eXt5FriJwfFMwQx2v2f9mCL', + name: 'JITO (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x4B1E80cAC91e2216EEb63e29B957eB91Ae9C2Be8', + decimals: 18, + id: 'JUP', + name: 'Jupiter', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'JUP_SOL', + issuerAddress: 'JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN', + name: 'Jupiter (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x16EB2971863587fb93E33619772361ecc013cdcC', + decimals: 18, + id: 'KARD', + name: 'Kard Coin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x2BEb7C3c63Df4C2167839cD7F532338d15beB441', + decimals: 18, + id: 'KATLAUSD', + name: 'KatlaUSD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x08d1E0A7fBd4eDBF56D81Da21D1b0c9c95Fb507F', + decimals: 18, + id: 'KAVA', + name: 'Kava', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'KAVA_KAVA', + name: 'KAVA', + nativeAsset: 'KAVA_KAVA', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xf3586684107CE0859c44aa2b2E0fB8cd8731a15a', + decimals: 7, + id: 'KBC', + name: 'Karatgold Coin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xf34960d9d60be18cC1D5Afc1A6F012A723a28811', + decimals: 6, + id: 'KCS', + name: 'KuCoin Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x95E40E065AFB3059dcabe4aaf404c1F92756603a', + decimals: 18, + id: 'KDAG', + name: 'King DAG', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x85Eee30c52B0b379b046Fb0F85F4f3Dc3009aFEC', + decimals: 18, + id: 'KEEP', + name: 'Keep Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x4ABB9cC67BD3da9Eb966d1159A71a0e68BD15432', + decimals: 18, + id: 'KEL', + name: 'KelVpn Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x4CC19356f2D37338b9802aa8E8fc58B0373296E7', + decimals: 18, + id: 'KEY', + name: 'SelfKey', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xEF53462838000184F35f7D991452e5f25110b207', + decimals: 18, + id: 'KFT', + name: 'Knit Finance', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x818Fc6C2Ec5986bc6E2CBf00939d90556aB12ce5', + decimals: 18, + id: 'KIN', + name: 'Kin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 5, + id: 'KIN_SOL', + issuerAddress: 'kinXdEcpDQeHPEuQnqmUgtYykqKGVFq6CeVX5iAHJq6', + name: 'KIN (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0xCbfef8fdd706cde6F208460f2Bf39Aa9c785F05D', + decimals: 18, + id: 'KINE', + name: 'Kine Governance Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xB1191F691A355b43542Bea9B8847bc73e7Abb137', + decimals: 18, + id: 'KIRO', + name: 'Kirobo', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'KLAY_KAIA', + name: 'Kaia', + nativeAsset: 'KLAY_KAIA', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xdeFA4e8a7bcBA345F687a2f1456F5Edd9CE97202', + decimals: 18, + id: 'KNC', + name: 'Kyber Network Crystal v2', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xdd974D5C2e2928deA5F71b9825b8b646686BD200', + decimals: 18, + id: 'KNC_OLD', + name: 'Kyber Network (Old)', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x7c3E3eAE4d893d11C61E74d5187C962Ba5744A3B', + decimals: 18, + id: 'KOKO', + name: 'Kokoswap Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x7320c128e89bA4584Ab02ed1C9c96285b726443C', + decimals: 18, + id: 'KOKO_BSC', + name: 'Kokoswap Token', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0x1cEB5cB57C4D4E2b2433641b95Dd330A33185A44', + decimals: 18, + id: 'KP3R', + name: 'Keep3rV1', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 12, + id: 'KSM', + name: 'Kusama', + nativeAsset: 'KSM', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x2aa69E8D25C045B659787BC1f03ce47a388DB6E8', + decimals: 18, + id: 'KSM_BSC', + name: 'Kusama (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0xac826952bc30504359a099c3a486d44E97415c77', + decimals: 6, + id: 'KUSDC', + name: 'kUSDCoin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x3a859b9ea4998D344547283C7Ce8EBc4aBb77656', + decimals: 0, + id: 'KVT', + name: 'KinesisVelocityToken', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'LAC', + name: 'LaCoin (LAC)', + nativeAsset: 'LAC', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xfD107B473AB90e8Fbd89872144a3DC92C40Fa8C9', + decimals: 18, + id: 'LALA', + name: 'LALA World', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'LARIX_SOL', + issuerAddress: 'Lrxqnh6ZHKbGy3dcrCED43nsoLkM1LTzU2jRfWe8qUC', + name: 'Larix (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x77d547256A2cD95F32F67aE0313E450Ac200648d', + decimals: 8, + id: 'LAZIO', + name: 'FC Lazio Fan Token', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0xfe5F141Bf94fE84bC28deD0AB966c16B17490657', + decimals: 18, + id: 'LBA', + name: 'Cred', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x5102791cA02FC3595398400BFE0e33d7B6C82267', + decimals: 18, + id: 'LDC', + name: 'Leadcoin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x5A98FcBEA516Cf06857215779Fd812CA3beF1B32', + decimals: 18, + id: 'LDO', + name: 'Lido DAO Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 8, + id: 'LDO_SOL', + issuerAddress: 'HZRCwxP2Vq9PCpPXooayhJ2bxTpo5xfpQrwB1svh332p', + name: 'Lido DAO Token (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x80fB784B7eD66730e8b1DBd9820aFD29931aab03', + decimals: 18, + id: 'LEND', + name: 'ETHLend', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x2AF5D2aD76741191D15Dfe7bF6aC92d4Bd912Ca3', + decimals: 18, + id: 'LEO', + name: 'Bitfinex LEO Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xFA3118B34522580c35Ae27F6cf52da1dBb756288', + decimals: 6, + id: 'LET', + name: 'LinkEye Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x1977A9FE002F6dBfFda79b8459Cb4F7036100d41', + decimals: 6, + id: 'LGCY', + name: 'Legacy Coin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x0a50C93c762fDD6E56D86215C24AaAD43aB629aa', + decimals: 8, + id: 'LGO', + name: 'LGO Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x02F61Fd266DA6E8B102D4121f5CE7b992640CF98', + decimals: 18, + id: 'LIKE', + name: 'LikeCoin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 9, + id: 'LIKE_SOL', + issuerAddress: '3bRTivrVsitbmCTGtqwp7hxXPsybkjn4XLNtPsHqa3zR', + name: 'Only1 (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x9D0B65a76274645B29e4cc41B8f23081fA09f4A3', + decimals: 18, + id: 'LIME', + name: 'iMe Lab', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x3E9BC21C9b189C09dF3eF1B824798658d5011937', + decimals: 18, + id: 'LINA', + name: 'Linear Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'LINEA', + name: 'Ethereum (Linea)', + nativeAsset: 'LINEA', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'LINEA_SEPOLIA_TEST', + name: 'Linea Sepolia Test', + nativeAsset: 'LINEA_SEPOLIA_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'LINEA_TEST', + name: 'Ethereum (Linea Test)', + nativeAsset: 'LINEA_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x514910771AF9Ca656af840dff83E8264EcF986CA', + decimals: 18, + id: 'LINK', + name: 'Chainlink', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xF8A0BF9cF54Bb92F17374d9e9A321E6a111a51bD', + decimals: 18, + id: 'LINK_BSC', + name: 'Binance-Peg ChainLink (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0x5947BB275c521040051D82396192181b413227A3', + decimals: 18, + id: 'LINK_E_AVAX', + name: 'Chainlink Token (Avalanche)', + nativeAsset: 'AVAX', + type: 'ERC20' + }, + { + contractAddress: '0xb3654dc3D10Ea7645f8319668E8F54d2574FBdC8', + decimals: 18, + id: 'LINK_FTM', + name: 'ChainLink (FTM)', + nativeAsset: 'FTM_FANTOM', + type: 'ERC20' + }, + { + contractAddress: '0x53E0bca35eC356BD5ddDFebbD1Fc0fD03FaBad39', + decimals: 18, + id: 'LINK_POLYGON', + name: 'ChainLink Token (Polygon)', + nativeAsset: 'MATIC_POLYGON', + type: 'ERC20' + }, + { + contractAddress: '0x2167FB82309CF76513E83B25123f8b0559d6b48f', + decimals: 18, + id: 'LION', + name: 'LionCoin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'LISK', + name: 'Lisk', + nativeAsset: 'LISK', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xb59490aB09A0f526Cc7305822aC65f2Ab12f9723', + decimals: 18, + id: 'LIT', + name: 'Litentry', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x80CE3027a70e0A928d9268994e9B85d03Bd4CDcf', + decimals: 18, + id: 'LKR', + name: 'Polkalokr', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x25B6325f5BB1c1E03cfbC3e53F470E1F1ca022E3', + decimals: 18, + id: 'LML', + name: 'LML', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x9c23D67AEA7B95D80942e3836BCDF7E708A747C2', + decimals: 18, + id: 'LOCI', + name: 'LOCIcoin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x897f505d9637622219e4687eC1A71b4Acf204816', + decimals: 18, + id: 'LODE', + name: 'LODE Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xf4d2888d29D722226FafA5d9B24F9164c092421E', + decimals: 18, + id: 'LOOKS', + name: 'LooksRare Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x42476F744292107e34519F9c357927074Ea3F75D', + decimals: 18, + id: 'LOOM', + name: 'Loom Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xA4e8C3Ec456107eA67d3075bF9e3DF3A75823DB0', + decimals: 18, + id: 'LOOM_OLD', + name: 'Loom Token(Old)', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x6149C26Cd2f7b5CCdb32029aF817123F6E37Df5B', + decimals: 18, + id: 'LPOOL', + name: 'Launchpool token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x58b6A8A3302369DAEc383334672404Ee733aB239', + decimals: 18, + id: 'LPT', + name: 'Livepeer Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x6DEA81C8171D0bA574754EF6F8b412F2Ed88c54D', + decimals: 18, + id: 'LQTY', + name: 'LQTY', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xBBbbCA6A901c926F240b89EacB641d8Aec7AEafD', + decimals: 18, + id: 'LRC', + name: 'Loopring', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 8, + id: 'LTC', + name: 'Litecoin', + nativeAsset: 'LTC', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x4338665CBB7B2485A8855A139b75D5e34AB0DB94', + decimals: 18, + id: 'LTC_BSC', + name: 'Binance-Peg Litecoin (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '', + decimals: 8, + id: 'LTC_TEST', + name: 'Litecoin Test', + nativeAsset: 'LTC_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x3DB6Ba6ab6F95efed1a6E794caD492fAAabF294D', + decimals: 8, + id: 'LTO', + name: 'LTO Network Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xa393473d64d2F9F026B60b6Df7859A689715d092', + decimals: 8, + id: 'LTX', + name: 'Lattice Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 7, + id: 'LU2426951195_XLM_TEST', + issuerAddress: 'GD4MGD3UZ5QY6NLH2FMXKOUCHH4NA3NRT3H6KUU5UMDWE52PIPETFBY2', + name: 'LU2426951195 (Stellar Test)', + nativeAsset: 'XLM_TEST', + type: 'XLM_ASSET' + }, + { + contractAddress: '', + decimals: 6, + id: 'LUNA2', + name: 'Terra Luna 2.0', + nativeAsset: 'LUNA2', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 6, + id: 'LUNA2_TEST', + name: 'Terra Luna 2.0 Test', + nativeAsset: 'LUNA2_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x5f98805A4E8be255a32880FDeC7F6728C6568bA0', + decimals: 18, + id: 'LUSD', + name: 'LUSD Stablecoin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xA8b919680258d369114910511cc87595aec0be6D', + decimals: 18, + id: 'LYXE', + name: 'LUKSO', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x0F5D2fB29fb7d3CFeE444a200298f468908cC942', + decimals: 18, + id: 'MANA', + name: 'Decentraland', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'MANTLE', + name: 'Mantle', + nativeAsset: 'MANTLE', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'MANTLE_TEST', + name: 'Mantle Sepolia', + nativeAsset: 'MANTLE_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x16CDA4028e9E872a38AcB903176719299beAed87', + decimals: 18, + id: 'MARS4', + name: 'MARS4', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x69af81e73A73B40adF4f3d4223Cd9b1ECE623074', + decimals: 18, + id: 'MASK', + name: 'Mask Network', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0', + decimals: 18, + id: 'MATIC', + name: 'Matic Token (Ethereum)', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xCC42724C6683B7E57334c4E856f4c9965ED682bD', + decimals: 18, + id: 'MATIC_BSC', + name: 'Matic Token (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '', + decimals: 18, + id: 'MATIC_POLYGON', + name: 'Matic Gas Token (Polygon)', + nativeAsset: 'MATIC_POLYGON', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 6, + id: 'MBS_SOL', + issuerAddress: 'Fm9rHUTF5v3hwMLbStjZXqNBBoZyGriQaFM6sTFz3K8A', + name: 'MonkeyBucks (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x949D48EcA67b17269629c7194F4b727d4Ef9E5d6', + decimals: 18, + id: 'MC_ETH', + name: 'Merit Circle', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x4e352cF164E64ADCBad318C3a1e222E9EBa4Ce42', + decimals: 18, + id: 'MCB', + name: 'MCDEX Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xB63B606Ac810a52cCa15e44bB630fd42D8d1d83d', + decimals: 8, + id: 'MCO', + name: 'Crypto.com', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xfC98e825A2264D890F9a1e68ed50E1526abCcacD', + decimals: 18, + id: 'MCO2', + name: 'Moss Carbon Credit', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x51DB5Ad35C671a87207d88fC11d593AC0C8415bd', + decimals: 18, + id: 'MDA', + name: 'Moeda Loyalty Points', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'MDF_SOL', + issuerAddress: 'ALQ9KMWjFmxVbew3vMkJj3ypbAKuorSgGst6svCHEe2z', + name: 'MatrixETF DAO Finance (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x947AEb02304391f8fbE5B25D7D98D649b57b1788', + decimals: 18, + id: 'MDX', + name: 'MANDALA EXCHANGE TOKEN', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'MEAN_SOL', + issuerAddress: 'MEANeD3XDdUmNMsRGjASkSWdC8prLYsoRJ61pPeHctD', + name: 'MEAN (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x42dbBd5ae373FEA2FC320F62d44C058522Bb3758', + decimals: 18, + id: 'MEM', + name: 'Memecoin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xD5525D397898e5502075Ea5E830d8914f6F0affe', + decimals: 8, + id: 'MEME', + name: 'MEME', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xDF2C7238198Ad8B389666574f2d8bc411A4b7428', + decimals: 18, + id: 'MFT', + name: 'Mainframe', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x40395044Ac3c0C57051906dA938B54BD6557F212', + decimals: 8, + id: 'MGO', + name: 'MobileGo', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3', + decimals: 18, + id: 'MIM', + name: 'Magic Internet Money', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xa3Fa99A148fA48D14Ed51d610c367C61876997F1', + decimals: 18, + id: 'MIMATIC_POLYGON', + name: 'miMATIC (Polygon)', + nativeAsset: 'MATIC_POLYGON', + type: 'ERC20' + }, + { + contractAddress: '0x90B831fa3Bebf58E9744A14D638E25B4eE06f9Bc', + decimals: 18, + id: 'MIMO', + name: 'MIMO Parallel Governance Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x09a3EcAFa817268f77BE1283176B946C4ff2E608', + decimals: 18, + id: 'MIR', + name: 'Wrapped MIR Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x68E374F856bF25468D365E539b700b648Bf94B67', + decimals: 18, + id: 'MIST_BSC', + name: 'Mist', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0x3893b9422Cd5D70a81eDeFfe3d5A1c6A978310BB', + decimals: 18, + id: 'MITH', + name: 'Mithril', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x4a527d8fc13C5203AB24BA0944F4Cb14658D1Db6', + decimals: 18, + id: 'MITX', + name: 'Morpheus Labs', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2', + decimals: 18, + id: 'MKR', + name: 'Maker', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x5f0Da599BB2ccCfcf6Fdfd7D81743B6020864350', + decimals: 18, + id: 'MKR_BSC', + name: 'Binance-Peg Maker (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0xec67005c4E498Ec7f55E092bd1d35cbC47C91892', + decimals: 18, + id: 'MLN', + name: 'Melon', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x9506d37f70eB4C3d79C398d326C871aBBf10521d', + decimals: 18, + id: 'MLT_ERC20', + name: 'MILC Platform', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 9, + id: 'MNDE_SOL', + issuerAddress: 'MNDEFzGvMt87ueuHvVU9VcTqsAP5b3fTGPsHuuPA5ey', + name: 'Marinade (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '', + decimals: 6, + id: 'MNGO_SOL', + issuerAddress: 'MangoCzJ36AjZyKwVj3VnYU4GTonjfVEnJmvvWaxLac', + name: 'Mango', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0xb96525143f23F2e9B2B2B260FCcd8AfC260656c8', + decimals: 18, + id: 'MOUNTAIN', + name: 'Mountain', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x4206Fc377c22eB4778B5DAc3C28d0fa92db43AE4', + decimals: 18, + id: 'MOUNTAINVUSD', + name: 'MountainVUSD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'MOVR_MOVR', + name: 'Moonriver', + nativeAsset: 'MOVR_MOVR', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x33349B282065b0284d756F0577FB39c158F935e6', + decimals: 18, + id: 'MPL', + name: 'Maple Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 9, + id: 'MSOL_SOL', + issuerAddress: 'mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So', + name: 'Marinade staked SOL (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0xa3BeD4E1c75D00fa6f4E5E6922DB7261B5E9AcD2', + decimals: 18, + id: 'MTA', + name: 'Meta', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xF501dd45a1198C2E1b5aEF5314A68B9006D842E0', + decimals: 18, + id: 'MTA_POLYGON', + name: 'Meta Polygon', + nativeAsset: 'MATIC_POLYGON', + type: 'ERC20' + }, + { + contractAddress: '0xF433089366899D83a9f26A773D59ec7eCF30355e', + decimals: 8, + id: 'MTL', + name: 'Metal', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xe2f2a5C287993345a840Db3B0845fbC70f5935a5', + decimals: 18, + id: 'MUSD', + name: 'mStable USD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x3564ad35b9E95340E5Ace2D6251dbfC76098669B', + decimals: 6, + id: 'MUSDC', + name: 'DMM: USDC', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x8E766F57F7d16Ca50B4A0b90b88f6468A09b0439', + decimals: 18, + id: 'MXM', + name: 'Maximine Coin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xa645264C5603E96c3b0B078cdab68733794B0A71', + decimals: 8, + id: 'MYST', + name: 'Mysterium', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xDf282f170f3C32AC9c49f3f5Be1D68e5aE6Eb742', + decimals: 8, + id: 'NAKA', + name: 'Nakamoto Debt Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x4a615bB7166210CCe20E6642a6f8Fb5d4D044496', + decimals: 18, + id: 'NAOS', + name: 'NAOSToken', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 4, + id: 'NAXAR_SOL', + issuerAddress: 'Fp4gjLpTsPqBN6xDGpDHwtnuEofjyiZKxxZxzvJnjxV6', + name: 'Naxar (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x809826cceAb68c387726af962713b64Cb5Cb3CCA', + decimals: 18, + id: 'NCASH', + name: 'NucleusVision', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 24, + id: 'NEAR', + name: 'NEAR Protocol', + nativeAsset: 'NEAR', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x1Fa4a73a3F0133f0025378af00236f3aBDEE5D63', + decimals: 18, + id: 'NEAR_BSC', + name: 'Binance-Peg NEAR Protocol', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '', + decimals: 24, + id: 'NEAR_TEST', + name: 'NEAR Protocol Test', + nativeAsset: 'NEAR_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xCc80C051057B774cD75067Dc48f8987C4Eb97A5e', + decimals: 18, + id: 'NEC', + name: 'Ethfinex Nectar Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 9, + id: 'NEST_SOL', + issuerAddress: 'Czt7Fc4dz6BpLh2vKiSYyotNK2uPPDhvbWrrLeD9QxhV', + name: 'Nest Arcade (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0xB62132e35a6c13ee1EE0f84dC5d40bad8d815206', + decimals: 18, + id: 'NEXO', + name: 'Nexo', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xcB8d1260F9c92A3A545d409466280fFdD7AF7042', + decimals: 18, + id: 'NFT', + name: 'NFT Protocol', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xEF40B859D21e4d566a3d713e756197c021BffaAa', + decimals: 6, + id: 'NFT1', + name: 'APENFT', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x87d73E916D7057945c9BcD8cdd94e42A6F47f776', + decimals: 18, + id: 'NFTX', + name: 'NFTX', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xf71982762D141f8679Eb944fAec8cEC415fB5E23', + decimals: 18, + id: 'NIAX', + name: 'NIAXToken', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x25de492f43661Af568f46C0a3F39850Aa1D066A0', + decimals: 18, + id: 'NIBBIOUSD', + name: 'NibbioUSD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x7e291890B01E5181f7ecC98D79ffBe12Ad23df9e', + decimals: 18, + id: 'NIF', + name: 'Unifty', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x7c8155909cd385F120A56eF90728dD50F9CcbE52', + decimals: 15, + id: 'NII', + name: 'Nahmii', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x852e5427c86A3b46DD25e5FE027bb15f53c4BCb8', + decimals: 15, + id: 'NIIFI', + name: 'NiiFiToken', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'NINJA_SOL', + issuerAddress: 'FgX1WD9WzMU3yLwXaFSarPfkgzjLb2DZCqmkx9ExpuvJ', + name: 'NINJA', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0xc813EA5e3b48BEbeedb796ab42A30C5599b01740', + decimals: 4, + id: 'NIOX', + name: 'Autonio', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x5Cf04716BA20127F1E2297AdDCf4B5035000c9eb', + decimals: 18, + id: 'NKN', + name: 'NKN', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x1776e1F26f98b1A5dF9cD347953a26dd3Cb46671', + decimals: 18, + id: 'NMR', + name: 'Numeraire', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xa8c8CfB141A3bB59FEA1E2ea6B79b5ECBCD7b6ca', + decimals: 18, + id: 'NOIA', + name: 'NOIA Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 9, + id: 'NOTCOIN_TON', + issuerAddress: 'EQAvlWFDxGF2lXm67y4yzC17wYKD9A0guwPkMs1gOsM__NOT', + name: 'Notcoin (Ton)', + nativeAsset: 'TON', + type: 'TON_ASSET' + }, + { + contractAddress: '0xCFEAead4947f0705A14ec42aC3D44129E1Ef3eD5', + decimals: 8, + id: 'NOTE_ETH', + name: 'Notional', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x25aE7B9808F6Cc3B5E9b8699b62b0395C3F01BE0', + decimals: 18, + id: 'NOTEUSD', + name: 'noteUSD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x97fB6Fc2AD532033Af97043B563131C5204F8A35', + decimals: 18, + id: 'NPLC', + name: 'Plus-Coin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'NPT_TRX', + issuerAddress: 'TQTShAfjdRztg8id1mrQPaNT6ccdK1HviG', + name: 'NPT (Tron)', + nativeAsset: 'TRX', + type: 'TRON_TRC20' + }, + { + contractAddress: '0xA15C7Ebe1f07CaF6bFF097D8a589fb8AC49Ae5B3', + decimals: 18, + id: 'NPXS', + name: 'Pundi X', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x20945cA1df56D237fD40036d47E866C7DcCD2114', + decimals: 18, + id: 'NSURE', + name: 'Nsure Network Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'NTRN', + name: 'Neutron', + nativeAsset: 'NTRN', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x4fE83213D56308330EC302a8BD641f1d0113A4Cc', + decimals: 18, + id: 'NU', + name: 'NuCypher', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 7, + id: 'NXDB', + issuerAddress: 'GBG4NNAO36LKRDOUE3J3TPZYXGF2J34CW4FRFE5SLL65ED54E7LFBMKK', + name: 'Nicoswap coin (DigitalBits)', + nativeAsset: 'XDB', + type: 'XDB_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'OAS', + name: 'Oasys', + nativeAsset: 'OAS', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'OAS_TEST', + name: 'Oasys Test', + nativeAsset: 'OAS_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x2F109021aFe75B949429fe30523Ee7C0D5B27207', + decimals: 18, + id: 'OCC', + name: 'OCC', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x967da4048cD07aB37855c090aAF366e4ce1b9F48', + decimals: 18, + id: 'OCEAN', + name: 'Ocean Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x4092678e4E78230F46A1534C0fbc8fA39780892B', + decimals: 18, + id: 'OCN', + name: 'Odyssey', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x7240aC91f01233BaAf8b064248E80feaA5912BA3', + decimals: 18, + id: 'OCTO', + name: 'Octo.fi', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x8207c1FfC5B6804F6024322CcF34F29c3541Ae26', + decimals: 18, + id: 'OGN', + name: 'OriginToken', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x383518188C0C6d7730D91b2c03a03C837814a899', + decimals: 9, + id: 'OHM', + name: 'Olympus', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x75231F58b43240C9718Dd58B4967c5114342a86c', + decimals: 18, + id: 'OKB', + name: 'OKB', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x6595b8fD9C920C81500dCa94e53Cdc712513Fb1f', + decimals: 18, + id: 'OLY', + name: 'Olyseum', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x3593D125a4f7849a1B059E64F4517A86Dd60c95d', + decimals: 18, + id: 'OM', + name: 'MANTRA DAO', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x76e63a3E7Ba1e2E61D3DA86a87479f983dE89a7E', + decimals: 18, + id: 'OMEN_POLYGON', + name: 'Augury Finance (Polygon)', + nativeAsset: 'MATIC_POLYGON', + type: 'ERC20' + }, + { + contractAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', + decimals: 18, + id: 'OMG', + name: 'OmiseGO', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xaBc6790673a60b8A7f588450f59D2d256b1aeF7F', + decimals: 18, + id: 'OMN_BSC', + name: 'OMNI Coin', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '', + decimals: 8, + id: 'OMNI_TEST', + name: 'Omni Test', + nativeAsset: 'BTC_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x03fF0ff224f904be3118461335064bB48Df47938', + decimals: 18, + id: 'ONE_BSC', + name: 'Harmony ONE (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0xd341d1680Eeee3255b8C4c75bCCE7EB57f144dAe', + decimals: 18, + id: 'ONG', + name: 'SoMee.Social', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xFd7B3A77848f1C2D67E05E54d78d174a0C850335', + decimals: 18, + id: 'ONT_BSC', + name: 'Binance-Peg Ontology Token (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0x9D86b1B2554ec410ecCFfBf111A6994910111340', + decimals: 8, + id: 'OPENC', + name: 'OPEN Chain', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x888888888889C00c67689029D7856AAC1065eC11', + decimals: 18, + id: 'OPIUM', + name: 'Opium Governance Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x80D55c03180349Fff4a229102F62328220A96444', + decimals: 18, + id: 'OPUL', + name: 'OpulousToken', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xEE1CeA7665bA7aa97e982EdeaeCb26B59a04d035', + decimals: 18, + id: 'ORAO', + name: 'ORAO Network', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xff56Cc6b1E6dEd347aA0B7676C85AB0B3D08B0FA', + decimals: 18, + id: 'ORBS', + name: 'Orbs', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x662b67d00A13FAf93254714DD601F5Ed49Ef2F51', + decimals: 18, + id: 'ORC', + name: 'Orbit Chain', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'ORCA_SOL', + issuerAddress: 'orcaEKTdK7LKz57vaAYr9QeNsVEPfiu6QeMU1kektZE', + name: 'Orca', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x0258F474786DdFd37ABCE6df6BBb1Dd5dfC4434a', + decimals: 8, + id: 'ORN', + name: 'Orion Protocol', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'OSMO', + name: 'Osmosis', + nativeAsset: 'OSMO', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 6, + id: 'OSMO_TEST', + name: 'Osmosis Test', + nativeAsset: 'OSMO_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x2C4e8f2D746113d0696cE89B35F0d8bF88E0AEcA', + decimals: 18, + id: 'OST', + name: 'OST', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x2401D75Bf6E88EF211e51BD3E15415860025fDb9', + decimals: 8, + id: 'OT', + name: 'O Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x2A8e1E676Ec238d8A992307B495b45B3fEAa5e86', + decimals: 18, + id: 'OUSD', + name: 'Origin Dollar', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x4575f41308EC1483f3d399aa9a2826d74Da13Deb', + decimals: 18, + id: 'OXT', + name: 'Orchid', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x46c9757C5497c5B1f2eb73aE79b6B67D119B0B58', + decimals: 18, + id: 'PACT_CELO', + name: 'impactMarket (CELO)', + nativeAsset: 'CELO', + type: 'ERC20' + }, + { + contractAddress: '0x1614F18Fc94f47967A3Fbe5FfcD46d4e7Da3D787', + decimals: 18, + id: 'PAID', + name: 'PAID Network', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xea5f88E54d982Cbb0c441cde4E79bC305e5b43Bc', + decimals: 18, + id: 'PARETO', + name: 'PARETO Rewards', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xeE4458e052B533b1aABD493B5f8c4d85D7B263Dc', + decimals: 6, + id: 'PASS', + name: 'Blockpass', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x8E870D67F660D95d5be530380D0eC0bd388289E1', + decimals: 18, + id: 'PAX', + name: 'PAX Dollar', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x45804880De22913dAFE09f4980848ECE6EcbAf78', + decimals: 18, + id: 'PAXG', + name: 'Paxos Gold', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xB97048628DB6B661D4C2aA833e95Dbe1A905B280', + decimals: 18, + id: 'PAY', + name: 'TenXPay', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x7e9928aFe96FefB820b85B4CE6597B8F660Fe4F4', + decimals: 18, + id: 'PBNB_POLYGON', + name: 'Orbit Bridge Polygon Binance Coin (Polygon)', + nativeAsset: 'MATIC_POLYGON', + type: 'ERC20' + }, + { + contractAddress: '0xD528cf2E081f72908e086F8800977df826B5a483', + decimals: 18, + id: 'PBX_ETH', + name: 'Paribus', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x334cBb5858417Aee161B53Ee0D5349cCF54514CF', + decimals: 18, + id: 'PCDAI', + name: 'PoolTogether Dai Ticket (Compound)', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xD81b1A8B1AD00Baa2D6609E0BAE28A38713872f7', + decimals: 6, + id: 'PCUSDC', + name: 'PoolTogether USDC Ticket (Compound)', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 0, + id: 'PCUST', + name: 'Philanthropic Credit', + nativeAsset: 'BTC', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x56e13ba0b311eDFEA176505B4fB7F2696778913C', + decimals: 0, + id: 'PCUST_ERC20', + name: 'Philanthropic Credit (ERC20)', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'PEAQ', + name: 'Peaq', + nativeAsset: 'PEAQ', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 2, + id: 'PEERACCOUNTTRANSFER_CHF', + name: 'CHF (Peer Transfer)', + nativeAsset: 'PEERACCOUNTTRANSFER_CHF', + type: 'FIAT' + }, + { + contractAddress: '', + decimals: 2, + id: 'PEERACCOUNTTRANSFER_EUR', + name: 'EUR (Peer Transfer)', + nativeAsset: 'PEERACCOUNTTRANSFER_EUR', + type: 'FIAT' + }, + { + contractAddress: '', + decimals: 2, + id: 'PEERACCOUNTTRANSFER_SGD', + name: 'SGD (Peer Transfer)', + nativeAsset: 'PEERACCOUNTTRANSFER_SGD', + type: 'FIAT' + }, + { + contractAddress: '', + decimals: 2, + id: 'PEERACCOUNTTRANSFER_USD', + name: 'USD (Peer Transfer)', + nativeAsset: 'PEERACCOUNTTRANSFER_USD', + type: 'FIAT' + }, + { + contractAddress: '0x808507121B80c02388fAd14726482e061B8da827', + decimals: 18, + id: 'PENDLE', + name: 'Pendle', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xbC396689893D065F41bc2C6EcbeE5e0085233447', + decimals: 18, + id: 'PERP', + name: 'Perpetual', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x3F9BEC82c776c47405BcB38070d2395Fd18F89d3', + decimals: 18, + id: 'PHM', + name: 'Phantom Protocol Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x4399AE7538c33cA24edD4C28C5dd7Ce9a80acF81', + decimals: 18, + id: 'PHM_BSC', + name: 'Phantom Protocol Token (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0xc2D31475a1fbce0725AD71665976F18502a37234', + decimals: 0, + id: 'PKC', + name: 'PKC', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xe3818504c1B32bF1557b16C238B2E01Fd3149C17', + decimals: 18, + id: 'PLR', + name: 'PILLAR', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xD8912C10681D8B21Fd3742244f44658dBA12264E', + decimals: 18, + id: 'PLU', + name: 'Pluton', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x47DA5456bC2e1ce391b645Ce80F2E97192e4976a', + decimals: 18, + id: 'PLUG', + name: 'Plug Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'PLUME', + name: 'Plume', + nativeAsset: 'PLUME', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x846C66cf71C43f80403B51fE3906B3599D63336f', + decimals: 18, + id: 'PMA', + name: 'PumaPay', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x93ED3FBe21207Ec2E8f2d3c3de6e058Cb73Bc04d', + decimals: 18, + id: 'PNK', + name: 'Pinakion', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x89Ab32156e46F46D02ade3FEcbe5Fc4243B9AAeD', + decimals: 18, + id: 'PNT', + name: 'pNetwork Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x455e53CBB86018Ac2B8092FdCd39d8444aFFC3F6', + decimals: 18, + id: 'POL_ETH_9RYQ', + name: 'Polygon Ecosystem Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 8, + id: 'POLIS_SOL', + issuerAddress: 'poLisWXnNRwC6oBu1vHiuKQzFjGL4XDSu4g9qjz9qVk', + name: 'Star Atlas DAO', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x83e6f1E41cdd28eAcEB20Cb649155049Fac3D5Aa', + decimals: 18, + id: 'POLS', + name: 'PolkastarterToken', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x9992eC3cF6A55b00978cdDF2b27BC6882d88D1eC', + decimals: 18, + id: 'POLY', + name: 'Polymath', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x57B946008913B82E4dF85f501cbAeD910e58D26C', + decimals: 18, + id: 'POND', + name: 'Marlin POND', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x0cEC1A9154Ff802e7934Fc916Ed7Ca50bDE6844e', + decimals: 18, + id: 'POOL', + name: 'PoolTogether', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x49f2145d6366099e13B10FbF80646C0F377eE7f6', + decimals: 8, + id: 'PORTO', + name: 'FC Porto Fan Token', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0x595832F8FC6BF59c85C527fEC3740A1b7a361269', + decimals: 6, + id: 'POWR', + name: 'Power Ledger', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x054D64b73d3D8A21Af3D764eFd76bCaA774f3Bb2', + decimals: 18, + id: 'PPAY', + name: 'Plasma', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xd4fa1460F537bb9085d22C7bcCB5DD450Ef28e3a', + decimals: 8, + id: 'PPT', + name: 'Populous', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xEC213F83defB583af3A000B1c0ada660b1902A0F', + decimals: 18, + id: 'PRE', + name: 'Presearch', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x226bb599a12C826476e3A771454697EA52E9E220', + decimals: 8, + id: 'PRO', + name: 'Propy', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xfc82bb4ba86045Af6F327323a46E80412b91b27d', + decimals: 18, + id: 'PROM', + name: 'Token Prometeus Network', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x6fe56C0bcdD471359019FcBC48863d6c3e9d4F41', + decimals: 18, + id: 'PROPS', + name: 'Props Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x8642A849D0dcb7a15a974794668ADcfbe4794B56', + decimals: 18, + id: 'PROS', + name: 'Prosper', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'PRT_SOL', + issuerAddress: 'PRT88RkA4Kg5z7pKnezeNH4mafTvtQdfFgpQTGRjz44', + name: 'Parrot Protocol (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x2bf9671F00643afc813A6623074e0dDF6DB4Fc2B', + decimals: 18, + id: 'PSQ', + name: 'PSQ', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xC57d533c50bC22247d49a368880fb49a1caA39F7', + decimals: 18, + id: 'PTF', + name: 'PowerTrade Fuel Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x22d4002028f537599bE9f666d1c4Fa138522f9c8', + decimals: 18, + id: 'PTP_AVAX', + name: 'Platypus', + nativeAsset: 'AVAX', + type: 'ERC20' + }, + { + contractAddress: '0xC229c69eB3BB51828D0cAA3509A05a51083898dd', + decimals: 18, + id: 'PTU', + name: 'Pintu Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x0FD10b9899882a6f2fcb5c371E17e70FdEe00C38', + decimals: 18, + id: 'PUNDIX', + name: 'Pundi X Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xf418588522d5dd018b425E472991E52EBBeEEEEE', + decimals: 18, + id: 'PUSH', + name: 'Ethereum Push Notification Service', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x47e67BA66b0699500f18A53F94E2b9dB3D47437e', + decimals: 18, + id: 'PXG', + name: 'PlayGame', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x95aA5d2DbD3c16ee3fdea82D5C6EC3E38CE3314f', + decimals: 18, + id: 'PXP', + name: 'PointPay Crypto Banking Token V2', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x430EF9263E76DAE63c84292C3409D61c598E9682', + decimals: 18, + id: 'PYR', + name: 'PYR Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'PYTH_SOL', + issuerAddress: 'HZ1JovNiVvGrGNiiYvEozEVgZ58xaU3RKwX8eACQBCt3', + name: 'Pyth Network (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x6c3ea9036406852006290770BEdFcAbA0e23A0e8', + decimals: 6, + id: 'PYUSD_ETH', + name: 'PayPal USD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'PYUSD_SOL', + issuerAddress: '2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo', + name: 'PayPal USD (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x618E75Ac90b12c6049Ba3b27f5d5F8651b0037F6', + decimals: 6, + id: 'QASH', + name: 'QASH', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x1602af2C782cC03F9241992E243290Fccf73Bb13', + decimals: 18, + id: 'QBIT', + name: 'Qubitica', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x4A16BAf414b8e637Ed12019faD5Dd705735DB2e0', + decimals: 2, + id: 'QCAD', + name: 'QCAD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x9Adc7710E9d1b29d8a78c04d52D32532297C2Ef3', + decimals: 18, + id: 'QDT', + name: 'QuadransToken', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x9e3a9F1612028eeE48F85cA85f8Bed2f37d76848', + decimals: 18, + id: 'QDX_BSC', + name: 'Quidax Token (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0x8729438EB15e2C8B576fCc6AeCdA6A148776C0F5', + decimals: 18, + id: 'QI_AVAX', + name: 'BENQI (Avalanche)', + nativeAsset: 'AVAX', + type: 'ERC20' + }, + { + contractAddress: '0xEA26c4aC16D4a5A106820BC8AEE85fd0b7b2b664', + decimals: 18, + id: 'QKC', + name: 'QuarkChain', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x4a220E6096B25EADb88358cb44068A3248254675', + decimals: 18, + id: 'QNT', + name: 'Quant', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x99ea4dB9EE77ACD40B119BD1dC4E33e1C070b80d', + decimals: 18, + id: 'QSP', + name: 'Quantstamp', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x35aF993EF3E89C076e41e463Fbd4CD00d3105cD1', + decimals: 18, + id: 'QUAKE', + name: 'QuakeCoin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x6c28AeF8977c9B773996d0e8376d2EE379446F2f', + decimals: 18, + id: 'QUICK', + name: 'Quickswap (Old)', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x831753DD7087CaC61aB5644b308642cc1c33Dc13', + decimals: 18, + id: 'QUICK_POLYGON', + name: 'Quickswap (Old Polygon)', + nativeAsset: 'MATIC_POLYGON', + type: 'ERC20' + }, + { + contractAddress: '0x31c8EAcBFFdD875c74b94b077895Bd78CF1E64A3', + decimals: 18, + id: 'RAD', + name: 'Radicle', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x94804dc4948184fFd7355f62Ccbb221c9765886F', + decimals: 18, + id: 'RAGE', + name: 'RageToken', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x33D0568941C0C64ff7e0FB4fbA0B11BD37deEd9f', + decimals: 18, + id: 'RAMP', + name: 'RAMP DEFI', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x8519EA49c997f50cefFa444d240fB655e89248Aa', + decimals: 18, + id: 'RAMP_BSC', + name: 'RAMP DEFI (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0xba5BDe662c17e2aDFF1075610382B9B691296350', + decimals: 18, + id: 'RARE', + name: 'SuperRare', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xFca59Cd816aB1eaD66534D82bc21E7515cE441CF', + decimals: 18, + id: 'RARI', + name: 'Rarible', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x5245C0249e5EEB2A0838266800471Fd32Adb1089', + decimals: 6, + id: 'RAY', + name: 'Raydium', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'RAY_SOL', + issuerAddress: '4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX6R', + name: 'Raydium (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0xFc2C4D8f95002C14eD0a7aA65102Cac9e5953b5E', + decimals: 18, + id: 'RBLX', + name: 'Rublix', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x6123B0049F904d730dB3C36a31167D9d4121fA6B', + decimals: 18, + id: 'RBN', + name: 'Ribbon', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'RBTC', + name: 'RSK Smart Bitcoin', + nativeAsset: 'RBTC', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'RBTC_TEST', + name: 'RSK Smart Bitcoin (Test)', + nativeAsset: 'RBTC_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x431CD3C9AC9Fc73644BF68bF5691f4B83F9E104f', + decimals: 18, + id: 'RBW_POLYGON_UZYB', + name: 'Rainbow Token', + nativeAsset: 'MATIC_POLYGON', + type: 'ERC20' + }, + { + contractAddress: '0xF970b8E36e23F7fC3FD752EeA86f8Be8D83375A6', + decimals: 18, + id: 'RCN', + name: 'Ripio Credit Network', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x252739487C1fa66eaeaE7CED41d6358aB2a6bCa9', + decimals: 8, + id: 'RCOIN', + name: 'ArCoin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x2d919F19D4892381D58edeBeca66D5642Cef1a1f', + decimals: 18, + id: 'RDOC_RBTC', + name: 'RIF Dollar on Chain (RSK)', + nativeAsset: 'RBTC', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 9, + id: 'REAL_SOL', + issuerAddress: 'AD27ov5fVU2XzwsbvnFvb1JpCBaCB5dRXrczV9CqSVGb', + name: 'Realy Token (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'REDBELLY', + name: 'Redbelly', + nativeAsset: 'REDBELLY', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'REDBELLY_TEST', + name: 'Redbelly Test', + nativeAsset: 'REDBELLY_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xFE3E6a25e6b192A42a44ecDDCd13796471735ACf', + decimals: 18, + id: 'REEF', + name: 'Reef.finance', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x408e41876cCCDC0F92210600ef50372656052a38', + decimals: 18, + id: 'REN', + name: 'Republic', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xEB4C2781e4ebA804CE9a9803C67d0893436bB27D', + decimals: 8, + id: 'RENBTC', + name: 'renBTC', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 8, + id: 'RENDER_SOL', + issuerAddress: 'rndrizKT3MK1iimdxRdWabcF7Zg7AR5T4nud4EkHBof', + name: 'Render Token (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x1985365e9f78359a9B6AD760e32412f4a445E862', + decimals: 18, + id: 'REP', + name: 'Augur', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x221657776846890989a759BA2973e427DfF5C9bB', + decimals: 18, + id: 'REPV2', + name: 'Reputation', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x8f8221aFbB33998d8584A2B05749bA73c37a938a', + decimals: 18, + id: 'REQ', + name: 'Request', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x557B933a7C2c45672B610F8954A3deB39a51A8Ca', + decimals: 18, + id: 'REVV', + name: 'REVV', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xa1d6Df714F91DeBF4e0802A542E13067f31b8262', + decimals: 18, + id: 'RFOX', + name: 'RFOX', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xd0929d411954c47438dc1d871dd6081F5C5e149c', + decimals: 4, + id: 'RFR', + name: 'Refereum', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xD291E7a03283640FDc51b121aC401383A46cC623', + decimals: 18, + id: 'RGT', + name: 'Rari Governance Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x168296bb09e24A88805CB9c33356536B980D3fC5', + decimals: 8, + id: 'RHOC', + name: 'RChain', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x2AcC95758f8b5F583470ba265EB685a8F45fC9D5', + decimals: 18, + id: 'RIF_RBTC', + name: 'RIF (RSK)', + nativeAsset: 'RBTC', + type: 'ERC20' + }, + { + contractAddress: '0xf4d27c56595Ed59B66cC7F03CFF5193e4bd74a61', + decimals: 18, + id: 'RIFP_RBTC', + name: 'RIF Pro (RSK)', + nativeAsset: 'RBTC', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 9, + id: 'RIN_SOL', + issuerAddress: 'E5ndSkaB17Dm7CsD22dvcjfrYSDLCxFcMd6z8ddCk5wp', + name: 'Aldrin (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x9469D013805bFfB7D3DEBe5E7839237e535ec483', + decimals: 18, + id: 'RING', + name: 'Darwinia Network Native Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x607F4C5BB672230e8672085532f7e901544a7375', + decimals: 9, + id: 'RLC', + name: 'iExec RLC', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xf1f955016EcbCd7321c7266BccFB96c68ea5E49b', + decimals: 18, + id: 'RLY', + name: 'Rally', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x8D5682941cE456900b12d47ac06a88b47C764CE1', + decimals: 18, + id: 'RMESH', + name: 'RightMesh', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x6De037ef9aD2725EB40118Bb1702EBb27e4Aeb24', + decimals: 18, + id: 'RNDR', + name: 'Render Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'RON', + name: 'Ronin', + nativeAsset: 'RON', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xfA5047c9c78B8877af97BDcb85Db743fD7313d4a', + decimals: 18, + id: 'ROOK', + name: 'ROOK', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x7eaF9C89037e4814DC0d9952Ac7F888C784548DB', + decimals: 18, + id: 'ROYA', + name: 'Royale', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xB4EFd85c19999D84251304bDA99E90B92300Bd93', + decimals: 18, + id: 'RPL', + name: 'Rocket Pool (Old)', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xD33526068D116cE69F19A9ee46F0bd304F21A51f', + decimals: 18, + id: 'RPL2', + name: 'Rocket Pool (New)', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x490c95bE16384E1f28B9e864e98fFEcFCBfF386d', + decimals: 18, + id: 'RPM', + name: 'Repme', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x320623b8E4fF03373931769A31Fc52A4E78B5d70', + decimals: 18, + id: 'RSR', + name: 'Reserve Rights (new contract)', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x8762db106B2c2A0bccB3A80d1Ed41273552616E8', + decimals: 18, + id: 'RSR_OLD', + name: 'Reserve Rights (old)', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x196f4727526eA7FB1e17b2071B3d8eAA38486988', + decimals: 18, + id: 'RSV', + name: 'Reserve', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 9, + id: 'RUN_SOL', + issuerAddress: '6F9XriABHfWhit6zmMUYAQBSy6XK5VF1cHXuW5LDpRtC', + name: 'Run Token (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x3155BA85D5F96b2d030a4966AF206230e46849cb', + decimals: 18, + id: 'RUNE', + name: 'THORChain ETH.RUNE', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xA9776B590bfc2f956711b3419910A5Ec1F63153E', + decimals: 18, + id: 'RUNE_BSC', + name: 'Rune (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '', + decimals: 8, + id: 'RUNE_THOR', + name: 'THORChain Rune', + nativeAsset: 'RUNE_THOR', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 8, + id: 'RUNE_THOR_TEST', + name: 'THORChain Rune Test', + nativeAsset: 'RUNE_THOR_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x8076C74C5e3F5852037F31Ff0093Eeb8c8ADd8D3', + decimals: 9, + id: 'SAFEMOON_BSC', + name: 'SafeMoon (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359', + decimals: 18, + id: 'SAI', + name: 'Sai', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x4156D3342D5c385a87D264F90653733592000581', + decimals: 8, + id: 'SALT', + name: 'SALT', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 9, + id: 'SAMO_SOL', + issuerAddress: '7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU', + name: 'Samoyed Coin (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x3845badAde8e6dFF049820680d1F14bD3903a5d0', + decimals: 18, + id: 'SAND', + name: 'SAND', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x7697B462A7c4Ff5F8b55BDBC2F4076c2aF9cF51A', + decimals: 18, + id: 'SARCO', + name: 'Sarcophagus', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xDf49C9f599A0A9049D97CFF34D0C30E468987389', + decimals: 18, + id: 'SATT', + name: 'Smart Advertising Transaction Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'SB_SOL', + issuerAddress: 'SuperbZyz7TsSdSoFAZ6RYHfAWe9NmjXBLVQpS8hqdx', + name: 'SuperBonds Token (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '', + decimals: 6, + id: 'SBR_SOL', + issuerAddress: 'Saber2gLauYim4Mvftnrasomsv6NvAuncvMEZwcLpD1', + name: 'Saber Protocol Token (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x74FD51a98a4A1ECBeF8Cc43be801cce630E260Bd', + decimals: 18, + id: 'SCC', + name: 'SiaCashCoin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'SCROLL', + name: 'Scroll Ethereum', + nativeAsset: 'SCROLL', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'SCROLL_SEPOLIA_TEST', + name: 'Scroll Sepolia Test', + nativeAsset: 'SCROLL_SEPOLIA_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 9, + id: 'SCT_SOL', + issuerAddress: '4Te4KJgjtnZe4aE2zne8G4NPfrPjCwDmaiEx9rKnyDVZ', + name: 'SolClout (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '', + decimals: 9, + id: 'SCY_SOL', + issuerAddress: 'SCYfrGCw8aDiqdgcpdGjV6jp4UVVQLuphxTDLNWu36f', + name: 'Synchrony (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x993864E43Caa7F7F12953AD6fEb1d1Ca635B875F', + decimals: 18, + id: 'SDAO', + name: 'Singularity Dao', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'SEI', + name: 'Sei', + nativeAsset: 'SEI', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'SEI_TEST', + name: 'Sei', + nativeAsset: 'SEI_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 2, + id: 'SEN_TEST_USD', + name: 'Silvergate SEN Test', + nativeAsset: 'SEN_TEST_USD', + type: 'FIAT' + }, + { + contractAddress: '', + decimals: 2, + id: 'SEN_USD', + name: 'Silvergate SEN', + nativeAsset: 'SEN_USD', + type: 'FIAT' + }, + { + contractAddress: '0x6745fAB6801e376cD24F03572B9C9B0D4EdDDCcf', + decimals: 8, + id: 'SENSE', + name: 'Sense', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xD71eCFF9342A5Ced620049e616c5035F1dB98620', + decimals: 18, + id: 'SEUR', + name: 'Synth sEUR', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xb753428af26E81097e7fD17f40c88aaA3E04902c', + decimals: 18, + id: 'SFI', + name: 'Spice', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xed0849BF46CfB9845a2d900A0A4E593F2dD3673c', + decimals: 18, + id: 'SGA', + name: 'Saga', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'SGB', + name: 'Songbird', + nativeAsset: 'SGB', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'SGB_LEGACY', + name: 'Songbird (Legacy derivation)', + nativeAsset: 'SGB_LEGACY', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xB2135AB9695a7678Dd590B1A996CB0f37BCB0718', + decimals: 9, + id: 'SGN', + name: 'Signals Network', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xAEa8e1b6CB5c05D1dAc618551C76bcD578EA3524', + decimals: 18, + id: 'SGR', + name: 'Sogur', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x232FB065D9d24c34708eeDbF03724f2e95ABE768', + decimals: 18, + id: 'SHEESHA_BSC', + name: 'Sheesha Finance', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0xcba3eAe7f55D0F423AF43cC85E67ab0fBF87B61C', + decimals: 18, + id: 'SHFT', + name: 'Shyft [ Byfrost ]', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xb17C88bDA07D28B3838E0c1dE6a30eAfBCF52D85', + decimals: 18, + id: 'SHFT_WRAPPED', + name: 'Shyft _ Wrapped _', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x95aD61b0a150d79219dCF64E1E6Cc01f0B64C4cE', + decimals: 18, + id: 'SHIB', + name: 'SHIBA INU', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x2859e4544C4bB03966803b044A93563Bd2D0DD4D', + decimals: 18, + id: 'SHIB_BSC', + name: 'SHIBA INU (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '', + decimals: 8, + id: 'SHIB_SOL', + issuerAddress: 'CiKu4eHsVrc1eueVQeHn7qhXTcVu95gSQmBpX4utjL9z', + name: 'SHIBA INU (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '', + decimals: 6, + id: 'SHILL_SOL', + issuerAddress: '6cVgJUqo4nmvQpbgrDZwyfd6RwWw5bfnCamS3M9N1fd', + name: 'Project SEED Token (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0xe25b0BBA01Dc5630312B6A21927E578061A13f55', + decimals: 18, + id: 'SHIP', + name: 'ShipChain', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x7BEF710a5759d197EC0Bf621c3Df802C2D60D848', + decimals: 18, + id: 'SHOPX', + name: 'SPLYT SHOPX', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x7C84e62859D0715eb77d1b1C4154Ecd6aBB21BEC', + decimals: 18, + id: 'SHPING', + name: 'Shping Coin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xd98F75b1A3261dab9eEd4956c93F33749027a964', + decimals: 2, + id: 'SHR', + name: 'ShareToken', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 7, + id: 'SHX_XLM', + issuerAddress: 'GDSTRSHXHGJ7ZIVRBXEYE5Q74XUVCUSEKEBR7UCHEUUEK72N7I7KJ6JH', + name: 'Stronghold SHx (Stellar)', + nativeAsset: 'XLM', + type: 'XLM_ASSET' + }, + { + contractAddress: '0x549020a9Cb845220D66d3E9c6D9F9eF61C981102', + decimals: 18, + id: 'SIDUS', + name: 'SIDUS', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 2, + id: 'SIGNET_TEST_USD', + name: 'Signet Test', + nativeAsset: 'SIGNET_TEST_USD', + type: 'FIAT' + }, + { + contractAddress: '', + decimals: 2, + id: 'SIGNET_USD', + name: 'Signet', + nativeAsset: 'SIGNET_USD', + type: 'FIAT' + }, + { + contractAddress: '0x6D728fF862Bfe74be2aba30537E992A24F259a22', + decimals: 18, + id: 'SIH', + name: 'Salient Investment Holding', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xd38BB40815d2B0c2d2c866e0c72c5728ffC76dd9', + decimals: 18, + id: 'SIS', + name: 'Symbiosis', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x00c83aeCC790e8a4453e5dD3B0B4b3680501a7A7', + decimals: 18, + id: 'SKL', + name: 'SKALE', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'SLC_SOL', + issuerAddress: 'METAmTMXwdb8gYzyCPfXXFmZZw4rUsXX58PNsDg7zjL', + name: 'Solice', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '', + decimals: 6, + id: 'SLIM_SOL', + issuerAddress: 'xxxxa1sKNGwFtw2kFn8XauW9xq8hBZ5kVtcSesTT9fW', + name: 'Solanium (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '', + decimals: 6, + id: 'SLND_SOL', + issuerAddress: 'SLNDpmoWTVADgEdndyvWzroNL7zSi1dF9PC3xHGtPwp', + name: 'Solend (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0xd4e7a6e2D03e4e48DfC27dd3f46DF1c176647E38', + decimals: 18, + id: 'SLP_D4E7A_ETH', + name: 'SushiSwap LP Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xa8754b9Fa15fc18BB59458815510E40a12cD2014', + decimals: 0, + id: 'SLP_RON', + name: 'Smooth Love Potion (Ronin)', + nativeAsset: 'RON', + type: 'ERC20' + }, + { + contractAddress: '0xCC8Fa225D80b9c7D42F96e9570156c65D6cAAa25', + decimals: 0, + id: 'SLP1', + name: 'Smooth Love Potion', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x397FF1542f962076d0BFE58eA045FfA2d347ACa0', + decimals: 18, + id: 'SLPUSDCETH', + name: 'SushiSwap USDC/ETH LP', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'SLRS_SOL', + issuerAddress: 'SLRSSpSLUTP7okbCUBYStWCo1vUgyt775faPqz8HUMr', + name: 'Solrise Finance (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'SMARTBCH', + name: 'SmartBCH', + nativeAsset: 'SMARTBCH', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'SMR_SMR', + name: 'Shimmer', + nativeAsset: 'SMR_SMR', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'SMR_TEST', + name: 'Shimmer Test', + nativeAsset: 'SMR_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xF4134146AF2d511Dd5EA8cDB1C4AC88C57D60404', + decimals: 18, + id: 'SNC', + name: 'SunContract', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xaeC2E87E0A235266D9C5ADc9DEb4b2E29b54D009', + decimals: 0, + id: 'SNGLS', + name: 'SingularDTV', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x983F6d60db79ea8cA4eB9968C6aFf8cfA04B3c63', + decimals: 18, + id: 'SNM', + name: 'SONM', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x744d70FDBE2Ba4CF95131626614a1763DF805B9E', + decimals: 18, + id: 'SNT', + name: 'Status', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F', + decimals: 18, + id: 'SNX', + name: 'Synthetix Network Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x23B608675a2B2fB1890d3ABBd85c5775c51691d5', + decimals: 18, + id: 'SOCKS', + name: 'Unisocks Edition 0', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'SOETH_SOL', + issuerAddress: '2FPyTwcZLUg1MDrwsyoP4D6s1tM7hAkHYRjkNb5w6Pxk', + name: 'Wrapped Ethereum (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x04F2694C8fcee23e8Fd0dfEA1d4f5Bb8c352111F', + decimals: 9, + id: 'SOHM', + name: 'Staked Olympus', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 9, + id: 'SOL', + name: 'Solana', + nativeAsset: 'SOL', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x41848d32f281383F214C69B7b248DC7C2E0a7374', + decimals: 18, + id: 'SOL_BSC', + name: 'Solana (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '', + decimals: 6, + id: 'SOL_MAPS_FD7T', + issuerAddress: 'MAPS41MDahZ9QdKXhVa4dWB9RuyfV4XqhyAZ8XcYepb', + name: 'MAPS (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '', + decimals: 6, + id: 'SOL_OXY_4TTN', + issuerAddress: 'z3dn17yLaGMKffVogeFHQ9zWVcXgqgf3PQnDsNs2g6M', + name: 'Oxygen (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '', + decimals: 6, + id: 'SOL_SRM_R62M', + issuerAddress: 'SRMuApVNdxXokk5GT7XD5cUUgXMBCoAz2LHeuAoKWRt', + name: 'Serum (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '', + decimals: 9, + id: 'SOL_TEST', + name: 'Solana Test', + nativeAsset: 'SOL_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 9, + id: 'SOL_TTOKEN_CHGU', + issuerAddress: 'FYEEA9iZJpad1ZCkigi9BvkCNcW4QNun23hEPrAfELDA', + name: 'Solana Test Token', + nativeAsset: 'SOL_TEST', + type: 'SOL_ASSET' + }, + { + contractAddress: '', + decimals: 6, + id: 'SOL_USDC_PTHX', + issuerAddress: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', + name: 'USD Coin (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '', + decimals: 6, + id: 'SOL_USDT_EWAY', + issuerAddress: 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB', + name: 'USDT (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x570A5D26f7765Ecb712C0924E4De545B89fD43dF', + decimals: 18, + id: 'SOL2_BSC', + name: 'SOLANA BSC (2)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0x446C9033E7516D820cc9a2ce2d0B7328b579406F', + decimals: 8, + id: 'SOLVE', + name: 'Solve.Care', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 9, + id: 'SOLX_SOL', + issuerAddress: 'CH74tuRLTYcxG7qNJCsV9rghfLXJCQJbsu7i52a8F1Gn', + name: 'Soldex (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x3E8FFc8c3Cb0DB3081Df85DeC91B63abBbe99F71', + decimals: 18, + id: 'SOME', + name: 'Mixsome', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 9, + id: 'SONAR_SOL', + issuerAddress: 'sonarX4VtVkQemriJeLm6CKeW3GDMyiBnnAEMw1MRAE', + name: 'Sonar Watch (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'SONEIUM_MINATO_TEST', + name: 'Soneium Minato Test', + nativeAsset: 'SONEIUM_MINATO_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xEFc78fc7d48b64958315949279Ba181c2114ABBd', + decimals: 18, + id: 'SOV_RBTC', + name: 'Sovryn Token (RSK)', + nativeAsset: 'RBTC', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 2, + id: 'SPEI_MXN', + name: 'MXN (SPEI)', + nativeAsset: 'SPEI_MXN', + type: 'FIAT' + }, + { + contractAddress: '0x090185f2135308BaD17527004364eBcC2D37e5F6', + decimals: 18, + id: 'SPELL', + name: 'Spell Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xE11829A7D5d8806BB36E118461a1012588faFD89', + decimals: 18, + id: 'SPICE_SMARTBCH', + name: 'SPICE (SmartBCH)', + nativeAsset: 'SMARTBCH', + type: 'ERC20' + }, + { + contractAddress: '0x1633b7157e7638C4d6593436111Bf125Ee74703F', + decimals: 18, + id: 'SPS_BSC', + name: 'Splintershards (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0xe516D78d784C77D479977BE58905B3f2b1111126', + decimals: 18, + id: 'SPWN', + name: 'BitSpawn Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 9, + id: 'SPWN_SOL', + issuerAddress: '5U9QqCPhqXAJcEv9uyzFJd5zhN93vuPk1aNNkXnUfPnt', + name: 'Bitspawn Token (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x476c5E26a75bd202a9683ffD34359C0CC15be0fF', + decimals: 6, + id: 'SRM', + name: 'Serum', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x68d57c9a1C35f63E2c83eE8e49A64e9d70528D25', + decimals: 18, + id: 'SRN', + name: 'SIRIN LABS Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x624d520BAB2E4aD83935Fa503fB130614374E850', + decimals: 4, + id: 'SSP', + name: 'smartshare token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x0Ae055097C6d159879521C384F1D2123D1f195e6', + decimals: 18, + id: 'STAKE', + name: 'STAKE', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x78474F29aF6D4EB0cfB3168eff1c117cf13569e8', + decimals: 8, + id: 'STDASH', + name: 'stakedDASH', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xD79311EB6c74C408e678b8364B69B4744A5778f4', + decimals: 10, + id: 'STDOT', + name: 'stakedDOT', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 9, + id: 'STEP_SOL', + issuerAddress: 'StepAscQoEioFxxWGnh2sLBDFp9d8rvKz2Yp39iDpyT', + name: 'Step (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0xDFe66B14D37C77F4E9b180cEb433d1b164f0281D', + decimals: 18, + id: 'STETH', + name: 'stakedETH', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84', + decimals: 18, + id: 'STETH_ETH', + name: 'Liquid staked Ether 2_0', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x3F1c547b21f65e10480dE3ad8E19fAAC46C95034', + decimals: 18, + id: 'STETH_ETH_TEST6_DZFA', + name: 'Liquid staked Ether 2_0', + nativeAsset: 'ETH_TEST6', + type: 'ERC20' + }, + { + contractAddress: '0x160B1E5aaBFD70B2FC40Af815014925D71CEEd7E', + decimals: 8, + id: 'STFIRO', + name: 'stakedFiro', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xAf5191B0De278C7286d6C7CC6ab6BB8A73bA2Cd6', + decimals: 18, + id: 'STG', + name: 'StargateToken', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xD309142A629d07B023E5007feeF608d161B01156', + decimals: 18, + id: 'STGFBTC', + name: 'stgfBTC', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xe2ff59F37C3F07100bdEb5F79B98131F18D9D28B', + decimals: 18, + id: 'STGFETH', + name: 'stgfETH', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x8B6327a3050798b7A2843A6Edd0B310E97BEE113', + decimals: 18, + id: 'STGFUSD', + name: 'stgfUSD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x7A4B43dE058073F49774eA527Fc24Abd29e2738D', + decimals: 18, + id: 'STGFUSD_SMARTBCH', + name: 'stgfUSD (SmartBCH)', + nativeAsset: 'SMARTBCH', + type: 'ERC20' + }, + { + contractAddress: '0x4da27a545c0c5B758a6BA100e3a049001de870f5', + decimals: 18, + id: 'STKAAVE', + name: 'Staked Aave', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x19FfA8fc52dF8982cEa39B492E56AbB2f8Abc644', + decimals: 18, + id: 'STMATIC', + name: 'stakedMATIC', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xbE9375C6a420D2eEB258962efB95551A5b722803', + decimals: 18, + id: 'STMX', + name: 'StormX', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xB64ef51C888972c908CFacf59B47C1AfBC0Ab8aC', + decimals: 8, + id: 'STORJ', + name: 'Storj', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xD0a4b8946Cb52f0661273bfbC6fD0E0C75Fc6433', + decimals: 18, + id: 'STORM', + name: 'Storm', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xDe7D85157d9714EADf595045CC12Ca4A5f3E2aDb', + decimals: 18, + id: 'STPT', + name: 'STPT', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 9, + id: 'STR_SOL', + issuerAddress: '9zoqdwEBKWEi9G5Ze8BSkdmppxGgVv1Kw4LuigDiNr9m', + name: 'Solster', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x990f341946A3fdB507aE7e52d17851B87168017c', + decimals: 18, + id: 'STRONG', + name: 'Strong', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 9, + id: 'STSOL_SOL', + issuerAddress: '7dHbWXmci3dT8UFYWYZweBLXgycu7Y3iL6trKn1Y7ARj', + name: 'Lido Staked SOL (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x0371A82e4A9d0A4312f3ee2Ac9c6958512891372', + decimals: 18, + id: 'STU', + name: 'bitJob', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x006BeA43Baa3f7A6f765F14f10A1a1b08334EF45', + decimals: 18, + id: 'STX', + name: 'Stox', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x0C63cAE5fcC2Ca3dDE60a35e50362220651eBEc8', + decimals: 8, + id: 'STXEM', + name: 'stakedXEM', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x31B595e7cfDB624D10A3E7A562eD98c3567e3865', + decimals: 8, + id: 'STZEN', + name: 'stakedZEN', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x8D75959f1E61EC2571aa72798237101F084DE63a', + decimals: 18, + id: 'SUB', + name: 'Substratum', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x0763fdCCF1aE541A5961815C0872A8c5Bc6DE4d7', + decimals: 18, + id: 'SUKU', + name: 'SUKU Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'SUNNY_SOL', + issuerAddress: 'SUNNYWgPQmFxe9wTZzNK7iPnJ3vYDrkgnxJRJm1s3ag', + name: 'Sunny Governance Token (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0xe53EC727dbDEB9E2d5456c3be40cFF031AB40A55', + decimals: 18, + id: 'SUPER', + name: 'SuperVerse', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x57Ab1ec28D129707052df4dF418D58a2D46d5f51', + decimals: 18, + id: 'SUSD', + name: 'Synth sUSD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x6B3595068778DD592e39A122f4f5a5cF09C90fE2', + decimals: 18, + id: 'SUSHI', + name: 'Sushi Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x0b3F868E0BE5597D5DB7fEB59E1CADBb0fdDa50a', + decimals: 18, + id: 'SUSHI_POLYGON', + name: 'SushiSwap (Polygon)', + nativeAsset: 'MATIC_POLYGON', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 8, + id: 'SUSHI_SOL', + issuerAddress: 'ChVzxWRmrTeSgwd3Ui3UumcN8KX7VK3WaD4KGeSKpypj', + name: 'SushiToken (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '', + decimals: 6, + id: 'SVT_SOL', + issuerAddress: 'svtMpL5eQzdmB3uqK9NXaQkq8prGZoKQFNVJghdWCkV', + name: 'Solvent', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'SWEAT_NEAR', + issuerAddress: 'token.sweat', + name: 'SWEAT', + nativeAsset: 'NEAR', + type: 'NEAR_ASSET' + }, + { + contractAddress: '0x48C3399719B582dD63eB5AADf12A40B4C3f52FA2', + decimals: 18, + id: 'SWISE', + name: 'StakeWise', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xB8BAa0e4287890a5F79863aB62b7F175ceCbD433', + decimals: 18, + id: 'SWRV', + name: 'Swerve DAO Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x8CE9137d39326AD0cD6491fb5CC0CbA0e089b6A9', + decimals: 18, + id: 'SXP', + name: 'Swipe', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xf293d23BF2CDc05411Ca0edDD588eb1977e8dcd4', + decimals: 18, + id: 'SYLO', + name: 'Sylo', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x0f2D719407FdBeFF09D87557AbB7232601FD9F29', + decimals: 18, + id: 'SYN', + name: 'Synapse', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 9, + id: 'SYP_SOL', + issuerAddress: 'FnKE9n6aGjQoNWRBZXy4RW6LZVao7qwBonUbiD7edUmZ', + name: 'Sypool (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '', + decimals: 6, + id: 't14_XRP_TEST_YB4D', + issuerAddress: 'rDFUVuBZmdACfEm44ieCu73CE75pdi4fXa', + name: 't14', + nativeAsset: 'XRP_TEST', + type: 'XRP_ASSET' + }, + { + contractAddress: '', + decimals: 7, + id: 'TAB1_XLM_OXFD_YK4G', + issuerAddress: 'GCWAT6HJIHKNCA6UELZCIRLXP44RDVVPN2NOFNVLFOEOXG7GMK7AOSH3', + name: 'TAB1 (Stellar Test)', + nativeAsset: 'XLM_TEST', + type: 'XLM_ASSET' + }, + { + contractAddress: '0xc27A2F05fa577a83BA0fDb4c38443c0718356501', + decimals: 18, + id: 'TAU', + name: 'Lamden Tau', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xdFa3b0019EcF48c753B58908B5A21d11641bA56f', + decimals: 18, + id: 'TAU_BSC', + name: 'Lamden', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0x00006100F7090010005F1bd7aE6122c3C2CF0090', + decimals: 18, + id: 'TAUD', + name: 'TrueAUD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x8dAEBADE922dF735c38C80C7eBD708Af50815fAa', + decimals: 18, + id: 'TBTC', + name: 'tBTC', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x00000100F2A2bd000715001920eB70D229700085', + decimals: 18, + id: 'TCAD', + name: 'TrueCAD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xA72159FC390f0E3C6D415e658264c7c4051E9b87', + decimals: 18, + id: 'TCR_ARB', + name: 'Tracer', + nativeAsset: 'ETH-AETH', + type: 'ERC20' + }, + { + contractAddress: '0x467Bccd9d29f223BcE8043b84E8C8B282827790F', + decimals: 2, + id: 'TEL', + name: 'Telcoin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'TELOS', + name: 'TELOS', + nativeAsset: 'TELOS', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'TELOS_TEST', + name: 'Telos Test', + nativeAsset: 'TELOS_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xDD16eC0F66E54d453e6756713E533355989040E4', + decimals: 18, + id: 'TEN', + name: 'Tokenomy', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x00000000441378008EA67F4284A57932B1c000a5', + decimals: 18, + id: 'TGBP', + name: 'TrueGBP', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x0000852600CEB001E08e00bC008be620d60031F2', + decimals: 18, + id: 'THKD', + name: 'TrueHKD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x1Cb3209D45B2a60B7fBCA1cCDBF87f674237A4aa', + decimals: 4, + id: 'THR', + name: 'ThoreCoin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x29CbD0510EEc0327992CD6006e63F9Fa8E7f33B7', + decimals: 18, + id: 'TIDAL', + name: 'Tidal Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xb54f16fB19478766A268F172C9480f8da1a7c9C3', + decimals: 9, + id: 'TIME_AVAX', + name: 'Time (Avalanche)', + nativeAsset: 'AVAX', + type: 'ERC20' + }, + { + contractAddress: '0x3A8cCCB969a61532d1E6005e2CE12C200caeCe87', + decimals: 18, + id: 'TITAN', + name: 'TitanSwap', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x24E89bDf2f65326b94E36978A7EDeAc63623DAFA', + decimals: 18, + id: 'TKING', + name: 'Tiger King', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x9f589e3eabe42ebC94A44727b3f3531C0c877809', + decimals: 18, + id: 'TKO', + name: 'TKO (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '', + decimals: 18, + id: 'TKX', + name: 'TokenX', + nativeAsset: 'TKX', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x888888848B652B3E3a0f34c96E00EEC0F3a23F72', + decimals: 4, + id: 'TLM1', + name: 'Alien Worlds Trilium', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x08f5a9235B08173b7569F83645d2c7fB55e8cCD8', + decimals: 8, + id: 'TNT', + name: 'Tierion', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x2e9d63788249371f1DFC918a52f8d799F4a38C94', + decimals: 18, + id: 'TOKE', + name: 'Tokemak', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x4507cEf57C46789eF8d1a19EA45f4216bae2B528', + decimals: 9, + id: 'TOKEN_BSC_RLDP', + name: 'TokenFi', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0x4507cEf57C46789eF8d1a19EA45f4216bae2B528', + decimals: 9, + id: 'TOKEN_ETH_JIKQ', + name: 'TokenFi', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 9, + id: 'TON', + name: 'TON', + nativeAsset: 'TON', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 9, + id: 'TON_TEST', + name: 'TON Test', + nativeAsset: 'TON_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xdcD85914b8aE28c1E62f1C488E1D968D5aaFfE2b', + decimals: 18, + id: 'TOP', + name: 'TOP Network', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x3Dd98C8A089dBCFF7e8FC8d4f532BD493501Ab7F', + decimals: 8, + id: 'TOWN', + name: 'TownCoin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xaA7a9CA87d3694B5755f213B5D04094b8d0F0A6F', + decimals: 18, + id: 'TRAC', + name: 'OriginTrail', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x88dF592F8eb5D7Bd38bFeF7dEb0fBc02cf3778a0', + decimals: 18, + id: 'TRB', + name: 'Tellor Tributes', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x0Ba45A8b5d5575935B8158a88C631E9F9C95a2e5', + decimals: 18, + id: 'TRB_L', + name: 'Tellor Tributes (Legacy)', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xc7283b66Eb1EB5FB86327f08e1B5816b0720212B', + decimals: 18, + id: 'TRIBE', + name: 'Tribe', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x4C19596f5aAfF459fA38B0f7eD92F11AE6543784', + decimals: 8, + id: 'TRU', + name: 'TrueFi', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xA4d17AB1eE0efDD23edc2869E7BA96B89eEcf9AB', + decimals: 18, + id: 'TRUE', + name: 'TrueChain', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'TRX', + name: 'Tron', + nativeAsset: 'TRX', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x85EAC5Ac2F758618dFa09bDbe0cf174e7d574D5B', + decimals: 18, + id: 'TRX_BSC', + name: 'TRON (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '', + decimals: 6, + id: 'TRX_TEST', + name: 'Tron Test', + nativeAsset: 'TRX_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 6, + id: 'TRX_USDC_6NU3', + issuerAddress: 'TEkxiTehnzSmSe2XqrBj4w32RUN966rdz8', + name: 'USD Coin (Tron)', + nativeAsset: 'TRX', + type: 'TRON_TRC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'TRX_USDC_SKL5', + issuerAddress: 'TFGBSrddCjLJAwuryZ9DUxtEmKv13BPjnh', + name: 'USD Coin Test (Tron)', + nativeAsset: 'TRX_TEST', + type: 'TRON_TRC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'TRX_USDT_S2UZ', + issuerAddress: 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t', + name: 'USD Tether (Tron)', + nativeAsset: 'TRX', + type: 'TRON_TRC20' + }, + { + contractAddress: '0x2C537E5624e4af88A7ae4060C022609376C8D0EB', + decimals: 6, + id: 'TRYB', + name: 'BiLira', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x564A341Df6C126f90cf3ECB92120FD7190ACb401', + decimals: 6, + id: 'TRYB_AVAX', + name: 'BiLira (Avalanche)', + nativeAsset: 'AVAX', + type: 'ERC20' + }, + { + contractAddress: '0xC1fdbed7Dac39caE2CcC0748f7a80dC446F6a594', + decimals: 6, + id: 'TRYB_BSC', + name: 'BiLira (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '', + decimals: 6, + id: 'TRYB_SOL', + issuerAddress: 'A94X2fRy3wydNShU4dRaDyap2UuoeWJGWyATtyp61WZf', + name: 'BiLira (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0xD9baE39c725A1864b1133Ad0eF1640d02f79B78c', + decimals: 18, + id: 'TST', + name: 'Touch Smart Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xa760e26aA76747020171fCF8BdA108dFdE8Eb930', + decimals: 18, + id: 'TTOKE', + name: 'TokemakTokePool', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x9F599410D207f3D2828a8712e5e543AC2E040382', + decimals: 18, + id: 'TTT', + name: 'Tapcoin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'TTT_SPL', + issuerAddress: 'FNFKRV3V8DtA3gVJN6UshMiLGYA8izxFwkNWmJbFjmRj', + name: 'TabTrader (SOLANA)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x6558392AfdA386d1A6b451640e809a27153151d8', + decimals: 18, + id: 'TTTT_ETH_TEST6', + name: 'TTTT_ETH_TEST6', + nativeAsset: 'ETH_TEST6', + type: 'ERC20' + }, + { + contractAddress: '0x0000000000085d4780B73119b644AE5ecd22b376', + decimals: 18, + id: 'TUSD', + name: 'TrueUSD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x1C20E891Bab6b1727d14Da358FAe2984Ed9B59EB', + decimals: 18, + id: 'TUSD_AVAX', + name: 'TrueUSD (Avalanche)', + nativeAsset: 'AVAX', + type: 'ERC20' + }, + { + contractAddress: '0xd084B83C305daFD76AE3E1b4E1F1fe2eCcCb3988', + decimals: 18, + id: 'TVK', + name: 'Terra Virtua Kolect', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x4463e6A3dEd0dBE3F6e15bC8420dFc55e5FeA830', + decimals: 18, + id: 'TXA', + name: 'TXA', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x547b2F82ceCfAb9C2B1D36fddA96eF9F58C63B8C', + decimals: 18, + id: 'TXT', + name: 'Taxa Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x8400D94A5cb0fa0D041a3788e395285d61c9ee5e', + decimals: 8, + id: 'UBT', + name: 'UniBright', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x8a3d77e9d6968b780564936d15B09805827C21fa', + decimals: 18, + id: 'UCO', + name: 'UnirisToken', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xD1E5b0FF1287aA9f9A268759062E4Ab08b9Dacbe', + decimals: 18, + id: 'UD', + name: '.crypto', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x12f649A9E821F90BB143089a6e56846945892ffB', + decimals: 18, + id: 'UDOO', + name: 'uDOO', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x0202Be363B8a4820f3F4DE7FaF5224fF05943AB1', + decimals: 18, + id: 'UFT', + name: 'UniLend Finance Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x24692791Bc444c5Cd0b81e3CBCaba4b04Acd1F3B', + decimals: 18, + id: 'UKG', + name: 'Unikoin Gold', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x04Fa0d235C4abf4BcF4787aF4CF447DE572eF828', + decimals: 18, + id: 'UMA', + name: 'UMA Voting Token v1', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x5872E64C3f93363822D2B1e4717Be3398FDCEA51', + decimals: 18, + id: 'UMASK', + name: 'Hashmask', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x6fC13EACE26590B80cCCAB1ba5d51890577D83B2', + decimals: 18, + id: 'UMB', + name: 'Umbrella', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984', + decimals: 18, + id: 'UNI', + name: 'Uniswap', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xBf5140A22578168FD562DCcF235E5D43A02ce9B1', + decimals: 18, + id: 'UNI_BSC', + name: 'Binance-Peg Uniswap (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984', + decimals: 18, + id: 'UNI_ETH_TEST5_IXAC', + name: 'Uniswap', + nativeAsset: 'ETH_TEST5', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 8, + id: 'UNI_SOL', + issuerAddress: '8FU95xFJhUUkyyCLU13HSzDLs7oC4QZdXQHL6SCeab36', + name: 'Uniswap (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x9861F7187b58023d89B2C2b0767bdEE43345620A', + decimals: 18, + id: 'UNI-V2-2GT-2', + name: 'Uniswap V2: 2GT 2', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x600Cf1C039e1fD31Bc4762a39D322Dd8977Dd1aB', + decimals: 18, + id: 'UNI-V2-SMOL', + name: 'Uniswap V2: SMOL', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x64060aB139Feaae7f06Ca4E63189D86aDEb51691', + decimals: 18, + id: 'UNIM_POLYGON_LACR', + name: 'Unicorn Milk', + nativeAsset: 'MATIC_POLYGON', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'UNQ_SOL', + issuerAddress: 'UNQtEecZ5Zb4gSSVHCAWUQEoNnSVEbWiKCi1v9kdUJJ', + name: 'UNQ', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0xD13c7342e1ef687C5ad21b27c2b65D772cAb5C8c', + decimals: 4, + id: 'UOS', + name: 'Ultra Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xc7461b398005e50BCc43c8e636378C6722E76c01', + decimals: 8, + id: 'UPBTC', + name: 'Universal Bitcoin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x6C103D85C15107Dce19F5a75fC746227e610AaBd', + decimals: 2, + id: 'UPEUR', + name: 'Universal Euro', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xC86D054809623432210c107af2e3F619DcFbf652', + decimals: 18, + id: 'UPP', + name: 'SENTINEL PROTOCOL', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x6CA88Cc8D9288f5cAD825053B6A1B179B05c76fC', + decimals: 18, + id: 'UPT', + name: 'Universal Protocol Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x86367c0e517622DAcdab379f2de389c3C9524345', + decimals: 2, + id: 'UPUSD', + name: 'Universal US Dollar', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x0557Df767419296474C3f551Bb0A0ED4c2DD3380', + decimals: 5, + id: 'UPXAU', + name: 'Universal Gold', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 2, + id: 'USD_BY_WIRE', + name: 'USD (wire)', + nativeAsset: 'USD_BY_WIRE', + type: 'FIAT' + }, + { + contractAddress: '', + decimals: 2, + id: 'USD_BY_WIRE_TEST', + name: 'USD Test (wire)', + nativeAsset: 'USD_BY_WIRE_TEST', + type: 'FIAT' + }, + { + contractAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + decimals: 6, + id: 'USDC', + name: 'USD Coin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582', + decimals: 6, + id: 'USDC_AMOY_POLYGON_TEST_7WWV', + name: 'USDC', + nativeAsset: 'AMOY_POLYGON_TEST', + type: 'ERC20' + }, + { + contractAddress: '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', + decimals: 6, + id: 'USDC_ARB', + name: 'Bridged USDC (Arbitrum)', + nativeAsset: 'ETH-AETH', + type: 'ERC20' + }, + { + contractAddress: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', + decimals: 6, + id: 'USDC_ARB_3SBJ', + name: 'USD Coin (Arbitrum)', + nativeAsset: 'ETH-AETH', + type: 'ERC20' + }, + { + contractAddress: '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E', + decimals: 6, + id: 'USDC_AVAX', + name: 'USD Coin (Avalanche)', + nativeAsset: 'AVAX', + type: 'ERC20' + }, + { + contractAddress: '0x5425890298aed601595a70AB815c96711a31Bc65', + decimals: 6, + id: 'USDC_AVAX_FUJI', + name: ' USD Coin (Avalanche Fuji)', + nativeAsset: 'AVAXTEST', + type: 'ERC20' + }, + { + contractAddress: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', + decimals: 6, + id: 'USDC_BASECHAIN_ETH_5I5C', + name: 'USD Coin', + nativeAsset: 'BASECHAIN_ETH', + type: 'ERC20' + }, + { + contractAddress: '0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d', + decimals: 18, + id: 'USDC_BSC', + name: 'Binance-Peg USD Coin (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0xcebA9300f2b948710d2653dD7B07f33A8B32118C', + decimals: 6, + id: 'USDC_CELO_ROI8', + name: 'USDC', + nativeAsset: 'CELO', + type: 'ERC20' + }, + { + contractAddress: '0xA7D7079b0FEaD91F3e65f86E8915Cb59c1a4C664', + decimals: 6, + id: 'USDC_E_AVAX', + name: 'USD Coin (Avalanche)', + nativeAsset: 'AVAX', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'USDC_E_NEAR', + issuerAddress: 'a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48.factory.bridge.near', + name: 'USD Coin Bridged', + nativeAsset: 'NEAR', + type: 'NEAR_ASSET' + }, + { + contractAddress: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238', + decimals: 6, + id: 'USDC_ETH_TEST5_0GER', + name: 'USDC', + nativeAsset: 'ETH_TEST5', + type: 'ERC20' + }, + { + contractAddress: '0x04068DA6C83AFCFA0e13ba15A6696662335D5B75', + decimals: 6, + id: 'USDC_FANTOM', + name: 'USD Coin (Fantom)', + nativeAsset: 'FTM_FANTOM', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'USDC_NEAR', + issuerAddress: '17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a1', + name: 'USD Coin', + nativeAsset: 'NEAR', + type: 'NEAR_ASSET' + }, + { + contractAddress: '', + decimals: 6, + id: 'USDC_NOBLE', + name: 'USDC Noble', + nativeAsset: 'USDC_NOBLE', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 6, + id: 'USDC_NOBLE_TEST', + name: 'USDC Noble Testnet', + nativeAsset: 'USDC_NOBLE_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174', + decimals: 6, + id: 'USDC_POLYGON', + name: 'USD Coin (Polygon)', + nativeAsset: 'MATIC_POLYGON', + type: 'ERC20' + }, + { + contractAddress: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359', + decimals: 6, + id: 'USDC_POLYGON_NXTB', + name: 'USD Coin (Polygon)', + nativeAsset: 'MATIC_POLYGON', + type: 'ERC20' + }, + { + contractAddress: '0xBdbe4D9e43E8f305AfE9462802B8691C45Caf596', + decimals: 18, + id: 'USDD', + name: 'USD Digital', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x1c48f86ae57291F7686349F12601910BD8D470bb', + decimals: 18, + id: 'USDK', + name: 'USDK', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xbdC7c08592Ee4aa51D06C27Ee23D5087D65aDbcD', + decimals: 18, + id: 'USDL_ETH_HYWN', + name: 'Lift Dollar', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x674C6Ad92Fd080e4004b2312b45f796a192D27a0', + decimals: 18, + id: 'USDN', + name: 'Neutrino USD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x3A15461d8aE0F0Fb5Fa2629e9DA7D66A794a6e37', + decimals: 18, + id: 'USDRIF_RSK_14FQ', + name: 'RIF US Dollar', + nativeAsset: 'RBTC', + type: 'ERC20' + }, + { + contractAddress: '0xA4Bdb11dc0a2bEC88d24A3aa1E6Bb17201112eBe', + decimals: 6, + id: 'USDS', + name: 'StableUSD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xc7198437980c041c805A1EDcbA50c1Ce5db95118', + decimals: 6, + id: 'USDT_AVAX', + name: 'Tether USD (Avalanche)', + nativeAsset: 'AVAX', + type: 'ERC20' + }, + { + contractAddress: '0x55d398326f99059fF775485246999027B3197955', + decimals: 18, + id: 'USDT_BSC', + name: 'Binance-Peg Tether (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0x337610d27c682E347C9cD60BD4b3b107C9d34dDd', + decimals: 18, + id: 'USDT_BSC_TEST', + name: 'USDT Token (BSC Test)', + nativeAsset: 'BNB_TEST', + type: 'BEP20' + }, + { + contractAddress: '0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e', + decimals: 6, + id: 'USDT_CELO', + name: 'Tether USD (Celo)', + nativeAsset: 'CELO', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'USDT_E_NEAR', + issuerAddress: 'dac17f958d2ee523a2206206994597c13d831ec7.factory.bridge.near', + name: 'USDT Tether Bridged', + nativeAsset: 'NEAR', + type: 'NEAR_ASSET' + }, + { + contractAddress: '0xdAC17F958D2ee523a2206206994597C13D831ec7', + decimals: 6, + id: 'USDT_ERC20', + name: 'Tether USD (Ethereum)', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'USDT_NEAR', + issuerAddress: 'usdt.tether-token.near', + name: 'USD Tether', + nativeAsset: 'NEAR', + type: 'NEAR_ASSET' + }, + { + contractAddress: '', + decimals: 8, + id: 'USDT_OMNI', + name: 'Tether (Omni)', + nativeAsset: 'BTC', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xc2132D05D31c914a87C6611C10748AEb04B58e8F', + decimals: 6, + id: 'USDT_POLYGON', + name: '(PoS) Tether USD (Polygon)', + nativeAsset: 'MATIC_POLYGON', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'USDT_TON', + issuerAddress: 'EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs', + name: 'Tether USD (Ton)', + nativeAsset: 'TON', + type: 'TON_ASSET' + }, + { + contractAddress: '0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7', + decimals: 6, + id: 'USDT2_AVAX', + name: 'TetherToken _Avalanche_ - USDT2', + nativeAsset: 'AVAX', + type: 'ERC20' + }, + { + contractAddress: '0x4000369AcfA25C8FE5d17fE3312e30C332beF633', + decimals: 9, + id: 'USG', + name: 'US Gold', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xa47c8bf37f92aBed4A126BDA807A7b7498661acD', + decimals: 18, + id: 'UST', + name: 'Wrapped UST Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x23396cF899Ca06c4472205fC903bDB4de249D6fC', + decimals: 18, + id: 'UST_BSC', + name: 'Wrapped UST Token', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0xa693B19d2931d498c5B318dF961919BB4aee87a5', + decimals: 6, + id: 'UST_ETH', + name: 'UST (Wormhole)', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'UST_SOL', + issuerAddress: '9vMJfxuKxXBoEa7rM12mYLMwTacLMLDJqHozw96WQL8i', + name: 'UST (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x340D2bdE5Eb28c1eed91B2f790723E3B160613B7', + decimals: 18, + id: 'VEE', + name: 'BLOCKv', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xcB84d72e61e383767C4DFEb2d8ff7f4FB89abc6e', + decimals: 18, + id: 'VEGA', + name: 'VEGA', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x5F0bc16D50F72d10b719dBF6845DE2E599eb5624', + decimals: 18, + id: 'VENT', + name: 'VENT', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x37F04d2C3AE075Fad5483bB918491F656B12BDB6', + decimals: 8, + id: 'VEST', + name: 'VestChain', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x4D61577d8Fd2208A0afb814ea089fDeAe19ed202', + decimals: 18, + id: 'VFOX_BSC', + name: 'VFOX (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0x3C4B6E6e1eA3D4863700D7F76b36B7f3D3f13E3d', + decimals: 8, + id: 'VGX_ETH', + name: 'Voyager Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x2C974B2d0BA1716E644c1FC59982a89DDD2fF724', + decimals: 18, + id: 'VIB', + name: 'Viberate', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'VICTION', + name: 'Viction', + nativeAsset: 'VICTION', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x2C9023bBc572ff8dc1228c7858A280046Ea8C9E5', + decimals: 18, + id: 'VID', + name: 'VideoCoin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xfeF4185594457050cC9c23980d301908FE057Bb1', + decimals: 18, + id: 'VIDT', + name: 'VIDT Datalink', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xC77b230F31b517F1ef362e59c173C2BE6540B5E8', + decimals: 18, + id: 'VIDY', + name: 'VidyCoin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x3D3D35bb9bEC23b06Ca00fe472b50E7A4c692C30', + decimals: 18, + id: 'VIDYA', + name: 'Vidya', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xF938424F7210f31dF2Aee3011291b658f872e91e', + decimals: 18, + id: 'VISR', + name: 'VISOR', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'VLX_TEST', + name: 'Velas Test (VLX)', + nativeAsset: 'VLX_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'VLX_VLX', + name: 'Velas (VLX)', + nativeAsset: 'VLX_VLX', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xd0258a3fD00f38aa8090dfee343f10A9D4d30D3F', + decimals: 18, + id: 'VOXEL_POLYGON', + name: 'VOXEL Token (Polygon)', + nativeAsset: 'MATIC_POLYGON', + type: 'ERC20' + }, + { + contractAddress: '0xF411903cbC70a74d22900a5DE66A2dda66507255', + decimals: 18, + id: 'VRA', + name: 'VERA', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x1b40183EFB4Dd766f11bDa7A7c3AD8982e998421', + decimals: 18, + id: 'VSP', + name: 'VesperToken', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xB0fFa8000886e57F86dd5264b9582b2Ad87b2b91', + decimals: 18, + id: 'W_ETH_S5P9', + name: 'Wormhole Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'W_SOL', + issuerAddress: '85VBFQZC9TZkfaptBWjvUw7YbZjy52A6mjtPGjstQAmQ', + name: 'Wormhole', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7', + decimals: 18, + id: 'WAVAX_AVAX', + name: 'Wrapped AVAX (Avalanche)', + nativeAsset: 'AVAX', + type: 'ERC20' + }, + { + contractAddress: '0x1cF4592ebfFd730c7dc92c1bdFFDfc3B9EfCf29a', + decimals: 18, + id: 'WAVES', + name: 'WAVES token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c', + decimals: 18, + id: 'WBNB_BSC', + name: 'Wrapped BNB (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', + decimals: 8, + id: 'WBTC', + name: 'Wrapped BTC', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x50b7545627a5162F82A992c33b87aDc75187B218', + decimals: 8, + id: 'WBTC_AVAX', + name: 'Wrapped BTC (Avalanche)', + nativeAsset: 'AVAX', + type: 'ERC20' + }, + { + contractAddress: '0xc221b7E65FfC80DE234bbB6667aBDd46593D34F0', + decimals: 18, + id: 'WCFG', + name: 'Wrapped Centrifuge', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x61cc6aF18C351351148815c5F4813A16DEe7A7E4', + decimals: 18, + id: 'WCT_B6QT1TZK_TZBJ', + name: 'WalletConnect', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xeF4461891DfB3AC8572cCf7C794664A8DD927945', + decimals: 18, + id: 'WCT_B7K5S6PF_H7HU', + name: 'WalletConnect', + nativeAsset: 'ETH-OPT', + type: 'ERC20' + }, + { + contractAddress: '0x123151402076fc819B7564510989e475c9cD93CA', + decimals: 8, + id: 'WDGLD', + name: 'wrapped-DGLD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'WEMIX', + name: 'WEMIX', + nativeAsset: 'WEMIX', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'WEMIX_TEST', + name: 'WEMIX Test', + nativeAsset: 'WEMIX_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', + decimals: 18, + id: 'WETH', + name: 'Wrapped Ether', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB', + decimals: 18, + id: 'WETH_E', + name: 'Wrapped Ether (Avalanche)', + nativeAsset: 'AVAX', + type: 'ERC20' + }, + { + contractAddress: '0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14', + decimals: 18, + id: 'WETH_ETH_TEST5_PU4S', + name: 'Wrapped Ether', + nativeAsset: 'ETH_TEST5', + type: 'ERC20' + }, + { + contractAddress: '0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619', + decimals: 18, + id: 'WETH_POLYGON', + name: 'Wrapped Ether (Polygon)', + nativeAsset: 'MATIC_POLYGON', + type: 'ERC20' + }, + { + contractAddress: '0x21be370D5312f44cB42ce377BC9b8a0cEF1A4C83', + decimals: 18, + id: 'WFTM_FANTOM', + name: 'Wrapped Fantom (Fantom)', + nativeAsset: 'FTM_FANTOM', + type: 'ERC20' + }, + { + contractAddress: '0x9355372396e3F6daF13359B7b607a3374cc638e0', + decimals: 4, + id: 'WHALE', + name: 'WHALE', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x0fa5B0608633c13f4E135F9b1F3570508B4f7046', + decimals: 8, + id: 'WHBAR', + name: 'Wrapped Hbar', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x2a3bFF78B79A009976EeA096a51A948a3dC00e34', + decimals: 18, + id: 'WILD', + name: 'Wilder', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xaeF0d72a118ce24feE3cD1d43d383897D05B4e99', + decimals: 18, + id: 'WIN_BSC', + name: 'WINk', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0x667088b212ce3d06a1b553a7221E1fD19000d9aF', + decimals: 18, + id: 'WINGS', + name: 'Wings', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x971fC3880aD395c165e812b029E7Df76FcB63eD8', + decimals: 18, + id: 'WIRE', + name: 'Airwire', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xDecade1c6Bf2cD9fb89aFad73e4a519C867adcF5', + decimals: 18, + id: 'WIS', + name: 'Experty Wisdom Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xd2877702675e6cEb975b4A1dFf9fb7BAF4C91ea9', + decimals: 18, + id: 'WLUNA', + name: 'Wrapped LUNA Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270', + decimals: 18, + id: 'WMATIC_POLYGON', + name: 'Wrapped Matic (Polygon)', + nativeAsset: 'MATIC_POLYGON', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 12, + id: 'WND', + name: 'Westend', + nativeAsset: 'WND', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x0d438F3b5175Bebc262bF23753C1E53d03432bDE', + decimals: 18, + id: 'WNXM', + name: 'Wrapped NXM', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xBd356a39BFf2cAda8E9248532DD879147221Cf76', + decimals: 18, + id: 'WOM', + name: 'WOM Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x4691937a7508860F876c9c0a2a617E7d9E945D4B', + decimals: 18, + id: 'WOO', + name: 'Wootrade Network (Ethereum)', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x7A8d51b82b36Fa5B50fb77001D6d189E920d2f75', + decimals: 18, + id: 'WOPIUM', + name: 'Wrapped Opium Governance Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'WORLDCHAIN', + name: 'Worldchain', + nativeAsset: 'WORLDCHAIN', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'WORLDCHAIN_TEST', + name: 'Worldchain Test', + nativeAsset: 'WORLDCHAIN_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xd1e2d5085b39B80C9948AeB1b9aA83AF6756bcc5', + decimals: 9, + id: 'WOXEN', + name: 'Wrapped OXEN', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x4CF488387F035FF08c371515562CBa712f9015d4', + decimals: 18, + id: 'WPR', + name: 'WePower', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x542fDA317318eBF1d3DEAf76E0b632741A7e677d', + decimals: 18, + id: 'WRBTC_RSK_VNPH', + name: 'Wrapped BTC', + nativeAsset: 'RBTC', + type: 'ERC20' + }, + { + contractAddress: '0xFF0a024B66739357c4ED231fB3DBC0c8C22749F5', + decimals: 8, + id: 'WRX', + name: 'Wazirx Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x8e17ed70334C87eCE574C9d537BC153d8609e2a3', + decimals: 8, + id: 'WRX_BSC', + name: 'Wazirx Token (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0xa3C22370de5f9544f0c4De126b1e46cEadF0A51B', + decimals: 18, + id: 'WSTRAX', + name: 'WrappedStrax', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xb7cB1C96dB6B22b0D3d9536E0108d062BD488F74', + decimals: 18, + id: 'WTC', + name: 'Waltonchain', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xa02120696c7B8fE16C09C749E4598819b2B0E915', + decimals: 18, + id: 'WXT', + name: 'Wirex Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x68749665FF8D2d112Fa859AA293F07A622782F38', + decimals: 6, + id: 'XAUT2', + name: 'Tether Gold (New)', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x57C09A8de0b0F471F8567609777aDdFfb5c46a08', + decimals: 18, + id: 'XBX', + name: 'Bitex Global XBX Coin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x03678f2c2c762DC63c2Bb738c3a837D366eDa560', + decimals: 18, + id: 'XCASH_POLYGON', + name: 'X-Cash (PoS)', + nativeAsset: 'MATIC_POLYGON', + type: 'ERC20' + }, + { + contractAddress: '0xB4272071eCAdd69d933AdcD19cA99fe80664fc08', + decimals: 18, + id: 'XCHF', + name: 'CryptoFranc', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 18, + id: 'XDAI', + name: 'Gnosis xDAI', + nativeAsset: 'XDAI', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'XDAI_TEST', + name: 'Gnosis xDAI Test', + nativeAsset: 'XDAI_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 7, + id: 'XDB', + name: 'XDB', + nativeAsset: 'XDB', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xB9EefC4b0d472A44be93970254Df4f4016569d27', + decimals: 7, + id: 'XDB_ETH', + name: 'Digitalbits (ETH)', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 7, + id: 'XDB_ROMA_G5H1', + issuerAddress: 'GBJPYIYYLCJED2ETN3YWPG23P77JWIE3SSNHZJPW2FOHKRBXNKF5UEEL', + name: 'ROMA (DigitalBits)', + nativeAsset: 'XDB', + type: 'XDB_ASSET' + }, + { + contractAddress: '', + decimals: 7, + id: 'XDB_TEST', + name: 'XDB Test', + nativeAsset: 'XDB_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 7, + id: 'XDB_USDS_7FSS', + issuerAddress: 'GBFOHHXUNGIYJHPLXAC3AKNDDXWR6NSUJSKBMXY452Y4AQBZEUL7EKAB', + name: 'USDS (DigitalBits)', + nativeAsset: 'XDB', + type: 'XDB_ASSET' + }, + { + contractAddress: '', + decimals: 7, + id: 'XDB_ZUSD_Q74F', + issuerAddress: 'GBFOHHXUNGIYJHPLXAC3AKNDDXWR6NSUJSKBMXY452Y4AQBZEUL7EKAB', + name: 'ZUSD (DigitalBits)', + nativeAsset: 'XDB', + type: 'XDB_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'XDC', + name: 'XDC Network', + nativeAsset: 'XDC', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 2, + id: 'XEC', + name: 'eCash', + nativeAsset: 'XEC', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 2, + id: 'XEC_TEST', + name: 'eCash Test', + nativeAsset: 'XEC_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 6, + id: 'XEM', + name: 'XEM', + nativeAsset: 'XEM', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 6, + id: 'XEM_TEST', + name: 'XEM Test', + nativeAsset: 'XEM_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x4aa41bC1649C9C3177eD16CaaA11482295fC7441', + decimals: 18, + id: 'XFIT', + name: 'XFIT', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xA974c709cFb4566686553a20790685A47acEAA33', + decimals: 18, + id: 'XIN', + name: 'Mixin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 7, + id: 'XLM', + name: 'Stellar', + nativeAsset: 'XLM', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 7, + id: 'XLM_AKN_GNFL', + issuerAddress: 'GACSHAJ2XBNKRNJEVDAII6E2EAASIAMDBCLJ3VKSZEWK3KC7Y7DPXUFX', + name: 'Akoin (Stellar)', + nativeAsset: 'XLM', + type: 'XLM_ASSET' + }, + { + contractAddress: '', + decimals: 7, + id: 'XLM_BRL_LQ3J', + issuerAddress: 'GDVKY2GU2DRXWTBEYJJWSFXIGBZV6AZNBVVSUHEPZI54LIS6BA7DVVSP', + name: 'BRL (Stellar)', + nativeAsset: 'XLM', + type: 'XLM_ASSET' + }, + { + contractAddress: '', + decimals: 7, + id: 'XLM_BRZ_EDTE', + issuerAddress: 'GABMA6FPH3OJXNTGWO7PROF7I5WPQUZOB4BLTBTP4FK6QV7HWISLIEO2', + name: 'BRZ Token (Stellar)', + nativeAsset: 'XLM', + type: 'XLM_ASSET' + }, + { + contractAddress: '', + decimals: 7, + id: 'XLM_BTCE_DP2P', + issuerAddress: 'GBOPFWZZJZUMTS6KVQAHUUNLMXO424ZF7IWHF6GONLAVCDSN4TBBKCLV', + name: 'BTCe Test (Stellar)', + nativeAsset: 'XLM_TEST', + type: 'XLM_ASSET' + }, + { + contractAddress: '', + decimals: 7, + id: 'XLM_BTCEM_T_MVE5', + issuerAddress: 'GBOPFWZZJZUMTS6KVQAHUUNLMXO424ZF7IWHF6GONLAVCDSN4TBBKCLV', + name: 'BTCEM Test (Stellar)', + nativeAsset: 'XLM_TEST', + type: 'XLM_ASSET' + }, + { + contractAddress: '', + decimals: 7, + id: 'XLM_EURE_O4P4', + issuerAddress: 'GBOPFWZZJZUMTS6KVQAHUUNLMXO424ZF7IWHF6GONLAVCDSN4TBBKCLV', + name: 'EURe Test (Stellar)', + nativeAsset: 'XLM_TEST', + type: 'XLM_ASSET' + }, + { + contractAddress: '', + decimals: 7, + id: 'XLM_EUREM_T_B7SB', + issuerAddress: 'GBOPFWZZJZUMTS6KVQAHUUNLMXO424ZF7IWHF6GONLAVCDSN4TBBKCLV', + name: 'EUREM Test (Stellar)', + nativeAsset: 'XLM_TEST', + type: 'XLM_ASSET' + }, + { + contractAddress: '', + decimals: 7, + id: 'XLM_FBTEST_7SNX', + issuerAddress: 'GC3NA75PU6HD5OWCZ7OHCSAL6HZSELNTTBAGHAOCGHBSAQTVI7GCQK2J', + name: 'Fireblocks Test Token (Stellar)', + nativeAsset: 'XLM_TEST', + type: 'XLM_ASSET' + }, + { + contractAddress: '', + decimals: 7, + id: 'XLM_GYEN_TLIE', + issuerAddress: 'GDF6VOEGRWLOZ64PQQGKD2IYWA22RLT37GJKS2EJXZHT2VLAGWLC5TOB', + name: 'GMO JPY (Stellar)', + nativeAsset: 'XLM', + type: 'XLM_ASSET' + }, + { + contractAddress: '', + decimals: 7, + id: 'XLM_GYEN_ZN63', + issuerAddress: 'GAQQSET64FFYJLZB3XIFUVPGRDMETG2USH2R7VPUY2E4YEXH7STKRISN', + name: 'GMO JPY Test (Stellar)', + nativeAsset: 'XLM_TEST', + type: 'XLM_ASSET' + }, + { + contractAddress: '', + decimals: 7, + id: 'XLM_HODL_EFOE', + issuerAddress: 'GAQEDFS2JK6JSQO53DWT23TGOLH5ZUZG4O3MNLF3CFUZWEJ6M7MMGJAV', + name: 'HODL Token (Stellar)', + nativeAsset: 'XLM', + type: 'XLM_ASSET' + }, + { + contractAddress: '', + decimals: 7, + id: 'XLM_IDK_JM2C', + issuerAddress: 'GAVDGVOARGIMZA47POPHGPC2FRDE7I7ZF3NGNNIGDPGEZRMTELFAD6DN', + name: 'IDK (Stellar)', + nativeAsset: 'XLM', + type: 'XLM_ASSET' + }, + { + contractAddress: '', + decimals: 7, + id: 'XLM_LUNA_T_WZ5J', + issuerAddress: 'GBDH4456HKE3BNIMIRWRHQDWN2KSOTY3FZFGUJTRZXY33Y3JEJGGFMCT', + name: 'Luna Test (Stellar)', + nativeAsset: 'XLM_TEST', + type: 'XLM_ASSET' + }, + { + contractAddress: '', + decimals: 7, + id: 'XLM_NTT_PZV2', + issuerAddress: 'GBWFD4RZAEMXLBDLVYTGTRZ53IIGLWOAPEMVRF5V62M7FH76QER5JNMI', + name: 'NTT Test (Stellar)', + nativeAsset: 'XLM_TEST', + type: 'XLM_ASSET' + }, + { + contractAddress: '', + decimals: 7, + id: 'XLM_ROMA_G5H1', + issuerAddress: 'GBJPYIYYLCJED2ETN3YWPG23P77JWIE3SSNHZJPW2FOHKRBXNKF5UEEL', + name: 'ROMA _DigitalBits_', + nativeAsset: 'XDB', + type: 'XDB_ASSET' + }, + { + contractAddress: '', + decimals: 7, + id: 'XLM_SBDD_T_GC74', + issuerAddress: 'GC74OM3VHSTARP2BNCEFFCU5GUNRXGNYZUORHFVZIZJH7IPISKOVDHM4', + name: 'SBDD Issuance Wallet Test (Stellar)', + nativeAsset: 'XLM_TEST', + type: 'XLM_ASSET' + }, + { + contractAddress: '', + decimals: 7, + id: 'XLM_SBDD_T_GD7R', + issuerAddress: 'GD7RN27CQZAAYDZZ5WCIFYRSXSFQCB72IKMFEU2LE6V5M7ILZOONALOK', + name: 'SBDD Distribution Wallet Test (Stellar)', + nativeAsset: 'XLM_TEST', + type: 'XLM_ASSET' + }, + { + contractAddress: '', + decimals: 7, + id: 'XLM_SIX_BIQ4', + issuerAddress: 'GDMS6EECOH6MBMCP3FYRYEVRBIV3TQGLOFQIPVAITBRJUMTI6V7A2X6Z', + name: 'SIX.Network', + nativeAsset: 'XLM', + type: 'XLM_ASSET' + }, + { + contractAddress: '', + decimals: 7, + id: 'XLM_SOLA_T_7WZU', + issuerAddress: 'GDFREACG4LEESEGBBQZKSMS7FS47YNULFKBKFP5WGNKEHXOGNQVGSZHV', + name: 'Sola Test (Stellar)', + nativeAsset: 'XLM_TEST', + type: 'XLM_ASSET' + }, + { + contractAddress: '', + decimals: 7, + id: 'XLM_TEST', + name: 'Stellar Test', + nativeAsset: 'XLM_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 7, + id: 'XLM_TLFTST_UH6X', + issuerAddress: 'GBN54AOKMC6H4Q25Y623IRVUJHVREZJV7DQEJKQ26WISKQZDY4MC6VI3', + name: 'TLFTST Test (Stellar)', + nativeAsset: 'XLM_TEST', + type: 'XLM_ASSET' + }, + { + contractAddress: '', + decimals: 7, + id: 'XLM_USDC_5F3T', + issuerAddress: 'GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN', + name: 'USD Coin (Stellar)', + nativeAsset: 'XLM', + type: 'XLM_ASSET' + }, + { + contractAddress: '', + decimals: 7, + id: 'XLM_USDC_T_CEKS', + issuerAddress: 'GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5', + name: 'USD Coin Test (Stellar)', + nativeAsset: 'XLM_TEST', + type: 'XLM_ASSET' + }, + { + contractAddress: '', + decimals: 7, + id: 'XLM_WXT_DQLC', + issuerAddress: 'GASBLVHS5FOABSDNW5SPPH3QRJYXY5JHA2AOA2QHH2FJLZBRXSG4SWXT', + name: 'Wirex Token (Stellar)', + nativeAsset: 'XLM', + type: 'XLM_ASSET' + }, + { + contractAddress: '', + decimals: 7, + id: 'XLM_ZUSD_VQXC', + issuerAddress: 'GDF6VOEGRWLOZ64PQQGKD2IYWA22RLT37GJKS2EJXZHT2VLAGWLC5TOB', + name: 'Z.com USD (Stellar)', + nativeAsset: 'XLM', + type: 'XLM_ASSET' + }, + { + contractAddress: '', + decimals: 7, + id: 'XLM_ZUSD_XCYQ', + issuerAddress: 'GAQQSET64FFYJLZB3XIFUVPGRDMETG2USH2R7VPUY2E4YEXH7STKRISN', + name: 'Z.com USD Test (Stellar)', + nativeAsset: 'XLM_TEST', + type: 'XLM_ASSET' + }, + { + contractAddress: '0x3aaDA3e213aBf8529606924d8D1c55CbDc70Bf74', + decimals: 18, + id: 'XMON', + name: 'XMON', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'XRP', + name: 'XRP (Ripple)', + nativeAsset: 'XRP', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 6, + id: 'XRP_TEST', + name: 'XRP Test', + nativeAsset: 'XRP_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x70e8dE73cE538DA2bEEd35d14187F6959a8ecA96', + decimals: 6, + id: 'XSGD', + name: 'XSGD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x8798249c2E607446EfB7Ad49eC89dD1865Ff4272', + decimals: 18, + id: 'XSUSHI', + name: 'SushiBar', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x6368e1E18c4C419DDFC608A0BEd1ccb87b9250fc', + decimals: 18, + id: 'XTP', + name: 'TAP', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x9c794f933b4DD8B49031A79b0f924D68BEF43992', + decimals: 18, + id: 'XTRD', + name: 'XTRD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 6, + id: 'XTZ', + name: 'Tezos', + nativeAsset: 'XTZ', + type: 'BASE_ASSET' + }, + { + contractAddress: '0x16939ef78684453bfDFb47825F8a5F714f12623a', + decimals: 18, + id: 'XTZ_BSC', + name: 'Tezos BSC Token', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '', + decimals: 18, + id: 'XTZ_ETHERLINK', + name: 'Tezos (Etherlink)', + nativeAsset: 'XTZ_ETHERLINK', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'XTZ_ETHERLINK_TEST', + name: 'Tezos Test (Etherlink Testnet)', + nativeAsset: 'XTZ_ETHERLINK_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 6, + id: 'XTZ_TEST', + name: 'Tezos Test', + nativeAsset: 'XTZ_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xb5999795BE0EbB5bAb23144AA5FD6A02D080299F', + decimals: 18, + id: 'XUSD_RBTC', + name: 'XUSD Babelfish stablecoin (RSK)', + nativeAsset: 'RBTC', + type: 'ERC20' + }, + { + contractAddress: '0xcF6BB5389c92Bdda8a3747Ddb454cB7a64626C63', + decimals: 18, + id: 'XVS_BSC', + name: 'Venus (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0x55296f69f40Ea6d20E478533C15A6B08B654E758', + decimals: 18, + id: 'XYO', + name: 'XY Oracle', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x618679dF9EfCd19694BB1daa8D00718Eacfa2883', + decimals: 18, + id: 'XYZ', + name: 'XYZ Governance Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x0AaCfbeC6a24756c20D41914F2caba817C0d8521', + decimals: 18, + id: 'YAM', + name: 'YAM', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 9, + id: 'YARD_SOL', + issuerAddress: '8RYSc3rrS4X4bvBCtSJnhcpPpMaAJkXnVKZPzANxQHgz', + name: 'SolYard Finance (Solana)', + nativeAsset: 'SOL', + type: 'SOL_ASSET' + }, + { + contractAddress: '0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e', + decimals: 18, + id: 'YFI', + name: 'Yearn Finance', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xa1d0E215a23d7030842FC67cE582a6aFa3CCaB83', + decimals: 18, + id: 'YFII', + name: 'YFII.finance', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x28cb7e841ee97947a86B06fA4090C8451f64c0be', + decimals: 18, + id: 'YFL', + name: 'YFLink', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x25f8087EAD173b73D6e8B84329989A8eEA16CF73', + decimals: 18, + id: 'YGG', + name: 'Yield Guild Games Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xF94b5C5651c888d928439aB6514B93944eEE6F48', + decimals: 18, + id: 'YLD', + name: 'Yield', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xA26Cbb76156090f4B40A1799A220fc4C946aFB3c', + decimals: 18, + id: 'YNG', + name: 'Young Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xAE1eaAE3F627AAca434127644371b67B18444051', + decimals: 8, + id: 'YOP', + name: 'YOP', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xd6aD7a6750A7593E092a9B218d66C0A814a3436e', + decimals: 6, + id: 'YUSDC', + name: 'iearn USDC', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x7Da96a3891Add058AdA2E826306D812C638D87a7', + decimals: 6, + id: 'YVUSDT', + name: 'USDT yVault', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x2994529C0652D127b7842094103715ec5299bBed', + decimals: 18, + id: 'YYCRV', + name: 'yearn Curve.fi', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xC52C326331E9Ce41F04484d3B5E5648158028804', + decimals: 18, + id: 'ZCX', + name: 'ZEN Exchange Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x6cfDDfeCa2D22F3611E35c4915994472b07Ca315', + decimals: 18, + id: 'ZDC', + name: 'Zodiac', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '', + decimals: 8, + id: 'ZEC', + name: 'ZCash', + nativeAsset: 'ZEC', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 8, + id: 'ZEC_TEST', + name: 'ZCash Test', + nativeAsset: 'ZEC_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xF0939011a9bb95c3B791f0cb546377Ed2693a574', + decimals: 18, + id: 'ZERO', + name: 'Zero.Exchange Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x7BeBd226154E865954A87650FAefA8F485d36081', + decimals: 18, + id: 'ZIG', + name: 'ZigCoin', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x7BeBd226154E865954A87650FAefA8F485d36081', + decimals: 18, + id: 'ZIG_BSC', + name: 'ZigCoin (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '0xb86AbCb37C3A4B64f74f59301AFF131a1BEcC787', + decimals: 12, + id: 'ZIL_BSC', + name: 'Zilliqa (BSC)', + nativeAsset: 'BNB_BSC', + type: 'BEP20' + }, + { + contractAddress: '', + decimals: 18, + id: 'ZIL_MAINNET', + name: 'Zilliqa EVM Mainnet', + nativeAsset: 'ZIL_MAINNET', + type: 'BASE_ASSET' + }, + { + contractAddress: '', + decimals: 18, + id: 'ZIL_TEST', + name: 'Zilliqa EVM Test', + nativeAsset: 'ZIL_TEST', + type: 'BASE_ASSET' + }, + { + contractAddress: '0xA9d2927d3a04309E008B6af6E2e282AE2952e7fD', + decimals: 18, + id: 'ZIP', + name: 'Zipper', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xe4815AE53B124e7263F08dcDBBB757d41Ed658c6', + decimals: 18, + id: 'ZKS', + name: 'Zks Token', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0x69cf3091C91EB72DB05E45C76e58225177dEA742', + decimals: 18, + id: 'ZOOM', + name: 'CoinZoom', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xE41d2489571d322189246DaFA5ebDe1F4699F498', + decimals: 18, + id: 'ZRX', + name: '0x', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xc56c2b7e71B54d38Aab6d52E94a04Cbfa8F604fA', + decimals: 6, + id: 'ZUSD', + name: 'Z.com USD', + nativeAsset: 'ETH', + type: 'ERC20' + }, + { + contractAddress: '0xbf0f3cCB8fA385A287106FbA22e6BB722F94d686', + decimals: 6, + id: 'ZYTARAUSD', + name: 'Zytara USD', + nativeAsset: 'ETH', + type: 'ERC20' + } +] + +@Injectable() +export class FireblocksAssetService { + constructor( + private readonly networkRepository: NetworkRepository, + private readonly logger: LoggerService + ) {} + + private mapFireblocksAsset(network: Network, fireblocksAsset: FireblocksAsset): Asset { + return { + decimals: fireblocksAsset.decimals, + externalId: fireblocksAsset.id, + name: fireblocksAsset.name, + networkId: network.networkId, + onchainId: fireblocksAsset.contractAddress || fireblocksAsset.issuerAddress || undefined + } + } + + async findByExternalId(externalId: string): Promise { + for (const fireblocksAsset of FIREBLOCKS_ASSETS) { + if (fireblocksAsset.id === externalId) { + const network = await this.networkRepository.findByExternalId(Provider.FIREBLOCKS, fireblocksAsset.nativeAsset) + + if (network) { + return this.mapFireblocksAsset(network, fireblocksAsset) + } + } + } + + return null + } + + async findAll(): Promise { + const networkExternalIdIndex = await this.networkRepository.buildProviderExternalIdIndex(Provider.FIREBLOCKS) + const assets: Asset[] = [] + + for (const fireblocksAsset of FIREBLOCKS_ASSETS) { + const network = networkExternalIdIndex.get(fireblocksAsset.nativeAsset) + + if (network) { + assets.push(this.mapFireblocksAsset(network, fireblocksAsset)) + } else { + this.logger.warn('Fireblocks asset network not found', { fireblocksAsset }) + } + } + + return assets + } + + async findByOnchainId(networkId: string, onchainId: string): Promise { + for (const fireblocksAsset of FIREBLOCKS_ASSETS) { + if ( + fireblocksAsset.contractAddress?.toLowerCase() === onchainId.toLowerCase() || + fireblocksAsset.issuerAddress?.toLowerCase() === onchainId.toLowerCase() + ) { + const network = await this.networkRepository.findByExternalId(Provider.FIREBLOCKS, fireblocksAsset.nativeAsset) + + if (network?.networkId === networkId) { + return this.mapFireblocksAsset(network, fireblocksAsset) + } + } + } + + return null + } + + async findNativeAsset(networkId: string): Promise { + const network = await this.networkRepository.findById(networkId) + + if (network) { + const externalNetwork = getExternalNetwork(network, Provider.FIREBLOCKS) + + for (const fireblocksAsset of FIREBLOCKS_ASSETS) { + // If network matches and asset doesn't have a contract address or issuer address, it must be the + // native asset. + if ( + externalNetwork?.externalId === fireblocksAsset.nativeAsset && + !fireblocksAsset.contractAddress && + !fireblocksAsset.issuerAddress + ) { + return this.mapFireblocksAsset(network, fireblocksAsset) + } + } + } + + return null + } +} diff --git a/apps/vault/src/broker/core/type/asset.type.ts b/apps/vault/src/broker/core/type/asset.type.ts new file mode 100644 index 000000000..eaea7f115 --- /dev/null +++ b/apps/vault/src/broker/core/type/asset.type.ts @@ -0,0 +1,10 @@ +import { z } from 'zod' + +export const Asset = z.object({ + decimals: z.number().nullable(), + externalId: z.string(), + name: z.string(), + networkId: z.string(), + onchainId: z.string().optional() +}) +export type Asset = z.infer diff --git a/apps/vault/src/broker/core/type/network.type.ts b/apps/vault/src/broker/core/type/network.type.ts index e4a5007ab..d0eed7e4f 100644 --- a/apps/vault/src/broker/core/type/network.type.ts +++ b/apps/vault/src/broker/core/type/network.type.ts @@ -1,10 +1,17 @@ import { z } from 'zod' +import { Provider } from './provider.type' + +export const ExternalNetwork = z.object({ + externalId: z.string(), + provider: z.nativeEnum(Provider) +}) +export type ExternalNetwork = z.infer export const Network = z.object({ networkId: z.string(), coinType: z.number().nullable(), name: z.string(), - anchorageId: z.string().optional(), - fireblocksId: z.string().optional() + externalNetworks: z.array(ExternalNetwork).default([]), + createdAt: z.date().optional() }) export type Network = z.infer diff --git a/apps/vault/src/broker/core/type/transfer.type.ts b/apps/vault/src/broker/core/type/transfer.type.ts index b11d9cde3..4882d596c 100644 --- a/apps/vault/src/broker/core/type/transfer.type.ts +++ b/apps/vault/src/broker/core/type/transfer.type.ts @@ -31,7 +31,7 @@ export type AddressDestination = z.infer export const Destination = z.union([TransferParty, AddressDestination]) export type Destination = z.infer -export const Asset = z +export const TransferAsset = z .object({ assetId: z.string().optional().describe('ID of the asset. Can be used instead of address+networkId.'), externalAssetId: z @@ -49,7 +49,7 @@ export const Asset = z networkId: z.string().optional().describe('Network of the asset. Required if address is provided.') }) .describe('The asset being transferred') -export type Asset = z.infer +export type TransferAsset = z.infer export const SendTransfer = z.object({ source: Source, @@ -57,7 +57,7 @@ export const SendTransfer = z.object({ amount: z.string(), assetId: z.string().optional().describe('@deprecated use asset instead'), // @deprecated use asset instead - asset: Asset, + asset: TransferAsset, // This is optional on the base transfer and always default on the // provider-specific transfer service. networkFeeAttribution: z.nativeEnum(NetworkFeeAttribution).optional(), diff --git a/apps/vault/src/broker/core/util/network.util.ts b/apps/vault/src/broker/core/util/network.util.ts index 2e5af2b17..be649f755 100644 --- a/apps/vault/src/broker/core/util/network.util.ts +++ b/apps/vault/src/broker/core/util/network.util.ts @@ -1,4 +1,5 @@ -import { Network } from '../type/network.type' +import { ExternalNetwork, Network } from '../type/network.type' +import { Provider } from '../type/provider.type' export const isNetworkIdFromTestnet = (networkId: string): boolean => { const id = networkId.toUpperCase() @@ -23,3 +24,7 @@ export const isNetworkIdFromTestnet = (networkId: string): boolean => { export const isTestnet = (network: Network): boolean => { return Boolean(network.coinType && network.coinType === 1) } + +export const getExternalNetwork = (network: Network, provider: Provider): ExternalNetwork | null => { + return network.externalNetworks.find((externalNetwork) => externalNetwork.provider === provider) || null +} diff --git a/apps/vault/src/broker/http/rest/controller/asset.controller.ts b/apps/vault/src/broker/http/rest/controller/asset.controller.ts new file mode 100644 index 000000000..f7056a128 --- /dev/null +++ b/apps/vault/src/broker/http/rest/controller/asset.controller.ts @@ -0,0 +1,51 @@ +import { ApiClientIdHeader } from '@narval/nestjs-shared' +import { BadRequestException, Controller, Get, HttpStatus, Query } from '@nestjs/common' +import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' +import { PermissionGuard } from '../../../../shared/decorator/permission-guard.decorator' +import { VaultPermission } from '../../../../shared/type/domain.type' +import { AnchorageAssetService } from '../../../core/provider/anchorage/anchorage-asset.service' +import { FireblocksAssetService } from '../../../core/provider/fireblocks/fireblocks-asset.service' +import { Asset } from '../../../core/type/asset.type' +import { Provider } from '../../../core/type/provider.type' +import { ProviderAssetDto } from '../dto/response/provider-asset.dto' + +@Controller({ + path: 'assets', + version: '1' +}) +@ApiClientIdHeader() +@ApiTags('Provider Asset') +export class AssetController { + constructor( + private readonly anchorageAssetService: AnchorageAssetService, + private readonly fireblocksAssetService: FireblocksAssetService + ) {} + + @Get() + @PermissionGuard(VaultPermission.CONNECTION_READ) + @ApiOperation({ + summary: 'Retrieve all assets', + description: 'This endpoint retrieves a list of all available assets for a specified provider.' + }) + @ApiResponse({ + status: HttpStatus.OK, + description: 'The assets were successfully retrieved.', + type: ProviderAssetDto + }) + async list(@Query('provider') provider: Provider): Promise { + const data = await this.findAllByProvider(provider) + + return ProviderAssetDto.create({ data }) + } + + private findAllByProvider(provider: Provider): Promise { + switch (provider) { + case Provider.ANCHORAGE: + return this.anchorageAssetService.findAll() + case Provider.FIREBLOCKS: + return this.fireblocksAssetService.findAll() + default: + throw new BadRequestException(`Provider ${provider} not implemented`) + } + } +} diff --git a/apps/vault/src/broker/http/rest/controller/network.controller.ts b/apps/vault/src/broker/http/rest/controller/network.controller.ts index dabc5fcf8..d955f236c 100644 --- a/apps/vault/src/broker/http/rest/controller/network.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/network.controller.ts @@ -5,7 +5,7 @@ import { PermissionGuard } from '../../../../shared/decorator/permission-guard.d import { VaultPermission } from '../../../../shared/type/domain.type' import { Provider } from '../../../core/type/provider.type' import { NetworkRepository } from '../../../persistence/repository/network.repository' -import { NetworkDto } from '../dto/response/network.dto' +import { ProviderNetworkDto } from '../dto/response/provider-network.dto' @Controller({ path: 'networks', @@ -25,13 +25,11 @@ export class NetworkController { @ApiResponse({ status: HttpStatus.OK, description: 'The networks were successfully retrieved.', - type: NetworkDto + type: ProviderNetworkDto }) - async list(@Query('provider') provider: Provider): Promise { - const networks = await this.networkRepository.findAll({ - filters: { provider } - }) + async list(@Query('provider') provider: Provider): Promise { + const data = await this.networkRepository.findAll({ filters: { provider } }) - return NetworkDto.create({ data: networks }) + return ProviderNetworkDto.create({ data }) } } diff --git a/apps/vault/src/broker/http/rest/dto/response/provider-asset.dto.ts b/apps/vault/src/broker/http/rest/dto/response/provider-asset.dto.ts new file mode 100644 index 000000000..486c793a0 --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/response/provider-asset.dto.ts @@ -0,0 +1,11 @@ +import { Page } from '@narval/nestjs-shared' +import { createZodDto } from 'nestjs-zod' +import { z } from 'zod' +import { Asset } from '../../../../core/type/asset.type' + +export class ProviderAssetDto extends createZodDto( + z.object({ + data: z.array(Asset), + page: Page + }) +) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/network.dto.ts b/apps/vault/src/broker/http/rest/dto/response/provider-network.dto.ts similarity index 57% rename from apps/vault/src/broker/http/rest/dto/response/network.dto.ts rename to apps/vault/src/broker/http/rest/dto/response/provider-network.dto.ts index 9ed29c787..c289e7b32 100644 --- a/apps/vault/src/broker/http/rest/dto/response/network.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/provider-network.dto.ts @@ -3,9 +3,13 @@ import { createZodDto } from 'nestjs-zod' import { z } from 'zod' import { Network } from '../../../../core/type/network.type' -export class NetworkDto extends createZodDto( +export class ProviderNetworkDto extends createZodDto( z.object({ - data: z.array(Network), + data: z.array( + Network.extend({ + createdAt: z.coerce.date().optional() + }) + ), page: Page }) ) {} diff --git a/apps/vault/src/broker/persistence/connection.seed.ts b/apps/vault/src/broker/persistence/connection.seed.ts deleted file mode 100644 index 964199de2..000000000 --- a/apps/vault/src/broker/persistence/connection.seed.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Injectable } from '@nestjs/common' -import { SeedService } from '../../shared/module/persistence/service/seed.service' -import { ConnectionWithCredentials } from '../core/type/connection.type' -import { ConnectionRepository } from './repository/connection.repository' - -@Injectable() -export class ConnectionSeedService extends SeedService { - constructor(private connectionRepository: ConnectionRepository) { - super() - } - - async createConnection(connection: ConnectionWithCredentials) { - const createdConnection = await this.connectionRepository.create(connection) - return createdConnection - } -} diff --git a/apps/vault/src/broker/persistence/repository/network.repository.ts b/apps/vault/src/broker/persistence/repository/network.repository.ts index ee1826fbb..e0a25cea9 100644 --- a/apps/vault/src/broker/persistence/repository/network.repository.ts +++ b/apps/vault/src/broker/persistence/repository/network.repository.ts @@ -1,5 +1,8 @@ -import { Injectable } from '@nestjs/common' -import { Network } from '../../core/type/network.type' +import { LoggerService } from '@narval/nestjs-shared' +import { Injectable, OnApplicationBootstrap } from '@nestjs/common' +import { Prisma } from '@prisma/client/vault' +import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' +import { ExternalNetwork, Network } from '../../core/type/network.type' import { Provider } from '../../core/type/provider.type' type FindAllOptions = { @@ -8,594 +11,38 @@ type FindAllOptions = { } } -const NETWORKS: Network[] = [ - { - networkId: 'AETH', - coinType: 514, - name: 'Aetherius', - fireblocksId: 'ETH-AETH' - }, - { - networkId: 'AEVO', - coinType: null, - name: 'Aevo', - fireblocksId: 'AEVO' - }, - { - networkId: 'AGORIC', - coinType: 564, - name: 'Agoric', - anchorageId: 'BLD' - }, - { - networkId: 'ALEPH_ZERO', - coinType: 643, - name: 'Aleph Zero', - fireblocksId: 'ALEPH_ZERO_EVM' - }, - { - networkId: 'ALGORAND', - coinType: 283, - name: 'Algorand', - fireblocksId: 'ALGO' - }, - { - networkId: 'ALGORAND_TESTNET', - coinType: 1, - name: 'Algorand Testnet', - fireblocksId: 'ALGO_TEST' - }, - { - networkId: 'ALLORA', - coinType: null, - name: 'Allora', - anchorageId: 'ALLO' - }, - { - networkId: 'ALLORA_TESTNET', - coinType: 1, - name: 'Allora Testnet', - anchorageId: 'ALLO_T' - }, - { - networkId: 'APTOS', - coinType: 637, - name: 'Aptos', - anchorageId: 'APT' - }, - { - networkId: 'APTOS_TESTNET', - coinType: 1, - name: 'Aptos Testnet', - anchorageId: 'APT_T' - }, - { - networkId: 'ARBITRUM_SEPOLIA', - coinType: 1, - name: 'Arbitrum Sepolia Testnet', - anchorageId: 'ARBITRUM_SEPOLIA' - }, - { - networkId: 'ASTAR', - coinType: 810, - name: 'Astar', - fireblocksId: 'ASTR_ASTR' - }, - { - networkId: 'ASTAR_TESTNET', - coinType: 1, - name: 'Astar Testnet', - fireblocksId: 'ASTR_TEST' - }, - { - networkId: 'ATOM', - coinType: 118, - name: 'Atom', - anchorageId: 'COSMOS', - fireblocksId: 'ATOM_COS' - }, - { - networkId: 'ATOM_TESTNET', - coinType: 1, - name: 'Atom Testnet', - fireblocksId: 'ATOM_COS_TEST' - }, - { - networkId: 'AURORA', - coinType: 2570, - name: 'Aurora', - fireblocksId: 'AURORA_DEV' - }, - { - networkId: 'AVAX', - coinType: 9000, - name: 'Avalanche', - fireblocksId: 'AVAX' - }, - { - networkId: 'AVAX_TESTNET', - coinType: 1, - name: 'Avalanche Testnet', - fireblocksId: 'AVAXTEST' - }, - { - networkId: 'AXELAR', - coinType: null, - name: 'Axelar', - anchorageId: 'AXL' - }, - { - networkId: 'AXELAR_TESTNET', - coinType: 1, - name: 'Axelar Testnet', - anchorageId: 'AXL_T' - }, - { - networkId: 'BABYLON', - coinType: null, - name: 'Babylon', - anchorageId: 'BBN' - }, - { - networkId: 'BASE', - coinType: 8453, - name: 'Base', - fireblocksId: 'BASECHAIN_ETH' - }, - { - networkId: 'BASE_TESTNET', - coinType: 1, - name: 'Base Testnet', - fireblocksId: 'BASECHAIN_ETH_TEST5' - }, - { - networkId: 'BINANCE_SMART_CHAIN', - coinType: 9006, - name: 'Binance Smart Chain', - fireblocksId: 'BNB_BSC' - }, - { - networkId: 'BINANCE_SMART_CHAIN_TESTNET', - coinType: 1, - name: 'Binance Smart Chain Testnet', - fireblocksId: 'BNB_TEST' - }, - { - networkId: 'BITCOIN', - coinType: 0, - name: 'Bitcoin', - anchorageId: 'BTC', - fireblocksId: 'BTC' - }, - { - networkId: 'BITCOIN_CASH', - coinType: 145, - name: 'Bitcoin Cash', - anchorageId: 'BCH', - fireblocksId: 'BCH' - }, - { - networkId: 'BITCOIN_CASH_TESTNET', - coinType: 1, - name: 'Bitcoin Cash Testnet', - fireblocksId: 'BCH_TEST' - }, - { - networkId: 'BITCOIN_SIGNET', - coinType: 1, - name: 'Bitcoin Signet', - anchorageId: 'BTC_S' - }, - { - networkId: 'BITCOIN_SV', - coinType: 236, - name: 'BitcoinSV', - fireblocksId: 'BSV' - }, - { - networkId: 'BITCOIN_SV_TESTNET', - coinType: 1, - name: 'BitcoinSV Testnet', - fireblocksId: 'BSV_TEST' - }, - { - networkId: 'BITCOIN_TESTNET', - coinType: 1, - name: 'Bitcoin Testnet', - fireblocksId: 'BTC_TEST' - }, - { - networkId: 'CARDANO', - coinType: 1815, - name: 'Cardano', - fireblocksId: 'ADA' - }, - { - networkId: 'CARDANO_TESTNET', - coinType: 1, - name: 'Cardano Testnet', - fireblocksId: 'ADA_TEST' - }, - { - networkId: 'CELESTIA', - coinType: null, - name: 'Celestia', - anchorageId: 'TIA' - }, - { - networkId: 'CELO', - coinType: 52752, - name: 'Celo', - fireblocksId: 'CELO' - }, - { - networkId: 'CELO_ALFAJORES', - coinType: null, - name: 'Celo Alfajores', - fireblocksId: 'CELO_ALF' - }, - { - networkId: 'CELO_BAKLAVA', - coinType: 1, - name: 'Celo Baklava', - anchorageId: 'CGLD_TB', - fireblocksId: 'CELO_BAK' - }, - { - networkId: 'CHILIZ', - coinType: null, - name: 'Chiliz', - fireblocksId: 'CHZ_$CHZ' - }, - { - networkId: 'DABACUS', - coinType: 521, - name: 'Dabacus', - fireblocksId: 'ABA' - }, - { - networkId: 'DOGECOIN', - coinType: 3, - name: 'Dogecoin', - anchorageId: 'DOGE', - fireblocksId: 'DOGE' - }, - { - networkId: 'DOGECOIN_TESTNET', - coinType: 1, - name: 'Dogecoin Testnet', - fireblocksId: 'DOGE_TEST' - }, - { - networkId: 'DYDX_CHAIN', - coinType: null, - name: 'Dydx Chain', - anchorageId: 'DYDX_CHAIN' - }, - { - networkId: 'DYDX_CHAIN_TESTNET', - coinType: 1, - name: 'Dydx Testnet', - anchorageId: 'DYDX_CHAIN_T' - }, - { - networkId: 'ETHEREUM', - coinType: 60, - name: 'Ethereum', - anchorageId: 'ETH', - fireblocksId: 'ETH' - }, - { - networkId: 'ETHEREUM_HOLESKY', - coinType: 1, - name: 'Ethereum Holešky', - anchorageId: 'ETHHOL' - }, - { - networkId: 'ETHEREUM_SEPOLIA', - coinType: 1, - name: 'Ethereum Sepolia', - anchorageId: 'ETHSEP' - }, - { - networkId: 'EVMOS', - coinType: null, - name: 'Evmos', - anchorageId: 'EVMOS' - }, - { - networkId: 'EVMOS_TESTNET', - coinType: 1, - name: 'Evmos Testnet', - anchorageId: 'EVMOS_T' - }, - { - networkId: 'FILECOIN', - coinType: 461, - name: 'Filecoin', - anchorageId: 'FIL' - }, - { - networkId: 'FLOW_TESTNET', - coinType: 1, - name: 'Flow Testnet', - anchorageId: 'FLOW_T' - }, - { - networkId: 'LITECOIN', - coinType: 2, - name: 'Litecoin', - anchorageId: 'LTC', - fireblocksId: 'LTC' - }, - { - networkId: 'LITECOIN_TESTNET', - coinType: 1, - name: 'Litecoin Testnet', - fireblocksId: 'LTC_TEST' - }, - { - networkId: 'NEUTRON', - coinType: null, - name: 'Neutron', - anchorageId: 'NTRN' - }, - { - networkId: 'OASIS', - coinType: 474, - name: 'Oasis', - anchorageId: 'OAC' - }, - { - networkId: 'OM_MANTRA', - coinType: null, - name: 'OM Mantra', - anchorageId: 'OM_MANTRA' - }, - { - networkId: 'OM_MANTRA_TESTNET', - coinType: 1, - name: 'OM Mantra Testnet', - anchorageId: 'OM_MANTRA_T' - }, - { - networkId: 'OSMOSIS', - coinType: 10000118, - name: 'Osmosis', - anchorageId: 'OSMO', - fireblocksId: 'OSMO' - }, - { - networkId: 'PLUME_SEPOLIA', - coinType: 1, - name: 'Plume Sepolia Testnet', - anchorageId: 'PLUME_SEPOLIA' - }, - { - networkId: 'POLYGON', - coinType: 966, - name: 'Polygon', - anchorageId: 'POLYGON', - fireblocksId: 'MATIC_POLYGON' - }, - { - networkId: 'PROVENANCE', - coinType: 505, - name: 'Provenance', - anchorageId: 'HASH' - }, - { - networkId: 'RARIMO', - coinType: null, - name: 'Rarimo', - anchorageId: 'RMO' - }, - { - networkId: 'RIPPLE', - coinType: 144, - name: 'Ripple', - anchorageId: 'XRP', - fireblocksId: 'XRP' - }, - { - networkId: 'RIPPLE_TESTNET', - coinType: 1, - name: 'Ripple Testnet', - fireblocksId: 'XRP_TEST' - }, - { - networkId: 'SEI', - coinType: 19000118, - name: 'Sei', - anchorageId: 'SEI', - fireblocksId: 'SEI' - }, - { - networkId: 'SEI_TESTNET', - coinType: 1, - name: 'Sei Testnet', - anchorageId: 'SEI_T', - fireblocksId: 'SEI_TEST' - }, - { - networkId: 'SOLANA', - coinType: 501, - name: 'Solana', - fireblocksId: 'SOL' - }, - { - networkId: 'SOLANA_TESTNET', - coinType: 1, - name: 'Solana Testnet', - anchorageId: 'SOL_TD', - fireblocksId: 'SOL_TEST' - }, - { - networkId: 'STARKNET', - coinType: 9004, - name: 'Starknet', - anchorageId: 'STARK_STARKNET' - }, - { - networkId: 'STARKNET_TESTNET', - coinType: 1, - name: 'Starknet Testnet', - anchorageId: 'STRK_STARKNET_T' - }, - { - networkId: 'STELLAR_LUMENS', - coinType: 148, - name: 'Stellar Lumens', - fireblocksId: 'XLM' - }, - { - networkId: 'STELLAR_LUMENS_TESTNET', - coinType: 1, - name: 'Stellar Lumens Testnet', - fireblocksId: 'XLM_TEST' - }, - { - networkId: 'STRIDE', - coinType: null, - name: 'Stride', - anchorageId: 'STRD' - }, - { - networkId: 'SUI_TESTNET', - coinType: 1, - name: 'Sui Testnet', - anchorageId: 'SUI_T' - }, - { - networkId: 'TRON', - coinType: 195, - name: 'Tron', - fireblocksId: 'TRX' - }, - { - networkId: 'TRON_TESTNET', - coinType: 1, - name: 'Tron Testnet', - fireblocksId: 'TRX_TEST' - }, - { - networkId: 'VANA', - coinType: null, - name: 'Vana', - anchorageId: 'VANA' - }, - { - networkId: 'VANA_MOKSHA_TESTNET', - coinType: 1, - name: 'Vana Moksha Testnet', - anchorageId: 'VANA_MOKSHA_TESTNET' - }, - { - networkId: 'ZKSYNC_SEPOLIA', - coinType: 1, - name: 'ZKsync Sepolia Testnet', - anchorageId: 'ZKSYNC_SEPOLIA' - }, - { - networkId: 'POLKADOT', - coinType: 354, - name: 'Polkadot', - fireblocksId: 'DOT' - }, - { - networkId: 'EOS', - coinType: 194, - name: 'EOS', - fireblocksId: 'EOS' - }, - { - networkId: 'EOS_TESTNET', - coinType: 1, - name: 'EOS Testnet', - fireblocksId: 'EOS_TEST' - }, - { - networkId: 'OASYS', - coinType: 685, - name: 'Oasys', - fireblocksId: 'OAS' - }, - { - networkId: 'OASYS_TESTNET', - coinType: 1, - name: 'Oasys Testnet', - fireblocksId: 'OAS_TEST' - }, - { - networkId: 'OSMOSIS_TESTNET', - coinType: 1, - name: 'Osmosis Testnet', - fireblocksId: 'OSMO_TEST' - }, - { - networkId: 'TELOS', - coinType: 424, - name: 'Telos', - fireblocksId: 'TELOS' - }, - { - networkId: 'TELOS_TESTNET', - coinType: 1, - name: 'Telos Testnet', - fireblocksId: 'TELOS_TEST' - }, - { - networkId: 'TEZOS', - coinType: 1729, - name: 'Tezos', - fireblocksId: 'XTZ' - }, - { - networkId: 'TEZOS_TESTNET', - coinType: 1, - name: 'Tezos Testnet', - fireblocksId: 'XTZ_TEST' - }, - { - networkId: 'DASH', - coinType: 5, - name: 'Dash', - fireblocksId: 'DASH' - }, - { - networkId: 'DASH_TESTNET', - coinType: 1, - name: 'Dash Testnet', - fireblocksId: 'DASH_TEST' - }, - { - networkId: 'OPTIMISM', - coinType: 614, - name: 'Optimism', - fireblocksId: 'ETH-OPT' - }, - { - networkId: 'OPTIMISM_SEPOLIA', - coinType: 1, - name: 'Optimism Sepolia', - fireblocksId: 'ETH-OPT_SEPOLIA' - }, - { - networkId: 'OPTIMISM_KOVAN', - coinType: 1, - name: 'Optimism Kovan', - fireblocksId: 'ETH-OPT_KOV' - } -] - @Injectable() -export class NetworkRepository { +export class NetworkRepository implements OnApplicationBootstrap { private networkById: Map private networkByProviderAndExternalId: Map private networksByProvider: Map - constructor() { - this.index() + constructor( + private readonly prismaService: PrismaService, + private readonly logger: LoggerService + ) {} + + static parseModel( + model: Prisma.NetworkGetPayload<{ + include: { + externalNetworks: true + } + }> + ): Network { + return Network.parse({ + networkId: model.id, + coinType: model.coinType, + name: model.name, + createdAt: model.createdAt, + externalNetworks: model.externalNetworks.map(({ externalId, provider }) => ({ + provider, + externalId + })) + }) + } + + async onApplicationBootstrap() { + await this.index() } /** @@ -603,58 +50,212 @@ export class NetworkRepository { * * Creates three indexes: * - networkById: Maps networkId -> Network for direct lookups - * - networkByProviderAndExternalId: Maps "provider:externalId" -> Network for external ID lookups - * - networksByProvider: Maps provider -> Network[] for provider-specific filtering + * - networkByProviderAndExternalId: Maps "provider:externalId" -> Network + * for external ID lookups + * - networksByProvider: Maps provider -> Network[] for provider-specific + * filtering * - * This is a one-time O(n) operation at initialization to avoid O(n) - * array traversals on subsequent queries. All lookups become O(1) - * after indexing at the cost of O(n) additional memory. + * This is a one-time O(n) operation at initialization to avoid O(n) array + * traversals on subsequent queries. All lookups become O(1) after indexing + * at the cost of O(n) additional memory. */ - private index(): void { + private async index(): Promise { + const networks = await this.findAll() + this.networkById = new Map() this.networkByProviderAndExternalId = new Map() this.networksByProvider = new Map() - for (const network of NETWORKS) { + for (const network of networks) { this.networkById.set(network.networkId, network) - if (network.anchorageId) { - const key = `${Provider.ANCHORAGE}:${network.anchorageId}` + for (const externalNetwork of network.externalNetworks) { + const key = `${externalNetwork.provider}:${externalNetwork.externalId}` this.networkByProviderAndExternalId.set(key, network) - const providerNetworks = this.networksByProvider.get(Provider.ANCHORAGE) || [] + const providerNetworks = this.networksByProvider.get(externalNetwork.provider) || [] providerNetworks.push(network) + this.networksByProvider.set(externalNetwork.provider, providerNetworks) + } + } + } - this.networksByProvider.set(Provider.ANCHORAGE, providerNetworks) + async buildProviderExternalIdIndex(provider: Provider): Promise> { + const networks = await this.findAll({ filters: { provider } }) + const index = new Map() + + for (const network of networks) { + for (const externalNetwork of network.externalNetworks) { + if (externalNetwork.provider === provider) { + index.set(externalNetwork.externalId, network) + } } + } - if (network.fireblocksId) { - const key = `${Provider.FIREBLOCKS}:${network.fireblocksId}` - this.networkByProviderAndExternalId.set(key, network) + return index + } - const providerNetworks = this.networksByProvider.get(Provider.FIREBLOCKS) || [] - providerNetworks.push(network) + getNetworksByProvider(provider: Provider): Network[] { + return this.networksByProvider?.get(provider) || [] + } - this.networksByProvider.set(Provider.FIREBLOCKS, providerNetworks) - } + async bulkCreate(networks: Network[]): Promise { + for (const network of networks) { + const createdAt = network.createdAt || new Date() + + await this.prismaService.network.create({ + data: { + createdAt, + id: network.networkId, + coinType: network.coinType, + name: network.name, + externalNetworks: { + createMany: { + data: network.externalNetworks.map(({ provider, externalId }) => ({ + provider, + externalId, + createdAt + })) + } + } + }, + include: { + externalNetworks: true + } + }) } + + return networks + } + + async addExternalNetwork(networkId: string, externalNetwork: ExternalNetwork): Promise { + await this.prismaService.providerNetwork.create({ + data: { + ...externalNetwork, + networkId + } + }) + + return externalNetwork + } + + async bulkAddExternalNetwork( + params: { + networkId: string + externalNetwork: ExternalNetwork + }[] + ): Promise { + await this.prismaService.providerNetwork.createMany({ + data: params.map(({ networkId, externalNetwork }) => ({ + ...externalNetwork, + networkId + })) + }) + + return true } async findAll(options?: FindAllOptions): Promise { - if (!options?.filters?.provider) { - return NETWORKS + let networks: Network[] = [] + + if (this.networkById) { + if (options?.filters?.provider) { + networks = this.getNetworksByProvider(options.filters.provider) + } else { + networks = Array.from(this.networkById.values()) + } + } + + if (networks.length) { + return networks } - return this.networksByProvider.get(options.filters.provider) || [] + this.logger.log('Failed to findAll network in the index. Fallback to the database') + + const models = await this.prismaService.network.findMany({ + where: { + ...(options?.filters?.provider + ? { + externalNetworks: { + some: { + provider: options.filters.provider + } + } + } + : {}) + }, + include: { + externalNetworks: true + } + }) + + return models.map(NetworkRepository.parseModel) } async findById(networkId: string): Promise { - return this.networkById.get(networkId) || null + let network: Network | null = null + + if (this.networkById) { + network = this.networkById.get(networkId) || null + } + + if (network) { + return network + } + + this.logger.log('Failed to findById network in the index. Fallback to the database', { networkId }) + + const model = await this.prismaService.network.findUnique({ + where: { + id: networkId + }, + include: { + externalNetworks: true + } + }) + + if (model) { + return NetworkRepository.parseModel(model) + } + + return null } async findByExternalId(provider: Provider, externalId: string): Promise { - const key = `${provider}:${externalId}` + let network: Network | null = null + + if (this.networkByProviderAndExternalId) { + const key = `${provider}:${externalId}` + network = this.networkByProviderAndExternalId.get(key) || null + } + + if (network) { + return network + } + + this.logger.log('Failed to findByExternalId network in the index. Fallback to the database', { + provider, + externalId + }) + + const model = await this.prismaService.network.findFirst({ + where: { + externalNetworks: { + some: { + provider, + externalId + } + } + }, + include: { + externalNetworks: true + } + }) + + if (model) { + return NetworkRepository.parseModel(model) + } - return this.networkByProviderAndExternalId.get(key) || null + return null } } diff --git a/apps/vault/src/broker/persistence/seed/network.seed.ts b/apps/vault/src/broker/persistence/seed/network.seed.ts new file mode 100644 index 000000000..9172d847a --- /dev/null +++ b/apps/vault/src/broker/persistence/seed/network.seed.ts @@ -0,0 +1,626 @@ +import { LoggerService } from '@narval/nestjs-shared' +import { Injectable } from '@nestjs/common' +import { Provider } from '../../core/type/provider.type' +import { NetworkRepository } from '../repository/network.repository' + +@Injectable() +export class NetworkSeed { + constructor( + private readonly networkRepository: NetworkRepository, + private readonly logger: LoggerService + ) {} + + // IMPORTANT: There's already a data migration for base networks. + // See 20250115095035_add_network_table_and_data/migration.sql + async seed(): Promise { + this.logger.log('🌐 Seeding networks') + + await this.networkRepository.bulkCreate( + this.getNetworks().map((network) => ({ + networkId: network.networkId, + coinType: network.coinType, + name: network.name, + externalNetworks: [ + ...(network.anchorageId + ? [ + { + provider: Provider.ANCHORAGE, + externalId: network.anchorageId + } + ] + : []), + ...(network.fireblocksId + ? [ + { + provider: Provider.FIREBLOCKS, + externalId: network.fireblocksId + } + ] + : []) + ] + })) + ) + } + + getNetworks() { + return [ + { + networkId: 'AETH', + coinType: 514, + name: 'Aetherius', + fireblocksId: 'ETH-AETH' + }, + { + networkId: 'AEVO', + coinType: null, + name: 'Aevo', + fireblocksId: 'AEVO' + }, + { + networkId: 'AGORIC', + coinType: 564, + name: 'Agoric', + anchorageId: 'BLD' + }, + { + networkId: 'ALEPH_ZERO', + coinType: 643, + name: 'Aleph Zero', + fireblocksId: 'ALEPH_ZERO_EVM' + }, + { + networkId: 'ALGORAND', + coinType: 283, + name: 'Algorand', + fireblocksId: 'ALGO' + }, + { + networkId: 'ALGORAND_TESTNET', + coinType: 1, + name: 'Algorand Testnet', + fireblocksId: 'ALGO_TEST' + }, + { + networkId: 'ALLORA', + coinType: null, + name: 'Allora', + anchorageId: 'ALLO' + }, + { + networkId: 'ALLORA_TESTNET', + coinType: 1, + name: 'Allora Testnet', + anchorageId: 'ALLO_T' + }, + { + networkId: 'APTOS', + coinType: 637, + name: 'Aptos', + anchorageId: 'APT' + }, + { + networkId: 'APTOS_TESTNET', + coinType: 1, + name: 'Aptos Testnet', + anchorageId: 'APT_T' + }, + { + networkId: 'ARBITRUM_SEPOLIA', + coinType: 1, + name: 'Arbitrum Sepolia Testnet', + anchorageId: 'ARBITRUM_SEPOLIA' + }, + { + networkId: 'ASTAR', + coinType: 810, + name: 'Astar', + fireblocksId: 'ASTR_ASTR' + }, + { + networkId: 'ASTAR_TESTNET', + coinType: 1, + name: 'Astar Testnet', + fireblocksId: 'ASTR_TEST' + }, + { + networkId: 'ATOM', + coinType: 118, + name: 'Atom', + anchorageId: 'COSMOS', + fireblocksId: 'ATOM_COS' + }, + { + networkId: 'ATOM_TESTNET', + coinType: 1, + name: 'Atom Testnet', + fireblocksId: 'ATOM_COS_TEST' + }, + { + networkId: 'AURORA', + coinType: 2570, + name: 'Aurora', + fireblocksId: 'AURORA_DEV' + }, + { + networkId: 'AVAX', + coinType: 9000, + name: 'Avalanche', + fireblocksId: 'AVAX' + }, + { + networkId: 'AVAX_TESTNET', + coinType: 1, + name: 'Avalanche Testnet', + fireblocksId: 'AVAXTEST' + }, + { + networkId: 'AXELAR', + coinType: null, + name: 'Axelar', + anchorageId: 'AXL' + }, + { + networkId: 'AXELAR_TESTNET', + coinType: 1, + name: 'Axelar Testnet', + anchorageId: 'AXL_T' + }, + { + networkId: 'BABYLON', + coinType: null, + name: 'Babylon', + anchorageId: 'BBN' + }, + { + networkId: 'BASE', + coinType: 8453, + name: 'Base', + fireblocksId: 'BASECHAIN_ETH' + }, + { + networkId: 'BASE_TESTNET', + coinType: 1, + name: 'Base Testnet', + fireblocksId: 'BASECHAIN_ETH_TEST5' + }, + { + networkId: 'BINANCE_SMART_CHAIN', + coinType: 9006, + name: 'Binance Smart Chain', + fireblocksId: 'BNB_BSC' + }, + { + networkId: 'BINANCE_SMART_CHAIN_TESTNET', + coinType: 1, + name: 'Binance Smart Chain Testnet', + fireblocksId: 'BNB_TEST' + }, + { + networkId: 'BITCOIN', + coinType: 0, + name: 'Bitcoin', + anchorageId: 'BTC', + fireblocksId: 'BTC' + }, + { + networkId: 'BITCOIN_CASH', + coinType: 145, + name: 'Bitcoin Cash', + anchorageId: 'BCH', + fireblocksId: 'BCH' + }, + { + networkId: 'BITCOIN_CASH_TESTNET', + coinType: 1, + name: 'Bitcoin Cash Testnet', + fireblocksId: 'BCH_TEST' + }, + { + networkId: 'BITCOIN_SIGNET', + coinType: 1, + name: 'Bitcoin Signet', + anchorageId: 'BTC_S' + }, + { + networkId: 'BITCOIN_SV', + coinType: 236, + name: 'BitcoinSV', + fireblocksId: 'BSV' + }, + { + networkId: 'BITCOIN_SV_TESTNET', + coinType: 1, + name: 'BitcoinSV Testnet', + fireblocksId: 'BSV_TEST' + }, + { + networkId: 'BITCOIN_TESTNET', + coinType: 1, + name: 'Bitcoin Testnet', + fireblocksId: 'BTC_TEST' + }, + { + networkId: 'CARDANO', + coinType: 1815, + name: 'Cardano', + fireblocksId: 'ADA' + }, + { + networkId: 'CARDANO_TESTNET', + coinType: 1, + name: 'Cardano Testnet', + fireblocksId: 'ADA_TEST' + }, + { + networkId: 'CELESTIA', + coinType: null, + name: 'Celestia', + anchorageId: 'TIA' + }, + { + networkId: 'CELO', + coinType: 52752, + name: 'Celo', + fireblocksId: 'CELO' + }, + { + networkId: 'CELO_ALFAJORES', + coinType: null, + name: 'Celo Alfajores', + fireblocksId: 'CELO_ALF' + }, + { + networkId: 'CELO_BAKLAVA', + coinType: 1, + name: 'Celo Baklava', + anchorageId: 'CGLD_TB', + fireblocksId: 'CELO_BAK' + }, + { + networkId: 'CHILIZ', + coinType: null, + name: 'Chiliz', + fireblocksId: 'CHZ_$CHZ' + }, + { + networkId: 'DABACUS', + coinType: 521, + name: 'Dabacus', + fireblocksId: 'ABA' + }, + { + networkId: 'DOGECOIN', + coinType: 3, + name: 'Dogecoin', + anchorageId: 'DOGE', + fireblocksId: 'DOGE' + }, + { + networkId: 'DOGECOIN_TESTNET', + coinType: 1, + name: 'Dogecoin Testnet', + fireblocksId: 'DOGE_TEST' + }, + { + networkId: 'DYDX_CHAIN', + coinType: null, + name: 'Dydx Chain', + anchorageId: 'DYDX_CHAIN' + }, + { + networkId: 'DYDX_CHAIN_TESTNET', + coinType: 1, + name: 'Dydx Testnet', + anchorageId: 'DYDX_CHAIN_T' + }, + { + networkId: 'ETHEREUM', + coinType: 60, + name: 'Ethereum', + anchorageId: 'ETH', + fireblocksId: 'ETH' + }, + { + networkId: 'ETHEREUM_HOLESKY', + coinType: 1, + name: 'Ethereum Holešky', + anchorageId: 'ETHHOL' + }, + { + networkId: 'ETHEREUM_SEPOLIA', + coinType: 1, + name: 'Ethereum Sepolia', + anchorageId: 'ETHSEP' + }, + { + networkId: 'EVMOS', + coinType: null, + name: 'Evmos', + anchorageId: 'EVMOS' + }, + { + networkId: 'EVMOS_TESTNET', + coinType: 1, + name: 'Evmos Testnet', + anchorageId: 'EVMOS_T' + }, + { + networkId: 'FILECOIN', + coinType: 461, + name: 'Filecoin', + anchorageId: 'FIL' + }, + { + networkId: 'FLOW_TESTNET', + coinType: 1, + name: 'Flow Testnet', + anchorageId: 'FLOW_T' + }, + { + networkId: 'LITECOIN', + coinType: 2, + name: 'Litecoin', + anchorageId: 'LTC', + fireblocksId: 'LTC' + }, + { + networkId: 'LITECOIN_TESTNET', + coinType: 1, + name: 'Litecoin Testnet', + fireblocksId: 'LTC_TEST' + }, + { + networkId: 'NEUTRON', + coinType: null, + name: 'Neutron', + anchorageId: 'NTRN' + }, + { + networkId: 'OASIS', + coinType: 474, + name: 'Oasis', + anchorageId: 'OAC' + }, + { + networkId: 'OM_MANTRA', + coinType: null, + name: 'OM Mantra', + anchorageId: 'OM_MANTRA' + }, + { + networkId: 'OM_MANTRA_TESTNET', + coinType: 1, + name: 'OM Mantra Testnet', + anchorageId: 'OM_MANTRA_T' + }, + { + networkId: 'OSMOSIS', + coinType: 10000118, + name: 'Osmosis', + anchorageId: 'OSMO', + fireblocksId: 'OSMO' + }, + { + networkId: 'PLUME_SEPOLIA', + coinType: 1, + name: 'Plume Sepolia Testnet', + anchorageId: 'PLUME_SEPOLIA' + }, + { + networkId: 'POLYGON', + coinType: 966, + name: 'Polygon', + anchorageId: 'POLYGON', + fireblocksId: 'MATIC_POLYGON' + }, + { + networkId: 'PROVENANCE', + coinType: 505, + name: 'Provenance', + anchorageId: 'HASH' + }, + { + networkId: 'RARIMO', + coinType: null, + name: 'Rarimo', + anchorageId: 'RMO' + }, + { + networkId: 'RIPPLE', + coinType: 144, + name: 'Ripple', + anchorageId: 'XRP', + fireblocksId: 'XRP' + }, + { + networkId: 'RIPPLE_TESTNET', + coinType: 1, + name: 'Ripple Testnet', + fireblocksId: 'XRP_TEST' + }, + { + networkId: 'SEI', + coinType: 19000118, + name: 'Sei', + anchorageId: 'SEI', + fireblocksId: 'SEI' + }, + { + networkId: 'SEI_TESTNET', + coinType: 1, + name: 'Sei Testnet', + anchorageId: 'SEI_T', + fireblocksId: 'SEI_TEST' + }, + { + networkId: 'SOLANA', + coinType: 501, + name: 'Solana', + fireblocksId: 'SOL' + }, + { + networkId: 'SOLANA_TESTNET', + coinType: 1, + name: 'Solana Testnet', + anchorageId: 'SOL_TD', + fireblocksId: 'SOL_TEST' + }, + { + networkId: 'STARKNET', + coinType: 9004, + name: 'Starknet', + anchorageId: 'STARK_STARKNET' + }, + { + networkId: 'STARKNET_TESTNET', + coinType: 1, + name: 'Starknet Testnet', + anchorageId: 'STRK_STARKNET_T' + }, + { + networkId: 'STELLAR_LUMENS', + coinType: 148, + name: 'Stellar Lumens', + fireblocksId: 'XLM' + }, + { + networkId: 'STELLAR_LUMENS_TESTNET', + coinType: 1, + name: 'Stellar Lumens Testnet', + fireblocksId: 'XLM_TEST' + }, + { + networkId: 'STRIDE', + coinType: null, + name: 'Stride', + anchorageId: 'STRD' + }, + { + networkId: 'SUI_TESTNET', + coinType: 1, + name: 'Sui Testnet', + anchorageId: 'SUI_T' + }, + { + networkId: 'TRON', + coinType: 195, + name: 'Tron', + fireblocksId: 'TRX' + }, + { + networkId: 'TRON_TESTNET', + coinType: 1, + name: 'Tron Testnet', + fireblocksId: 'TRX_TEST' + }, + { + networkId: 'VANA', + coinType: null, + name: 'Vana', + anchorageId: 'VANA' + }, + { + networkId: 'VANA_MOKSHA_TESTNET', + coinType: 1, + name: 'Vana Moksha Testnet', + anchorageId: 'VANA_MOKSHA_TESTNET' + }, + { + networkId: 'ZKSYNC_SEPOLIA', + coinType: 1, + name: 'ZKsync Sepolia Testnet', + anchorageId: 'ZKSYNC_SEPOLIA' + }, + { + networkId: 'POLKADOT', + coinType: 354, + name: 'Polkadot', + fireblocksId: 'DOT' + }, + { + networkId: 'EOS', + coinType: 194, + name: 'EOS', + fireblocksId: 'EOS' + }, + { + networkId: 'EOS_TESTNET', + coinType: 1, + name: 'EOS Testnet', + fireblocksId: 'EOS_TEST' + }, + { + networkId: 'OASYS', + coinType: 685, + name: 'Oasys', + fireblocksId: 'OAS' + }, + { + networkId: 'OASYS_TESTNET', + coinType: 1, + name: 'Oasys Testnet', + fireblocksId: 'OAS_TEST' + }, + { + networkId: 'OSMOSIS_TESTNET', + coinType: 1, + name: 'Osmosis Testnet', + fireblocksId: 'OSMO_TEST' + }, + { + networkId: 'TELOS', + coinType: 424, + name: 'Telos', + fireblocksId: 'TELOS' + }, + { + networkId: 'TELOS_TESTNET', + coinType: 1, + name: 'Telos Testnet', + fireblocksId: 'TELOS_TEST' + }, + { + networkId: 'TEZOS', + coinType: 1729, + name: 'Tezos', + fireblocksId: 'XTZ' + }, + { + networkId: 'TEZOS_TESTNET', + coinType: 1, + name: 'Tezos Testnet', + fireblocksId: 'XTZ_TEST' + }, + { + networkId: 'DASH', + coinType: 5, + name: 'Dash', + fireblocksId: 'DASH' + }, + { + networkId: 'DASH_TESTNET', + coinType: 1, + name: 'Dash Testnet', + fireblocksId: 'DASH_TEST' + }, + { + networkId: 'OPTIMISM', + coinType: 614, + name: 'Optimism', + fireblocksId: 'ETH-OPT' + }, + { + networkId: 'OPTIMISM_SEPOLIA', + coinType: 1, + name: 'Optimism Sepolia', + fireblocksId: 'ETH-OPT_SEPOLIA' + }, + { + networkId: 'OPTIMISM_KOVAN', + coinType: 1, + name: 'Optimism Kovan', + fireblocksId: 'ETH-OPT_KOV' + } + ] + } +} diff --git a/apps/vault/src/main.config.ts b/apps/vault/src/main.config.ts index d94025882..6f865c101 100644 --- a/apps/vault/src/main.config.ts +++ b/apps/vault/src/main.config.ts @@ -302,3 +302,7 @@ export const load = (): Config => { throw new Error(`Invalid application configuration: ${result.error.message}`) } + +export const getEnv = (): Env => { + return z.nativeEnum(Env).parse(process.env.NODE_ENV) +} diff --git a/apps/vault/src/shared/module/persistence/persistence.module.ts b/apps/vault/src/shared/module/persistence/persistence.module.ts index 01c9fe22a..644f7f326 100644 --- a/apps/vault/src/shared/module/persistence/persistence.module.ts +++ b/apps/vault/src/shared/module/persistence/persistence.module.ts @@ -6,6 +6,7 @@ import { AppService } from '../../../app.service' import { AppModule } from '../../../main.module' import { EncryptionModuleOptionFactory } from '../../factory/encryption-module-option.factory' import { PrismaService } from './service/prisma.service' +import { SeederService } from './service/seeder.service' import { TestPrismaService } from './service/test-prisma.service' @Module({}) @@ -35,8 +36,8 @@ export class PersistenceModule { useClass: EncryptionModuleOptionFactory }) ], - providers: [PrismaService, TestPrismaService], - exports: [PrismaService, TestPrismaService] + providers: [PrismaService, TestPrismaService, SeederService], + exports: [PrismaService, TestPrismaService, SeederService] } } } diff --git a/apps/vault/src/shared/module/persistence/schema/migrations/20250115095035_add_network_table_and_data/migration.sql b/apps/vault/src/shared/module/persistence/schema/migrations/20250115095035_add_network_table_and_data/migration.sql new file mode 100644 index 000000000..36fa759ca --- /dev/null +++ b/apps/vault/src/shared/module/persistence/schema/migrations/20250115095035_add_network_table_and_data/migration.sql @@ -0,0 +1,252 @@ +-- CreateTable +CREATE TABLE "network" ( + "id" TEXT NOT NULL, + "coin_type" INTEGER, + "name" TEXT NOT NULL, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "network_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "provider_network" ( + "external_id" TEXT NOT NULL, + "network_id" TEXT NOT NULL, + "provider" TEXT NOT NULL, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +-- CreateIndex +CREATE UNIQUE INDEX "provider_network_provider_external_id_key" ON "provider_network"("provider", "external_id"); + +-- CreateIndex +CREATE UNIQUE INDEX "provider_network_provider_network_id_key" ON "provider_network"("provider", "network_id"); + +-- AddForeignKey +ALTER TABLE "provider_network" ADD CONSTRAINT "provider_network_network_id_fkey" FOREIGN KEY ("network_id") REFERENCES "network"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- InsertProviderNetwork +INSERT INTO public.network (id,coin_type,name,created_at) VALUES + ('AETH',514,'Aetherius','2025-01-13 16:19:11.019'), + ('AEVO',NULL,'Aevo','2025-01-13 16:19:11.024'), + ('AGORIC',564,'Agoric','2025-01-13 16:19:11.026'), + ('ALEPH_ZERO',643,'Aleph Zero','2025-01-13 16:19:11.027'), + ('ALGORAND',283,'Algorand','2025-01-13 16:19:11.029'), + ('ALGORAND_TESTNET',1,'Algorand Testnet','2025-01-13 16:19:11.031'), + ('ALLORA',NULL,'Allora','2025-01-13 16:19:11.032'), + ('ALLORA_TESTNET',1,'Allora Testnet','2025-01-13 16:19:11.034'), + ('APTOS',637,'Aptos','2025-01-13 16:19:11.036'), + ('APTOS_TESTNET',1,'Aptos Testnet','2025-01-13 16:19:11.037'); +INSERT INTO public.network (id,coin_type,name,created_at) VALUES + ('ARBITRUM_SEPOLIA',1,'Arbitrum Sepolia Testnet','2025-01-13 16:19:11.039'), + ('ASTAR',810,'Astar','2025-01-13 16:19:11.040'), + ('ASTAR_TESTNET',1,'Astar Testnet','2025-01-13 16:19:11.042'), + ('ATOM',118,'Atom','2025-01-13 16:19:11.043'), + ('ATOM_TESTNET',1,'Atom Testnet','2025-01-13 16:19:11.045'), + ('AURORA',2570,'Aurora','2025-01-13 16:19:11.046'), + ('AVAX',9000,'Avalanche','2025-01-13 16:19:11.047'), + ('AVAX_TESTNET',1,'Avalanche Testnet','2025-01-13 16:19:11.049'), + ('AXELAR',NULL,'Axelar','2025-01-13 16:19:11.050'), + ('AXELAR_TESTNET',1,'Axelar Testnet','2025-01-13 16:19:11.052'); +INSERT INTO public.network (id,coin_type,name,created_at) VALUES + ('BABYLON',NULL,'Babylon','2025-01-13 16:19:11.053'), + ('BASE',8453,'Base','2025-01-13 16:19:11.054'), + ('BASE_TESTNET',1,'Base Testnet','2025-01-13 16:19:11.056'), + ('BINANCE_SMART_CHAIN',9006,'Binance Smart Chain','2025-01-13 16:19:11.057'), + ('BINANCE_SMART_CHAIN_TESTNET',1,'Binance Smart Chain Testnet','2025-01-13 16:19:11.058'), + ('BITCOIN',0,'Bitcoin','2025-01-13 16:19:11.059'), + ('BITCOIN_CASH',145,'Bitcoin Cash','2025-01-13 16:19:11.061'), + ('BITCOIN_CASH_TESTNET',1,'Bitcoin Cash Testnet','2025-01-13 16:19:11.062'), + ('BITCOIN_SIGNET',1,'Bitcoin Signet','2025-01-13 16:19:11.063'), + ('BITCOIN_SV',236,'BitcoinSV','2025-01-13 16:19:11.064'); +INSERT INTO public.network (id,coin_type,name,created_at) VALUES + ('BITCOIN_SV_TESTNET',1,'BitcoinSV Testnet','2025-01-13 16:19:11.066'), + ('BITCOIN_TESTNET',1,'Bitcoin Testnet','2025-01-13 16:19:11.067'), + ('CARDANO',1815,'Cardano','2025-01-13 16:19:11.068'), + ('CARDANO_TESTNET',1,'Cardano Testnet','2025-01-13 16:19:11.070'), + ('CELESTIA',NULL,'Celestia','2025-01-13 16:19:11.071'), + ('CELO',52752,'Celo','2025-01-13 16:19:11.072'), + ('CELO_ALFAJORES',NULL,'Celo Alfajores','2025-01-13 16:19:11.073'), + ('CELO_BAKLAVA',1,'Celo Baklava','2025-01-13 16:19:11.075'), + ('CHILIZ',NULL,'Chiliz','2025-01-13 16:19:11.076'), + ('DABACUS',521,'Dabacus','2025-01-13 16:19:11.077'); +INSERT INTO public.network (id,coin_type,name,created_at) VALUES + ('DOGECOIN',3,'Dogecoin','2025-01-13 16:19:11.079'), + ('DOGECOIN_TESTNET',1,'Dogecoin Testnet','2025-01-13 16:19:11.080'), + ('DYDX_CHAIN',NULL,'Dydx Chain','2025-01-13 16:19:11.081'), + ('DYDX_CHAIN_TESTNET',1,'Dydx Testnet','2025-01-13 16:19:11.083'), + ('ETHEREUM',60,'Ethereum','2025-01-13 16:19:11.084'), + ('ETHEREUM_HOLESKY',1,'Ethereum Holešky','2025-01-13 16:19:11.085'), + ('ETHEREUM_SEPOLIA',1,'Ethereum Sepolia','2025-01-13 16:19:11.086'), + ('EVMOS',NULL,'Evmos','2025-01-13 16:19:11.088'), + ('EVMOS_TESTNET',1,'Evmos Testnet','2025-01-13 16:19:11.089'), + ('FILECOIN',461,'Filecoin','2025-01-13 16:19:11.090'); +INSERT INTO public.network (id,coin_type,name,created_at) VALUES + ('FLOW_TESTNET',1,'Flow Testnet','2025-01-13 16:19:11.091'), + ('LITECOIN',2,'Litecoin','2025-01-13 16:19:11.093'), + ('LITECOIN_TESTNET',1,'Litecoin Testnet','2025-01-13 16:19:11.094'), + ('NEUTRON',NULL,'Neutron','2025-01-13 16:19:11.095'), + ('OASIS',474,'Oasis','2025-01-13 16:19:11.097'), + ('OM_MANTRA',NULL,'OM Mantra','2025-01-13 16:19:11.098'), + ('OM_MANTRA_TESTNET',1,'OM Mantra Testnet','2025-01-13 16:19:11.099'), + ('OSMOSIS',10000118,'Osmosis','2025-01-13 16:19:11.101'), + ('PLUME_SEPOLIA',1,'Plume Sepolia Testnet','2025-01-13 16:19:11.102'), + ('POLYGON',966,'Polygon','2025-01-13 16:19:11.103'); +INSERT INTO public.network (id,coin_type,name,created_at) VALUES + ('PROVENANCE',505,'Provenance','2025-01-13 16:19:11.104'), + ('RARIMO',NULL,'Rarimo','2025-01-13 16:19:11.106'), + ('RIPPLE',144,'Ripple','2025-01-13 16:19:11.107'), + ('RIPPLE_TESTNET',1,'Ripple Testnet','2025-01-13 16:19:11.108'), + ('SEI',19000118,'Sei','2025-01-13 16:19:11.110'), + ('SEI_TESTNET',1,'Sei Testnet','2025-01-13 16:19:11.111'), + ('SOLANA',501,'Solana','2025-01-13 16:19:11.112'), + ('SOLANA_TESTNET',1,'Solana Testnet','2025-01-13 16:19:11.114'), + ('STARKNET',9004,'Starknet','2025-01-13 16:19:11.115'), + ('STARKNET_TESTNET',1,'Starknet Testnet','2025-01-13 16:19:11.116'); +INSERT INTO public.network (id,coin_type,name,created_at) VALUES + ('STELLAR_LUMENS',148,'Stellar Lumens','2025-01-13 16:19:11.117'), + ('STELLAR_LUMENS_TESTNET',1,'Stellar Lumens Testnet','2025-01-13 16:19:11.119'), + ('STRIDE',NULL,'Stride','2025-01-13 16:19:11.120'), + ('SUI_TESTNET',1,'Sui Testnet','2025-01-13 16:19:11.121'), + ('TRON',195,'Tron','2025-01-13 16:19:11.122'), + ('TRON_TESTNET',1,'Tron Testnet','2025-01-13 16:19:11.123'), + ('VANA',NULL,'Vana','2025-01-13 16:19:11.124'), + ('VANA_MOKSHA_TESTNET',1,'Vana Moksha Testnet','2025-01-13 16:19:11.126'), + ('ZKSYNC_SEPOLIA',1,'ZKsync Sepolia Testnet','2025-01-13 16:19:11.127'), + ('POLKADOT',354,'Polkadot','2025-01-13 16:19:11.128'); +INSERT INTO public.network (id,coin_type,name,created_at) VALUES + ('EOS',194,'EOS','2025-01-13 16:19:11.129'), + ('EOS_TESTNET',1,'EOS Testnet','2025-01-13 16:19:11.131'), + ('OASYS',685,'Oasys','2025-01-13 16:19:11.132'), + ('OASYS_TESTNET',1,'Oasys Testnet','2025-01-13 16:19:11.133'), + ('OSMOSIS_TESTNET',1,'Osmosis Testnet','2025-01-13 16:19:11.134'), + ('TELOS',424,'Telos','2025-01-13 16:19:11.136'), + ('TELOS_TESTNET',1,'Telos Testnet','2025-01-13 16:19:11.137'), + ('TEZOS',1729,'Tezos','2025-01-13 16:19:11.138'), + ('TEZOS_TESTNET',1,'Tezos Testnet','2025-01-13 16:19:11.139'), + ('DASH',5,'Dash','2025-01-13 16:19:11.140'); +INSERT INTO public.network (id,coin_type,name,created_at) VALUES + ('DASH_TESTNET',1,'Dash Testnet','2025-01-13 16:19:11.141'), + ('OPTIMISM',614,'Optimism','2025-01-13 16:19:11.143'), + ('OPTIMISM_SEPOLIA',1,'Optimism Sepolia','2025-01-13 16:19:11.144'), + ('OPTIMISM_KOVAN',1,'Optimism Kovan','2025-01-13 16:19:11.145'); + +-- InsertProviderExternalNetwork +INSERT INTO public.provider_network (external_id,network_id,provider,created_at) VALUES + ('ETH-AETH','AETH','fireblocks','2025-01-13 16:19:11.019'), + ('AEVO','AEVO','fireblocks','2025-01-13 16:19:11.024'), + ('BLD','AGORIC','anchorage','2025-01-13 16:19:11.026'), + ('ALEPH_ZERO_EVM','ALEPH_ZERO','fireblocks','2025-01-13 16:19:11.027'), + ('ALGO','ALGORAND','fireblocks','2025-01-13 16:19:11.029'), + ('ALGO_TEST','ALGORAND_TESTNET','fireblocks','2025-01-13 16:19:11.031'), + ('ALLO','ALLORA','anchorage','2025-01-13 16:19:11.032'), + ('ALLO_T','ALLORA_TESTNET','anchorage','2025-01-13 16:19:11.034'), + ('APT','APTOS','anchorage','2025-01-13 16:19:11.036'), + ('APT_T','APTOS_TESTNET','anchorage','2025-01-13 16:19:11.037'); +INSERT INTO public.provider_network (external_id,network_id,provider,created_at) VALUES + ('ARBITRUM_SEPOLIA','ARBITRUM_SEPOLIA','anchorage','2025-01-13 16:19:11.039'), + ('ASTR_ASTR','ASTAR','fireblocks','2025-01-13 16:19:11.040'), + ('ASTR_TEST','ASTAR_TESTNET','fireblocks','2025-01-13 16:19:11.042'), + ('COSMOS','ATOM','anchorage','2025-01-13 16:19:11.043'), + ('ATOM_COS','ATOM','fireblocks','2025-01-13 16:19:11.043'), + ('ATOM_COS_TEST','ATOM_TESTNET','fireblocks','2025-01-13 16:19:11.045'), + ('AURORA_DEV','AURORA','fireblocks','2025-01-13 16:19:11.046'), + ('AVAX','AVAX','fireblocks','2025-01-13 16:19:11.047'), + ('AVAXTEST','AVAX_TESTNET','fireblocks','2025-01-13 16:19:11.049'), + ('AXL','AXELAR','anchorage','2025-01-13 16:19:11.050'); +INSERT INTO public.provider_network (external_id,network_id,provider,created_at) VALUES + ('AXL_T','AXELAR_TESTNET','anchorage','2025-01-13 16:19:11.052'), + ('BBN','BABYLON','anchorage','2025-01-13 16:19:11.053'), + ('BASECHAIN_ETH','BASE','fireblocks','2025-01-13 16:19:11.054'), + ('BASECHAIN_ETH_TEST5','BASE_TESTNET','fireblocks','2025-01-13 16:19:11.056'), + ('BNB_BSC','BINANCE_SMART_CHAIN','fireblocks','2025-01-13 16:19:11.057'), + ('BNB_TEST','BINANCE_SMART_CHAIN_TESTNET','fireblocks','2025-01-13 16:19:11.058'), + ('BTC','BITCOIN','anchorage','2025-01-13 16:19:11.059'), + ('BTC','BITCOIN','fireblocks','2025-01-13 16:19:11.059'), + ('BCH','BITCOIN_CASH','anchorage','2025-01-13 16:19:11.061'), + ('BCH','BITCOIN_CASH','fireblocks','2025-01-13 16:19:11.061'); +INSERT INTO public.provider_network (external_id,network_id,provider,created_at) VALUES + ('BCH_TEST','BITCOIN_CASH_TESTNET','fireblocks','2025-01-13 16:19:11.062'), + ('BTC_S','BITCOIN_SIGNET','anchorage','2025-01-13 16:19:11.063'), + ('BSV','BITCOIN_SV','fireblocks','2025-01-13 16:19:11.064'), + ('BSV_TEST','BITCOIN_SV_TESTNET','fireblocks','2025-01-13 16:19:11.066'), + ('BTC_TEST','BITCOIN_TESTNET','fireblocks','2025-01-13 16:19:11.067'), + ('ADA','CARDANO','fireblocks','2025-01-13 16:19:11.068'), + ('ADA_TEST','CARDANO_TESTNET','fireblocks','2025-01-13 16:19:11.070'), + ('TIA','CELESTIA','anchorage','2025-01-13 16:19:11.071'), + ('CELO','CELO','fireblocks','2025-01-13 16:19:11.072'), + ('CELO_ALF','CELO_ALFAJORES','fireblocks','2025-01-13 16:19:11.073'); +INSERT INTO public.provider_network (external_id,network_id,provider,created_at) VALUES + ('CGLD_TB','CELO_BAKLAVA','anchorage','2025-01-13 16:19:11.075'), + ('CELO_BAK','CELO_BAKLAVA','fireblocks','2025-01-13 16:19:11.075'), + ('CHZ_$CHZ','CHILIZ','fireblocks','2025-01-13 16:19:11.076'), + ('ABA','DABACUS','fireblocks','2025-01-13 16:19:11.077'), + ('DOGE','DOGECOIN','anchorage','2025-01-13 16:19:11.079'), + ('DOGE','DOGECOIN','fireblocks','2025-01-13 16:19:11.079'), + ('DOGE_TEST','DOGECOIN_TESTNET','fireblocks','2025-01-13 16:19:11.080'), + ('DYDX_CHAIN','DYDX_CHAIN','anchorage','2025-01-13 16:19:11.081'), + ('DYDX_CHAIN_T','DYDX_CHAIN_TESTNET','anchorage','2025-01-13 16:19:11.083'), + ('ETH','ETHEREUM','anchorage','2025-01-13 16:19:11.084'); +INSERT INTO public.provider_network (external_id,network_id,provider,created_at) VALUES + ('ETH','ETHEREUM','fireblocks','2025-01-13 16:19:11.084'), + ('ETHHOL','ETHEREUM_HOLESKY','anchorage','2025-01-13 16:19:11.085'), + ('ETHSEP','ETHEREUM_SEPOLIA','anchorage','2025-01-13 16:19:11.086'), + ('EVMOS','EVMOS','anchorage','2025-01-13 16:19:11.088'), + ('EVMOS_T','EVMOS_TESTNET','anchorage','2025-01-13 16:19:11.089'), + ('FIL','FILECOIN','anchorage','2025-01-13 16:19:11.090'), + ('FLOW_T','FLOW_TESTNET','anchorage','2025-01-13 16:19:11.091'), + ('LTC','LITECOIN','anchorage','2025-01-13 16:19:11.093'), + ('LTC','LITECOIN','fireblocks','2025-01-13 16:19:11.093'), + ('LTC_TEST','LITECOIN_TESTNET','fireblocks','2025-01-13 16:19:11.094'); +INSERT INTO public.provider_network (external_id,network_id,provider,created_at) VALUES + ('NTRN','NEUTRON','anchorage','2025-01-13 16:19:11.095'), + ('OAC','OASIS','anchorage','2025-01-13 16:19:11.097'), + ('OM_MANTRA','OM_MANTRA','anchorage','2025-01-13 16:19:11.098'), + ('OM_MANTRA_T','OM_MANTRA_TESTNET','anchorage','2025-01-13 16:19:11.099'), + ('OSMO','OSMOSIS','anchorage','2025-01-13 16:19:11.101'), + ('OSMO','OSMOSIS','fireblocks','2025-01-13 16:19:11.101'), + ('PLUME_SEPOLIA','PLUME_SEPOLIA','anchorage','2025-01-13 16:19:11.102'), + ('POLYGON','POLYGON','anchorage','2025-01-13 16:19:11.103'), + ('MATIC_POLYGON','POLYGON','fireblocks','2025-01-13 16:19:11.103'), + ('HASH','PROVENANCE','anchorage','2025-01-13 16:19:11.104'); +INSERT INTO public.provider_network (external_id,network_id,provider,created_at) VALUES + ('RMO','RARIMO','anchorage','2025-01-13 16:19:11.106'), + ('XRP','RIPPLE','anchorage','2025-01-13 16:19:11.107'), + ('XRP','RIPPLE','fireblocks','2025-01-13 16:19:11.107'), + ('XRP_TEST','RIPPLE_TESTNET','fireblocks','2025-01-13 16:19:11.108'), + ('SEI','SEI','anchorage','2025-01-13 16:19:11.110'), + ('SEI','SEI','fireblocks','2025-01-13 16:19:11.110'), + ('SEI_T','SEI_TESTNET','anchorage','2025-01-13 16:19:11.111'), + ('SEI_TEST','SEI_TESTNET','fireblocks','2025-01-13 16:19:11.111'), + ('SOL','SOLANA','fireblocks','2025-01-13 16:19:11.112'), + ('SOL_TD','SOLANA_TESTNET','anchorage','2025-01-13 16:19:11.114'); +INSERT INTO public.provider_network (external_id,network_id,provider,created_at) VALUES + ('SOL_TEST','SOLANA_TESTNET','fireblocks','2025-01-13 16:19:11.114'), + ('STARK_STARKNET','STARKNET','anchorage','2025-01-13 16:19:11.115'), + ('STRK_STARKNET_T','STARKNET_TESTNET','anchorage','2025-01-13 16:19:11.116'), + ('XLM','STELLAR_LUMENS','fireblocks','2025-01-13 16:19:11.117'), + ('XLM_TEST','STELLAR_LUMENS_TESTNET','fireblocks','2025-01-13 16:19:11.119'), + ('STRD','STRIDE','anchorage','2025-01-13 16:19:11.120'), + ('SUI_T','SUI_TESTNET','anchorage','2025-01-13 16:19:11.121'), + ('TRX','TRON','fireblocks','2025-01-13 16:19:11.122'), + ('TRX_TEST','TRON_TESTNET','fireblocks','2025-01-13 16:19:11.123'), + ('VANA','VANA','anchorage','2025-01-13 16:19:11.124'); +INSERT INTO public.provider_network (external_id,network_id,provider,created_at) VALUES + ('VANA_MOKSHA_TESTNET','VANA_MOKSHA_TESTNET','anchorage','2025-01-13 16:19:11.126'), + ('ZKSYNC_SEPOLIA','ZKSYNC_SEPOLIA','anchorage','2025-01-13 16:19:11.127'), + ('DOT','POLKADOT','fireblocks','2025-01-13 16:19:11.128'), + ('EOS','EOS','fireblocks','2025-01-13 16:19:11.129'), + ('EOS_TEST','EOS_TESTNET','fireblocks','2025-01-13 16:19:11.131'), + ('OAS','OASYS','fireblocks','2025-01-13 16:19:11.132'), + ('OAS_TEST','OASYS_TESTNET','fireblocks','2025-01-13 16:19:11.133'), + ('OSMO_TEST','OSMOSIS_TESTNET','fireblocks','2025-01-13 16:19:11.134'), + ('TELOS','TELOS','fireblocks','2025-01-13 16:19:11.136'), + ('TELOS_TEST','TELOS_TESTNET','fireblocks','2025-01-13 16:19:11.137'); +INSERT INTO public.provider_network (external_id,network_id,provider,created_at) VALUES + ('XTZ','TEZOS','fireblocks','2025-01-13 16:19:11.138'), + ('XTZ_TEST','TEZOS_TESTNET','fireblocks','2025-01-13 16:19:11.139'), + ('DASH','DASH','fireblocks','2025-01-13 16:19:11.140'), + ('DASH_TEST','DASH_TESTNET','fireblocks','2025-01-13 16:19:11.141'), + ('ETH-OPT','OPTIMISM','fireblocks','2025-01-13 16:19:11.143'), + ('ETH-OPT_SEPOLIA','OPTIMISM_SEPOLIA','fireblocks','2025-01-13 16:19:11.144'), + ('ETH-OPT_KOV','OPTIMISM_KOVAN','fireblocks','2025-01-13 16:19:11.145'); diff --git a/apps/vault/src/shared/module/persistence/schema/schema.prisma b/apps/vault/src/shared/module/persistence/schema/schema.prisma index ef7c7737e..feb9c4c5e 100644 --- a/apps/vault/src/shared/module/persistence/schema/schema.prisma +++ b/apps/vault/src/shared/module/persistence/schema/schema.prisma @@ -278,3 +278,29 @@ model ProviderTransfer { @@index([createdAt, clientId]) @@map("provider_transfer") } + +model Network { + id String @id + coinType Int? @map("coin_type") + name String + createdAt DateTime @default(now()) @map("created_at") + + externalNetworks ProviderNetwork[] + + @@map("network") +} + +model ProviderNetwork { + externalId String @map("external_id") + networkId String @map("network_id") + provider String + createdAt DateTime @default(now()) @map("created_at") + + network Network? @relation(fields: [networkId], references: [id]) + + // Prevent duplication of external network by provider. + @@unique([provider, externalId]) + // Prevent duplication of provider supported network. + @@unique([provider, networkId]) + @@map("provider_network") +} diff --git a/apps/vault/src/shared/module/persistence/seed.ts b/apps/vault/src/shared/module/persistence/seed.ts index 158a8027e..471008582 100644 --- a/apps/vault/src/shared/module/persistence/seed.ts +++ b/apps/vault/src/shared/module/persistence/seed.ts @@ -1,309 +1,37 @@ -/* eslint-disable */ -import { ConfigService } from '@narval/config-module' import { LoggerService } from '@narval/nestjs-shared' -import { ed25519PrivateKeySchema, ed25519PublicKeySchema } from '@narval/signature' +import { NestFactory } from '@nestjs/core' import { PrismaClient } from '@prisma/client/vault' -import { ConnectionSeedService } from 'apps/vault/src/broker/persistence/connection.seed' -import { Config, load } from 'apps/vault/src/main.config' -import { v4 } from 'uuid' -import { ConnectionStatus } from '../../../broker/core/type/connection.type' -import { Provider } from '../../../broker/core/type/provider.type' -import { ConnectionRepository } from '../../../broker/persistence/repository/connection.repository' -import { PrismaService } from './service/prisma.service' +import { MainModule } from '../../../main.module' +import { SeederService } from './service/seeder.service' const prisma = new PrismaClient() - -const clientId = 'client-1' - -const privateKey = ed25519PrivateKeySchema.parse({ - kty: 'OKP', - crv: 'Ed25519', - alg: 'EDDSA', - kid: '0x64c3fa0c628c59c5795782356161bbe5bde6507f92d17256c174bfd19ed9a9bb', - x: 'wl2BAebjqX4_tvZcZo_VK3ZSxWZ-9-CGKe-3E9rlvB0', - d: 'A3imDr5aM3N1Iy2AMqn46PUsiiM2R4mRyj42yt3OAXM' -}) -const publicKey = ed25519PublicKeySchema.parse(privateKey) - -const privateKey2 = ed25519PrivateKeySchema.parse({ - kty: 'OKP', - crv: 'Ed25519', - alg: 'EDDSA', - kid: '0x5594dd8a27608b37a496787df068bc7843ec55322f54c8cd0d32ac4361caba58', - x: 'qQoqY2hWQ9c2CgnTE7TALK8ogWe2PBl3SrEH_ADihMY', - d: '4VBMwn8ZPV8c9E9Evv6yx_b71HjESKMaElXmbOcfMtU' -}) - -const publicKey2 = ed25519PublicKeySchema.parse(privateKey2) -// Organize all data by connection -const ANCHORAGE_CONNECTIONS = [ - { - connection: { - connectionId: 'connection-1', - clientId, - provider: Provider.ANCHORAGE, - integrity: 'sample-integrity-hash', - url: 'https://api.anchorage-staging.com', - label: 'Anchorage Staging - SubCustomer 1', - credentials: { - apiKey: 'sample-api-key', - privateKey, - publicKey - }, - createdAt: new Date(), - updatedAt: new Date(), - status: ConnectionStatus.ACTIVE - }, - wallets: [ - { - id: 'wallet-1', - clientId, - provider: 'anchorage', - label: 'Wallet for SubCustomer 1', - externalId: 'vault_1', - createdAt: new Date(), - updatedAt: new Date(), - accounts: [ - { - id: 'accountWallet1Btc', - clientId, - provider: 'anchorage', - label: 'Bitcoin Mainnet', - externalId: 'wallet_1', - networkId: '1', - createdAt: new Date(), - updatedAt: new Date(), - addresses: [ - { - id: 'address-acc-wallet-1-btc-1', - clientId, - provider: 'anchorage', - externalId: 'btc_address_1', - address: 'b1742d35Cc6634C0532925a3b844Bc454e4438f44e', - createdAt: new Date(), - updatedAt: new Date() - }, - { - id: 'address-acc-wallet-1-btc-2', - clientId, - provider: 'anchorage', - externalId: 'btc_address_2', - address: 'b1123d35Cc6634C0532925a3b844Bc454e4438f789', - createdAt: new Date(), - updatedAt: new Date() - } - ] - }, - { - id: 'accountWallet1Eth', - clientId, - provider: 'anchorage', - label: 'Trading BTC', - externalId: 'wallet_3', - networkId: '60', - createdAt: new Date(), - updatedAt: new Date(), - addresses: [ - { - id: 'address-account-wallet-1-eth', - clientId, - provider: 'anchorage', - externalId: 'eth_addr', - address: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e', - createdAt: new Date(), - updatedAt: new Date() - } - ] - } - ] - } - ], - knownDestinations: [ - { - id: 'dest1', - clientId, - label: 'Destination 1', - provider: 'anchorage', - assetId: 'BTC', - externalId: 'dest1', - address: 'bt12NGZrVvZG92qGYqzTLjCAewvPZ7JE8S8VxE', - networkId: 'BTC', - externalClassification: 'trusted', - createdAt: new Date(), - updatedAt: new Date() - } - ] - }, - { - connection: { - connectionId: 'connection-2', - clientId, - provider: Provider.ANCHORAGE, - integrity: 'sample-integrity-hash-2', - url: 'https://api.anchorage-staging.com', - label: 'Anchorage Staging - SubCustomer 2', - credentials: { - apiKey: 'sample-api-key-2', - privateKey: privateKey2, - publicKey: publicKey2 - }, - createdAt: new Date(), - updatedAt: new Date(), - status: ConnectionStatus.ACTIVE - }, - wallets: [ - { - id: 'wallet-2', - clientId, - provider: 'anchorage', - label: 'Wallet for SubCustomer 2', - externalId: 'vault_2', - createdAt: new Date(), - updatedAt: new Date(), - accounts: [ - { - id: 'accountWallet2Eth', - clientId, - provider: 'anchorage', - label: 'Ethereum Mainnet', - externalId: 'wallet_2', - networkId: '60', - createdAt: new Date(), - updatedAt: new Date(), - addresses: [ - { - id: 'address-account-wallet-2-eth', - clientId, - provider: 'anchorage', - externalId: 'btc_trading_addr_1', - address: 'bt12NGZrVvZG92qGYqzTLjCAewvPZ7JE8S8VxE', - createdAt: new Date(), - updatedAt: new Date() - } - ] - } - ] - } - ], - knownDestinations: [] - } -] +const logger = new LoggerService() async function main() { - const logger = new LoggerService() - const config = new ConfigService(load()) - const prismaService = new PrismaService(config, logger) - const connRepository = new ConnectionRepository(prismaService) - const connSeed = new ConnectionSeedService(connRepository) - - logger.log('Seeding Vault database with Anchorage provider data') - - await prisma.$transaction(async (txn) => { - // Process each connection group - for (const group of ANCHORAGE_CONNECTIONS) { - // Create connection - const connection = await connSeed.createConnection(group.connection) - - const wallets = group.wallets.map((wallet) => ({ - id: wallet.id, - clientId: wallet.clientId, - provider: wallet.provider, - label: wallet.label, - externalId: wallet.externalId, - createdAt: wallet.createdAt, - updatedAt: wallet.updatedAt - })) - - const providerWalletConnection = wallets.map((wallet) => ({ - clientId: wallet.clientId, - connectionId: connection.connectionId, - walletId: wallet.id - })) - - const accounts = group.wallets.flatMap((wallet) => - wallet.accounts.map((account) => ({ - id: account.id, - clientId: account.clientId, - provider: account.provider, - label: account.label, - externalId: account.externalId, - walletId: wallet.id, - networkId: account.networkId, - createdAt: account.createdAt, - updatedAt: account.updatedAt - })) - ) - - const addresses = group.wallets.flatMap((wallet) => - wallet.accounts.flatMap((acc) => - acc.addresses.map((address) => ({ - id: address.id, - clientId: address.clientId, - provider: address.provider, - externalId: address.externalId, - accountId: acc.id, - address: address.address, - createdAt: address.createdAt, - updatedAt: address.updatedAt - })) - ) - ) - - const knownDestinations = group.knownDestinations.map((dest) => ({ - ...dest - })) - - const knownDestinationConnection = knownDestinations.map((dest) => ({ - clientId: dest.clientId, - connectionId: connection.connectionId, - knownDestinationId: dest.id - })) - - const sync = { - id: v4(), - clientId, - connectionId: group.connection.connectionId, - status: 'success' - } - - await txn.providerWallet.createMany({ - data: wallets - }) - - await txn.providerWalletConnection.createMany({ - data: providerWalletConnection - }) - - await txn.providerAccount.createMany({ - data: accounts - }) - - await txn.providerAddress.createMany({ - data: addresses - }) - - await txn.providerKnownDestination.createMany({ - data: knownDestinations - }) - - await txn.providerSync.create({ - data: sync - }) - - await txn.providerKnownDestinationConnection.createMany({ - data: knownDestinationConnection - }) - } - }) - logger.log('Vault database germinated 🌱') + // Create a standalone application without any network listeners like + // controllers. + // + // See https://docs.nestjs.com/standalone-applications + const application = await NestFactory.createApplicationContext(MainModule) + application.useLogger(application.get(LoggerService)) + const seeder = application.get(SeederService) + + logger.log('🌱 Seeding database') + + try { + await seeder.seed() + } finally { + logger.log('✅ Database seeded') + await application.close() + } } main() .then(async () => { await prisma.$disconnect() }) - .catch(async (e) => { - console.error(e) + .catch(async (error) => { + logger.error('❌ Seed error', error) await prisma.$disconnect() process.exit(1) }) diff --git a/apps/vault/src/shared/module/persistence/service/seed.service.ts b/apps/vault/src/shared/module/persistence/service/seed.service.ts index 194bdce1d..78933d5ec 100644 --- a/apps/vault/src/shared/module/persistence/service/seed.service.ts +++ b/apps/vault/src/shared/module/persistence/service/seed.service.ts @@ -1,7 +1,7 @@ import { NotImplementedException } from '@nestjs/common' export abstract class SeedService { - germinate(): Promise { + seed(): Promise { throw new NotImplementedException() } } diff --git a/apps/vault/src/shared/module/persistence/service/seeder.service.ts b/apps/vault/src/shared/module/persistence/service/seeder.service.ts new file mode 100644 index 000000000..f7551a8c6 --- /dev/null +++ b/apps/vault/src/shared/module/persistence/service/seeder.service.ts @@ -0,0 +1,47 @@ +import { ConfigService } from '@narval/config-module' +import { LoggerService } from '@narval/nestjs-shared' +import { Inject, Injectable } from '@nestjs/common' +import { ModulesContainer } from '@nestjs/core' +import { Config, Env } from '../../../../main.config' +import { SeedService } from './seed.service' + +@Injectable() +export class SeederService { + constructor( + @Inject(ModulesContainer) private modulesContainer: ModulesContainer, + private configService: ConfigService, + private logger: LoggerService + ) {} + + async seed() { + if (this.configService.get('env') === Env.PRODUCTION) { + throw new Error('Cannot seed production database!') + } + + for (const service of this.getSeedServices()) { + const name = service.constructor.name + + this.logger.log(`🌱 Seeding ${name}`) + + let error: unknown | null = null + try { + await service.seed() + } catch (err) { + this.logger.error(`❌ Error while seeding ${name}`, err) + + error = err + } + + if (!error) { + this.logger.log(`✅ ${name} seeded`) + } + } + } + + private getSeedServices(): SeedService[] { + return Array.from(this.modulesContainer.values()) + .flatMap((module) => Array.from(module.providers.values())) + .map((provider) => provider.instance) + .filter((instance): instance is SeedService => instance instanceof SeedService) + } +} From 1691a7481e8cd61232689a5ff713d526d1ac9965 Mon Sep 17 00:00:00 2001 From: Matt Schoch Date: Wed, 15 Jan 2025 12:48:26 +0100 Subject: [PATCH 090/120] Fixing anchorage sync pagination; removing credentials in logging --- .../anchorage/anchorage-sync.service.ts | 6 +++--- .../src/broker/http/client/anchorage.client.ts | 18 ++++++++++++++---- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage-sync.service.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage-sync.service.ts index f2f09c955..10f957412 100644 --- a/apps/vault/src/broker/core/provider/anchorage/anchorage-sync.service.ts +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage-sync.service.ts @@ -130,7 +130,7 @@ export class AnchorageSyncService implements ProviderSyncService { const { connection } = context this.logger.log('Sync Anchorage accounts', { - connectionId: connection.credentials, + connectionId: connection.connectionId, clientId: connection.clientId, url: connection.url }) @@ -235,7 +235,7 @@ export class AnchorageSyncService implements ProviderSyncService { const { connection } = context this.logger.log('Sync Anchorage addresses', { - connectionId: connection.credentials, + connectionId: connection.connectionId, clientId: connection.clientId, url: connection.url }) @@ -334,7 +334,7 @@ export class AnchorageSyncService implements ProviderSyncService { const { connection } = context this.logger.log('Sync Anchorage known destinations', { - connectionId: connection.credentials, + connectionId: connection.connectionId, clientId: connection.clientId, url: connection.url }) diff --git a/apps/vault/src/broker/http/client/anchorage.client.ts b/apps/vault/src/broker/http/client/anchorage.client.ts index c0984512d..b1313f1f7 100644 --- a/apps/vault/src/broker/http/client/anchorage.client.ts +++ b/apps/vault/src/broker/http/client/anchorage.client.ts @@ -380,7 +380,11 @@ export class AnchorageClient { return this.sendSignedRequest({ schema: GetVaultsResponse, request: { - url: response.page.next + url: `${url}${response.page.next}`, + method: 'GET', + params: { + limit: opts.limit + } }, apiKey, signKey @@ -431,7 +435,8 @@ export class AnchorageClient { return this.sendSignedRequest({ schema: GetWalletsResponse, request: { - url: response.page.next + url: `${url}${response.page.next}`, + method: 'GET' }, apiKey, signKey @@ -484,7 +489,8 @@ export class AnchorageClient { return this.sendSignedRequest({ schema: GetTrustedDestinationsResponse, request: { - url: response.page.next + url: `${url}${response.page.next}`, + method: 'GET' }, apiKey, signKey @@ -542,7 +548,11 @@ export class AnchorageClient { return this.sendSignedRequest({ schema: GetVaultAddressesResponse, request: { - url: response.page.next + url: `${url}${response.page.next}`, + method: 'GET', + params: { + assetType + } }, apiKey, signKey From e14cb7f54025c7de0312cf2b83e771bfeb587ccd Mon Sep 17 00:00:00 2001 From: Matt Schoch Date: Wed, 15 Jan 2025 14:39:07 +0100 Subject: [PATCH 091/120] Updating transfer example; working to a destination address (#82) * Updating transfer example; working to a destination address * Adding additional functions --- examples/unified-api/5-create-transfer.ts | 28 ++++++++++++++++---- examples/unified-api/6-sync.ts | 11 ++++++++ examples/unified-api/7-known-destinations.ts | 13 +++++++++ 3 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 examples/unified-api/6-sync.ts create mode 100644 examples/unified-api/7-known-destinations.ts diff --git a/examples/unified-api/5-create-transfer.ts b/examples/unified-api/5-create-transfer.ts index ad277b865..716a0a79a 100644 --- a/examples/unified-api/5-create-transfer.ts +++ b/examples/unified-api/5-create-transfer.ts @@ -1,8 +1,10 @@ import { v4 } from 'uuid' import { vaultClient } from './vault.client' -const fromId = '11904d17-f621-4cbe-bdcb-d587e7bc8045' -const toId = '3b102898-5468-445b-99ac-f672033d6f37' +// const fromId = '11904d17-f621-4cbe-bdcb-d587e7bc8045' +const fromId = '32dc1495-3566-4975-ac20-061ecc73b925' // Vault 1 +// const toId = '3b102898-5468-445b-99ac-f672033d6f37' +const toId = 'f8af8ad6-0ce3-41d3-a614-9d5d1edef4d5' const assetType = 'BTC_S' const amount = '0.00001' const connectionId = process.env.CONNECTION_ID @@ -23,13 +25,29 @@ const main = async () => { id: fromId }, destination: { - type: 'account', - id: toId + address: 'tb1q7r7rz03p45lln2c3lz2q9ztyrgwzf6gx85n4r3' // Matt's BTC Signet address, which is a Trusted Destination }, asset: { assetId: assetType }, - amount + amount, + providerSpecific: { + transferAmlQuestionnaire: { + destinationType: 'SELFHOSTED_WALLET', + recipientType: 'PERSON', + purpose: 'INVESTMENT', + originatorType: 'MY_ORGANIZATION', + selfhostedDescription: 'a wallet description', + recipientFirstName: 'John', + recipientLastName: 'Recipient', + recipientFullName: 'John Recipient Full Name', + recipientCountry: 'US', + recipientStreetAddress: 'Some Recipient Street', + recipientCity: 'New York', + recipientStateProvince: 'NY', + recipientPostalCode: '10101' + } + } } }) diff --git a/examples/unified-api/6-sync.ts b/examples/unified-api/6-sync.ts new file mode 100644 index 000000000..a8a4b6e1b --- /dev/null +++ b/examples/unified-api/6-sync.ts @@ -0,0 +1,11 @@ +import { vaultClient } from './vault.client' + +const main = async () => { + const wallets = await vaultClient.startSync({ data: { connectionId: process.env.CONNECTION_ID || 'xxx' } }) + + console.log(wallets) +} + +main() + .then(() => console.log('done')) + .catch(console.error) diff --git a/examples/unified-api/7-known-destinations.ts b/examples/unified-api/7-known-destinations.ts new file mode 100644 index 000000000..72d38b26d --- /dev/null +++ b/examples/unified-api/7-known-destinations.ts @@ -0,0 +1,13 @@ +import { vaultClient } from './vault.client' + +const main = async () => { + const addresses = await vaultClient.listProviderKnownDestinations({ + connectionId: process.env.CONNECTION_ID || 'xxx' + }) + + console.log(addresses) +} + +main() + .then(() => console.log('done')) + .catch(console.error) From 63551ff5c9a228adb9d4b9aec8fe8f195f540086 Mon Sep 17 00:00:00 2001 From: Matt Schoch Date: Wed, 15 Jan 2025 18:03:35 +0100 Subject: [PATCH 092/120] Adding more space for clock skew in jws signatures --- packages/signature/src/lib/verify.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/signature/src/lib/verify.ts b/packages/signature/src/lib/verify.ts index 2093bb808..22b2c42e5 100644 --- a/packages/signature/src/lib/verify.ts +++ b/packages/signature/src/lib/verify.ts @@ -345,13 +345,15 @@ export function verifyJwsdHeader( if (jwsdHeader.created && now - jwsdHeader.created > opts.maxTokenAge) { throw new JwtError({ message: 'JWS is too old, created field is too far in the past', - context: { header, opts } + context: { header, opts, now } }) } - if (jwsdHeader.created && now - jwsdHeader.created < -3) { + // Allow for some clock skew (e.g., 15 seconds) + const ALLOWED_CLOCK_SKEW = 15 + if (jwsdHeader.created && now - jwsdHeader.created < -ALLOWED_CLOCK_SKEW) { throw new JwtError({ message: 'JWS is too old, created field is too far in the future, did you use milliseconds instead of seconds?', - context: { header, opts } + context: { header, opts, now } }) } From a1f0c2ecbe062a2ff8cdfa008dc057466b2d072b Mon Sep 17 00:00:00 2001 From: Matt Schoch Date: Thu, 16 Jan 2025 16:46:30 +0100 Subject: [PATCH 093/120] Updates to the /examples/unified-api scripts --- examples/unified-api/.env.default | 12 - examples/unified-api/.gitignore | 3 + .../{1-activate.ts => 1-connect.ts} | 24 +- examples/unified-api/2-read-wallets.ts | 20 +- examples/unified-api/3-read-accounts.ts | 23 +- examples/unified-api/4-create-transfer.ts | 77 ++++++ examples/unified-api/4-read-addresses.ts | 11 - examples/unified-api/5-create-transfer.ts | 59 ----- examples/unified-api/5-sync.ts | 26 ++ examples/unified-api/6-known-destinations.ts | 18 ++ examples/unified-api/6-sync.ts | 11 - examples/unified-api/7-known-destinations.ts | 13 - examples/unified-api/README-quickstart.md | 233 ++++++++++++++++++ examples/unified-api/README.md | 140 ++++++++--- examples/unified-api/config.default.json | 15 ++ examples/unified-api/generate-key.ts | 18 ++ examples/unified-api/package-lock.json | 19 +- examples/unified-api/package.json | 3 +- examples/unified-api/vault.client.ts | 90 ++++++- 19 files changed, 631 insertions(+), 184 deletions(-) delete mode 100644 examples/unified-api/.env.default create mode 100644 examples/unified-api/.gitignore rename examples/unified-api/{1-activate.ts => 1-connect.ts} (50%) create mode 100644 examples/unified-api/4-create-transfer.ts delete mode 100644 examples/unified-api/4-read-addresses.ts delete mode 100644 examples/unified-api/5-create-transfer.ts create mode 100644 examples/unified-api/5-sync.ts create mode 100644 examples/unified-api/6-known-destinations.ts delete mode 100644 examples/unified-api/6-sync.ts delete mode 100644 examples/unified-api/7-known-destinations.ts create mode 100644 examples/unified-api/README-quickstart.md create mode 100644 examples/unified-api/config.default.json create mode 100644 examples/unified-api/generate-key.ts diff --git a/examples/unified-api/.env.default b/examples/unified-api/.env.default deleted file mode 100644 index 35ea01dd5..000000000 --- a/examples/unified-api/.env.default +++ /dev/null @@ -1,12 +0,0 @@ -# SETUP -# You should replace the values of the variables below with the ones you received or provided during setup -# During onboarding -CLIENT_ID='' -MASTER_PRIVATE_KEY='' -BASE_URL='https://vault.armory.playnarval.com' - -# ANCHORAGE CONNECTION VARIABLES -CONNECTION_ID='' -CONNECTION_PRIVATE_KEY='' -CONNECTION_API_KEY='' -CONNECTION_URL='https://api.anchorage-staging.com' diff --git a/examples/unified-api/.gitignore b/examples/unified-api/.gitignore new file mode 100644 index 000000000..3df2574c7 --- /dev/null +++ b/examples/unified-api/.gitignore @@ -0,0 +1,3 @@ +.env +node_modules +config.json \ No newline at end of file diff --git a/examples/unified-api/1-activate.ts b/examples/unified-api/1-connect.ts similarity index 50% rename from examples/unified-api/1-activate.ts rename to examples/unified-api/1-connect.ts index a66aef329..2d028fb9f 100644 --- a/examples/unified-api/1-activate.ts +++ b/examples/unified-api/1-connect.ts @@ -1,22 +1,13 @@ import { rsaPublicKeySchema } from '@narval-xyz/armory-sdk' import { rsaEncrypt } from '@narval-xyz/armory-sdk/signature' import dotenv from 'dotenv' -import { vaultClient } from './vault.client' +import { config, setConfig, vaultClient } from './vault.client' dotenv.config() const main = async () => { - const apiKey = process.env.CONNECTION_API_KEY - const privateKey = process.env.CONNECTION_PRIVATE_KEY - const connectionId = process.env.CONNECTION_ID - const url = process.env.CONNECTION_URL - - if (!apiKey || !privateKey || !connectionId || !url) { - console.error( - 'Please provide CONNECTION_API_KEY, CONNECTION_PRIVATE_KEY, CONNECTION_ID, and CONNECTION_URL in your .env file' - ) - process.exit(1) - } - + const apiKey = config.connectionApiKey + const privateKey = config.connectionPrivateKey + const url = config.connectionUrl const credentials = { apiKey, privateKey @@ -28,10 +19,13 @@ const main = async () => { const encryptedCredentials = await rsaEncrypt(JSON.stringify(credentials), encryptionKey) const connection = await vaultClient.createConnection({ - data: { connectionId, url, encryptedCredentials, provider: 'anchorage' } + data: { url, encryptedCredentials, provider: 'anchorage' } }) - console.dir(connection) + // Save the connectionId to the config file + setConfig('connectionId', connection.data.connectionId) + + console.dir(connection.data) } main() diff --git a/examples/unified-api/2-read-wallets.ts b/examples/unified-api/2-read-wallets.ts index 8b36da920..00fa42b3b 100644 --- a/examples/unified-api/2-read-wallets.ts +++ b/examples/unified-api/2-read-wallets.ts @@ -1,9 +1,23 @@ -import { vaultClient } from './vault.client' +import { config, vaultClient } from './vault.client' const main = async () => { - const wallets = await vaultClient.listProviderWallets() + if (!config.connectionId) { + console.error('No connectionId found in config.json. Please connect first.') + process.exit(1) + } - console.log(wallets) + const { data, page } = await vaultClient.listProviderWallets({ + connectionId: config.connectionId + }) + + console.dir( + data.map((wallet) => ({ + label: wallet.label, + walletId: wallet.walletId, + provider: wallet.provider, + externalId: wallet.externalId + })) + ) } main() diff --git a/examples/unified-api/3-read-accounts.ts b/examples/unified-api/3-read-accounts.ts index 8a4761e7b..da4bb4c24 100644 --- a/examples/unified-api/3-read-accounts.ts +++ b/examples/unified-api/3-read-accounts.ts @@ -1,9 +1,26 @@ -import { vaultClient } from './vault.client' +import { config, vaultClient } from './vault.client' const main = async () => { - const accounts = await vaultClient.listProviderAccounts({}) + if (!config.connectionId) { + console.error('No connectionId found in config.json. Please connect first.') + process.exit(1) + } - console.log(accounts) + const { data, page } = await vaultClient.listProviderAccounts({ + connectionId: config.connectionId + }) + + console.dir( + data.map((account) => ({ + label: account.label, + accountId: account.accountId, + provider: account.provider, + externalId: account.externalId, + networkId: account.networkId, + walletId: account.walletId, + addresses: account?.addresses?.map((address) => address.address) + })) + ) } main() diff --git a/examples/unified-api/4-create-transfer.ts b/examples/unified-api/4-create-transfer.ts new file mode 100644 index 000000000..ee65305a5 --- /dev/null +++ b/examples/unified-api/4-create-transfer.ts @@ -0,0 +1,77 @@ +import { v4 as uuid } from 'uuid' +import { config, vaultClient } from './vault.client' + +const main = async () => { + const destination = + config.destinationType && config.destinationId + ? { + type: config.destinationType, + id: config.destinationId + } + : config.destinationAddress + ? { address: config.destinationAddress } + : null + + if (!config.connectionId || !config.sourceId || !destination || !config.assetId || !config.amount) { + console.error('Please provide transfer parameters in config.json') + process.exit(1) + } + + const initiatedTransfer = await vaultClient.sendTransfer({ + connectionId: config.connectionId, + data: { + idempotenceId: uuid(), + source: { + type: 'account', + id: config.sourceId + }, + destination, + asset: { + assetId: config.assetId + }, + amount: config.amount, + providerSpecific: config.destinationAddress + ? { + transferAmlQuestionnaire: { + destinationType: 'SELFHOSTED_WALLET', + recipientType: 'PERSON', + purpose: 'INVESTMENT', + originatorType: 'MY_ORGANIZATION', + selfhostedDescription: 'a wallet description', + recipientFirstName: 'John', + recipientLastName: 'Recipient', + recipientFullName: 'John Recipient Full Name', + recipientCountry: 'US', + recipientStreetAddress: 'Some Recipient Street', + recipientCity: 'New York', + recipientStateProvince: 'NY', + recipientPostalCode: '10101' + } + } + : null + } + }) + + console.dir(initiatedTransfer) + + // Poll transfer status until it's no longer processing + let transfer + do { + transfer = await vaultClient.getTransfer({ + connectionId: config.connectionId, + transferId: initiatedTransfer.data.transferId + }) + + console.log(`Transfer status: ${transfer.data.status}`) + + if (transfer.data.status === 'processing') { + await new Promise((resolve) => setTimeout(resolve, 2000)) // Wait 2 seconds between polls + } + } while (transfer.data.status === 'processing') + + console.dir(transfer) +} + +main() + .then(() => console.log('done')) + .catch(console.error) diff --git a/examples/unified-api/4-read-addresses.ts b/examples/unified-api/4-read-addresses.ts deleted file mode 100644 index aaa4b52a8..000000000 --- a/examples/unified-api/4-read-addresses.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { vaultClient } from './vault.client' - -const main = async () => { - const addresses = await vaultClient.listProviderAddresses({}) - - console.log(addresses) -} - -main() - .then(() => console.log('done')) - .catch(console.error) diff --git a/examples/unified-api/5-create-transfer.ts b/examples/unified-api/5-create-transfer.ts deleted file mode 100644 index 716a0a79a..000000000 --- a/examples/unified-api/5-create-transfer.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { v4 } from 'uuid' -import { vaultClient } from './vault.client' - -// const fromId = '11904d17-f621-4cbe-bdcb-d587e7bc8045' -const fromId = '32dc1495-3566-4975-ac20-061ecc73b925' // Vault 1 -// const toId = '3b102898-5468-445b-99ac-f672033d6f37' -const toId = 'f8af8ad6-0ce3-41d3-a614-9d5d1edef4d5' -const assetType = 'BTC_S' -const amount = '0.00001' -const connectionId = process.env.CONNECTION_ID -const url = process.env.CONNECTION_URL - -if (!connectionId) { - console.error('Please provide CONNECTION_ID in your .env file') - process.exit(1) -} - -const main = async () => { - const transfer = await vaultClient.sendTransfer({ - connectionId, - data: { - idempotenceId: v4(), - source: { - type: 'account', - id: fromId - }, - destination: { - address: 'tb1q7r7rz03p45lln2c3lz2q9ztyrgwzf6gx85n4r3' // Matt's BTC Signet address, which is a Trusted Destination - }, - asset: { - assetId: assetType - }, - amount, - providerSpecific: { - transferAmlQuestionnaire: { - destinationType: 'SELFHOSTED_WALLET', - recipientType: 'PERSON', - purpose: 'INVESTMENT', - originatorType: 'MY_ORGANIZATION', - selfhostedDescription: 'a wallet description', - recipientFirstName: 'John', - recipientLastName: 'Recipient', - recipientFullName: 'John Recipient Full Name', - recipientCountry: 'US', - recipientStreetAddress: 'Some Recipient Street', - recipientCity: 'New York', - recipientStateProvince: 'NY', - recipientPostalCode: '10101' - } - } - } - }) - - console.dir(transfer) -} - -main() - .then(() => console.log('done')) - .catch(console.error) diff --git a/examples/unified-api/5-sync.ts b/examples/unified-api/5-sync.ts new file mode 100644 index 000000000..efc9bc2b7 --- /dev/null +++ b/examples/unified-api/5-sync.ts @@ -0,0 +1,26 @@ +import { config, vaultClient } from './vault.client' + +const main = async () => { + if (!config.connectionId) { + console.error('No connectionId found in config.json. Please connect first.') + process.exit(1) + } + + const { data } = await vaultClient.startSync({ data: { connectionId: config.connectionId } }) + console.log('Sync Started') + let sync + do { + sync = await vaultClient.getSync({ syncId: data.syncs[0].syncId }) + console.log(`Sync Status: ${sync.data.status}`) + if (sync.data.status === 'processing') { + // Wait for 1 second before next poll + await new Promise((resolve) => setTimeout(resolve, 1000)) + } + } while (sync.data.status === 'processing') + + console.log(sync) +} + +main() + .then(() => console.log('done')) + .catch(console.error) diff --git a/examples/unified-api/6-known-destinations.ts b/examples/unified-api/6-known-destinations.ts new file mode 100644 index 000000000..5cb246231 --- /dev/null +++ b/examples/unified-api/6-known-destinations.ts @@ -0,0 +1,18 @@ +import { config, vaultClient } from './vault.client' + +const main = async () => { + if (!config.connectionId) { + console.error('No connectionId found in config.json. Please connect first.') + process.exit(1) + } + + const addresses = await vaultClient.listProviderKnownDestinations({ + connectionId: config.connectionId + }) + + console.log(addresses) +} + +main() + .then(() => console.log('done')) + .catch(console.error) diff --git a/examples/unified-api/6-sync.ts b/examples/unified-api/6-sync.ts deleted file mode 100644 index a8a4b6e1b..000000000 --- a/examples/unified-api/6-sync.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { vaultClient } from './vault.client' - -const main = async () => { - const wallets = await vaultClient.startSync({ data: { connectionId: process.env.CONNECTION_ID || 'xxx' } }) - - console.log(wallets) -} - -main() - .then(() => console.log('done')) - .catch(console.error) diff --git a/examples/unified-api/7-known-destinations.ts b/examples/unified-api/7-known-destinations.ts deleted file mode 100644 index 72d38b26d..000000000 --- a/examples/unified-api/7-known-destinations.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { vaultClient } from './vault.client' - -const main = async () => { - const addresses = await vaultClient.listProviderKnownDestinations({ - connectionId: process.env.CONNECTION_ID || 'xxx' - }) - - console.log(addresses) -} - -main() - .then(() => console.log('done')) - .catch(console.error) diff --git a/examples/unified-api/README-quickstart.md b/examples/unified-api/README-quickstart.md new file mode 100644 index 000000000..25652718f --- /dev/null +++ b/examples/unified-api/README-quickstart.md @@ -0,0 +1,233 @@ +# Narval Quickstart - Unified API + +## Prerequisites + +- Node.js 18+ +- tsx (`npm i -g tsx`) +- Narval SDK (`npm i @narval-xyz/armory-sdk`) + +Note: This has only been tested on Mac + +### Narval Setup + +All API requests are signed by a private key. Begin by generating a credential. + +```shell + tsx generate-key.ts + + ## Outputs + # { + # "publicHexKey": "0x432...", // Provide this to Narval + # "privateHex": "0xa288..." // Store this securely + # } +``` + +Provide the PUBLIC key when activating your Narval account. + +> Use the provided invite link to activate your Narval account, then return here with your Client ID. + +Set up the following environment variables: + +### Example Script Config + +```properties +# Set these in .env +CLIENT_ID=your_narval_client_id +NARVAL_AUTH_PRIVATE_KEY=Private key you generated above +BASE_URL=https://vault.armory.playnarval.com +``` + +## 0. Initialize SDK + +SDK should be installed already, or install with `npm i @narval-xyz/armory-sdk` + +```typescript +// Initialize an SDK Client with your clientId and your private key credential +import { Hex, privateKeyToJwk, VaultClient } from '@narval-xyz/armory-sdk' +import { buildSignerEdDSA } from '@narval-xyz/armory-sdk/signature' + +const vaultClient = new VaultClient({ + clientId: CLIENT_ID, + signer: { + sign: buildSignerEdDSA(NARVAL_AUTH_PRIVATE_KEY_HEX), + jwk: privateKeyToJwk(NARVAL_AUTH_PRIVATE_KEY_HEX as Hex, 'EDDSA'), + alg: 'EDDSA' + }, + host: BASE_URL +}) +``` + +## 1. Create a new Connection + +A Connection is a set of authenticate credentials to a custody provider. + +There are two flows possible: + +1. Generate the API Signing Key Pair in the Vault so the private key never leaves the TEE. +2. Generate the API Signing Key Pair outside the TEE and provide it to the Vault. + +Method 1 is recommended for production environments. + +Method 2 is easier for development so you can re-use the same provider API keys. + +### Method 1 - Generate the API Signing Key Pair in the Vault + +First, initiate a connection. This returns the API Signing Public Key, and an encryption key for the next step. + +```typescript +const { + data: { connectionId, publicKey, encryptionPublicKey } +} = await vaultClient.initiateConnection({ data: { provider: 'anchorage' } }) +``` + +Go to Anchorage and create a new API key, using the publicKey hex value. (note: remove the 0x prefix when pasting into Anchorage). + +After creating the API Key in Anchorage, return here to activate the connection by providing the Anchorage API Key. + +```typescript +import { rsaPublicKeySchema } from '@narval-xyz/armory-sdk' +import { rsaEncrypt } from '@narval-xyz/armory-sdk/signature' + +// Encrypt the Anchorage API Key with the encryption key +const encryptionKey = rsaPublicKeySchema.parse(encryptionPublicKey.jwk) +const encryptedCredentials = await rsaEncrypt( + JSON.stringify({ + apiKey: 'your_api_key' + }), + encryptionKey +) + +// Activate the connection in the Vault +const connection = await vaultClient.createConnection({ + data: { + connectionId, + url: 'https://api.anchorage-staging.com', + encryptedCredentials, + provider: 'anchorage', + label: 'My Anchorage Connection' + } +}) +``` + +### Method 2 - Generate the API Signing Key Pair outside the Vault + +Generate your EDDSA key pair and create an API key in Anchorage. +If you need to generate a new key pair, you can use the util method mentioned above: `tsx generate-key.ts` + +```typescript +import { rsaPublicKeySchema } from '@narval-xyz/armory-sdk' +import { rsaEncrypt } from '@narval-xyz/armory-sdk/signature' + +// Generate the transit encryption key +const jwk = await vaultClient.generateEncryptionKey() +const encryptionKey = rsaPublicKeySchema.parse(jwk) + +// Encrypt the Anchorage API Key with the encryption key +const encryptedCredentials = await rsaEncrypt( + JSON.stringify({ + apiKey: 'your_api_key', + privateKey: 'your_private_key' // hex string of the eddsa private key registered with Anchorage + }), + encryptionKey +) + +const connection = await vaultClient.createConnection({ + data: { + url: 'https://api.anchorage-staging.com', + encryptedCredentials, + provider: 'anchorage', + label: 'My Anchorage Connection' + } +}) +``` + +## 2. Read Methods + +Narval normalizes the provider data model into a standard structure of Wallets > Accounts > Addresses, where a Wallet has 1 or more Accounts, and an Account has 1 or more Addresses. Accounts are network-specific, while Wallets can have multiple accounts of the same or different networks. + +### List available Wallets + +```typescript +const { data, page } = await vaultClient.listProviderWallets({ + connectionId +}) +``` + +### List available Accounts + +```typescript +const { data, page } = await vaultClient.listProviderAccounts({ + connectionId +}) +``` + +## 3. Write Methods + +### Create a Transfer + +```typescript +const initiatedTransfer = await vaultClient.sendTransfer({ + connectionId, + data: { + idempotenceId: new Date().toISOString(), // use a real unique id in production + source: { + type: 'account', + id: sourceId // The AccountId to send from, from the listProviderAccounts call + }, + destination: { + type: 'account', + id: destinationId // The AccountId to send to, from the listProviderAccounts call + }, // can also pass in `address` instead of `type`+`id` to send to an external address + asset: { + externalAssetId: assetType // The asset type to send. `externalAssetId` expects the providers asset type, while `assetId` will use Narval's mapping of the asset types. + }, + amount: '0.00001', + // Optional provider specific fields. Anchorage external transfers require transferAmlQuestionnaire. + providerSpecific: null + } +}) +``` + +The transfer could take a bit, particularly if it requires quorum approval. + +```typescript +// Poll transfer status until it's no longer processing +let transfer +do { + transfer = await vaultClient.getTransfer({ + connectionId, + transferId: initiatedTransfer.data.transferId + }) + + console.log(`Transfer status: ${transfer.data.status}`) + + if (transfer.data.status === 'processing') { + await new Promise((resolve) => setTimeout(resolve, 2000)) // Wait 2 seconds between polls + } +} while (transfer.data.status === 'processing') +``` + +### Re-sync data + +Narval syncs the account data from the Provider when the connection is established. If Accounts are created after the connection, you may need to re-sync. + +```typescript +// Start the sync +const { data } = await vaultClient.startSync({ data: { connectionId } }) + +// Poll the sync until it's complete. Could take a bit if lots of data. +let sync +do { + sync = await vaultClient.getSync({ syncId: data.syncs[0].syncId }) + if (sync.data.status === 'processing') { + // Wait for 1 second before next poll + await new Promise((resolve) => setTimeout(resolve, 1000)) + } +} while (sync.data.status === 'processing') +``` + +## API Reference + +Underlying API is documented here: +All endpoints are available through the Typescript SDK. +https://narval.apidocumentation.com/ diff --git a/examples/unified-api/README.md b/examples/unified-api/README.md index ebbc4d453..5adf94b8e 100644 --- a/examples/unified-api/README.md +++ b/examples/unified-api/README.md @@ -1,67 +1,125 @@ +# Narval Unified API Example Scripts + ## Prerequisites -### Anchorage API Setup +- Node.js 18+ +- tsx (`npm i -g tsx`) + +Note: This has only been tested on Mac + +## Narval Setup + +### Project Setup + +Set up the example project + +- `cp config.default.json config.json` +- `npm install` -You need to have an API connection registered with Anchorage, which requires: -A generated Private Key (you provide them the hex public key) -An API secret key (provided by Anchorage in exchange for your hex public key) +### Narval Credential Setup -To generate EDDSA keys in hexadecimal format for Anchorage registration, run: -npx tsx generate-key.ts -This will output: +All API requests are signed by a private key. Begin by generating a credential. + +```shell + tsx generate-key.ts + + ## Outputs + # { + # "publicHexKey": "0x432...", // Provide this to Narval + # "privateHex": "0xa288..." // Store this securely + # } +``` + +Provide the PUBLIC key when activating your Narval account. + +> Use the provided invite link to activate your Narval account, then return here with your Client ID. + +Set up the following into your `config.json` file: + +```json +// config.json { -"publicHexKey": "0x432...", // Provide this to Anchorage -"privateHex": "0xa288..." // Store this securely + "clientId": "YOUR NARVAL CLIENT ID", + "narvalAuthPrivateKey": "YOUR NARVAL AUTH PRIVATE KEY, HEX ENCODED (0x...)" + // ... } +``` -### Narval Client Console Onboarding +### Anchorage API Setup -Complete the following steps in the Narval Client Console: -Generate a master key -Securely store the private hex component -Register the public component in the Narval cloud console +To use the scripts, you'll need an API key already registered with Anchorage. -Note: You can use the same key generation process as described above for Anchorage credentials. +This requires: -Installation -Run from the project directory: -`npm i` +1. An EDDSA Key Pair (you provide them the hex public key) +2. An API secret key (provided by Anchorage in exchange for your hex public key) -## Configuration +Generate your EDDSA key pair and create an API key in Anchorage. +If you need to generate a new key pair, you can use the util method mentioned above: `tsx generate-key.ts` -Set up the following environment variables: +Note: Remove the `0x` prefix when pasting into Anchorage. -### Narval Config +```shell +tsx generate-key.ts +``` -CLIENT_ID=your_narval_client_id -MASTER_PRIVATE_KEY=private_key_from_onboarding -BASE_URL=url_to_environment +> Go create your Anchorage API Key if you don't have one already. When finished, return here to set your config.json -### Connection Configuration +```json +// config.json +{ + // ... + "connectionPrivateKey": "YOUR ANCHORAGE API SIGNING PRIVATE KEY, HEX ENCODED (0x...)", + "connectionApiKey": "YOUR ANCHORAGE API KEY" + // ... +} +``` -CONNECTION_ID=arbitrary_string -CONNECTION_PRIVATE_KEY=hex_private_key_registered_with_anchorage -CONNECTION_API_KEY=api_key_from_anchorage -CONNECTION_URL=provider_url # defaults to Anchorage +## Script Usage Guide -## Usage Guide +Basic scripts are available for the following operations: -Execute the following commands in sequence: +1. Create Connection -1. Activate Connection - Activates the connection in our provider unified API: - `tsx 1-activate.ts` + Creates the connection in our provider unified API: + + ```shell + tsx 1-connect.ts + ``` 2. List Available Wallets + Retrieves all readable wallets for this connection: - `tsx 2-read-wallets.ts` + + ```shell + tsx 2-read-wallets.ts + ``` 3. List Available Accounts - `tsx 3-read-accounts.ts` -4. List Available Addresses - `tsx 4-read-addresses.ts` + Retrieves all readable accounts for this connection: + + ```shell + tsx 3-read-accounts.ts + ``` + +4. Create Transfer + + Creates a transfer between two accounts. + Using `tsx 3-read-accounts.ts`, you can get the account IDs for the source and destination. Set the `sourceId`, `destinationId`, `destinationType`, `assetId`, and `amount` in the `config.json` file. `destinationAddress` can be used for external transfers. + + ```shell + tsx 4-create-transfer.ts + ``` + +5. Re-sync Connection + + Re-syncs the connection with the provider. This is useful if new Accounts have been created since the connection was established. + + ```shell + tsx 5-sync.ts + ``` + +## More Info -5. Create Transfer - Create a transfer between two accounts. You will need to modify the script with relevant data from previous responses - `tsx 5-create-transfer.ts` +Go to the [README-quickstart.md](README-quickstart.md) for a more detailed guide on how to work with the SDK diff --git a/examples/unified-api/config.default.json b/examples/unified-api/config.default.json new file mode 100644 index 000000000..87384f5d7 --- /dev/null +++ b/examples/unified-api/config.default.json @@ -0,0 +1,15 @@ +{ + "clientId": "YOUR NARVAL CLIENT ID", + "narvalAuthPrivateKey": "YOUR NARVAL AUTH PRIVATE KEY, HEX ENCODED (0x...)", + "baseUrl": "https://vault.armory.playnarval.com", + "connectionPrivateKey": "YOUR ANCHORAGE API SIGNING PRIVATE KEY, HEX ENCODED (0x...)", + "connectionApiKey": "YOUR ANCHORAGE API KEY", + "connectionUrl": "https://api.anchorage-staging.com", + "connectionId": null, + "sourceId": null, + "destinationId": null, + "destinationType": null, + "destinationAddress": null, + "amount": null, + "assetId": null +} diff --git a/examples/unified-api/generate-key.ts b/examples/unified-api/generate-key.ts new file mode 100644 index 000000000..aab055d8d --- /dev/null +++ b/examples/unified-api/generate-key.ts @@ -0,0 +1,18 @@ +import { Alg, generateJwk } from '@narval-xyz/armory-sdk' +import { privateKeyToHex, publicKeyToHex } from '@narval-xyz/armory-sdk/signature' + +const main = async () => { + const key = await generateJwk(Alg.EDDSA) + const privateKeyHex = await privateKeyToHex(key) + const publicKeyHex = await publicKeyToHex(key) + + console.log({ + key, + privateKeyHex, + publicKeyHex + }) +} + +main() + .then(() => console.log('done')) + .catch(console.error) diff --git a/examples/unified-api/package-lock.json b/examples/unified-api/package-lock.json index 763011c04..a015a478d 100644 --- a/examples/unified-api/package-lock.json +++ b/examples/unified-api/package-lock.json @@ -11,7 +11,8 @@ "dependencies": { "@narval-xyz/armory-sdk": "0.17.0", "dotenv": "16.4.5", - "tsx": "4.19.2" + "tsx": "4.19.2", + "zod": "^3.24.1" } }, "node_modules/@adraffy/ens-normalize": { @@ -397,6 +398,15 @@ "zod": "3.23.8" } }, + "node_modules/@narval-xyz/armory-sdk/node_modules/zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, "node_modules/@noble/curves": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.6.0.tgz", @@ -846,9 +856,10 @@ } }, "node_modules/zod": { - "version": "3.23.8", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", - "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "version": "3.24.1", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz", + "integrity": "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/examples/unified-api/package.json b/examples/unified-api/package.json index 33a90467c..516c33453 100644 --- a/examples/unified-api/package.json +++ b/examples/unified-api/package.json @@ -11,6 +11,7 @@ "dependencies": { "@narval-xyz/armory-sdk": "0.17.0", "dotenv": "16.4.5", - "tsx": "4.19.2" + "tsx": "4.19.2", + "zod": "3.24.1" } } diff --git a/examples/unified-api/vault.client.ts b/examples/unified-api/vault.client.ts index 8a3e41ae9..1c1f4d4ed 100644 --- a/examples/unified-api/vault.client.ts +++ b/examples/unified-api/vault.client.ts @@ -1,25 +1,93 @@ import { Hex, privateKeyToJwk, VaultClient } from '@narval-xyz/armory-sdk' import { buildSignerEdDSA } from '@narval-xyz/armory-sdk/signature' import dotenv from 'dotenv' +import fs from 'fs' +import path from 'path' +import { z } from 'zod' dotenv.config() -const CLIENT_ID = process.env.CLIENT_ID -const MASTER_PRIVATE_KEY_HEX = process.env.MASTER_PRIVATE_KEY -const BASE_URL = process.env.BASE_URL -const CONNECTION_ID = process.env.CONNECTION_ID +const configSchema = z.object({ + // Narval variables + clientId: z.string(), + narvalAuthPrivateKey: z.string(), + baseUrl: z.string(), -if (!CLIENT_ID || !MASTER_PRIVATE_KEY_HEX || !BASE_URL || !CONNECTION_ID) { - throw new Error('Missing CLIENT_ID or MASTER_PRIVATE_KEY') + // Connection variables + connectionPrivateKey: z.string(), + connectionApiKey: z.string(), + connectionUrl: z.string(), + connectionId: z.string().nullable(), + + // Transfer variables + sourceId: z.string().nullable(), + destinationId: z.string().nullable(), + destinationType: z.union([z.literal('account'), z.literal('address')]).nullable(), + destinationAddress: z.string().nullable(), + amount: z.string().nullable(), + assetId: z.string().nullable() +}) + +let config: z.infer +const configPath = path.join(__dirname, 'config.json') +try { + if (!fs.existsSync(configPath)) { + const CLIENT_ID = process.env.CLIENT_ID + const NARVAL_AUTH_PRIVATE_KEY_HEX = process.env.NARVAL_AUTH_PRIVATE_KEY + const BASE_URL = process.env.BASE_URL + + if (!CLIENT_ID || !NARVAL_AUTH_PRIVATE_KEY_HEX || !BASE_URL) { + throw new Error('CLIENT_ID or NARVAL_AUTH_PRIVATE_KEY or BASE_URL must be in .env or config.json') + } + + // Default configuration + const defaultConfig = { + clientId: CLIENT_ID, + narvalAuthPrivateKey: NARVAL_AUTH_PRIVATE_KEY_HEX, + baseUrl: BASE_URL, + connectionId: null, + connectionPrivateKey: '', + connectionApiKey: '', + connectionUrl: 'https://api.anchorage-staging.com', + sourceId: null, + destinationId: null, + destinationType: null, + destinationAddress: null, + amount: null, + assetId: null + } + fs.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 2)) + config = defaultConfig + } else { + const configFile = fs.readFileSync(configPath, 'utf8') + config = configSchema.parse(JSON.parse(configFile)) + } +} catch (error) { + console.error('Error handling config.json:', error) + throw error +} + +if (!config.connectionApiKey || !config.connectionPrivateKey) { + console.error('Missing `connectionApiKey` or `connectionPrivateKey` in config.json. Please add them and try again.') + process.exit(1) +} + +export const setConfig = ( + key: keyof z.infer, + value: z.infer[keyof z.infer] +) => { + const newConfig = configSchema.parse({ ...config, [key]: value }) + fs.writeFileSync(configPath, JSON.stringify(newConfig, null, 2)) + config = newConfig } -const masterPrivateKeyJwk = privateKeyToJwk(MASTER_PRIVATE_KEY_HEX as Hex, 'EDDSA') +export { config } export const vaultClient = new VaultClient({ - clientId: CLIENT_ID, + clientId: config.clientId, signer: { - sign: buildSignerEdDSA(MASTER_PRIVATE_KEY_HEX), - jwk: masterPrivateKeyJwk, + sign: buildSignerEdDSA(config.narvalAuthPrivateKey), + jwk: privateKeyToJwk(config.narvalAuthPrivateKey as Hex, 'EDDSA'), alg: 'EDDSA' }, - host: BASE_URL + host: config.baseUrl }) From 0bf011432efc63022de7a486326970df3fe0b0f6 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Fri, 17 Jan 2025 09:56:57 +0100 Subject: [PATCH 094/120] Fireblocks transfer (#80) * Persist network unified list * Add asset list * Add findByOnchainId and findNativeAsset for Fireblocks * Remove asset indexes * Support transfers on Fireblocks * Add integration tests * Improve integration tests * Fix wrong format * Add network data migration * Simplify Fireblocks destination map * Rename network model Change uniqueness constraints in the network and provider network models. Address some minor request changes. * Fix FB client unit tests Remove unncessary provider from send transfer request. * Fix FB destination resolve to include internal addresses * Remove findByAddress from the repository * Fix transfer idempotence Add more logs. Add external transfer status. * Remove console.log * Fix Anchorage source and destination Add test to cover transfers to addresses * Add comment explaining Anchorage address destination * Delete transfer party service --- .../src/broker/__test__/e2e/transfer.spec.ts | 87 +++- apps/vault/src/broker/broker.module.ts | 4 +- .../anchorage-transfer.service.spec.ts | 67 ++- .../anchorage/anchorage-transfer.service.ts | 141 +++--- .../core/provider/anchorage/anchorage.type.ts | 7 + .../core/provider/anchorage/anchorage.util.ts | 22 +- .../fireblocks-transfer.service.spec.ts | 471 ++++++++++++++++++ .../response/get-transaction-200.json | 58 +++ .../response/get-transfer-200.json | 28 -- .../get-trusted-destinations-200-second.json | 35 -- .../get-trusted-destinations-200-third.json | 16 - .../get-trusted-destinations-200.json | 44 -- .../response/get-vault-accounts-200.json | 35 -- .../response/post-transaction-201.json | 4 + .../response/post-transfer-201.json | 6 - .../response/post-transfer-400.json | 4 - .../fireblocks/__test__/server-mock/server.ts | 17 +- .../fireblocks/fireblocks-transfer.service.ts | 386 ++++++++++++++ .../broker/core/service/address.service.ts | 24 +- .../core/service/transfer-party.service.ts | 135 ----- .../broker/core/service/transfer.service.ts | 14 +- .../src/broker/core/service/wallet.service.ts | 4 +- .../src/broker/core/type/provider.type.ts | 13 + .../src/broker/core/type/transfer.type.ts | 30 +- .../__test__/unit/fireblocks.client.spec.ts | 11 +- .../broker/http/client/anchorage.client.ts | 16 +- .../broker/http/client/fireblocks.client.ts | 199 +++++++- .../rest/dto/request/send-transfer.dto.ts | 2 +- .../repository/address.repository.ts | 24 +- .../repository/transfer.repository.ts | 10 + 30 files changed, 1424 insertions(+), 490 deletions(-) create mode 100644 apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-transfer.service.spec.ts create mode 100644 apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-transaction-200.json delete mode 100644 apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-transfer-200.json delete mode 100644 apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-trusted-destinations-200-second.json delete mode 100644 apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-trusted-destinations-200-third.json delete mode 100644 apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-trusted-destinations-200.json delete mode 100644 apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-vault-accounts-200.json create mode 100644 apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/post-transaction-201.json delete mode 100644 apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/post-transfer-201.json delete mode 100644 apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/post-transfer-400.json create mode 100644 apps/vault/src/broker/core/provider/fireblocks/fireblocks-transfer.service.ts delete mode 100644 apps/vault/src/broker/core/service/transfer-party.service.ts diff --git a/apps/vault/src/broker/__test__/e2e/transfer.spec.ts b/apps/vault/src/broker/__test__/e2e/transfer.spec.ts index 722d40194..d2824d218 100644 --- a/apps/vault/src/broker/__test__/e2e/transfer.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/transfer.spec.ts @@ -23,6 +23,7 @@ import { Provider } from '../../core/type/provider.type' import { InternalTransfer, NetworkFeeAttribution, + SendTransfer, TransferPartyType, TransferStatus } from '../../core/type/transfer.type' @@ -127,6 +128,7 @@ describe('Transfer', () => { id: accountTwo.accountId }, externalId: uuid(), + externalStatus: null, grossAmount: '0.00001', idempotenceId: uuid(), memo: 'Test transfer', @@ -198,21 +200,25 @@ describe('Transfer', () => { }) describe(`POST ${ENDPOINT}`, () => { - const requiredPayload = { - source: { - type: TransferPartyType.ACCOUNT, - id: accountOne.accountId - }, - destination: { - type: TransferPartyType.ACCOUNT, - id: accountTwo.accountId - }, - amount: '0.0001', - asset: { - assetId: 'BTC_S' - }, - idempotenceId: uuid() - } + let requiredPayload: SendTransfer + + beforeEach(() => { + requiredPayload = { + source: { + type: TransferPartyType.ACCOUNT, + id: accountOne.accountId + }, + destination: { + type: TransferPartyType.ACCOUNT, + id: accountTwo.accountId + }, + amount: '0.0001', + asset: { + assetId: 'BTC_S' + }, + idempotenceId: uuid() + } + }) it('sends transfer to anchorage', async () => { const { status, body } = await request(app.getHttpServer()) @@ -238,6 +244,7 @@ describe('Transfer', () => { createdAt: expect.any(String), customerRefId: null, destination: requiredPayload.destination, + externalStatus: expect.any(String), grossAmount: requiredPayload.amount, idempotenceId: expect.any(String), memo: null, @@ -353,10 +360,44 @@ describe('Transfer', () => { message: 'Missing or invalid x-connection-id header' }) }) + + it('responds with conflict when idempotence id was already used', async () => { + await request(app.getHttpServer()) + .post(ENDPOINT) + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set(REQUEST_HEADER_CONNECTION_ID, connection.connectionId) + .set( + 'detached-jws', + await getJwsd({ + payload: requiredPayload, + userPrivateJwk: testUserPrivateJwk, + requestUrl: ENDPOINT, + htm: 'POST' + }) + ) + .send(requiredPayload) + + const { status } = await request(app.getHttpServer()) + .post(ENDPOINT) + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set(REQUEST_HEADER_CONNECTION_ID, connection.connectionId) + .set( + 'detached-jws', + await getJwsd({ + payload: requiredPayload, + userPrivateJwk: testUserPrivateJwk, + requestUrl: ENDPOINT, + htm: 'POST' + }) + ) + .send(requiredPayload) + + expect(status).toEqual(HttpStatus.CONFLICT) + }) }) describe(`GET ${ENDPOINT}/:transferId`, () => { - const transfer = { + const internalTransfer = { assetId: 'BTC', clientId: connection.clientId, createdAt: new Date(), @@ -366,6 +407,7 @@ describe('Transfer', () => { id: accountTwo.accountId }, externalId: uuid(), + externalStatus: null, grossAmount: '0.00001', idempotenceId: uuid(), memo: 'Test transfer', @@ -381,12 +423,12 @@ describe('Transfer', () => { } beforeEach(async () => { - await transferRepository.bulkCreate([transfer]) + await transferRepository.bulkCreate([internalTransfer]) }) it('responds with the specific transfer', async () => { const { status, body } = await request(app.getHttpServer()) - .get(`${ENDPOINT}/${transfer.transferId}`) + .get(`${ENDPOINT}/${internalTransfer.transferId}`) .set(REQUEST_HEADER_CLIENT_ID, clientId) .set(REQUEST_HEADER_CONNECTION_ID, connection.connectionId) .set( @@ -394,7 +436,7 @@ describe('Transfer', () => { await getJwsd({ payload: {}, userPrivateJwk: testUserPrivateJwk, - requestUrl: `${ENDPOINT}/${transfer.transferId}`, + requestUrl: `${ENDPOINT}/${internalTransfer.transferId}`, htm: 'GET' }) ) @@ -402,11 +444,12 @@ describe('Transfer', () => { expect(body).toEqual({ data: { - ...transfer, + ...internalTransfer, // NOTE: The status is different from `transfer` because it's coming // from the Anchorage API. The `findById` merges the state we have in // the database with the API's. status: TransferStatus.SUCCESS, + externalStatus: expect.any(String), createdAt: expect.any(String) } }) @@ -416,14 +459,14 @@ describe('Transfer', () => { it('fails if connection header is missing', async () => { const { body } = await request(app.getHttpServer()) - .get(`${ENDPOINT}/${transfer.transferId}`) + .get(`${ENDPOINT}/${internalTransfer.transferId}`) .set(REQUEST_HEADER_CLIENT_ID, clientId) .set( 'detached-jws', await getJwsd({ payload: {}, userPrivateJwk: testUserPrivateJwk, - requestUrl: `${ENDPOINT}/${transfer.transferId}`, + requestUrl: `${ENDPOINT}/${internalTransfer.transferId}`, htm: 'GET' }) ) diff --git a/apps/vault/src/broker/broker.module.ts b/apps/vault/src/broker/broker.module.ts index 65a254bfe..6eb557479 100644 --- a/apps/vault/src/broker/broker.module.ts +++ b/apps/vault/src/broker/broker.module.ts @@ -19,13 +19,13 @@ import { FireblocksAssetService } from './core/provider/fireblocks/fireblocks-as import { FireblocksCredentialService } from './core/provider/fireblocks/fireblocks-credential.service' import { FireblocksProxyService } from './core/provider/fireblocks/fireblocks-proxy.service' import { FireblocksSyncService } from './core/provider/fireblocks/fireblocks-sync.service' +import { FireblocksTransferService } from './core/provider/fireblocks/fireblocks-transfer.service' import { AccountService } from './core/service/account.service' import { AddressService } from './core/service/address.service' import { ConnectionService } from './core/service/connection.service' import { KnownDestinationService } from './core/service/known-destination.service' import { ProxyService } from './core/service/proxy.service' import { SyncService } from './core/service/sync.service' -import { TransferPartyService } from './core/service/transfer-party.service' import { TransferService } from './core/service/transfer.service' import { WalletService } from './core/service/wallet.service' import { ConnectionSyncEventHandler } from './event/handler/connection-sync.event-handler' @@ -101,13 +101,13 @@ const SEEDS = [NetworkSeed] FireblocksCredentialService, FireblocksProxyService, FireblocksSyncService, + FireblocksTransferService, KnownDestinationRepository, KnownDestinationService, NetworkRepository, ProxyService, SyncRepository, SyncService, - TransferPartyService, TransferRepository, TransferService, WalletRepository, diff --git a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts index d2fdecb11..f9f224969 100644 --- a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts +++ b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts @@ -4,6 +4,7 @@ import { Ed25519PrivateKey, getPublicKey } from '@narval/signature' import { INestApplication } from '@nestjs/common' import { Test, TestingModule } from '@nestjs/testing' import { v4 as uuid } from 'uuid' +import { generatePrivateKey, privateKeyToAddress } from 'viem/accounts' import { ClientService } from '../../../../../../client/core/service/client.service' import { MainModule } from '../../../../../../main.module' import { ProvisionService } from '../../../../../../provision.service' @@ -29,7 +30,6 @@ import { TransferPartyType, TransferStatus } from '../../../../type/transfer.type' -import { AnchorageAssetService } from '../../anchorage-asset.service' import { AnchorageTransferService } from '../../anchorage-transfer.service' import { ANCHORAGE_TEST_API_BASE_URL, getHandlers } from '../server-mock/server' @@ -40,7 +40,6 @@ describe(AnchorageTransferService.name, () => { let accountRepository: AccountRepository let addressRepository: AddressRepository - let anchorageAssetService: AnchorageAssetService let anchorageTransferService: AnchorageTransferService let clientService: ClientService let connectionRepository: ConnectionRepository @@ -151,6 +150,7 @@ describe(AnchorageTransferService.name, () => { id: accountTwo.accountId }, externalId, + externalStatus: null, assetId: 'BTC', memo: 'Test transfer', grossAmount: '0.00001', @@ -187,7 +187,6 @@ describe(AnchorageTransferService.name, () => { accountRepository = module.get(AccountRepository) addressRepository = module.get(AddressRepository) - anchorageAssetService = module.get(AnchorageAssetService) connectionRepository = module.get(ConnectionRepository) knownDestinationRepository = module.get(KnownDestinationRepository) networkSeed = module.get(NetworkSeed) @@ -304,10 +303,11 @@ describe(AnchorageTransferService.name, () => { } it('creates an internal transfer on success', async () => { - const internalTransfer = await anchorageTransferService.send(connection, requiredSendTransfer) - const actualInternalTransfer = await transferRepository.findById(clientId, internalTransfer.transferId) + const { externalStatus, ...transfer } = await anchorageTransferService.send(connection, requiredSendTransfer) + const actualInternalTransfer = await transferRepository.findById(clientId, transfer.transferId) - expect(actualInternalTransfer).toEqual(internalTransfer) + expect(actualInternalTransfer).toMatchObject(transfer) + expect(externalStatus).toEqual(expect.any(String)) }) it('creates with optional properties', async () => { @@ -365,6 +365,33 @@ describe(AnchorageTransferService.name, () => { ) }) + it('calls Anchorage with address', async () => { + const [spy] = useRequestSpy(mockServer) + const address = privateKeyToAddress(generatePrivateKey()) + const sendTransfer = { + ...requiredSendTransfer, + destination: { address }, + transferId: 'test-transfer-id' + } + + await anchorageTransferService.send(connection, sendTransfer) + + expect(spy).toHaveBeenCalledWith( + expect.objectContaining({ + body: expect.objectContaining({ + source: { + type: 'WALLET', + id: accountOne.externalId + }, + destination: { + type: 'ADDRESS', + id: address + } + }) + }) + ) + }) + // IMPORTANT: We never send the customerRefId to Anchorage because they // have deprecated it and it seems to get transfers stuck on their side. it('does not send customerRefId', async () => { @@ -433,33 +460,5 @@ describe(AnchorageTransferService.name, () => { }) ) }) - - it('sends to an internal address', async () => { - const sendTransfer = { - ...requiredSendTransfer, - destination: { - address: address.address - } - } - - const internalTransfer = await anchorageTransferService.send(connection, sendTransfer) - const actualInternalTransfer = await transferRepository.findById(clientId, internalTransfer.transferId) - - expect(actualInternalTransfer).toMatchObject(internalTransfer) - }) - - it('sends to a known destination', async () => { - const sendTransfer = { - ...requiredSendTransfer, - destination: { - address: knownDestination.address - } - } - - const internalTransfer = await anchorageTransferService.send(connection, sendTransfer) - const actualInternalTransfer = await transferRepository.findById(clientId, internalTransfer.transferId) - - expect(actualInternalTransfer).toMatchObject(internalTransfer) - }) }) }) diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts index 69ed81285..6d3694e4b 100644 --- a/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts @@ -5,10 +5,10 @@ import { AnchorageClient } from '../../../http/client/anchorage.client' import { NetworkRepository } from '../../../persistence/repository/network.repository' import { TransferRepository } from '../../../persistence/repository/transfer.repository' import { BrokerException } from '../../exception/broker.exception' -import { TransferPartyService } from '../../service/transfer-party.service' +import { AccountService } from '../../service/account.service' +import { WalletService } from '../../service/wallet.service' import { Asset } from '../../type/asset.type' import { ConnectionWithCredentials } from '../../type/connection.type' -import { Network } from '../../type/network.type' import { Provider, ProviderTransferService } from '../../type/provider.type' import { Destination, @@ -24,7 +24,7 @@ import { isProviderSpecific } from '../../type/transfer.type' import { AnchorageAssetService } from './anchorage-asset.service' -import { validateConnection } from './anchorage.util' +import { transferPartyTypeToAnchorageResourceType, validateConnection } from './anchorage.util' @Injectable() export class AnchorageTransferService implements ProviderTransferService { @@ -32,23 +32,24 @@ export class AnchorageTransferService implements ProviderTransferService { private readonly anchorageAssetService: AnchorageAssetService, private readonly anchorageClient: AnchorageClient, private readonly networkRepository: NetworkRepository, - private readonly transferPartyService: TransferPartyService, + private readonly accountService: AccountService, + private readonly walletService: WalletService, private readonly transferRepository: TransferRepository, private readonly logger: LoggerService ) {} async findById(connection: ConnectionWithCredentials, transferId: string): Promise { - this.logger.log('Find Anchorage transfer by ID', { - clientId: connection.clientId, - connectionId: connection.connectionId, - transferId - }) + const { clientId, connectionId } = connection + + const context = { clientId, connectionId, transferId } + + this.logger.log('Find Anchorage transfer by ID', context) validateConnection(connection) const internalTransfer = await this.transferRepository.findById(connection.clientId, transferId) - this.logger.log('Found internal transfer by ID', internalTransfer) + this.logger.log('Found internal transfer by ID', { ...context, internalTransfer }) const anchorageTransfer = await this.anchorageClient.getTransferById({ url: connection.url, @@ -57,7 +58,7 @@ export class AnchorageTransferService implements ProviderTransferService { transferId: internalTransfer.externalId }) - this.logger.log('Found remote transfer by external ID', anchorageTransfer) + this.logger.log('Found remote transfer by external ID', { ...context, anchorageTransfer }) const transfer = { assetId: internalTransfer.assetId, @@ -66,6 +67,7 @@ export class AnchorageTransferService implements ProviderTransferService { customerRefId: internalTransfer.customerRefId, destination: internalTransfer.destination, externalId: internalTransfer.externalId, + externalStatus: anchorageTransfer.status, grossAmount: anchorageTransfer.amount.quantity, idempotenceId: internalTransfer.idempotenceId, memo: anchorageTransfer.transferMemo || internalTransfer.memo || null, @@ -87,7 +89,7 @@ export class AnchorageTransferService implements ProviderTransferService { : [] } - this.logger.log('Combined internal and remote transfer', transfer) + this.logger.log('Combined internal and remote Anchorage transfer', { ...context, transfer }) return transfer } @@ -139,11 +141,10 @@ export class AnchorageTransferService implements ProviderTransferService { } async send(connection: ConnectionWithCredentials, sendTransfer: SendTransfer): Promise { - this.logger.log('Send Anchorage transfer', { - clientId: connection.clientId, - connectionId: connection.connectionId, - sendTransfer - }) + const { clientId, connectionId } = connection + const context = { clientId, connectionId } + + this.logger.log('Send Anchorage transfer', { ...context, sendTransfer }) validateConnection(connection) @@ -165,19 +166,18 @@ export class AnchorageTransferService implements ProviderTransferService { }) } - const source = await this.transferPartyService.resolve(connection.clientId, sendTransfer.source, network.networkId) + const source = await this.getSource(clientId, sendTransfer.source) + const destination = await this.getDestination(clientId, sendTransfer.destination) - this.logger.log('Resolved Anchorage source', { source, networkId: network.networkId }) + this.logger.log('Resolved Anchorage source and destination', { ...context, source, destination }) - // NOTE: Because Anchorage defaults `deductFeeFromAmountIfSameType` to false, we - // default the fee attribution to ON_TOP to match their API's behaviour. + // NOTE: Because Anchorage defaults `deductFeeFromAmountIfSameType` to + // false, we default the fee attribution to ON_TOP to match their API's + // behaviour. const networkFeeAttribution = sendTransfer.networkFeeAttribution || NetworkFeeAttribution.ON_TOP const data = { - source: { - type: this.getResourceType(sendTransfer.source), - id: source.externalId - }, - destination: await this.getDestination(connection.clientId, network, sendTransfer), + source, + destination, assetType: asset.externalId, amount: sendTransfer.amount, transferMemo: sendTransfer.memo || null, @@ -186,6 +186,8 @@ export class AnchorageTransferService implements ProviderTransferService { ...(isProviderSpecific(sendTransfer.providerSpecific) ? { ...sendTransfer.providerSpecific } : {}) } + this.logger.log('Send create transfer request to Anchorage', { ...context, data }) + const anchorageTransfer = await this.anchorageClient.createTransfer({ url: connection.url, apiKey: connection.credentials.apiKey, @@ -193,14 +195,17 @@ export class AnchorageTransferService implements ProviderTransferService { data }) + this.logger.log('Anchorage transfer created', context) + const internalTransfer: InternalTransfer = { // TODO: switch this to the Narval assetId once that is a real thing. assetId: asset.externalId, - clientId: connection.clientId, + clientId: clientId, createdAt: new Date(), customerRefId: null, destination: sendTransfer.destination, externalId: anchorageTransfer.transferId, + externalStatus: anchorageTransfer.status, grossAmount: sendTransfer.amount, idempotenceId: sendTransfer.idempotenceId, memo: sendTransfer.memo || null, @@ -212,7 +217,7 @@ export class AnchorageTransferService implements ProviderTransferService { transferId: uuid() } - this.logger.log('Create internal transfer', internalTransfer) + this.logger.log('Create internal transfer', { ...context, internalTransfer }) await this.transferRepository.bulkCreate([internalTransfer]) @@ -225,10 +230,9 @@ export class AnchorageTransferService implements ProviderTransferService { * * Example: a request to transfer 5 BTC with * `deductFeeFromAmountIfSameType=false` would result in 5 exactly BTC - * received to the destination vault and just over 5 BTC spent by the source - * vault. + * received to the destination and just over 5 BTC spent by the source. * - * NOTE: Anchorage API defaults to `false`. + * Note: Anchorage API defaults to `false`. * * @see https://docs.anchorage.com/reference/createtransfer */ @@ -244,55 +248,66 @@ export class AnchorageTransferService implements ProviderTransferService { return false } - private async getDestination(clientId: string, network: Network, sendTransfer: SendTransfer) { - const destination = await this.transferPartyService.resolve(clientId, sendTransfer.destination, network.networkId) - const type = this.getResourceType(sendTransfer.destination) + private async getSource(clientId: string, source: Source) { + if (source.type === TransferPartyType.WALLET) { + const wallet = await this.walletService.findById(clientId, source.id) - this.logger.log('Resolved Anchorage destination', { - network: network.networkId, - type, - destination - }) - - // TODO: Automate test this. It's an important biz rule. - // If it's an Address or Known Destination - if (type === 'ADDRESS' && 'address' in destination) { return { - type, - id: destination.address + type: transferPartyTypeToAnchorageResourceType(source.type), + id: wallet.externalId } } - // TODO: When we send to an internal address, do we must pass and ID or the - // address as well? + if (source.type === TransferPartyType.ACCOUNT) { + const wallet = await this.accountService.findById(clientId, source.id) - return { - type, - id: destination.externalId + return { + type: transferPartyTypeToAnchorageResourceType(source.type), + id: wallet.externalId + } } + + throw new BrokerException({ + message: 'Cannot resolve Anchorage transfer source', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, + context: { clientId, source } + }) } - private getResourceType(transferParty: Source | Destination) { - if (isAddressDestination(transferParty)) { - return 'ADDRESS' + private async getDestination(clientId: string, destination: Destination) { + if (isAddressDestination(destination)) { + // IMPORTANT: For both known and unknown addresses, we pass them directly + // to Anchorage without validating their existence on our side. If the + // provided address is neither an Anchorage Address nor a Trusted + // Address, we let Anchorage handle the failure. + return { + type: transferPartyTypeToAnchorageResourceType(TransferPartyType.ADDRESS), + id: destination.address + } } - if (transferParty.type === TransferPartyType.WALLET) { - return 'VAULT' - } + if (destination.type === TransferPartyType.WALLET) { + const wallet = await this.walletService.findById(clientId, destination.id) - if (transferParty.type === TransferPartyType.ACCOUNT) { - return 'WALLET' + return { + type: transferPartyTypeToAnchorageResourceType(destination.type), + id: wallet.externalId + } } - if (transferParty.type === TransferPartyType.ADDRESS) { - return 'ADDRESS' + if (destination.type === TransferPartyType.ACCOUNT) { + const account = await this.accountService.findById(clientId, destination.id) + + return { + type: transferPartyTypeToAnchorageResourceType(destination.type), + id: account.externalId + } } throw new BrokerException({ - message: 'Cannot get Anchorage resource type from transfer party type', - suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, - context: { party: transferParty } + message: 'Cannot resolve Anchorage transfer destination', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, + context: { clientId, destination } }) } } diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage.type.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage.type.ts index 438ce6b25..cc54ed4e6 100644 --- a/apps/vault/src/broker/core/provider/anchorage/anchorage.type.ts +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage.type.ts @@ -14,3 +14,10 @@ export const AnchorageCredentials = z.object({ privateKey: ed25519PrivateKeySchema }) export type AnchorageCredentials = z.infer + +export const AnchorageResourceType = { + VAULT: 'VAULT', + WALLET: 'WALLET', + ADDRESS: 'ADDRESS' +} as const +export type AnchorageResourceType = (typeof AnchorageResourceType)[keyof typeof AnchorageResourceType] diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage.util.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage.util.ts index 93fa1032d..42bc84ed4 100644 --- a/apps/vault/src/broker/core/provider/anchorage/anchorage.util.ts +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage.util.ts @@ -1,8 +1,11 @@ import { Ed25519PrivateKey } from '@narval/signature' +import { HttpStatus } from '@nestjs/common' +import { BrokerException } from '../../exception/broker.exception' import { ConnectionInvalidException } from '../../exception/connection-invalid.exception' import { ConnectionWithCredentials } from '../../type/connection.type' import { Provider } from '../../type/provider.type' -import { AnchorageCredentials } from './anchorage.type' +import { TransferPartyType } from '../../type/transfer.type' +import { AnchorageCredentials, AnchorageResourceType } from './anchorage.type' export function validateConnection( connection: ConnectionWithCredentials @@ -51,3 +54,20 @@ export function validateConnection( }) } } + +export const transferPartyTypeToAnchorageResourceType = (type: TransferPartyType): AnchorageResourceType => { + switch (type) { + case TransferPartyType.WALLET: + return AnchorageResourceType.VAULT + case TransferPartyType.ACCOUNT: + return AnchorageResourceType.WALLET + case TransferPartyType.ADDRESS: + return AnchorageResourceType.ADDRESS + default: + throw new BrokerException({ + message: 'Cannot map transfer party to Anchorage resource type', + suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, + context: { type } + }) + } +} diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-transfer.service.spec.ts b/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-transfer.service.spec.ts new file mode 100644 index 000000000..569c994b9 --- /dev/null +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-transfer.service.spec.ts @@ -0,0 +1,471 @@ +import { EncryptionModuleOptionProvider } from '@narval/encryption-module' +import { LoggerModule } from '@narval/nestjs-shared' +import { RsaPrivateKey, getPublicKey } from '@narval/signature' +import { INestApplication } from '@nestjs/common' +import { Test, TestingModule } from '@nestjs/testing' +import { randomUUID } from 'crypto' +import { generatePrivateKey, privateKeyToAddress } from 'viem/accounts' +import { ClientService } from '../../../../../../client/core/service/client.service' +import { MainModule } from '../../../../../../main.module' +import { ProvisionService } from '../../../../../../provision.service' +import { KeyValueRepository } from '../../../../../../shared/module/key-value/core/repository/key-value.repository' +import { InMemoryKeyValueRepository } from '../../../../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' +import { TestPrismaService } from '../../../../../../shared/module/persistence/service/test-prisma.service' +import { getTestRawAesKeyring } from '../../../../../../shared/testing/encryption.testing' +import { testClient } from '../../../../../__test__/util/mock-data' +import { AccountRepository } from '../../../../../persistence/repository/account.repository' +import { AddressRepository } from '../../../../../persistence/repository/address.repository' +import { ConnectionRepository } from '../../../../../persistence/repository/connection.repository' +import { TransferRepository } from '../../../../../persistence/repository/transfer.repository' +import { WalletRepository } from '../../../../../persistence/repository/wallet.repository' +import { NetworkSeed } from '../../../../../persistence/seed/network.seed' +import { setupMockServer, useRequestSpy } from '../../../../../shared/__test__/mock-server' +import { Connection, ConnectionStatus, ConnectionWithCredentials } from '../../../../type/connection.type' +import { Account, Address, Wallet } from '../../../../type/indexed-resources.type' +import { Provider } from '../../../../type/provider.type' +import { + InternalTransfer, + NetworkFeeAttribution, + TransferPartyType, + TransferStatus +} from '../../../../type/transfer.type' +import { FireblocksTransferService } from '../../fireblocks-transfer.service' +import { FIREBLOCKS_TEST_API_BASE_URL, getHandlers } from '../server-mock/server' + +describe(FireblocksTransferService.name, () => { + let app: INestApplication + let module: TestingModule + let testPrismaService: TestPrismaService + + let accountRepository: AccountRepository + let fireblocksTransferService: FireblocksTransferService + let clientService: ClientService + let connectionRepository: ConnectionRepository + let networkSeed: NetworkSeed + let provisionService: ProvisionService + let transferRepository: TransferRepository + let walletRepository: WalletRepository + let addressRepository: AddressRepository + + const mockServer = setupMockServer(getHandlers()) + + const clientId = randomUUID() + + const walletOneId = randomUUID() + + const walletTwoId = randomUUID() + + const rsaPrivate: RsaPrivateKey = { + kty: 'RSA', + alg: 'RS256', + kid: '0x52920ad0d19d7779106bd9d9d600d26c4b976cdb3cbc49decb7fdc29db00b8e9', + n: 'xNdTjWL9hGa4bz4tLKbmFZ4yjQsQzW35-CMS0kno3403jEqg5y2Cs6sLVyPBX4N2hdK5ERPytpf1PrThHqB-eEO6LtEWpENBgFuNIf8DRHrv0tne7dLNxf7sx1aocGRrkgIk4Ws6Is4Ot3whm3-WihmDGnHoogE-EPwVkkSc2FYPXYlNq4htCZXC8_MUI3LuXry2Gn4tna5HsYSehYhfKDD-nfSajeWxdNUv_3wOeSCr9ICm9Udlo7hpIUHQgnX3Nz6kvfGYuweLGoj_ot-oEUCIdlbQqmrfStAclugbM5NI6tY__6wD0z_4ZBjToupXCBlXbYsde6_ZG9xPmYSykw', + e: 'AQAB', + d: 'QU4rIzpXX8jwob-gHzNUHJH6tX6ZWX6GM0P3p5rrztc8Oag8z9XyigdSYNu0-SpVdTqfOcJDgT7TF7XNBms66k2WBJhMCb1iiuJU5ZWEkQC0dmDgLEkHCgx0pAHlKjy2z580ezEm_YsdqNRfFgbze-fQ7kIiazU8UUhBI-DtpHv7baBgsfqEfQ5nCTiURUPmmpiIU74-ZIJWZjBXTOoJNH0EIsJK9IpZzxpeC9mTMTsWTcHKiR3acze1qf-9I97v461TTZ8e33N6YINyr9I4HZuvxlCJdV_lOM3fLvYM9gPvgkPozhVWL3VKR6xa9JpGGHrCRgH92INuviBB_SmF8Q', + p: '9BNku_-t4Df9Dg7M2yjiNgZgcTNKrDnNqexliIUAt67q0tGmSBubjxeI5unDJZ_giXWUR3q-02v7HT5GYx-ZVgKk2lWnbrrm_F7UZW-ueHzeVvQcjDXTk0z8taXzrDJgnIwZIaZ2XSG3P-VPOrXCaMba8GzSq38Gpzi4g3lTO9s', + q: 'znUtwrqdnVew14_aFjNTRgzOQNN8JhkjzJy3aTSLBScK5NbiuUUZBWs5dQ7Nv7aAoDss1-o9XVQZ1DVV-o9UufJtyrPNcvTnC0cWRrtJrSN5YiuUbECU3Uj3OvGxnhx9tsmhDHnMTo50ObPYUbHcIkNaXkf2FVgL84y1JRWdPak', + dp: 'UNDrFeS-6fMf8zurURXkcQcDf_f_za8GDjGcHOwNJMTiNBP-_vlFNMgSKINWfmrFqj4obtKRxOeIKlKoc8HOv8_4TeL2oY95VC8CHOQx3Otbo2cI3NQlziw7sNnWKTo1CyDIYYAAyS2Uw69l4Ia2bIMLk3g0-VwCE_SQA9h0Wuk', + dq: 'VBe6ieSFKn97UnIPfJdvRcsVf6YknUgEIuV6d2mlbnXWpBs6wgf5BxIDl0BuYbYuchVoUJHiaM9Grf8DhEk5U3wBaF0QQ9CpAxjzY-AJRHJ8kJX7oJQ1jmSX_vRPSn2EXx2FcZVyuFSh1pcAd1YgufwBJQHepBb21z7q0a4aG_E', + qi: 'KhZpFs6xfyRIjbJV8Q9gWxqF37ONayIzBpgio5mdAQlZ-FUmaWZ2_2VWP2xvsP48BmwFXydHqewHBqGnZYCQ1ZHXJgD_-KKEejoqS5AJN1pdI0ZKjs7UCfZ4RJ4DH5p0_35gpuKRzzdvcIhl1CjIC5W8o7nhwmLBJ_QAo9e4t9U' + } + + const testApiKey = 'test-api-key' + + const connection: ConnectionWithCredentials = { + clientId, + connectionId: randomUUID(), + createdAt: new Date(), + provider: Provider.FIREBLOCKS, + status: ConnectionStatus.ACTIVE, + updatedAt: new Date(), + url: FIREBLOCKS_TEST_API_BASE_URL, + credentials: { + privateKey: rsaPrivate, + publicKey: getPublicKey(rsaPrivate), + apiKey: testApiKey + } + } + + const accountOne: Account = { + accountId: randomUUID(), + addresses: [], + clientId, + createdAt: new Date(), + externalId: randomUUID(), + label: 'Account 1', + networkId: 'POLYGON', + provider: Provider.FIREBLOCKS, + updatedAt: new Date(), + walletId: walletOneId + } + + const accountTwo: Account = { + accountId: randomUUID(), + addresses: [], + clientId, + createdAt: new Date(), + externalId: randomUUID(), + label: 'Account 2', + networkId: 'POLYGON', + provider: Provider.FIREBLOCKS, + updatedAt: new Date(), + walletId: walletTwoId + } + + const walletOne: Wallet = { + clientId, + connections: [Connection.parse(connection)], + createdAt: new Date(), + externalId: randomUUID(), + label: null, + provider: Provider.FIREBLOCKS, + updatedAt: new Date(), + walletId: walletOneId + } + + const walletTwo: Wallet = { + clientId, + connections: [Connection.parse(connection)], + createdAt: new Date(), + externalId: randomUUID(), + label: null, + provider: Provider.FIREBLOCKS, + updatedAt: new Date(), + walletId: walletTwoId + } + + const address: Address = { + accountId: accountTwo.accountId, + address: '0x2c4895215973cbbd778c32c456c074b99daf8bf1', + addressId: randomUUID(), + clientId, + createdAt: new Date(), + externalId: randomUUID(), + provider: Provider.FIREBLOCKS, + updatedAt: new Date() + } + + const internalTransfer: InternalTransfer = { + clientId, + source: { + type: TransferPartyType.ACCOUNT, + id: accountOne.accountId + }, + destination: { + type: TransferPartyType.ACCOUNT, + id: accountTwo.accountId + }, + customerRefId: null, + idempotenceId: null, + externalId: randomUUID(), + externalStatus: null, + assetId: 'MATIC', + memo: 'Test transfer', + grossAmount: '0.00001', + networkFeeAttribution: NetworkFeeAttribution.DEDUCT, + provider: Provider.FIREBLOCKS, + transferId: randomUUID(), + createdAt: new Date() + } + + beforeAll(async () => { + module = await Test.createTestingModule({ + imports: [MainModule] + }) + .overrideModule(LoggerModule) + .useModule(LoggerModule.forTest()) + .overrideProvider(KeyValueRepository) + .useValue(new InMemoryKeyValueRepository()) + .overrideProvider(EncryptionModuleOptionProvider) + .useValue({ + keyring: getTestRawAesKeyring() + }) + .compile() + + app = module.createNestApplication() + + testPrismaService = module.get(TestPrismaService) + fireblocksTransferService = module.get(FireblocksTransferService) + provisionService = module.get(ProvisionService) + clientService = module.get(ClientService) + + accountRepository = module.get(AccountRepository) + addressRepository = module.get(AddressRepository) + connectionRepository = module.get(ConnectionRepository) + networkSeed = module.get(NetworkSeed) + transferRepository = module.get(TransferRepository) + walletRepository = module.get(WalletRepository) + + await testPrismaService.truncateAll() + }) + + afterAll(async () => { + await testPrismaService.truncateAll() + await module.close() + await app.close() + }) + + beforeEach(async () => { + await testPrismaService.truncateAll() + + await provisionService.provision() + await clientService.save(testClient) + await networkSeed.seed() + + await connectionRepository.create(connection) + await walletRepository.bulkCreate([walletOne, walletTwo]) + await accountRepository.bulkCreate([accountOne, accountTwo]) + await addressRepository.bulkCreate([address]) + await transferRepository.bulkCreate([internalTransfer]) + + await app.init() + }) + + describe('findById', () => { + it('maps data from internal transfer', async () => { + const transfer = await fireblocksTransferService.findById(connection, internalTransfer.transferId) + + expect(transfer).toMatchObject({ + assetId: internalTransfer.assetId, + clientId: internalTransfer.clientId, + customerRefId: internalTransfer.customerRefId, + destination: internalTransfer.destination, + externalId: internalTransfer.externalId, + idempotenceId: internalTransfer.idempotenceId, + networkFeeAttribution: internalTransfer.networkFeeAttribution, + provider: internalTransfer.provider, + source: internalTransfer.source, + transferId: internalTransfer.transferId + }) + }) + + it('maps gross amount from inbound transaction', async () => { + const transfer = await fireblocksTransferService.findById(connection, internalTransfer.transferId) + + expect(transfer.grossAmount).toEqual('0.001') + }) + + it('maps status from inbound transaction', async () => { + const transfer = await fireblocksTransferService.findById(connection, internalTransfer.transferId) + + expect(transfer.status).toEqual(TransferStatus.SUCCESS) + }) + + it('maps memo from internal transfer when inbound note is undefined', async () => { + const transfer = await fireblocksTransferService.findById(connection, internalTransfer.transferId) + + expect(transfer.memo).toEqual(internalTransfer.memo) + }) + + it('maps network fee from inbound transaction ', async () => { + const transfer = await fireblocksTransferService.findById(connection, internalTransfer.transferId) + + expect(transfer.fees.find(({ type }) => type === 'network')).toEqual({ + amount: '0.002354982918981', + assetId: 'MATIC_POLYGON', + attribution: internalTransfer.networkFeeAttribution, + type: 'network' + }) + }) + + it('maps gas price as a fee from inbound transaction', async () => { + const transfer = await fireblocksTransferService.findById(connection, internalTransfer.transferId) + + expect(transfer.fees.find(({ type }) => type === 'gas-price')).toEqual({ + amount: '112.14204376100001', + assetId: 'MATIC_POLYGON', + type: 'gas-price' + }) + }) + }) + + describe('send', () => { + const requiredSendTransfer = { + source: { + type: TransferPartyType.ACCOUNT, + id: accountOne.accountId + }, + destination: { + type: TransferPartyType.ACCOUNT, + id: accountTwo.accountId + }, + amount: '0.001', + asset: { + externalAssetId: 'MATIC_POLYGON' + }, + idempotenceId: randomUUID() + } + + it('creates an internal transfer on success', async () => { + const { externalStatus, ...transfer } = await fireblocksTransferService.send(connection, requiredSendTransfer) + const actualInternalTransfer = await transferRepository.findById(clientId, transfer.transferId) + + expect(actualInternalTransfer).toMatchObject(transfer) + expect(externalStatus).toEqual(expect.any(String)) + }) + + it('creates with optional properties', async () => { + const sendTransfer = { + ...requiredSendTransfer, + memo: 'Integration test transfer', + customerRefId: 'test-customer-ref-id', + networkFeeAttribution: NetworkFeeAttribution.DEDUCT, + idempotenceId: randomUUID() + } + + const internalTransfer = await fireblocksTransferService.send(connection, sendTransfer) + const actualInternalTransfer = await transferRepository.findById(clientId, internalTransfer.transferId) + + expect(actualInternalTransfer.idempotenceId).toEqual(sendTransfer.idempotenceId) + expect(actualInternalTransfer.memo).toEqual(sendTransfer.memo) + expect(actualInternalTransfer.customerRefId).toEqual(sendTransfer.customerRefId) + expect(actualInternalTransfer.networkFeeAttribution).toEqual(sendTransfer.networkFeeAttribution) + }) + + it('defaults network fee attribution to deduct', async () => { + const internalTransfer = await fireblocksTransferService.send(connection, requiredSendTransfer) + + expect(internalTransfer.networkFeeAttribution).toEqual(NetworkFeeAttribution.DEDUCT) + }) + + it('calls Fireblocks', async () => { + const [spy] = useRequestSpy(mockServer) + const sendTransfer = { + ...requiredSendTransfer, + memo: 'Integration test transfer', + transferId: 'test-transfer-id' + } + + await fireblocksTransferService.send(connection, sendTransfer) + + expect(spy).toHaveBeenCalledWith( + expect.objectContaining({ + body: { + amount: '0.001', + assetId: 'MATIC_POLYGON', + source: { + type: 'VAULT_ACCOUNT', + id: walletOne.externalId + }, + destination: { + type: 'VAULT_ACCOUNT', + id: walletTwo.externalId + }, + note: 'Integration test transfer', + externalTxId: sendTransfer.transferId, + treatAsGrossAmount: true + }, + headers: expect.objectContaining({ + 'x-api-key': testApiKey, + 'idempotency-key': requiredSendTransfer.idempotenceId + }) + }) + ) + }) + + it('calls Fireblocks with vault account as destination for internal address', async () => { + const [spy] = useRequestSpy(mockServer) + const sendTransfer = { + ...requiredSendTransfer, + destination: { address: address.address }, + transferId: 'test-transfer-id' + } + + await fireblocksTransferService.send(connection, sendTransfer) + + expect(spy).toHaveBeenCalledWith( + expect.objectContaining({ + body: expect.objectContaining({ + source: { + type: 'VAULT_ACCOUNT', + id: walletOne.externalId + }, + destination: { + type: 'VAULT_ACCOUNT', + id: walletTwo.externalId + } + }) + }) + ) + }) + + it('calls Fireblocks with one-time address', async () => { + const [spy] = useRequestSpy(mockServer) + const address = privateKeyToAddress(generatePrivateKey()) + const sendTransfer = { + ...requiredSendTransfer, + destination: { address }, + transferId: 'test-transfer-id' + } + + await fireblocksTransferService.send(connection, sendTransfer) + + expect(spy).toHaveBeenCalledWith( + expect.objectContaining({ + body: expect.objectContaining({ + source: { + type: 'VAULT_ACCOUNT', + id: walletOne.externalId + }, + destination: { + type: 'ONE_TIME_ADDRESS', + oneTimeAddress: { address } + } + }) + }) + ) + }) + + it('handles provider specific', async () => { + const [spy] = useRequestSpy(mockServer) + const providerSpecific = { + extraParameters: { + nodeControls: { + type: 'NODE_ROUTER' + }, + rawMessageData: { + messages: [ + { + preHash: { + hashAlgorithm: 'SHA256' + } + } + ] + } + } + } + const sendTransfer = { + ...requiredSendTransfer, + providerSpecific + } + + const internalTransfer = await fireblocksTransferService.send(connection, sendTransfer) + const actualInternalTransfer = await transferRepository.findById(clientId, internalTransfer.transferId) + + expect(spy).toHaveBeenCalledWith( + expect.objectContaining({ + body: expect.objectContaining({ ...sendTransfer.providerSpecific }) + }) + ) + + expect(actualInternalTransfer.providerSpecific).toEqual(sendTransfer.providerSpecific) + }) + + it('maps networkFeeAttribution on_top to treatAsGrossAmount false', async () => { + const [spy] = useRequestSpy(mockServer) + + await fireblocksTransferService.send(connection, { + ...requiredSendTransfer, + networkFeeAttribution: NetworkFeeAttribution.ON_TOP + }) + + expect(spy).toHaveBeenCalledWith( + expect.objectContaining({ + body: expect.objectContaining({ + treatAsGrossAmount: false + }) + }) + ) + }) + }) +}) diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-transaction-200.json b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-transaction-200.json new file mode 100644 index 000000000..d7e8496e8 --- /dev/null +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-transaction-200.json @@ -0,0 +1,58 @@ +{ + "id": "7ce5e75a-39cb-4d31-8a10-79d69c6f8e0e", + "assetId": "MATIC_POLYGON", + "source": { + "id": "4", + "type": "VAULT_ACCOUNT", + "name": "dev-2", + "subType": "" + }, + "destination": { + "id": "3", + "type": "VAULT_ACCOUNT", + "name": "dev-1", + "subType": "" + }, + "requestedAmount": 0.001, + "amount": 0.001, + "netAmount": 0.001, + "amountUSD": 0.00042585, + "fee": 0.002354982918981, + "networkFee": 0.002354982918981, + "createdAt": 1736775806138, + "lastUpdated": 1736775849692, + "status": "COMPLETED", + "txHash": "0xdd6bba7c8897d64e4dd21e4b395aa45ced7b9eb4b1cd356ad9ffbfa113a3fec1", + "subStatus": "CONFIRMED", + "sourceAddress": "0xe621c7D0D6711742B6B4aEE4cb30048d1Ef1d92e", + "destinationAddress": "0x6b1c79dBF7a7D90d6F4fD623393aFa3DfFd6bE4E", + "destinationAddressDescription": "", + "destinationTag": "", + "signedBy": ["da1e58d6-771c-1584-4eba-8b5ae8761eea"], + "createdBy": "ee425cf5-ca75-4537-b2ce-e1ace302e0a1", + "rejectedBy": "", + "addressType": "", + "note": "", + "exchangeTxId": "", + "feeCurrency": "MATIC_POLYGON", + "operation": "TRANSFER", + "numOfConfirmations": 1, + "amountInfo": { + "amount": "0.001", + "requestedAmount": "0.001", + "netAmount": "0.001", + "amountUSD": "0.00042585" + }, + "feeInfo": { + "networkFee": "0.002354982918981", + "gasPrice": "112.14204376100001" + }, + "signedMessages": [], + "destinations": [], + "blockInfo": { + "blockHeight": "66650299", + "blockHash": "0x62c064832c4a2ff9cc1e00c236427015cda4f639fd03ed62b0e7374bf652807a" + }, + "index": 0, + "assetType": "BASE_ASSET" +} diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-transfer-200.json b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-transfer-200.json deleted file mode 100644 index 1ba192755..000000000 --- a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-transfer-200.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "data": { - "amount": { - "assetType": "BTC_S", - "currentPrice": "104576.34", - "currentUSDValue": "1.05", - "quantity": "0.00001" - }, - "assetType": "BTC_S", - "blockchainTxId": "71ffe98ce4f51b4d12c77626dc455c9223f68b215c631f45ff05958623761e23", - "createdAt": "2024-12-18T14:04:10.519Z", - "destination": { - "id": "afb308d207a76f029257ea6d9d7d58ab", - "type": "WALLET" - }, - "endedAt": "2024-12-18T14:08:13.618Z", - "fee": { - "assetType": "BTC_S", - "quantity": "0.00001771" - }, - "source": { - "id": "6a46a1977959e0529f567e8e927e3895", - "type": "WALLET" - }, - "status": "COMPLETED", - "transferId": "60a0676772fdbd7a041e9451c61c3cb6b28ee901186e40ac99433308604e2e20" - } -} diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-trusted-destinations-200-second.json b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-trusted-destinations-200-second.json deleted file mode 100644 index cd627749f..000000000 --- a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-trusted-destinations-200-second.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "data": [ - { - "id": "toBeConnected", - "type": "crypto", - "crypto": { - "address": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", - "networkId": "ETH", - "assetType": "ETH" - } - }, - { - "id": "neverChanges", - "type": "crypto", - "crypto": { - "address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh", - "networkId": "BTC", - "assetType": "BTC" - } - }, - { - "id": "toBeUpdated", - "type": "crypto", - "crypto": { - "address": "0x8Bc2B8F33e5AeF847B8973Fa669B948A3028D6bd", - "networkId": "ETH", - "assetType": "USDC", - "memo": "new memo" - } - } - ], - "page": { - "next": null - } -} diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-trusted-destinations-200-third.json b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-trusted-destinations-200-third.json deleted file mode 100644 index 5985e2f1b..000000000 --- a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-trusted-destinations-200-third.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "data": [ - { - "id": "toBeConnected", - "type": "crypto", - "crypto": { - "address": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", - "networkId": "ETH", - "assetType": "ETH" - } - } - ], - "page": { - "next": null - } -} diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-trusted-destinations-200.json b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-trusted-destinations-200.json deleted file mode 100644 index 51dc594bd..000000000 --- a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-trusted-destinations-200.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "data": [ - { - "id": "toBeConnected", - "type": "crypto", - "crypto": { - "address": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", - "networkId": "ETH", - "assetType": "ETH" - } - }, - { - "id": "neverChanges", - "type": "crypto", - "crypto": { - "address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh", - "networkId": "BTC", - "assetType": "BTC" - } - }, - { - "id": "toBeUpdated", - "type": "crypto", - "crypto": { - "address": "0x8Bc2B8F33e5AeF847B8973Fa669B948A3028D6bd", - "networkId": "ETH", - "assetType": "USDC" - } - }, - { - "id": "toBeDeleted", - "type": "crypto", - "crypto": { - "address": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", - "networkId": "XRP", - "assetType": "XRP", - "memo": "123456" - } - } - ], - "page": { - "next": null - } -} diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-vault-accounts-200.json b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-vault-accounts-200.json deleted file mode 100644 index c94ac9682..000000000 --- a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-vault-accounts-200.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "accounts": { - "id": "3483", - "name": "prod-50-3085", - "hiddenOnUI": false, - "autoFuel": false, - "assets": [ - { - "id": "MATIC_POLYGON", - "total": "1065.275813068575650415", - "balance": "1065.275813068575650415", - "lockedAmount": "0", - "available": "1065.275813068575650415", - "pending": "0", - "frozen": "0", - "staked": "0", - "blockHeight": "65405786", - "blockHash": "0xa25d8a09a0fb05b3a417a8668b6044ab3d87d4e359aee1c339ad5763c163dea3" - }, - { - "id": "ETH-OPT", - "total": "0.001942589115042143", - "balance": "0.001942589115042143", - "lockedAmount": "0", - "available": "0.001942589115042143", - "pending": "0", - "frozen": "0", - "staked": "0", - "blockHeight": "124638003", - "blockHash": "0x6cdcecb4c1190ad0ffbc6ba51d4c9115caf1622fd1b32685165fd3abe247de3e" - } - ] - }, - "paging": {} -} diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/post-transaction-201.json b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/post-transaction-201.json new file mode 100644 index 000000000..deab3b11f --- /dev/null +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/post-transaction-201.json @@ -0,0 +1,4 @@ +{ + "id": "7ce5e75a-39cb-4d31-8a10-79d69c6f8e0e", + "status": "SUBMITTED" +} diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/post-transfer-201.json b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/post-transfer-201.json deleted file mode 100644 index d99d733ea..000000000 --- a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/post-transfer-201.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "data": { - "transferId": "008d3ec72558ce907571886df63ef51594b5bd8cf106a0b7fa8f12a30dfc867f", - "status": "IN_PROGRESS" - } -} diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/post-transfer-400.json b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/post-transfer-400.json deleted file mode 100644 index 56891b250..000000000 --- a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/post-transfer-400.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "errorType": "InternalError", - "message": "Missing required field 'amount'." -} diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/server.ts b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/server.ts index 99a119034..bab2c993e 100644 --- a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/server.ts +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/server.ts @@ -1,9 +1,8 @@ import { HttpResponse, http } from 'msw' -import getAssetWalletsOk from './response/get-asset-wallets-200.json' -import getTransferOk from './response/get-transfer-200.json' +import getTransactionOk from './response/get-transaction-200.json' import getWalletAddressesMaticOk from './response/get-wallet-addresses-matic-200.json' import getWalletAddressesOptOk from './response/get-wallet-addresses-optimism-200.json' -import postTransferCreated from './response/post-transfer-201.json' +import postTransactionCreated from './response/post-transaction-201.json' export const FIREBLOCKS_TEST_API_BASE_URL = 'https://test-mock-api.fireblocks.com' @@ -21,16 +20,12 @@ export const getAddressesHandlers = (baseUrl = FIREBLOCKS_TEST_API_BASE_URL) => } export const getHandlers = (baseUrl = FIREBLOCKS_TEST_API_BASE_URL) => [ - http.get(`${baseUrl}/v2/wallets`, () => { - return new HttpResponse(JSON.stringify(getAssetWalletsOk)) + http.get(`${baseUrl}/v1/transactions/:txId`, () => { + return new HttpResponse(JSON.stringify(getTransactionOk)) }), - http.get(`${baseUrl}/v2/transfers/:transferId`, () => { - return new HttpResponse(JSON.stringify(getTransferOk)) - }), - - http.post(`${baseUrl}/v2/transfers`, () => { - return new HttpResponse(JSON.stringify(postTransferCreated)) + http.post(`${baseUrl}/v1/transactions`, () => { + return new HttpResponse(JSON.stringify(postTransactionCreated)) }), getAddressesHandlers(baseUrl).getMatic diff --git a/apps/vault/src/broker/core/provider/fireblocks/fireblocks-transfer.service.ts b/apps/vault/src/broker/core/provider/fireblocks/fireblocks-transfer.service.ts new file mode 100644 index 000000000..3701fb377 --- /dev/null +++ b/apps/vault/src/broker/core/provider/fireblocks/fireblocks-transfer.service.ts @@ -0,0 +1,386 @@ +import { LoggerService } from '@narval/nestjs-shared' +import { HttpStatus, Injectable } from '@nestjs/common' +import { randomUUID } from 'crypto' +import { CreateTransaction, FireblocksClient } from '../../../http/client/fireblocks.client' +import { NetworkRepository } from '../../../persistence/repository/network.repository' +import { TransferRepository } from '../../../persistence/repository/transfer.repository' +import { BrokerException } from '../../exception/broker.exception' +import { AccountService } from '../../service/account.service' +import { AddressService } from '../../service/address.service' +import { WalletService } from '../../service/wallet.service' +import { Asset } from '../../type/asset.type' +import { ConnectionWithCredentials } from '../../type/connection.type' +import { Network } from '../../type/network.type' +import { Provider, ProviderTransferService } from '../../type/provider.type' +import { + Destination, + InternalTransfer, + NetworkFeeAttribution, + SendTransfer, + Transfer, + TransferAsset, + TransferPartyType, + TransferStatus, + isAddressDestination, + isProviderSpecific +} from '../../type/transfer.type' +import { FireblocksAssetService } from './fireblocks-asset.service' +import { validateConnection } from './fireblocks.util' + +@Injectable() +export class FireblocksTransferService implements ProviderTransferService { + constructor( + private readonly fireblocksAssetService: FireblocksAssetService, + private readonly fireblocksClient: FireblocksClient, + private readonly networkRepository: NetworkRepository, + private readonly walletService: WalletService, + private readonly accountService: AccountService, + private readonly addressService: AddressService, + private readonly transferRepository: TransferRepository, + private readonly logger: LoggerService + ) {} + + async findById(connection: ConnectionWithCredentials, transferId: string): Promise { + const { clientId, connectionId } = connection + const context = { clientId, connectionId, transferId } + + this.logger.log('Find Fireblocks transfer by ID', context) + + validateConnection(connection) + + const internalTransfer = await this.transferRepository.findById(connection.clientId, transferId) + + this.logger.log('Found internal transfer by ID', { + clientId, + internalTransfer + }) + + const fireblocksTransaction = await this.fireblocksClient.getTransactionById({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey, + txId: internalTransfer.externalId + }) + + this.logger.log('Found Fireblocks transaction by ID', context) + + const transfer = { + assetId: internalTransfer.assetId, + clientId: internalTransfer.clientId, + createdAt: new Date(fireblocksTransaction.createdAt), + customerRefId: internalTransfer.customerRefId, + destination: internalTransfer.destination, + externalId: internalTransfer.externalId, + externalStatus: fireblocksTransaction.subStatus || fireblocksTransaction.status || null, + grossAmount: fireblocksTransaction.amountInfo.amount, + idempotenceId: internalTransfer.idempotenceId, + memo: fireblocksTransaction.note || internalTransfer.memo || null, + networkFeeAttribution: internalTransfer.networkFeeAttribution, + provider: internalTransfer.provider, + providerSpecific: internalTransfer.providerSpecific, + source: internalTransfer.source, + status: this.mapStatus(fireblocksTransaction.status), + transferId: internalTransfer.transferId, + fees: [ + ...(fireblocksTransaction.feeInfo.networkFee + ? [ + { + type: 'network', + attribution: internalTransfer.networkFeeAttribution, + amount: fireblocksTransaction.feeInfo.networkFee, + // TODO: (@wcalderipe, 13/01/25): Replace by Narval asset ID + // once it's a thing. + assetId: fireblocksTransaction.feeCurrency + } + ] + : []), + ...(fireblocksTransaction.feeInfo.gasPrice + ? [ + { + type: 'gas-price', + amount: fireblocksTransaction.feeInfo.gasPrice, + // TODO: (@wcalderipe, 13/01/25): Replace by Narval asset ID + // once it's a thing. + assetId: fireblocksTransaction.feeCurrency + } + ] + : []) + ] + } + + this.logger.log('Combined internal and remote Fireblocks transfer', { ...context, transfer }) + + return transfer + } + + async send(connection: ConnectionWithCredentials, sendTransfer: SendTransfer): Promise { + const { clientId, connectionId } = connection + const context = { clientId, connectionId } + + this.logger.log('Send Fireblocks transfer', { ...context, sendTransfer }) + + validateConnection(connection) + + const asset = await this.resolveAsset(sendTransfer.asset) + if (!asset) { + throw new BrokerException({ + message: 'Cannot resolve asset', + suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, + context: { asset: sendTransfer.asset } + }) + } + + const network = await this.networkRepository.findById(asset.networkId) + if (!network) { + throw new BrokerException({ + message: 'Cannot resolve Narval networkId from Anchorage networkId', + suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, + context: { asset } + }) + } + + const source = await this.getSource(connection.clientId, sendTransfer) + const destination = await this.getDestination(connection.clientId, network, sendTransfer.destination) + + this.logger.log('Resolved source and destination', { + ...context, + destination, + source, + networkId: network.networkId + }) + + // NOTE: Defaults the `networkFeeAttribution` to deduct to match most + // blockchain behaviors since Fireblocks API isn't specific about what's + // the default value for `treatAsGrossAmount` parameter. + // + // IMPORTANT: This parameter can only be considered if a transaction’s asset is + // a base asset, such as ETH or MATIC. If the asset can’t be used for + // transaction fees, like USDC, this parameter is ignored and the fee is + // deducted from the relevant base asset wallet in the source account. + // + // See https://developers.fireblocks.com/reference/createtransaction + const networkFeeAttribution = sendTransfer.networkFeeAttribution || NetworkFeeAttribution.DEDUCT + const transferId = sendTransfer.transferId || randomUUID() + const data: CreateTransaction = { + source, + destination, + amount: sendTransfer.amount, + assetId: asset.externalId, + customerRefId: sendTransfer.customerRefId, + externalTxId: transferId, + note: sendTransfer.memo, + treatAsGrossAmount: this.getTreatAsGrossAmount(networkFeeAttribution), + idempotencyKey: sendTransfer.idempotenceId, + ...(isProviderSpecific(sendTransfer.providerSpecific) ? { ...sendTransfer.providerSpecific } : {}) + } + + this.logger.log('Send create transaction request to Fireblocks', { ...context, data }) + + const createTransactionResponse = await this.fireblocksClient.createTransaction({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey, + data + }) + + this.logger.log('Fireblocks transaction created', context) + + const internalTransfer: InternalTransfer = { + // TODO: switch this to the Narval assetId once that is a real thing. + assetId: asset.externalId, + clientId: connection.clientId, + createdAt: new Date(), + customerRefId: sendTransfer.customerRefId || null, + destination: sendTransfer.destination, + externalId: createTransactionResponse.id, + externalStatus: createTransactionResponse.status, + grossAmount: sendTransfer.amount, + idempotenceId: sendTransfer.idempotenceId, + memo: sendTransfer.memo || null, + networkFeeAttribution, + provider: Provider.FIREBLOCKS, + providerSpecific: sendTransfer.providerSpecific || null, + source: sendTransfer.source, + status: this.mapStatus(createTransactionResponse.status), + transferId + } + + this.logger.log('Create internal transfer', internalTransfer) + + await this.transferRepository.bulkCreate([internalTransfer]) + + return internalTransfer + } + + private async resolveAsset(asset: TransferAsset): Promise { + if (asset.externalAssetId) { + return this.fireblocksAssetService.findByExternalId(asset.externalAssetId) + } + + if (asset.assetId) { + // TODO: Look up by the narval assetId; for now we just treat it as the + // same as the Fireblocks one. + return this.fireblocksAssetService.findByExternalId(asset.assetId) + } + + if (!asset.networkId) { + throw new BrokerException({ + message: 'Cannot resolve asset without networkId', + suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, + context: { asset } + }) + } + + if (asset.address) { + return this.fireblocksAssetService.findByOnchainId(asset.networkId, asset.address) + } + + return this.fireblocksAssetService.findNativeAsset(asset.networkId) + } + + /** + * When Fireblocks `treatAsGrossAmount` is set to `true`, the fee will be + * deducted from the requested amount. + * + * Note: This parameter can only be considered if a transaction’s asset is a + * base asset, such as ETH or MATIC. If the asset can’t be used for + * transaction fees, like USDC, this parameter is ignored and the fee is + * deducted from the relevant base asset wallet in the source account. + * + * Example: a request to transfer 5 BTC with `treatAsGrossAmount=false` would + * result in 5 exactly BTC received to the destination and just over 5 BTC + * spent by the source. + * + * @see https://developers.fireblocks.com/reference/createtransaction + */ + private getTreatAsGrossAmount(attribution: NetworkFeeAttribution): boolean { + if (attribution === NetworkFeeAttribution.DEDUCT) { + return true + } + + if (attribution === NetworkFeeAttribution.ON_TOP) { + return false + } + + return false + } + + private async getSource(clientId: string, sendTransfer: SendTransfer) { + if (sendTransfer.source.type === TransferPartyType.ACCOUNT) { + const account = await this.accountService.findById(clientId, sendTransfer.source.id) + + if (account) { + const wallet = await this.walletService.findById(clientId, account.walletId) + + if (wallet) { + return { + type: 'VAULT_ACCOUNT', + id: wallet.externalId + } + } + } + } + + throw new BrokerException({ + message: 'Cannot resolve Fireblocks transfer source', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, + context: { source: sendTransfer.source } + }) + } + + private async getDestination(clientId: string, network: Network, destination: Destination) { + this.logger.log('Resolved Fireblocks destination', { + clientId, + destination, + network: network.networkId + }) + + if (isAddressDestination(destination)) { + const address = await this.addressService.findByAddressAndNetwork( + clientId, + destination.address, + network.networkId + ) + + if (address) { + const account = await this.accountService.findById(clientId, address.accountId) + + if (account) { + const wallet = await this.walletService.findById(clientId, account.walletId) + + if (wallet) { + return { + type: 'VAULT_ACCOUNT', + id: wallet.externalId + } + } + } + } + + return { + type: 'ONE_TIME_ADDRESS', + oneTimeAddress: { + address: destination.address + } + } + } + + if (destination.type === TransferPartyType.ACCOUNT) { + const account = await this.accountService.findById(clientId, destination.id) + + if (account) { + const wallet = await this.walletService.findById(clientId, account.walletId) + + if (wallet) { + return { + type: 'VAULT_ACCOUNT', + id: wallet.externalId + } + } + } + } + + throw new BrokerException({ + message: 'Cannot resolve Fireblocks transfer destination', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, + context: { destination } + }) + } + + private mapStatus(status: string): TransferStatus { + const upperCasedStatus = status.toUpperCase() + + // For FB transaction statuses, see + // https://developers.fireblocks.com/reference/gettransaction + const statuses: Record = { + SUBMITTED: TransferStatus.PROCESSING, + PENDING_AML_SCREENING: TransferStatus.PROCESSING, + PENDING_ENRICHMENT: TransferStatus.PROCESSING, + PENDING_AUTHORIZATION: TransferStatus.PROCESSING, + QUEUED: TransferStatus.PROCESSING, + PENDING_SIGNATURE: TransferStatus.PROCESSING, + PENDING_3RD_PARTY_MANUAL_APPROVAL: TransferStatus.PROCESSING, + PENDING_3RD_PARTY: TransferStatus.PROCESSING, + BROADCASTING: TransferStatus.PROCESSING, + CONFIRMING: TransferStatus.PROCESSING, + CANCELLING: TransferStatus.PROCESSING, + + COMPLETED: TransferStatus.SUCCESS, + + CANCELLED: TransferStatus.FAILED, + BLOCKED: TransferStatus.FAILED, + REJECTED: TransferStatus.FAILED, + FAILED: TransferStatus.FAILED + } + + if (upperCasedStatus in statuses) { + return statuses[upperCasedStatus] + } + + throw new BrokerException({ + message: 'Cannot map Fireblocks transaction status', + suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, + context: { status: upperCasedStatus } + }) + } +} diff --git a/apps/vault/src/broker/core/service/address.service.ts b/apps/vault/src/broker/core/service/address.service.ts index 4a182c2ba..ba3ad4c28 100644 --- a/apps/vault/src/broker/core/service/address.service.ts +++ b/apps/vault/src/broker/core/service/address.service.ts @@ -1,6 +1,7 @@ import { PaginatedResult, PaginationOptions } from '@narval/nestjs-shared' -import { Injectable } from '@nestjs/common' +import { HttpStatus, Injectable } from '@nestjs/common' import { AddressRepository, FindAllOptions } from '../../persistence/repository/address.repository' +import { BrokerException } from '../exception/broker.exception' import { Address } from '../type/indexed-resources.type' @Injectable() @@ -22,4 +23,25 @@ export class AddressService { async findAll(clientId: string, opts?: FindAllOptions): Promise> { return this.addressRepository.findAll(clientId, opts) } + + async findById(clientId: string, addressId: string): Promise
{ + return this.addressRepository.findById(clientId, addressId) + } + + async findByAddressAndNetwork(clientId: string, address: string, networkId: string): Promise
{ + const addresses = await this.addressRepository.findByAddressAndNetwork(clientId, address, networkId) + + if (addresses.length > 1) { + throw new BrokerException({ + message: 'Cannot resolve the right address due to ambiguity', + suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, + context: { + clientId, + addresses: addresses.map(({ address, addressId }) => ({ addressId, address })) + } + }) + } + + return addresses.length ? addresses[0] : null + } } diff --git a/apps/vault/src/broker/core/service/transfer-party.service.ts b/apps/vault/src/broker/core/service/transfer-party.service.ts deleted file mode 100644 index d0c034e58..000000000 --- a/apps/vault/src/broker/core/service/transfer-party.service.ts +++ /dev/null @@ -1,135 +0,0 @@ -import { LoggerService, TraceService } from '@narval/nestjs-shared' -import { HttpStatus, Inject, Injectable } from '@nestjs/common' -import { SpanStatusCode } from '@opentelemetry/api' -import { AccountRepository } from '../../persistence/repository/account.repository' -import { AddressRepository } from '../../persistence/repository/address.repository' -import { KnownDestinationRepository } from '../../persistence/repository/known-destination.repository' -import { WalletRepository } from '../../persistence/repository/wallet.repository' -import { BrokerException } from '../exception/broker.exception' -import { Account, Address, KnownDestination, Wallet } from '../type/indexed-resources.type' -import { Destination, Source, TransferPartyType, isAddressDestination } from '../type/transfer.type' - -@Injectable() -export class TransferPartyService { - constructor( - private readonly walletRepository: WalletRepository, - private readonly accountRepository: AccountRepository, - private readonly addressRepository: AddressRepository, - private readonly knownDestinationRepository: KnownDestinationRepository, - private readonly logger: LoggerService, - @Inject(TraceService) private readonly traceService: TraceService - ) {} - - async resolve( - clientId: string, - transferParty: Source | Destination, - networkId: string - ): Promise { - const span = this.traceService.startSpan(`${TransferPartyService.name}.resolve`) - - try { - return this.findTransferParty(clientId, transferParty, networkId) - } catch (error) { - this.logger.error('Unable to resolve transfer party', { clientId, transferParty, error }) - - span.recordException(error) - span.setStatus({ code: SpanStatusCode.ERROR }) - span.end() - - throw error - } finally { - span.end() - } - } - - private async findTransferParty( - clientId: string, - transferParty: Source | Destination, - networkId: string - ): Promise { - this.logger.log('Find transfer party', { clientId, transferParty }) - - // TODO: Need Network. - if (isAddressDestination(transferParty)) { - const rawAddress = transferParty.address - - this.logger.log('Starting search address destination by raw address', { clientId, rawAddress }) - - const providerAddress = await this.addressRepository.findByAddress(clientId, transferParty.address, networkId) - - if (providerAddress) { - this.logger.log('Successfully found account address destination for raw address', { - clientId, - address: providerAddress - }) - - return providerAddress - } - - this.logger.log('Starting search known destination by raw address', { clientId, rawAddress }) - - const { data: knownDestinations } = await this.knownDestinationRepository.findAll(clientId, { - filters: { - addresses: [transferParty.address], - networksIds: [networkId] - } - }) - - if (knownDestinations.length) { - if (knownDestinations.length > 1) { - throw new BrokerException({ - message: 'Cannot resolve the known destination due to ambiguity', - suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, - context: { - clientId, - addresses: knownDestinations.map(({ address, knownDestinationId }) => ({ knownDestinationId, address })) - } - }) - } - - this.logger.log('Successfully found known destination for raw address', { - clientId, - knownDestination: knownDestinations[0] - }) - - return knownDestinations[0] - } - - throw new BrokerException({ - message: 'Cannot resolve destination address', - suggestedHttpStatusCode: HttpStatus.NOT_FOUND, - context: { clientId, transferParty } - }) - } - - if (transferParty.type === TransferPartyType.WALLET) { - this.logger.log('Starting search for wallet by ID', { clientId, walletId: transferParty.id }) - const wallet = await this.walletRepository.findById(clientId, transferParty.id) - this.logger.log('Successfully found wallet', { clientId, wallet }) - - return wallet - } - - if (transferParty.type === TransferPartyType.ACCOUNT) { - this.logger.log('Starting search for account by ID', { clientId, accountId: transferParty.id }) - const account = await this.accountRepository.findById(clientId, transferParty.id) - this.logger.log('Successfully found account', { clientId, account }) - - return account - } - - if (transferParty.type === TransferPartyType.ADDRESS) { - this.logger.log('Starting search for address by ID', { clientId, addressId: transferParty.id }) - const address = await this.addressRepository.findById(clientId, transferParty.id) - this.logger.log('Successfully found address', { clientId, address }) - - return address - } - - throw new BrokerException({ - message: 'Cannot resolve transfer party type', - suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, - context: { transferParty } - }) - } -} diff --git a/apps/vault/src/broker/core/service/transfer.service.ts b/apps/vault/src/broker/core/service/transfer.service.ts index 0a1fe7af5..c353cb8ba 100644 --- a/apps/vault/src/broker/core/service/transfer.service.ts +++ b/apps/vault/src/broker/core/service/transfer.service.ts @@ -5,19 +5,19 @@ import { TransferRepository } from '../../persistence/repository/transfer.reposi import { OTEL_ATTR_CONNECTION_PROVIDER } from '../../shared/constant' import { BrokerException } from '../exception/broker.exception' import { AnchorageTransferService } from '../provider/anchorage/anchorage-transfer.service' +import { FireblocksTransferService } from '../provider/fireblocks/fireblocks-transfer.service' import { isActiveConnection } from '../type/connection.type' import { Provider, ProviderTransferService } from '../type/provider.type' import { InternalTransfer, SendTransfer } from '../type/transfer.type' import { ConnectionService } from './connection.service' -import { TransferPartyService } from './transfer-party.service' @Injectable() export class TransferService { constructor( private readonly transferRepository: TransferRepository, private readonly connectionService: ConnectionService, - private readonly transferPartyService: TransferPartyService, private readonly anchorageTransferService: AnchorageTransferService, + private readonly fireblocksTransferService: FireblocksTransferService, private readonly logger: LoggerService, @Inject(TraceService) private readonly traceService: TraceService ) {} @@ -47,6 +47,14 @@ export class TransferService { if (isActiveConnection(connection)) { span.setAttribute(OTEL_ATTR_CONNECTION_PROVIDER, connection.provider) + if (await this.transferRepository.existsByIdempotenceId(clientId, sendTransfer.idempotenceId)) { + throw new BrokerException({ + message: 'Transfer idempotence ID already used', + suggestedHttpStatusCode: HttpStatus.CONFLICT, + context: { idempotenceId: sendTransfer.idempotenceId } + }) + } + const transfer = await this.getProviderTransferService(connection.provider).send(connection, sendTransfer) span.end() @@ -71,6 +79,8 @@ export class TransferService { switch (provider) { case Provider.ANCHORAGE: return this.anchorageTransferService + case Provider.FIREBLOCKS: + return this.fireblocksTransferService default: throw new NotImplementedException(`Unsupported transfer for provider ${provider}`) } diff --git a/apps/vault/src/broker/core/service/wallet.service.ts b/apps/vault/src/broker/core/service/wallet.service.ts index 804eb8024..7c3d5aa6e 100644 --- a/apps/vault/src/broker/core/service/wallet.service.ts +++ b/apps/vault/src/broker/core/service/wallet.service.ts @@ -23,7 +23,7 @@ export class WalletService { return this.walletRepository.findAll(clientId, options) } - async findById(clientId: string, accountId: string): Promise { - return this.walletRepository.findById(clientId, accountId) + async findById(clientId: string, walletId: string): Promise { + return this.walletRepository.findById(clientId, walletId) } } diff --git a/apps/vault/src/broker/core/type/provider.type.ts b/apps/vault/src/broker/core/type/provider.type.ts index 807c07afe..276a72250 100644 --- a/apps/vault/src/broker/core/type/provider.type.ts +++ b/apps/vault/src/broker/core/type/provider.type.ts @@ -2,6 +2,7 @@ import { HttpStatus } from '@nestjs/common' import { UpdateAccount } from '../../persistence/repository/account.repository' +import { Asset } from './asset.type' import { ConnectionWithCredentials } from './connection.type' import { Account, Address, KnownDestination, UpdateWallet, Wallet } from './indexed-resources.type' import { InternalTransfer, SendTransfer, Transfer } from './transfer.type' @@ -327,3 +328,15 @@ export interface ProviderCredentialService { */ generate>(options?: Options): Promise } + +// +// Asset +// + +// TODO: still thinking.. +export interface ProviderAssetService { + findAll(): Promise + findByExternalId(externalId: string): Promise + findByOnchainId(networkId: string, onchainId: string): Promise + findNativeAsset(networkId: string): Promise +} diff --git a/apps/vault/src/broker/core/type/transfer.type.ts b/apps/vault/src/broker/core/type/transfer.type.ts index 4882d596c..4bbe35dcc 100644 --- a/apps/vault/src/broker/core/type/transfer.type.ts +++ b/apps/vault/src/broker/core/type/transfer.type.ts @@ -52,31 +52,40 @@ export const TransferAsset = z export type TransferAsset = z.infer export const SendTransfer = z.object({ + transferId: z.string().optional().describe('Sets the transfer ID to an arbitrary value'), source: Source, destination: Destination, amount: z.string(), - - assetId: z.string().optional().describe('@deprecated use asset instead'), // @deprecated use asset instead + /** + * @deprecated use asset instead + */ + assetId: z.string().optional().describe('@deprecated use asset instead'), asset: TransferAsset, - // This is optional on the base transfer and always default on the - // provider-specific transfer service. - networkFeeAttribution: z.nativeEnum(NetworkFeeAttribution).optional(), + networkFeeAttribution: z + .nativeEnum(NetworkFeeAttribution) + .optional() + .describe( + [ + 'Controls how network fees are charged.', + 'Example: a request to transfer 1 ETH with networkFeeAttribution=ON_TOP would result in exactly 1 ETH received to the destination and just over 1 ETH spent by the source.', + 'Note: This property is optional and its default always depend on the underlying provider.' + ].join('\n') + ), customerRefId: z.string().optional(), idempotenceId: z.string(), memo: z.string().optional(), provider: z.nativeEnum(Provider).optional(), - // Requires `provider` to be set. providerSpecific: z.unknown().optional() }) export type SendTransfer = z.infer -export const Fee = z.object({ +export const TransferFee = z.object({ type: z.string(), - attribution: z.string(), + attribution: z.string().optional(), amount: z.string(), assetId: z.string() }) -export type Fee = z.infer +export type TransferFee = z.infer export const TransferStatus = { PROCESSING: 'processing', @@ -92,6 +101,7 @@ export const InternalTransfer = z.object({ customerRefId: z.string().nullable(), destination: Destination, externalId: z.string(), + externalStatus: z.string().nullable(), grossAmount: z.string(), idempotenceId: z.string().nullable(), memo: z.string().nullable(), @@ -116,7 +126,7 @@ export const Transfer = InternalTransfer.extend({ // A transfer always has a status because we check with the provider to // combine the information from the API and the database. status: z.nativeEnum(TransferStatus), - fees: z.array(Fee) + fees: z.array(TransferFee) }) export type Transfer = z.infer diff --git a/apps/vault/src/broker/http/client/__test__/unit/fireblocks.client.spec.ts b/apps/vault/src/broker/http/client/__test__/unit/fireblocks.client.spec.ts index 2a1ade16e..ef45a35cd 100644 --- a/apps/vault/src/broker/http/client/__test__/unit/fireblocks.client.spec.ts +++ b/apps/vault/src/broker/http/client/__test__/unit/fireblocks.client.spec.ts @@ -117,12 +117,11 @@ describe(FireblocksClient.name, () => { }) // Check header structure - expect(result.headers).toHaveProperty('X-API-Key', 'test-api-key') - expect(result.headers).toHaveProperty('Authorization') + expect(result.headers).toHaveProperty('x-api-key', 'test-api-key') + expect(result.headers).toHaveProperty('authorization') // Verify the Bearer token format - const authHeader = result.headers?.Authorization - expect(authHeader).toMatch(/^Bearer [A-Za-z0-9-_=]+\.[A-Za-z0-9-_=]+\.[A-Za-z0-9-_.+/=]+$/) + expect(result.headers?.authorization).toMatch(/^Bearer [A-Za-z0-9-_=]+\.[A-Za-z0-9-_=]+\.[A-Za-z0-9-_.+/=]+$/) }) it('creates valid authorization headers for POST request with data', async () => { @@ -141,8 +140,8 @@ describe(FireblocksClient.name, () => { }) // Verify the basic structure stays the same for POST - expect(result.headers).toHaveProperty('X-API-Key', 'test-api-key') - expect(result.headers?.Authorization).toMatch(/^Bearer [A-Za-z0-9-_=]+\.[A-Za-z0-9-_=]+\.[A-Za-z0-9-_.+/=]+$/) + expect(result.headers).toHaveProperty('x-api-key', 'test-api-key') + expect(result.headers?.authorization).toMatch(/^Bearer [A-Za-z0-9-_=]+\.[A-Za-z0-9-_=]+\.[A-Za-z0-9-_.+/=]+$/) // Verify the data is properly set in the request expect(result.data).toEqual(requestData) diff --git a/apps/vault/src/broker/http/client/anchorage.client.ts b/apps/vault/src/broker/http/client/anchorage.client.ts index b1313f1f7..bbfc23990 100644 --- a/apps/vault/src/broker/http/client/anchorage.client.ts +++ b/apps/vault/src/broker/http/client/anchorage.client.ts @@ -342,7 +342,7 @@ export class AnchorageClient { switchMap((signedRequest) => this.httpService.request(signedRequest).pipe( tap((response) => { - this.logger.log('Received response', { + this.logger.log('Received Anchorage response', { url: opts.request.url, method: opts.request.method, nextPage: response.data?.page?.next @@ -405,7 +405,7 @@ export class AnchorageClient { }), reduce((vaults: Vault[], response) => [...vaults, ...response.data], []), tap((vaults) => { - this.logger.log('Completed fetching all vaults', { + this.logger.log('Completed fetching all Anchorage vaults', { vaultsCount: vaults.length, url: opts.url }) @@ -457,7 +457,7 @@ export class AnchorageClient { }), reduce((wallets: Wallet[], response) => [...wallets, ...response.data], []), tap((wallets) => { - this.logger.log('Completed fetching all wallets', { + this.logger.log('Completed fetching all Anchorage wallets', { url, walletsCount: wallets.length }) @@ -511,7 +511,7 @@ export class AnchorageClient { }), reduce((trustedDestinations: TrustedDestination[], response) => [...trustedDestinations, ...response.data], []), tap((trustedDestinations) => { - this.logger.log('Completed fetching all trusted-destinations', { + this.logger.log('Completed fetching all Anchorage trusted-destinations', { trustedDestinationsCount: trustedDestinations.length, url: opts.url }) @@ -574,7 +574,7 @@ export class AnchorageClient { }), reduce((addresses: Address[], response) => [...addresses, ...response.data], []), tap((addresses) => { - this.logger.log('Completed fetching all vault addresses', { + this.logger.log('Completed fetching all Anchorage vault addresses', { addressesCount: addresses.length, vaultId, assetType, @@ -603,7 +603,7 @@ export class AnchorageClient { }).pipe( map((response) => response.data), tap((transfer) => { - this.logger.log('Successfully fetched transfer', { + this.logger.log('Successfully fetched Anchorage transfer', { transferId, url, status: transfer.status @@ -617,7 +617,7 @@ export class AnchorageClient { async createTransfer(opts: RequestOptions & { data: CreateTransfer }): Promise { const { apiKey, signKey, url, data } = opts - this.logger.log('Sending create transfer in request to Anchorage', { data }) + this.logger.log('Sending create transfer request to Anchorage', { url, data }) return lastValueFrom( this.sendSignedRequest({ @@ -632,7 +632,7 @@ export class AnchorageClient { }).pipe( map((response) => response.data), tap((transfer) => { - this.logger.log('Successfully created transfer', { + this.logger.log('Successfully created Anchorage transfer', { transferId: transfer.transferId, url }) diff --git a/apps/vault/src/broker/http/client/fireblocks.client.ts b/apps/vault/src/broker/http/client/fireblocks.client.ts index 3cddadb37..985acab51 100644 --- a/apps/vault/src/broker/http/client/fireblocks.client.ts +++ b/apps/vault/src/broker/http/client/fireblocks.client.ts @@ -151,6 +151,116 @@ export type WhitelistedWallet = z.infer const GetWhitelistedWalletsResponse = z.array(WhitelistedWallet) type GetWhitelistedWalletsResponse = z.infer +const TransactionAmountInfo = z.object({ + amount: z.string(), + requestedAmount: z.string(), + netAmount: z.string().optional(), + amountUSD: z.string() +}) + +const TransactionFeeInfo = z.object({ + networkFee: z.string().optional(), + gasPrice: z.string().optional() +}) +export type TransactionFeeInfo = z.infer + +const TransactionBlockInfo = z.object({ + blockHeight: z.string().optional(), + blockHash: z.string().nullable() +}) + +const TransactionParty = z.object({ + id: z.string().nullable(), + type: z.string(), + name: z.string().optional(), + subType: z.string() +}) + +const Transaction = z.object({ + addressType: z.string(), + amount: z.number(), + amountInfo: TransactionAmountInfo, + amountUSD: z.number(), + assetId: z.string(), + assetType: z.string(), + blockInfo: TransactionBlockInfo, + createdAt: z.number(), + createdBy: z.string(), + destination: TransactionParty, + destinationAddress: z.string(), + destinationAddressDescription: z.string(), + destinationTag: z.string(), + destinations: z.array(z.unknown()), + exchangeTxId: z.string(), + fee: z.number(), + feeCurrency: z.string(), + feeInfo: TransactionFeeInfo, + id: z.string(), + index: z.number().optional(), + lastUpdated: z.number(), + netAmount: z.number(), + networkFee: z.number(), + note: z.string(), + numOfConfirmations: z.number().optional(), + operation: z.string(), + rejectedBy: z.string(), + requestedAmount: z.number(), + signedBy: z.array(z.string()), + signedMessages: z.array(z.unknown()), + source: TransactionParty, + sourceAddress: z.string(), + status: z.string(), + subStatus: z.string(), + txHash: z.string() +}) +export type Transaction = z.infer + +const CreateTransactionResponse = z.object({ + id: z.string(), + status: z.string() +}) +type CreateTransactionResponse = z.infer + +interface RequestParams { + apiKey: string + signKey: RsaPrivateKey + url: string +} + +// IMPORTANT: These aren't all FB create transaction parameters. +// See https://developers.fireblocks.com/reference/createtransaction +export interface CreateTransaction { + amount: string + operation?: string + note?: string + externalTxId?: string + assetId: string + source: { + type: string + id?: string + } + destination: { + type: string + id?: string + oneTimeAddress?: { + address: string + } + } + treatAsGrossAmount?: boolean + feeLevel?: string + priorityFee?: string + failOnLowFee?: boolean + maxFee?: string + gasLimit?: string + gasPrice?: string + networkFee?: string + replaceTxByHash?: string + customerRefId?: string + useGasless?: boolean + // Headers + idempotencyKey?: string + requestId?: string +} @Injectable() export class FireblocksClient { constructor( @@ -199,7 +309,8 @@ export class FireblocksClient { const exp = now + 30 - const bodyHash = request.data ? toHex(sha256(JSON.stringify(request.data))).slice(2) : undefined + const bodyHash = this.getBodyHash(request) + const payload = { uri, nonce: opts.nonce || v4(), @@ -212,8 +323,9 @@ export class FireblocksClient { const token = await signJwt(payload, signKey) const headers = { - 'X-API-Key': apiKey, - Authorization: `Bearer ${token}` + ...(request.headers ? request.headers : {}), + 'x-api-key': apiKey, + authorization: `Bearer ${token}` } const data = request.data && request.method !== 'GET' ? request.data : undefined @@ -225,6 +337,19 @@ export class FireblocksClient { } } + /** + * Returns a hex-encoded SHA-256 hash of the raw HTTP request body. + * + * @see https://developers.fireblocks.com/reference/signing-a-request-jwt-structure#jwt-structure + */ + getBodyHash(request: AxiosRequestConfig): string { + if (request.data) { + return toHex(sha256(JSON.stringify(request.data))).slice(2) + } + + return '' + } + parseEndpoint(url: string): string { const regex = /(\/v\d+(?:\/.*)?)$/ const match = url.match(regex) @@ -245,7 +370,7 @@ export class FireblocksClient { if (error instanceof AxiosError) { throw new ProviderHttpException({ - provider: Provider.ANCHORAGE, + provider: Provider.FIREBLOCKS, origin: error, response: { status: error.response?.status ?? HttpStatus.INTERNAL_SERVER_ERROR, @@ -293,10 +418,11 @@ export class FireblocksClient { switchMap((signedRequest) => this.httpService.request(signedRequest).pipe( tap((response) => { - this.logger.log('Received response', { + this.logger.log('Received Fireblocks response', { url: opts.request.url, method: opts.request.method, - nextPage: response.data?.paging?.after + nextPage: response.data?.paging?.after, + body: response.data || null }) }), map((response) => opts.schema.parse(response.data)) @@ -583,4 +709,65 @@ export class FireblocksClient { ) ) } + + async createTransaction(params: RequestParams & { data: CreateTransaction }): Promise { + const { apiKey, signKey, url } = params + const { idempotencyKey, ...data } = params.data + + this.logger.log('Sending create transaction request to Fireblocks', { url, data: params.data }) + + return lastValueFrom( + this.sendSignedRequest({ + schema: CreateTransactionResponse, + request: { + url: `${url}/v1/transactions`, + method: 'POST', + data, + ...(idempotencyKey + ? { + headers: { + 'idempotency-key': idempotencyKey + } + } + : {}) + }, + apiKey, + signKey + }).pipe( + tap((tx) => { + this.logger.log('Successfully created Fireblocks transaction', { + transactionId: tx.id, + url + }) + }), + this.handleError('Failed to create Fireblocks transaction') + ) + ) + } + + async getTransactionById(params: RequestParams & { txId: string }): Promise { + const { apiKey, signKey, url, txId } = params + + this.logger.log('Request Fireblocks transaction by ID', { url, txId }) + + return lastValueFrom( + this.sendSignedRequest({ + schema: Transaction, + request: { + url: `${url}/v1/transactions/${txId}`, + method: 'GET' + }, + apiKey, + signKey + }).pipe( + tap((tx) => { + this.logger.log('Successfully got Fireblocks transaction', { + transactionId: tx.id, + url + }) + }), + this.handleError('Failed to get Fireblocks transaction by ID') + ) + ) + } } diff --git a/apps/vault/src/broker/http/rest/dto/request/send-transfer.dto.ts b/apps/vault/src/broker/http/rest/dto/request/send-transfer.dto.ts index 1fd8c8170..74426019e 100644 --- a/apps/vault/src/broker/http/rest/dto/request/send-transfer.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/request/send-transfer.dto.ts @@ -1,4 +1,4 @@ import { createZodDto } from 'nestjs-zod' import { SendTransfer } from '../../../../core/type/transfer.type' -export class SendTransferDto extends createZodDto(SendTransfer) {} +export class SendTransferDto extends createZodDto(SendTransfer.omit({ transferId: true })) {} diff --git a/apps/vault/src/broker/persistence/repository/address.repository.ts b/apps/vault/src/broker/persistence/repository/address.repository.ts index cd8126346..b14f9d497 100644 --- a/apps/vault/src/broker/persistence/repository/address.repository.ts +++ b/apps/vault/src/broker/persistence/repository/address.repository.ts @@ -1,9 +1,8 @@ import { PaginatedResult, PaginationOptions, applyPagination, getPaginatedResult } from '@narval/nestjs-shared' -import { HttpStatus, Injectable } from '@nestjs/common' +import { Injectable } from '@nestjs/common' import { ProviderAddress } from '@prisma/client/vault' import { z } from 'zod' import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' -import { BrokerException } from '../../core/exception/broker.exception' import { NotFoundException } from '../../core/exception/not-found.exception' import { Address } from '../../core/type/indexed-resources.type' import { Provider } from '../../core/type/provider.type' @@ -25,11 +24,11 @@ export class AddressRepository { static parseModel(model: ProviderAddress): Address { const { id, ...rest } = model - return { + return Address.parse({ ...rest, addressId: id, provider: z.nativeEnum(Provider).parse(model.provider) - } + }) } static parseEntity(entity: Address): ProviderAddress { @@ -75,8 +74,8 @@ export class AddressRepository { return AddressRepository.parseModel(address) } - async findByAddress(clientId: string, address: string, networkId: string): Promise
{ - const providerAddresses = await this.prismaService.providerAddress.findMany({ + async findByAddressAndNetwork(clientId: string, address: string, networkId: string): Promise { + const models = await this.prismaService.providerAddress.findMany({ where: { clientId, address, @@ -86,18 +85,7 @@ export class AddressRepository { } }) - if (providerAddresses.length > 1) { - throw new BrokerException({ - message: 'Cannot resolve the right address due to ambiguity', - suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, - context: { - clientId, - addresses: providerAddresses.map(({ address, id }) => ({ addressId: id, address })) - } - }) - } - - return providerAddresses.length ? AddressRepository.parseModel(providerAddresses[0]) : null + return models.map(AddressRepository.parseModel) } async findAll(clientId: string, opts?: FindAllOptions): Promise> { diff --git a/apps/vault/src/broker/persistence/repository/transfer.repository.ts b/apps/vault/src/broker/persistence/repository/transfer.repository.ts index 76598cd0b..a71e14936 100644 --- a/apps/vault/src/broker/persistence/repository/transfer.repository.ts +++ b/apps/vault/src/broker/persistence/repository/transfer.repository.ts @@ -84,6 +84,8 @@ export class TransferRepository { createdAt: model.createdAt, customerRefId: model.customerRefId, externalId: model.externalId, + // The external status is added at runtime. + externalStatus: null, grossAmount: model.grossAmount, idempotenceId: model.idempotenceId, memo: model.memo, @@ -170,4 +172,12 @@ export class TransferRepository { context: { transferId } }) } + + async existsByIdempotenceId(clientId: string, idempotenceId: string): Promise { + const count = await this.prismaService.providerTransfer.count({ + where: { clientId, idempotenceId } + }) + + return count > 0 + } } From b42048c0ad3a3ec17eafb890042fa1e05c23ada9 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Fri, 17 Jan 2025 10:47:50 +0100 Subject: [PATCH 095/120] Fix Fireblocks transaction type (#85) --- apps/vault/src/broker/http/client/fireblocks.client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/vault/src/broker/http/client/fireblocks.client.ts b/apps/vault/src/broker/http/client/fireblocks.client.ts index 985acab51..6c05108a4 100644 --- a/apps/vault/src/broker/http/client/fireblocks.client.ts +++ b/apps/vault/src/broker/http/client/fireblocks.client.ts @@ -183,7 +183,7 @@ const Transaction = z.object({ amountUSD: z.number(), assetId: z.string(), assetType: z.string(), - blockInfo: TransactionBlockInfo, + blockInfo: TransactionBlockInfo.optional(), createdAt: z.number(), createdBy: z.string(), destination: TransactionParty, From d827d52a9c9f65e329ed99cfb3698b07a927f3ec Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Fri, 17 Jan 2025 11:24:39 +0100 Subject: [PATCH 096/120] Fix Fireblocks block hash type (#87) --- apps/vault/src/broker/http/client/fireblocks.client.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/vault/src/broker/http/client/fireblocks.client.ts b/apps/vault/src/broker/http/client/fireblocks.client.ts index 6c05108a4..40e807f12 100644 --- a/apps/vault/src/broker/http/client/fireblocks.client.ts +++ b/apps/vault/src/broker/http/client/fireblocks.client.ts @@ -166,7 +166,7 @@ export type TransactionFeeInfo = z.infer const TransactionBlockInfo = z.object({ blockHeight: z.string().optional(), - blockHash: z.string().nullable() + blockHash: z.string().optional() }) const TransactionParty = z.object({ @@ -183,7 +183,7 @@ const Transaction = z.object({ amountUSD: z.number(), assetId: z.string(), assetType: z.string(), - blockInfo: TransactionBlockInfo.optional(), + blockInfo: TransactionBlockInfo, createdAt: z.number(), createdBy: z.string(), destination: TransactionParty, From 68e4243b0cbff68e30e1f234153dee52421edd16 Mon Sep 17 00:00:00 2001 From: Matt Schoch Date: Fri, 17 Jan 2025 17:16:06 +0100 Subject: [PATCH 097/120] Hotfix - pagination query params were breaking request signing --- .../__test__/unit/anchorage.client.spec.ts | 13 +++++++++++++ .../src/broker/http/client/anchorage.client.ts | 16 ++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/apps/vault/src/broker/http/client/__test__/unit/anchorage.client.spec.ts b/apps/vault/src/broker/http/client/__test__/unit/anchorage.client.spec.ts index 7e246099d..d9acfea99 100644 --- a/apps/vault/src/broker/http/client/__test__/unit/anchorage.client.spec.ts +++ b/apps/vault/src/broker/http/client/__test__/unit/anchorage.client.spec.ts @@ -95,6 +95,19 @@ describe(AnchorageClient.name, () => { expect(client.buildSignatureMessage(request, nowTimestamp)).toEqual(`${nowTimestamp}POST/v2/accounts?foo=bar`) }) + it('adds params as query string even if the url already has query params', () => { + const request: AxiosRequestConfig = { + method: 'POST', + url: '/v2/accounts?after=first', + data: undefined, + params: { foo: 'bar' } + } + + expect(client.buildSignatureMessage(request, nowTimestamp)).toEqual( + `${nowTimestamp}POST/v2/accounts?after=first&foo=bar` + ) + }) + it('does not add ? to the url when params is defined with undefined items', () => { const request: AxiosRequestConfig = { method: 'POST', diff --git a/apps/vault/src/broker/http/client/anchorage.client.ts b/apps/vault/src/broker/http/client/anchorage.client.ts index bbfc23990..5a6c868ab 100644 --- a/apps/vault/src/broker/http/client/anchorage.client.ts +++ b/apps/vault/src/broker/http/client/anchorage.client.ts @@ -320,8 +320,20 @@ export class AnchorageClient { const endpoint = this.parseEndpoint(request.url) const method = request.method.toUpperCase() - const queryParams = new URLSearchParams(omitBy(request.params, isNil)).toString() - const path = queryParams ? `${endpoint}?${queryParams}` : endpoint + + // Parse existing query params from the endpoint + const [endpointPath, existingParams] = endpoint.split('?') + const searchParams = new URLSearchParams(existingParams || '') + + // Add additional params from request.params + if (request.params) { + Object.entries(omitBy(request.params, isNil)).forEach(([key, value]) => { + searchParams.append(key, String(value)) + }) + } + + const queryString = searchParams.toString() + const path = queryString ? `${endpointPath}?${queryString}` : endpointPath return `${timestamp}${method}${path}${request.data && method !== 'GET' ? JSON.stringify(request.data) : ''}` } From bf72bcc82aa6b4e209028870544f8709a92b01d9 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Mon, 20 Jan 2025 11:33:06 +0100 Subject: [PATCH 098/120] Unified asset list (#89) * Add unified asset list * Correct migration * Remove Fireblocks and Anchorage asset services * Remove unused interface * Fix network seed * List USDT and USDC on Polygon and Arbitrum * Replace old asset type by next * Replace unique key by ID in the provider asset * Replace provider network unique key by ID --- .../src/broker/__test__/e2e/asset.spec.ts | 43 +- .../src/broker/__test__/e2e/network.spec.ts | 4 +- .../src/broker/__test__/e2e/transfer.spec.ts | 17 +- apps/vault/src/broker/broker.module.ts | 13 +- .../core/exception/ambiguity.exception.ts | 13 + .../broker/core/exception/asset.exception.ts | 13 + .../anchorage-transfer.service.spec.ts | 4 + .../anchorage/anchorage-asset.service.ts | 2706 ---- .../anchorage/anchorage-transfer.service.ts | 59 +- .../fireblocks-transfer.service.spec.ts | 17 +- .../fireblocks/fireblocks-asset.service.ts | 10720 ---------------- .../fireblocks/fireblocks-transfer.service.ts | 60 +- .../integration/asset.service.spec.ts | 193 + .../src/broker/core/service/asset.service.ts | 97 + apps/vault/src/broker/core/type/asset.type.ts | 14 +- .../src/broker/core/type/provider.type.ts | 13 - apps/vault/src/broker/core/util/asset.util.ts | 10 + .../http/rest/controller/asset.controller.ts | 36 +- .../rest/controller/network.controller.ts | 8 +- .../{provider-asset.dto.ts => asset.dto.ts} | 8 +- ...provider-network.dto.ts => network.dto.ts} | 2 +- .../repository/asset.repository.ts | 196 + .../src/broker/persistence/seed/asset.seed.ts | 389 + .../broker/persistence/seed/network.seed.ts | 77 +- .../module/persistence/persistence.module.ts | 1 + .../migration.sql | 135 + .../migration.sql | 5 + .../module/persistence/schema/schema.prisma | 33 +- 28 files changed, 1247 insertions(+), 13639 deletions(-) create mode 100644 apps/vault/src/broker/core/exception/ambiguity.exception.ts create mode 100644 apps/vault/src/broker/core/exception/asset.exception.ts delete mode 100644 apps/vault/src/broker/core/provider/anchorage/anchorage-asset.service.ts delete mode 100644 apps/vault/src/broker/core/provider/fireblocks/fireblocks-asset.service.ts create mode 100644 apps/vault/src/broker/core/service/__test__/integration/asset.service.spec.ts create mode 100644 apps/vault/src/broker/core/service/asset.service.ts create mode 100644 apps/vault/src/broker/core/util/asset.util.ts rename apps/vault/src/broker/http/rest/dto/response/{provider-asset.dto.ts => asset.dto.ts} (58%) rename apps/vault/src/broker/http/rest/dto/response/{provider-network.dto.ts => network.dto.ts} (85%) create mode 100644 apps/vault/src/broker/persistence/repository/asset.repository.ts create mode 100644 apps/vault/src/broker/persistence/seed/asset.seed.ts create mode 100644 apps/vault/src/shared/module/persistence/schema/migrations/20250120095438_add_asset_table_and_data/migration.sql create mode 100644 apps/vault/src/shared/module/persistence/schema/migrations/20250120095738_replace_network_provider_unique_key_by_id/migration.sql diff --git a/apps/vault/src/broker/__test__/e2e/asset.spec.ts b/apps/vault/src/broker/__test__/e2e/asset.spec.ts index 86928d9b9..00d629ee0 100644 --- a/apps/vault/src/broker/__test__/e2e/asset.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/asset.spec.ts @@ -11,10 +11,11 @@ import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/per import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' import { Provider } from '../../core/type/provider.type' +import { AssetDto } from '../../http/rest/dto/response/asset.dto' +import { AssetSeed } from '../../persistence/seed/asset.seed' import { NetworkSeed } from '../../persistence/seed/network.seed' import { TEST_CLIENT_ID, getJwsd, testClient, testUserPrivateJwk } from '../util/mock-data' -import { ProviderAssetDto } from '../../http/rest/dto/response/provider-asset.dto' import '../../shared/__test__/matcher' describe('Asset', () => { @@ -24,6 +25,7 @@ describe('Asset', () => { let provisionService: ProvisionService let clientService: ClientService let networkSeed: NetworkSeed + let assetSeed: AssetSeed beforeAll(async () => { module = await Test.createTestingModule({ @@ -43,6 +45,7 @@ describe('Asset', () => { clientService = module.get(ClientService) networkSeed = module.get(NetworkSeed) + assetSeed = module.get(AssetSeed) provisionService = module.get(ProvisionService) testPrismaService = module.get(TestPrismaService) @@ -61,6 +64,7 @@ describe('Asset', () => { await clientService.save(testClient) await networkSeed.seed() + await assetSeed.seed() await app.init() }) @@ -81,45 +85,10 @@ describe('Asset', () => { }) ) - expect(body).toMatchZodSchema(ProviderAssetDto.schema) + expect(body).toMatchZodSchema(AssetDto.schema) expect(status).toEqual(HttpStatus.OK) }) - it('returns 400 when provider parameter is missing', async () => { - const { status } = await request(app.getHttpServer()) - .get('/provider/assets') - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/assets', - payload: {}, - htm: 'GET' - }) - ) - - expect(status).toEqual(HttpStatus.BAD_REQUEST) - }) - - it('returns 400 when provider is invalid', async () => { - const { status } = await request(app.getHttpServer()) - .get('/provider/assets') - .query({ provider: 'INVALID' }) - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/assets?provider=INVALID', - payload: {}, - htm: 'GET' - }) - ) - - expect(status).toEqual(HttpStatus.BAD_REQUEST) - }) - it('returns different assets for different providers', async () => { const anchorageResponse = await request(app.getHttpServer()) .get('/provider/assets') diff --git a/apps/vault/src/broker/__test__/e2e/network.spec.ts b/apps/vault/src/broker/__test__/e2e/network.spec.ts index 3f10fd55b..411d6bb77 100644 --- a/apps/vault/src/broker/__test__/e2e/network.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/network.spec.ts @@ -10,10 +10,10 @@ import { KeyValueRepository } from '../../../shared/module/key-value/core/reposi import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' +import { NetworkDto } from '../../http/rest/dto/response/network.dto' import { NetworkSeed } from '../../persistence/seed/network.seed' import { TEST_CLIENT_ID, getJwsd, testClient, testUserPrivateJwk } from '../util/mock-data' -import { ProviderNetworkDto } from '../../http/rest/dto/response/provider-network.dto' import '../../shared/__test__/matcher' describe('Network', () => { @@ -80,7 +80,7 @@ describe('Network', () => { }) ) - expect(body).toMatchZodSchema(ProviderNetworkDto.schema) + expect(body).toMatchZodSchema(NetworkDto.schema) expect(body.data).toHaveLength(networkSeed.getNetworks().length) expect(status).toEqual(HttpStatus.OK) }) diff --git a/apps/vault/src/broker/__test__/e2e/transfer.spec.ts b/apps/vault/src/broker/__test__/e2e/transfer.spec.ts index d2824d218..1b83a1888 100644 --- a/apps/vault/src/broker/__test__/e2e/transfer.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/transfer.spec.ts @@ -31,6 +31,7 @@ import { AccountRepository } from '../../persistence/repository/account.reposito import { ConnectionRepository } from '../../persistence/repository/connection.repository' import { TransferRepository } from '../../persistence/repository/transfer.repository' import { WalletRepository } from '../../persistence/repository/wallet.repository' +import { AssetSeed } from '../../persistence/seed/asset.seed' import { NetworkSeed } from '../../persistence/seed/network.seed' import { setupMockServer } from '../../shared/__test__/mock-server' import { REQUEST_HEADER_CONNECTION_ID } from '../../shared/constant' @@ -48,6 +49,7 @@ describe('Transfer', () => { let accountRepository: AccountRepository let connectionRepository: ConnectionRepository let networkSeed: NetworkSeed + let assetSeed: AssetSeed let transferRepository: TransferRepository let walletRepository: WalletRepository @@ -164,15 +166,15 @@ describe('Transfer', () => { app = module.createNestApplication() - testPrismaService = module.get(TestPrismaService) - provisionService = module.get(ProvisionService) + accountRepository = module.get(AccountRepository) + assetSeed = module.get(AssetSeed) clientService = module.get(ClientService) - - transferRepository = module.get(TransferRepository) connectionRepository = module.get(ConnectionRepository) - walletRepository = module.get(WalletRepository) - accountRepository = module.get(AccountRepository) networkSeed = module.get(NetworkSeed) + provisionService = module.get(ProvisionService) + testPrismaService = module.get(TestPrismaService) + transferRepository = module.get(TransferRepository) + walletRepository = module.get(WalletRepository) await testPrismaService.truncateAll() }) @@ -195,6 +197,7 @@ describe('Transfer', () => { await transferRepository.bulkCreate([internalTransfer]) await networkSeed.seed() + await assetSeed.seed() await app.init() }) @@ -214,7 +217,7 @@ describe('Transfer', () => { }, amount: '0.0001', asset: { - assetId: 'BTC_S' + assetId: 'BTC' }, idempotenceId: uuid() } diff --git a/apps/vault/src/broker/broker.module.ts b/apps/vault/src/broker/broker.module.ts index 6eb557479..87e7d6778 100644 --- a/apps/vault/src/broker/broker.module.ts +++ b/apps/vault/src/broker/broker.module.ts @@ -10,18 +10,17 @@ import { PersistenceModule } from '../shared/module/persistence/persistence.modu import { EncryptionKeyService } from '../transit-encryption/core/service/encryption-key.service' import { EncryptionKeyRepository } from '../transit-encryption/persistence/encryption-key.repository' import { TransitEncryptionModule } from '../transit-encryption/transit-encryption.module' -import { AnchorageAssetService } from './core/provider/anchorage/anchorage-asset.service' import { AnchorageCredentialService } from './core/provider/anchorage/anchorage-credential.service' import { AnchorageProxyService } from './core/provider/anchorage/anchorage-proxy.service' import { AnchorageSyncService } from './core/provider/anchorage/anchorage-sync.service' import { AnchorageTransferService } from './core/provider/anchorage/anchorage-transfer.service' -import { FireblocksAssetService } from './core/provider/fireblocks/fireblocks-asset.service' import { FireblocksCredentialService } from './core/provider/fireblocks/fireblocks-credential.service' import { FireblocksProxyService } from './core/provider/fireblocks/fireblocks-proxy.service' import { FireblocksSyncService } from './core/provider/fireblocks/fireblocks-sync.service' import { FireblocksTransferService } from './core/provider/fireblocks/fireblocks-transfer.service' import { AccountService } from './core/service/account.service' import { AddressService } from './core/service/address.service' +import { AssetService } from './core/service/asset.service' import { ConnectionService } from './core/service/connection.service' import { KnownDestinationService } from './core/service/known-destination.service' import { ProxyService } from './core/service/proxy.service' @@ -43,15 +42,17 @@ import { TransferController } from './http/rest/controller/transfer.controller' import { ProviderWalletController } from './http/rest/controller/wallet.controller' import { AccountRepository } from './persistence/repository/account.repository' import { AddressRepository } from './persistence/repository/address.repository' +import { AssetRepository } from './persistence/repository/asset.repository' import { ConnectionRepository } from './persistence/repository/connection.repository' import { KnownDestinationRepository } from './persistence/repository/known-destination.repository' import { NetworkRepository } from './persistence/repository/network.repository' import { SyncRepository } from './persistence/repository/sync.repository' import { TransferRepository } from './persistence/repository/transfer.repository' import { WalletRepository } from './persistence/repository/wallet.repository' +import { AssetSeed } from './persistence/seed/asset.seed' import { NetworkSeed } from './persistence/seed/network.seed' -const SEEDS = [NetworkSeed] +const SEEDS = [NetworkSeed, AssetSeed] @Module({ imports: [ @@ -81,24 +82,24 @@ const SEEDS = [NetworkSeed] provide: APP_FILTER, useClass: ProviderHttpExceptionFilter }, + FireblocksCredentialService, AccountRepository, AccountService, AddressRepository, AddressService, - AnchorageAssetService, AnchorageClient, AnchorageCredentialService, AnchorageProxyService, AnchorageSyncService, AnchorageTransferService, + AssetRepository, + AssetService, ConnectionRepository, ConnectionService, ConnectionSyncEventHandler, EncryptionKeyRepository, EncryptionKeyService, - FireblocksAssetService, FireblocksClient, - FireblocksCredentialService, FireblocksProxyService, FireblocksSyncService, FireblocksTransferService, diff --git a/apps/vault/src/broker/core/exception/ambiguity.exception.ts b/apps/vault/src/broker/core/exception/ambiguity.exception.ts new file mode 100644 index 000000000..15c7e6742 --- /dev/null +++ b/apps/vault/src/broker/core/exception/ambiguity.exception.ts @@ -0,0 +1,13 @@ +import { HttpStatus } from '@nestjs/common' +import { ApplicationExceptionParams } from '../../../shared/exception/application.exception' +import { BrokerException } from './broker.exception' + +export class AmbiguityException extends BrokerException { + constructor(params?: Partial) { + super({ + message: params?.message || 'Cannot resolve request due to data ambiguity', + suggestedHttpStatusCode: params?.suggestedHttpStatusCode || HttpStatus.INTERNAL_SERVER_ERROR, + ...params + }) + } +} diff --git a/apps/vault/src/broker/core/exception/asset.exception.ts b/apps/vault/src/broker/core/exception/asset.exception.ts new file mode 100644 index 000000000..aca4f9fc7 --- /dev/null +++ b/apps/vault/src/broker/core/exception/asset.exception.ts @@ -0,0 +1,13 @@ +import { HttpStatus } from '@nestjs/common' +import { ApplicationExceptionParams } from '../../../shared/exception/application.exception' +import { BrokerException } from './broker.exception' + +export class AssetException extends BrokerException { + constructor(params?: Partial) { + super({ + message: params?.message || 'Asset exception', + suggestedHttpStatusCode: params?.suggestedHttpStatusCode || HttpStatus.INTERNAL_SERVER_ERROR, + ...params + }) + } +} diff --git a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts index f9f224969..cbfa323de 100644 --- a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts +++ b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts @@ -19,6 +19,7 @@ import { ConnectionRepository } from '../../../../../persistence/repository/conn import { KnownDestinationRepository } from '../../../../../persistence/repository/known-destination.repository' import { TransferRepository } from '../../../../../persistence/repository/transfer.repository' import { WalletRepository } from '../../../../../persistence/repository/wallet.repository' +import { AssetSeed } from '../../../../../persistence/seed/asset.seed' import { NetworkSeed } from '../../../../../persistence/seed/network.seed' import { setupMockServer, useRequestSpy } from '../../../../../shared/__test__/mock-server' import { Connection, ConnectionStatus, ConnectionWithCredentials } from '../../../../type/connection.type' @@ -41,6 +42,7 @@ describe(AnchorageTransferService.name, () => { let accountRepository: AccountRepository let addressRepository: AddressRepository let anchorageTransferService: AnchorageTransferService + let assetSeed: AssetSeed let clientService: ClientService let connectionRepository: ConnectionRepository let knownDestinationRepository: KnownDestinationRepository @@ -187,6 +189,7 @@ describe(AnchorageTransferService.name, () => { accountRepository = module.get(AccountRepository) addressRepository = module.get(AddressRepository) + assetSeed = module.get(AssetSeed) connectionRepository = module.get(ConnectionRepository) knownDestinationRepository = module.get(KnownDestinationRepository) networkSeed = module.get(NetworkSeed) @@ -208,6 +211,7 @@ describe(AnchorageTransferService.name, () => { await provisionService.provision() await clientService.save(testClient) await networkSeed.seed() + await assetSeed.seed() await connectionRepository.create(connection) await walletRepository.bulkCreate([wallet]) diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage-asset.service.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage-asset.service.ts deleted file mode 100644 index b9fb37fa8..000000000 --- a/apps/vault/src/broker/core/provider/anchorage/anchorage-asset.service.ts +++ /dev/null @@ -1,2706 +0,0 @@ -import { LoggerService } from '@narval/nestjs-shared' -import { Injectable } from '@nestjs/common' -import { NetworkRepository } from '../../../persistence/repository/network.repository' -import { Asset } from '../../type/asset.type' -import { Network } from '../../type/network.type' -import { Provider } from '../../type/provider.type' -import { getExternalNetwork } from '../../util/network.util' - -type AnchorageAsset = { - assetType: string - decimals: number - name: string - networkId: string - onchainIdentifier?: string -} - -const ANCHORAGE_ASSETS: AnchorageAsset[] = [ - { - assetType: '1INCH', - decimals: 18, - name: '1inch', - networkId: 'ETH', - onchainIdentifier: '0x111111111117dc0aa78b770fa6a738034120c302' - }, - { - assetType: 'A8', - decimals: 18, - name: 'Ancient8', - networkId: 'ETH', - onchainIdentifier: '0x3e5a19c91266ad8ce2477b91585d1856b84062df' - }, - { - assetType: 'AAVE', - decimals: 18, - name: 'Aave', - networkId: 'ETH', - onchainIdentifier: '0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9' - }, - { - assetType: 'ACX', - decimals: 18, - name: 'Across Protocol Token', - networkId: 'ETH', - onchainIdentifier: '0x44108f0223a3c3028f5fe7aec7f9bb2e66bef82f' - }, - { - assetType: 'AJNA', - decimals: 18, - name: 'AjnaToken', - networkId: 'ETH', - onchainIdentifier: '0x9a96ec9b57fb64fbc60b423d1f4da7691bd35079' - }, - { - assetType: 'ALD', - decimals: 18, - name: 'Aladdin Token', - networkId: 'ETH', - onchainIdentifier: '0xb26c4b3ca601136daf98593feaeff9e0ca702a8d' - }, - { - assetType: 'ALICE', - decimals: 6, - name: 'My Neighbor Alice', - networkId: 'ETH', - onchainIdentifier: '0xac51066d7bec65dc4589368da368b212745d63e8' - }, - { - assetType: 'ALLO', - decimals: 18, - name: 'Allora', - networkId: 'ALLO' - }, - { - assetType: 'ALLO_T', - decimals: 18, - name: 'Allora Testnet', - networkId: 'ALLO_T' - }, - { - assetType: 'ALPHA', - decimals: 18, - name: 'Alpha Finance Lab', - networkId: 'ETH', - onchainIdentifier: '0xa1faa113cbe53436df28ff0aee54275c13b40975' - }, - { - assetType: 'ALT', - decimals: 18, - name: 'AltLayer Token', - networkId: 'ETH', - onchainIdentifier: '0x8457ca5040ad67fdebbcc8edce889a335bc0fbfb' - }, - { - assetType: 'AMP', - decimals: 18, - name: 'Amp', - networkId: 'ETH', - onchainIdentifier: '0xff20817765cb7f73d4bde2e66e067e58d11095c2' - }, - { - assetType: 'ANGLE', - decimals: 18, - name: 'Angle', - networkId: 'ETH', - onchainIdentifier: '0x31429d1856ad1377a8a0079410b297e1a9e214c2' - }, - { - assetType: 'ANKR', - decimals: 18, - name: 'Ankr Network', - networkId: 'ETH', - onchainIdentifier: '0x8290333cef9e6d528dd5618fb97a76f268f3edd4' - }, - { - assetType: 'ANT', - decimals: 18, - name: 'Aragon', - networkId: 'ETH', - onchainIdentifier: '0xa117000000f279d81a1d3cc75430faa017fa5a2e' - }, - { - assetType: 'APE', - decimals: 18, - name: 'ApeCoin', - networkId: 'ETH', - onchainIdentifier: '0x4d224452801aced8b2f0aebe155379bb5d594381' - }, - { - assetType: 'API3', - decimals: 18, - name: 'API3', - networkId: 'ETH', - onchainIdentifier: '0x0b38210ea11411557c13457d4da7dc6ea731b88a' - }, - { - assetType: 'APT', - decimals: 8, - name: 'Aptos', - networkId: 'APT' - }, - { - assetType: 'APT_T', - decimals: 8, - name: 'Aptos Testnet', - networkId: 'APT_T' - }, - { - assetType: 'ARB', - decimals: 18, - name: 'Arbitrum', - networkId: 'ETH', - onchainIdentifier: '0xb50721bcf8d664c30412cfbc6cf7a15145234ad1' - }, - { - assetType: 'ARB_ARBITRUM_T', - decimals: 18, - name: 'ARB on Arbitrum Sepolia', - networkId: 'ARBITRUM_SEPOLIA', - onchainIdentifier: '0xf0114170db316047e508ce4714142cfad49f767d' - }, - { - assetType: 'ARCD', - decimals: 18, - name: 'Arcade', - networkId: 'ETH', - onchainIdentifier: '0xe020b01b6fbd83066aa2e8ee0ccd1eb8d9cc70bf' - }, - { - assetType: 'ARKM', - decimals: 18, - name: 'Arkham', - networkId: 'ETH', - onchainIdentifier: '0x6e2a43be0b1d33b726f0ca3b8de60b3482b8b050' - }, - { - assetType: 'ASTO', - decimals: 18, - name: 'Altered State Token', - networkId: 'ETH', - onchainIdentifier: '0x823556202e86763853b40e9cde725f412e294689' - }, - { - assetType: 'ATA', - decimals: 18, - name: 'Automata', - networkId: 'ETH', - onchainIdentifier: '0xa2120b9e674d3fc3875f415a7df52e382f141225' - }, - { - assetType: 'ATOM', - decimals: 6, - name: 'Cosmos', - networkId: 'COSMOS' - }, - { - assetType: 'AUCTION', - decimals: 18, - name: 'Bounce', - networkId: 'ETH', - onchainIdentifier: '0xa9b1eb5908cfc3cdf91f9b8b3a74108598009096' - }, - { - assetType: 'AUDIO', - decimals: 18, - name: 'Audius', - networkId: 'ETH', - onchainIdentifier: '0x18aaa7115705e8be94bffebde57af9bfc265b998' - }, - { - assetType: 'AURORA', - decimals: 18, - name: 'Aurora', - networkId: 'ETH', - onchainIdentifier: '0xaaaaaa20d9e0e2461697782ef11675f668207961' - }, - { - assetType: 'AUSD', - decimals: 6, - name: 'AUSD', - networkId: 'ETH', - onchainIdentifier: '0x00000000efe302beaa2b3e6e1b18d08d69a9012a' - }, - { - assetType: 'AVA', - decimals: 18, - name: 'Jadu AVA', - networkId: 'ETH', - onchainIdentifier: '0x86fc6f6c6702cef7d3bae87ef41256715416db71' - }, - { - assetType: 'AVAIL', - decimals: 18, - name: 'Avail', - networkId: 'ETH', - onchainIdentifier: '0xeeb4d8400aeefafc1b2953e0094134a887c76bd8' - }, - { - assetType: 'AVG', - decimals: 18, - name: 'Avocado DAO Token', - networkId: 'ETH', - onchainIdentifier: '0xa41f142b6eb2b164f8164cae0716892ce02f311f' - }, - { - assetType: 'AXL', - decimals: 6, - name: 'Axelar', - networkId: 'AXL' - }, - { - assetType: 'AXL_T', - decimals: 6, - name: 'Axelar Testnet', - networkId: 'AXL_T' - }, - { - assetType: 'AXS', - decimals: 18, - name: 'Axie Infinity', - networkId: 'ETH', - onchainIdentifier: '0xbb0e17ef65f82ab018d8edd776e8dd940327b28b' - }, - { - assetType: 'AXS_OLD', - decimals: 18, - name: 'Axie Infinity Shard', - networkId: 'ETH', - onchainIdentifier: '0xf5d669627376ebd411e34b98f19c868c8aba5ada' - }, - { - assetType: 'AZIMUTH', - decimals: 18, - name: 'Azimuth Points', - networkId: 'ETH', - onchainIdentifier: '0x33eecbf908478c10614626a9d304bfe18b78dd73' - }, - { - assetType: 'BADGER', - decimals: 18, - name: 'Badger DAO', - networkId: 'ETH', - onchainIdentifier: '0x3472a5a71965499acd81997a54bba8d852c6e53d' - }, - { - assetType: 'BAL', - decimals: 18, - name: 'Balancer', - networkId: 'ETH', - onchainIdentifier: '0xba100000625a3754423978a60c9317c58a424e3d' - }, - { - assetType: 'BANANA', - decimals: 18, - name: 'Banana', - networkId: 'ETH', - onchainIdentifier: '0x38e68a37e401f7271568cecaac63c6b1e19130b4' - }, - { - assetType: 'BAND', - decimals: 18, - name: 'BandToken', - networkId: 'ETH', - onchainIdentifier: '0xba11d00c5f74255f56a5e366f4f77f5a186d7f55' - }, - { - assetType: 'BAT', - decimals: 18, - name: 'Basic Attention', - networkId: 'ETH', - onchainIdentifier: '0x0d8775f648430679a709e98d2b0cb6250d2887ef' - }, - { - assetType: 'BAYC', - decimals: 18, - name: 'Bored Ape Yacht Club', - networkId: 'ETH', - onchainIdentifier: '0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d' - }, - { - assetType: 'BBN', - decimals: 6, - name: 'Babylon', - networkId: 'BBN' - }, - { - assetType: 'BCH', - decimals: 8, - name: 'Bitcoin Cash', - networkId: 'BCH' - }, - { - assetType: 'BEAM', - decimals: 18, - name: 'Beam', - networkId: 'ETH', - onchainIdentifier: '0x62d0a8458ed7719fdaf978fe5929c6d342b0bfce' - }, - { - assetType: 'BETA', - decimals: 18, - name: 'Beta Finance', - networkId: 'ETH', - onchainIdentifier: '0xbe1a001fe942f96eea22ba08783140b9dcc09d28' - }, - { - assetType: 'BGB_OLD', - decimals: 18, - name: 'BitgetToken', - networkId: 'ETH', - onchainIdentifier: '0x19de6b897ed14a376dda0fe53a5420d2ac828a28' - }, - { - assetType: 'BICO', - decimals: 18, - name: 'Biconomy Token', - networkId: 'ETH', - onchainIdentifier: '0xf17e65822b568b3903685a7c9f496cf7656cc6c2' - }, - { - assetType: 'BLD', - decimals: 6, - name: 'Agoric', - networkId: 'BLD' - }, - { - assetType: 'BLUR', - decimals: 18, - name: 'Blur', - networkId: 'ETH', - onchainIdentifier: '0x5283d291dbcf85356a21ba090e6db59121208b44' - }, - { - assetType: 'BNT', - decimals: 18, - name: 'Bancor', - networkId: 'ETH', - onchainIdentifier: '0x1f573d6fb3f13d689ff844b4ce37794d79a7ff1c' - }, - { - assetType: 'BOTTO', - decimals: 18, - name: 'Botto', - networkId: 'ETH', - onchainIdentifier: '0x9dfad1b7102d46b1b197b90095b5c4e9f5845bba' - }, - { - assetType: 'BREED', - decimals: 18, - name: 'BreederDAO', - networkId: 'ETH', - onchainIdentifier: '0x94e9eb8b5ab9fd6b9ea3169d55ffade62a01702e' - }, - { - assetType: 'BTC', - decimals: 8, - name: 'Bitcoin', - networkId: 'BTC' - }, - { - assetType: 'BTC_S', - decimals: 8, - name: 'Bitcoin Signet', - networkId: 'BTC_S' - }, - { - assetType: 'BTRST', - decimals: 18, - name: 'Braintrust', - networkId: 'ETH', - onchainIdentifier: '0x799ebfabe77a6e34311eeee9825190b9ece32824' - }, - { - assetType: 'BUIDL', - decimals: 6, - name: 'BlackRock USD Institutional Digital Liquidity Fund', - networkId: 'ETH', - onchainIdentifier: '0x7712c34205737192402172409a8f7ccef8aa2aec' - }, - { - assetType: 'BUIDLSEP', - decimals: 6, - name: 'BlackRock USD Institutional Digital Liquidity Fund (Sepolia Network)', - networkId: 'ETHSEP', - onchainIdentifier: '0xeb0609d3e6312f20bc82b6f500e0d266d6c3d8b5' - }, - { - assetType: 'BUIDL_APTOS', - decimals: 6, - name: 'Buidl on Aptos', - networkId: 'APT' - }, - { - assetType: 'BUSD', - decimals: 18, - name: 'Binance USD', - networkId: 'ETH', - onchainIdentifier: '0x4fabb145d64652a948d72533023f6e7a623c7c53' - }, - { - assetType: 'CBETH', - decimals: 18, - name: 'Coinbase Wrapped Staked ETH', - networkId: 'ETH', - onchainIdentifier: '0xbe9895146f7af43049ca1c1ae358b0541ea49704' - }, - { - assetType: 'CELLANA_APTOS', - decimals: 8, - name: 'CELLANA', - networkId: 'APT' - }, - { - assetType: 'CELO_TB', - decimals: 18, - name: 'Celo Testnet (Baklava)', - networkId: 'CELO_TB', - onchainIdentifier: '0xddc9be57f553fe75752d61606b94cbd7e0264ef8' - }, - { - assetType: 'CHZ', - decimals: 18, - name: 'Chiliz', - networkId: 'ETH', - onchainIdentifier: '0x3506424f91fd33084466f402d5d97f05f8e3b4af' - }, - { - assetType: 'CLONEX', - decimals: 18, - name: 'Clone X', - networkId: 'ETH', - onchainIdentifier: '0x49cf6f5d44e70224e2e23fdcdd2c053f30ada28b' - }, - { - assetType: 'COMP', - decimals: 18, - name: 'Compound', - networkId: 'ETH', - onchainIdentifier: '0xc00e94cb662c3520282e6f5717214004a7f26888' - }, - { - assetType: 'COW', - decimals: 18, - name: 'Cow Protocol Token', - networkId: 'ETH', - onchainIdentifier: '0xdef1ca1fb7fbcdc777520aa7f396b4e015f497ab' - }, - { - assetType: 'CPOOL', - decimals: 18, - name: 'Clearpool', - networkId: 'ETH', - onchainIdentifier: '0x66761fa41377003622aee3c7675fc7b5c1c2fac5' - }, - { - assetType: 'CQT', - decimals: 18, - name: 'Covalent Query Token', - networkId: 'ETH', - onchainIdentifier: '0xd417144312dbf50465b1c641d016962017ef6240' - }, - { - assetType: 'CREAM', - decimals: 18, - name: 'Cream Finance', - networkId: 'ETH', - onchainIdentifier: '0x2ba592f78db6436527729929aaf6c908497cb200' - }, - { - assetType: 'CRO', - decimals: 8, - name: 'Cronos', - networkId: 'ETH', - onchainIdentifier: '0xa0b73e1ff0b80914ab6fe0444e65848c4c34450b' - }, - { - assetType: 'CRV', - decimals: 18, - name: 'Curve DAO', - networkId: 'ETH', - onchainIdentifier: '0xd533a949740bb3306d119cc777fa900ba034cd52' - }, - { - assetType: 'CUSDC', - decimals: 8, - name: 'Compound USD Coin', - networkId: 'ETH', - onchainIdentifier: '0x39aa39c021dfbae8fac545936693ac917d5e7563' - }, - { - assetType: 'CVC', - decimals: 8, - name: 'Civic', - networkId: 'ETH', - onchainIdentifier: '0x41e5560054824ea6b0732e656e3ad64e20e94e45' - }, - { - assetType: 'CVX', - decimals: 18, - name: 'Convex Finance', - networkId: 'ETH', - onchainIdentifier: '0x4e3fbd56cd56c3e72c1403e103b45db9da5b9d2b' - }, - { - assetType: 'CYBER', - decimals: 18, - name: 'CyberConnect', - networkId: 'ETH', - onchainIdentifier: '0x14778860e937f509e651192a90589de711fb88a9' - }, - { - assetType: 'DAI', - decimals: 18, - name: 'Dai', - networkId: 'ETH', - onchainIdentifier: '0x6b175474e89094c44da98b954eedeac495271d0f' - }, - { - assetType: 'DAR', - decimals: 6, - name: 'Mines of Dalarnia', - networkId: 'ETH', - onchainIdentifier: '0x081131434f93063751813c619ecca9c4dc7862a3' - }, - { - assetType: 'DIMO', - decimals: 18, - name: 'Dimo', - networkId: 'ETH', - onchainIdentifier: '0x5fab9761d60419c9eeebe3915a8fa1ed7e8d2e1b' - }, - { - assetType: 'DODO', - decimals: 18, - name: 'DODO', - networkId: 'ETH', - onchainIdentifier: '0x43dfc4159d86f3a37a5a4b3d4580b888ad7d4ddd' - }, - { - assetType: 'DOGE', - decimals: 8, - name: 'Dogecoin', - networkId: 'DOGE' - }, - { - assetType: 'DPI', - decimals: 18, - name: 'DefiPulse Index', - networkId: 'ETH', - onchainIdentifier: '0x1494ca1f11d487c2bbe4543e90080aeba4ba3c2b' - }, - { - assetType: 'DYDX', - decimals: 18, - name: 'dYdX', - networkId: 'ETH', - onchainIdentifier: '0x92d6c1e31e14520e676a687f0a93788b716beff5' - }, - { - assetType: 'DYDX_CHAIN', - decimals: 18, - name: 'Dydx Chain', - networkId: 'DYDX_CHAIN' - }, - { - assetType: 'DYDX_CHAIN_T', - decimals: 18, - name: 'Dydx Chain Testnet', - networkId: 'DYDX_CHAIN_T' - }, - { - assetType: 'ECO', - decimals: 18, - name: 'Eco Fi Token', - networkId: 'ETH', - onchainIdentifier: '0xc242eb8e4e27eae6a2a728a41201152f19595c83' - }, - { - assetType: 'ECOX', - decimals: 18, - name: 'ECOx', - networkId: 'ETH', - onchainIdentifier: '0xcccd1ba9f7acd6117834e0d28f25645decb1736a' - }, - { - assetType: 'EIGEN', - decimals: 18, - name: 'Eigen', - networkId: 'ETH', - onchainIdentifier: '0xec53bf9167f50cdeb3ae105f56099aaab9061f83' - }, - { - assetType: 'EINUHOL', - decimals: 18, - name: 'EigenInu (Holesky Network)', - networkId: 'ETHHOL', - onchainIdentifier: '0xdeeeee2b48c121e6728ed95c860e296177849932' - }, - { - assetType: 'ELFI', - decimals: 18, - name: 'Element Fi', - networkId: 'ETH', - onchainIdentifier: '0x5c6d51ecba4d8e4f20373e3ce96a62342b125d6d' - }, - { - assetType: 'ELS', - decimals: 18, - name: 'Ethlas', - networkId: 'ETH', - onchainIdentifier: '0xeb575c45004bd7b61c6a8d3446a62a05a6ce18d8' - }, - { - assetType: 'ENA', - decimals: 18, - name: 'ENA', - networkId: 'ETH', - onchainIdentifier: '0x57e114b691db790c35207b2e685d4a43181e6061' - }, - { - assetType: 'ENFD', - decimals: 0, - name: 'EnergyFunders Yield FD I LLC', - networkId: 'ETH', - onchainIdentifier: '0x997bb865f307dbe0f979fd2864ae72c93b983d25' - }, - { - assetType: 'ENJ', - decimals: 18, - name: 'Enjin Coin', - networkId: 'ETH', - onchainIdentifier: '0xf629cbd94d3791c9250152bd8dfbdf380e2a3b9c' - }, - { - assetType: 'ENS', - decimals: 18, - name: 'ENS', - networkId: 'ETH', - onchainIdentifier: '0xc18360217d8f7ab5e7c516566761ea12ce7f9d72' - }, - { - assetType: 'ES', - decimals: 6, - name: 'Eclipse', - networkId: 'ETH', - onchainIdentifier: '0x6055dc6ff1077eebe5e6d2ba1a1f53d7ef8430de' - }, - { - assetType: 'ETH', - decimals: 18, - name: 'Ethereum', - networkId: 'ETH' - }, - { - assetType: 'ETHFI', - decimals: 18, - name: 'etherfi governance token', - networkId: 'ETH', - onchainIdentifier: '0xfe0c30065b384f05761f15d0cc899d4f9f9cc0eb' - }, - { - assetType: 'ETHHOL', - decimals: 18, - name: 'Ethereum Test (Holešky)', - networkId: 'ETHHOL' - }, - { - assetType: 'ETHSEP', - decimals: 18, - name: 'Ethereum Test (Sepolia)', - networkId: 'ETHSEP' - }, - { - assetType: 'ETHX', - decimals: 18, - name: 'ETHx', - networkId: 'ETH', - onchainIdentifier: '0xa35b1b31ce002fbf2058d22f30f95d405200a15b' - }, - { - assetType: 'ETH_ARBITRUM_T', - decimals: 18, - name: 'Ethereum on Arbitrum Sepolia Testnet', - networkId: 'ARBITRUM_SEPOLIA' - }, - { - assetType: 'ETH_PLUME_T', - decimals: 18, - name: 'Ethereum on Plume Sepolia Testnet', - networkId: 'PLUME_SEPOLIA' - }, - { - assetType: 'ETH_ZKSYNC_T', - decimals: 18, - name: 'Ethereum on ZKsync Sepolia Testnet', - networkId: 'ZKSYNC_SEPOLIA' - }, - { - assetType: 'EUL', - decimals: 18, - name: 'Euler', - networkId: 'ETH', - onchainIdentifier: '0xd9fcd98c322942075a5c3860693e9f4f03aae07b' - }, - { - assetType: 'EUROC', - decimals: 6, - name: 'Euro Coin', - networkId: 'ETH', - onchainIdentifier: '0x1abaea1f7c830bd89acc67ec4af516284b1bc33c' - }, - { - assetType: 'EVERY', - decimals: 18, - name: 'Everyworld', - networkId: 'ETH', - onchainIdentifier: '0x9afa9999e45484adf5d8eed8d9dfe0693bacd838' - }, - { - assetType: 'EVMOS', - decimals: 18, - name: 'Evmos', - networkId: 'EVMOS' - }, - { - assetType: 'EVMOS_T', - decimals: 18, - name: 'Evmos Testnet', - networkId: 'EVMOS_T' - }, - { - assetType: 'FEI', - decimals: 18, - name: 'Fei USD', - networkId: 'ETH', - onchainIdentifier: '0x956f47f50a910163d8bf957cf5846d573e7f87ca' - }, - { - assetType: 'FET', - decimals: 18, - name: 'Fetch', - networkId: 'ETH', - onchainIdentifier: '0xaea46a60368a7bd060eec7df8cba43b7ef41ad85' - }, - { - assetType: 'FIL', - decimals: 18, - name: 'Filecoin', - networkId: 'FIL' - }, - { - assetType: 'FIRE', - decimals: 18, - name: 'Ceramic Fire', - networkId: 'ETH', - onchainIdentifier: '0x2033e559cddff6dd36ec204e3014faa75a01052e' - }, - { - assetType: 'FLIP', - decimals: 18, - name: 'Chainflip', - networkId: 'ETH', - onchainIdentifier: '0x826180541412d574cf1336d22c0c0a287822678a' - }, - { - assetType: 'FLOW_T', - decimals: 8, - name: 'Flow Testnet', - networkId: 'FLOW_T' - }, - { - assetType: 'FLT', - decimals: 18, - name: 'Fluence', - networkId: 'ETH', - onchainIdentifier: '0x236501327e701692a281934230af0b6be8df3353' - }, - { - assetType: 'FLX', - decimals: 18, - name: 'Flex Ungovernance Token', - networkId: 'ETH', - onchainIdentifier: '0x6243d8cea23066d098a15582d81a598b4e8391f4' - }, - { - assetType: 'FLY', - decimals: 18, - name: 'FlyCoin', - networkId: 'ETH', - onchainIdentifier: '0x4e568ab95f029e8df1e39b30c9d6d076eaa15945' - }, - { - assetType: 'FOAM', - decimals: 18, - name: 'Foam', - networkId: 'ETH', - onchainIdentifier: '0x4946fcea7c692606e8908002e55a582af44ac121' - }, - { - assetType: 'FORT', - decimals: 18, - name: 'Forta', - networkId: 'ETH', - onchainIdentifier: '0x41545f8b9472d758bb669ed8eaeeecd7a9c4ec29' - }, - { - assetType: 'FOX', - decimals: 18, - name: 'Shapeshift FOX Token', - networkId: 'ETH', - onchainIdentifier: '0xc770eefad204b5180df6a14ee197d99d808ee52d' - }, - { - assetType: 'FRAX', - decimals: 18, - name: 'Frax', - networkId: 'ETH', - onchainIdentifier: '0x853d955acef822db058eb8505911ed77f175b99e' - }, - { - assetType: 'FST', - decimals: 18, - name: 'Futureswap', - networkId: 'ETH', - onchainIdentifier: '0x0e192d382a36de7011f795acc4391cd302003606' - }, - { - assetType: 'FTM', - decimals: 18, - name: 'Fantom', - networkId: 'ETH', - onchainIdentifier: '0x4e15361fd6b4bb609fa63c81a2be19d873717870' - }, - { - assetType: 'FTT', - decimals: 18, - name: 'FTX Token', - networkId: 'ETH', - onchainIdentifier: '0x50d1c9771902476076ecfc8b2a83ad6b9355a4c9' - }, - { - assetType: 'FUEL', - decimals: 18, - name: 'Fuel', - networkId: 'ETH', - onchainIdentifier: '0x56ebdae96d179549f279ea0cfea3b3432b8cd2bc' - }, - { - assetType: 'FWB', - decimals: 18, - name: 'Friends With Benefits Pro', - networkId: 'ETH', - onchainIdentifier: '0x35bd01fc9d6d5d81ca9e055db88dc49aa2c699a8' - }, - { - assetType: 'FXS', - decimals: 18, - name: 'Frax Share', - networkId: 'ETH', - onchainIdentifier: '0x3432b6a60d23ca0dfca7761b7ab56459d9c964d0' - }, - { - assetType: 'GEAR', - decimals: 18, - name: 'Gearbox', - networkId: 'ETH', - onchainIdentifier: '0xba3335588d9403515223f109edc4eb7269a9ab5d' - }, - { - assetType: 'GEL', - decimals: 18, - name: 'Gelato Network Token', - networkId: 'ETH', - onchainIdentifier: '0x15b7c0c907e4c6b9adaaaabc300c08991d6cea05' - }, - { - assetType: 'GF', - decimals: 18, - name: 'GuildFi Token', - networkId: 'ETH', - onchainIdentifier: '0xaaef88cea01475125522e117bfe45cf32044e238' - }, - { - assetType: 'GFI', - decimals: 18, - name: 'Goldfinch', - networkId: 'ETH', - onchainIdentifier: '0xdab396ccf3d84cf2d07c4454e10c8a6f5b008d2b' - }, - { - assetType: 'GLM', - decimals: 18, - name: 'Golem Network Token', - networkId: 'ETH', - onchainIdentifier: '0x7dd9c5cba05e151c895fde1cf355c9a1d5da6429' - }, - { - assetType: 'GMEE', - decimals: 18, - name: 'GAMEE', - networkId: 'ETH', - onchainIdentifier: '0xd9016a907dc0ecfa3ca425ab20b6b785b42f2373' - }, - { - assetType: 'GMT', - decimals: 8, - name: 'GreenMetaverseToken', - networkId: 'ETH', - onchainIdentifier: '0xe3c408bd53c31c085a1746af401a4042954ff740' - }, - { - assetType: 'GNO', - decimals: 18, - name: 'Gnosis', - networkId: 'ETH', - onchainIdentifier: '0x6810e776880c02933d47db1b9fc05908e5386b96' - }, - { - assetType: 'GNT', - decimals: 18, - name: 'Golem', - networkId: 'ETH', - onchainIdentifier: '0xa74476443119a942de498590fe1f2454d7d4ac0d' - }, - { - assetType: 'GRT', - decimals: 18, - name: 'Graph Token', - networkId: 'ETH', - onchainIdentifier: '0xc944e90c64b2c07662a292be6244bdf05cda44a7' - }, - { - assetType: 'GYEN', - decimals: 6, - name: 'GMO JPY', - networkId: 'ETH', - onchainIdentifier: '0xc08512927d12348f6620a698105e1baac6ecd911' - }, - { - assetType: 'HAIR', - decimals: 18, - name: 'HairDAO Token', - networkId: 'ETH', - onchainIdentifier: '0x9ce115f0341ae5dabc8b477b74e83db2018a6f42' - }, - { - assetType: 'HASH', - decimals: 9, - name: 'Provenance Hash', - networkId: 'HASH' - }, - { - assetType: 'HBOT', - decimals: 18, - name: 'Hummingbot Governance Token', - networkId: 'ETH', - onchainIdentifier: '0xe5097d9baeafb89f9bcb78c9290d545db5f9e9cb' - }, - { - assetType: 'HBTC', - decimals: 18, - name: 'Huobi BTC', - networkId: 'ETH', - onchainIdentifier: '0x0316eb71485b0ab14103307bf65a021042c6d380' - }, - { - assetType: 'HEGIC', - decimals: 18, - name: 'Hegic', - networkId: 'ETH', - onchainIdentifier: '0x584bc13c7d411c00c01a62e8019472de68768430' - }, - { - assetType: 'HFT', - decimals: 18, - name: 'Hashflow', - networkId: 'ETH', - onchainIdentifier: '0xb3999f658c0391d94a37f7ff328f3fec942bcadc' - }, - { - assetType: 'IDK', - decimals: 8, - name: 'IDKToken', - networkId: 'ETH', - onchainIdentifier: '0x61fd1c62551850d0c04c76fce614cbced0094498' - }, - { - assetType: 'ILV', - decimals: 18, - name: 'Illuvium', - networkId: 'ETH', - onchainIdentifier: '0x767fe9edc9e0df98e07454847909b5e959d7ca0e' - }, - { - assetType: 'IMX', - decimals: 18, - name: 'Immutable X', - networkId: 'ETH', - onchainIdentifier: '0xf57e7e7c23978c3caec3c3548e3d615c346e79ff' - }, - { - assetType: 'INDEX', - decimals: 18, - name: 'Index', - networkId: 'ETH', - onchainIdentifier: '0x0954906da0bf32d5479e25f46056d22f08464cab' - }, - { - assetType: 'INDI', - decimals: 18, - name: 'IndiGG', - networkId: 'ETH', - onchainIdentifier: '0x3392d8a60b77f8d3eaa4fb58f09d835bd31add29' - }, - { - assetType: 'IOTX', - decimals: 18, - name: 'IoTeX Network', - networkId: 'ETH', - onchainIdentifier: '0x6fb3e0a217407efff7ca062d46c26e5d60a14d69' - }, - { - assetType: 'KARATE', - decimals: 18, - name: 'Karate', - networkId: 'ETH', - onchainIdentifier: '0x80008bcd713c38af90a9930288d446bc3bd2e684' - }, - { - assetType: 'KARRAT', - decimals: 18, - name: 'KarratCoin', - networkId: 'ETH', - onchainIdentifier: '0xacd2c239012d17beb128b0944d49015104113650' - }, - { - assetType: 'KEEP', - decimals: 18, - name: 'Keep Network', - networkId: 'ETH', - onchainIdentifier: '0x85eee30c52b0b379b046fb0f85f4f3dc3009afec' - }, - { - assetType: 'KEYS', - decimals: 18, - name: 'KEYS Token', - networkId: 'ETH', - onchainIdentifier: '0xf24603654f1150926314badf00420d6a71ee343e' - }, - { - assetType: 'KINE', - decimals: 18, - name: 'Kine Governance Token', - networkId: 'ETH', - onchainIdentifier: '0xcbfef8fdd706cde6f208460f2bf39aa9c785f05d' - }, - { - assetType: 'KNC', - decimals: 18, - name: 'Kyber Network Crystal v2', - networkId: 'ETH', - onchainIdentifier: '0xdefa4e8a7bcba345f687a2f1456f5edd9ce97202' - }, - { - assetType: 'KNCL', - decimals: 18, - name: 'Kyber Network Legacy', - networkId: 'ETH', - onchainIdentifier: '0xdd974d5c2e2928dea5f71b9825b8b646686bd200' - }, - { - assetType: 'L3', - decimals: 18, - name: 'Layer3', - networkId: 'ETH', - onchainIdentifier: '0x88909d489678dd17aa6d9609f89b0419bf78fd9a' - }, - { - assetType: 'LAND', - decimals: 18, - name: "The Sandbox's LANDs", - networkId: 'ETH', - onchainIdentifier: '0x5cc5b05a8a13e3fbdb0bb9fccd98d38e50f90c38' - }, - { - assetType: 'LBTC', - decimals: 8, - name: 'Lombard Staked Bitcoin', - networkId: 'ETH', - onchainIdentifier: '0x8236a87084f8b84306f72007f36f2618a5634494' - }, - { - assetType: 'LDO', - decimals: 18, - name: 'Lido DAO', - networkId: 'ETH', - onchainIdentifier: '0x5a98fcbea516cf06857215779fd812ca3bef1b32' - }, - { - assetType: 'LINK', - decimals: 18, - name: 'Chainlink', - networkId: 'ETH', - onchainIdentifier: '0x514910771af9ca656af840dff83e8264ecf986ca' - }, - { - assetType: 'LINKSEP', - decimals: 18, - name: 'Chainlink Token Test', - networkId: 'ETHSEP', - onchainIdentifier: '0x779877a7b0d9e8603169ddbd7836e478b4624789' - }, - { - assetType: 'LINK_ARBITRUM_T', - decimals: 18, - name: 'Chainlink Token on Arbitrum Sepolia', - networkId: 'ARBITRUM_SEPOLIA', - onchainIdentifier: '0xb1d4538b4571d411f07960ef2838ce337fe1e80e' - }, - { - assetType: 'LINK_ZKSYNC_T', - decimals: 18, - name: 'Chainlink Token on ZKsync Sepolia', - networkId: 'ZKSYNC_SEPOLIA', - onchainIdentifier: '0x23a1afd896c8c8876af46adc38521f4432658d1e' - }, - { - assetType: 'LMWR', - decimals: 18, - name: 'LimeWire Token', - networkId: 'ETH', - onchainIdentifier: '0x628a3b2e302c7e896acc432d2d0dd22b6cb9bc88' - }, - { - assetType: 'LOKA', - decimals: 18, - name: 'League Of Kingdoms Arena', - networkId: 'ETH', - onchainIdentifier: '0x61e90a50137e1f645c9ef4a0d3a4f01477738406' - }, - { - assetType: 'LPT', - decimals: 18, - name: 'Livepeer Token', - networkId: 'ETH', - onchainIdentifier: '0x58b6a8a3302369daec383334672404ee733ab239' - }, - { - assetType: 'LRC', - decimals: 18, - name: 'Loopring', - networkId: 'ETH', - onchainIdentifier: '0xbbbbca6a901c926f240b89eacb641d8aec7aeafd' - }, - { - assetType: 'LRDS', - decimals: 18, - name: 'BLOCKLORDS', - networkId: 'ETH', - onchainIdentifier: '0xd0a6053f087e87a25dc60701ba6e663b1a548e85' - }, - { - assetType: 'LSETH', - decimals: 18, - name: 'Liquid Staked ETH', - networkId: 'ETH', - onchainIdentifier: '0x8c1bed5b9a0928467c9b1341da1d7bd5e10b6549' - }, - { - assetType: 'LSETHHOL', - decimals: 18, - name: 'Liquid Staked ETH (Holesky Network)', - networkId: 'ETHHOL', - onchainIdentifier: '0x1d8b30cc38dba8abce1ac29ea27d9cfd05379a09' - }, - { - assetType: 'LTC', - decimals: 8, - name: 'Litecoin', - networkId: 'LTC' - }, - { - assetType: 'M', - decimals: 6, - name: 'M by M^0', - networkId: 'ETH', - onchainIdentifier: '0x866a2bf4e572cbcf37d5071a7a58503bfb36be1b' - }, - { - assetType: 'MAGIC', - decimals: 18, - name: 'MAGIC', - networkId: 'ETH', - onchainIdentifier: '0xb0c7a3ba49c7a6eaba6cd4a96c55a1391070ac9a' - }, - { - assetType: 'MANA', - decimals: 18, - name: 'Decentraland', - networkId: 'ETH', - onchainIdentifier: '0x0f5d2fb29fb7d3cfee444a200298f468908cc942' - }, - { - assetType: 'MASK', - decimals: 18, - name: 'Mask Network', - networkId: 'ETH', - onchainIdentifier: '0x69af81e73a73b40adf4f3d4223cd9b1ece623074' - }, - { - assetType: 'MATIC', - decimals: 18, - name: 'Matic Token', - networkId: 'ETH', - onchainIdentifier: '0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0' - }, - { - assetType: 'MATICX', - decimals: 18, - name: 'Liquid Staking Matic', - networkId: 'ETH', - onchainIdentifier: '0xf03a7eb46d01d9ecaa104558c732cf82f6b6b645' - }, - { - assetType: 'MAV', - decimals: 18, - name: 'Maverick Token', - networkId: 'ETH', - onchainIdentifier: '0x7448c7456a97769f6cd04f1e83a4a23ccdc46abd' - }, - { - assetType: 'MAYC', - decimals: 18, - name: 'Mutant Ape Yacht Club', - networkId: 'ETH', - onchainIdentifier: '0x60e4d786628fea6478f785a6d7e704777c86a7c6' - }, - { - assetType: 'MIR', - decimals: 18, - name: 'Mirror Protocol', - networkId: 'ETH', - onchainIdentifier: '0x09a3ecafa817268f77be1283176b946c4ff2e608' - }, - { - assetType: 'MKR', - decimals: 18, - name: 'Maker', - networkId: 'ETH', - onchainIdentifier: '0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2' - }, - { - assetType: 'MLBCB', - decimals: 18, - name: 'LucidSight-MLB-NFT', - networkId: 'ETH', - onchainIdentifier: '0x8c9b261faef3b3c2e64ab5e58e04615f8c788099' - }, - { - assetType: 'MNT', - decimals: 18, - name: 'Mantle', - networkId: 'ETH', - onchainIdentifier: '0x3c3a81e81dc49a522a592e7622a7e711c06bf354' - }, - { - assetType: 'MOG', - decimals: 18, - name: 'Mog Coin', - networkId: 'ETH', - onchainIdentifier: '0xaaee1a9723aadb7afa2810263653a34ba2c21c7a' - }, - { - assetType: 'MOONBIRD', - decimals: 18, - name: 'Moonbirds', - networkId: 'ETH', - onchainIdentifier: '0x23581767a106ae21c074b2276d25e5c3e136a68b' - }, - { - assetType: 'MORPHO', - decimals: 18, - name: 'Morpho Token', - networkId: 'ETH', - onchainIdentifier: '0x9994e35db50125e0df82e4c2dde62496ce330999' - }, - { - assetType: 'MOVE', - decimals: 8, - name: 'Movement', - networkId: 'ETH', - onchainIdentifier: '0x3073f7aaa4db83f95e9fff17424f71d4751a3073' - }, - { - assetType: 'MPL', - decimals: 18, - name: 'Maple', - networkId: 'ETH', - onchainIdentifier: '0x33349b282065b0284d756f0577fb39c158f935e6' - }, - { - assetType: 'MPOND', - decimals: 18, - name: 'MPond', - networkId: 'ETH', - onchainIdentifier: '0x1c77d15857646687005dbbafff5873f4495a9731' - }, - { - assetType: 'MYC', - decimals: 18, - name: 'Mycelium', - networkId: 'ETH', - onchainIdentifier: '0x4b13006980acb09645131b91d259eaa111eaf5ba' - }, - { - assetType: 'MYTH', - decimals: 18, - name: 'Mythos', - networkId: 'ETH', - onchainIdentifier: '0xba41ddf06b7ffd89d1267b5a93bfef2424eb2003' - }, - { - assetType: 'NEXT', - decimals: 18, - name: 'Connext', - networkId: 'ETH', - onchainIdentifier: '0xfe67a4450907459c3e1fff623aa927dd4e28c67a' - }, - { - assetType: 'NFTX', - decimals: 18, - name: 'NFTX', - networkId: 'ETH', - onchainIdentifier: '0x87d73e916d7057945c9bcd8cdd94e42a6f47f776' - }, - { - assetType: 'NIGHT_APTOS', - decimals: 8, - name: 'Midnight Evergreen on Aptos', - networkId: 'APT' - }, - { - assetType: 'NII', - decimals: 15, - name: 'Nahmii', - networkId: 'ETH', - onchainIdentifier: '0x7c8155909cd385f120a56ef90728dd50f9ccbe52' - }, - { - assetType: 'NMR', - decimals: 18, - name: 'Numeraire', - networkId: 'ETH', - onchainIdentifier: '0x1776e1f26f98b1a5df9cd347953a26dd3cb46671' - }, - { - assetType: 'NMT', - decimals: 18, - name: 'NetMind Token', - networkId: 'ETH', - onchainIdentifier: '0x03aa6298f1370642642415edc0db8b957783e8d6' - }, - { - assetType: 'NOTE', - decimals: 8, - name: 'Notional', - networkId: 'ETH', - onchainIdentifier: '0xcfeaead4947f0705a14ec42ac3d44129e1ef3ed5' - }, - { - assetType: 'NOUN', - decimals: 18, - name: 'Nouns', - networkId: 'ETH', - onchainIdentifier: '0x9c8ff314c9bc7f6e59a9d9225fb22946427edc03' - }, - { - assetType: 'NSTR', - decimals: 18, - name: 'Nostra', - networkId: 'ETH', - onchainIdentifier: '0x610dbd98a28ebba525e9926b6aaf88f9159edbfd' - }, - { - assetType: 'NTRN', - decimals: 6, - name: 'Neutron', - networkId: 'NTRN' - }, - { - assetType: 'NXM', - decimals: 18, - name: 'NXM', - networkId: 'ETH', - onchainIdentifier: '0xd7c49cee7e9188cca6ad8ff264c1da2e69d4cf3b' - }, - { - assetType: 'NYM', - decimals: 6, - name: 'Nym', - networkId: 'ETH', - onchainIdentifier: '0x525a8f6f3ba4752868cde25164382bfbae3990e1' - }, - { - assetType: 'OBOL', - decimals: 18, - name: 'Obol Network Token', - networkId: 'ETH', - onchainIdentifier: '0x0b010000b7624eb9b3dfbc279673c76e9d29d5f7' - }, - { - assetType: 'OM', - decimals: 18, - name: 'MANTRA DAO', - networkId: 'ETH', - onchainIdentifier: '0x3593d125a4f7849a1b059e64f4517a86dd60c95d' - }, - { - assetType: 'OMG', - decimals: 18, - name: 'OMG Network', - networkId: 'ETH', - onchainIdentifier: '0xd26114cd6ee289accf82350c8d8487fedb8a0c07' - }, - { - assetType: 'OM_MANTRA', - decimals: 6, - name: 'OM Mantra', - networkId: 'OM_MANTRA' - }, - { - assetType: 'OM_MANTRA_T', - decimals: 6, - name: 'OM Mantra Testnet', - networkId: 'OM_MANTRA_T' - }, - { - assetType: 'ONDO', - decimals: 18, - name: 'Ondo', - networkId: 'ETH', - onchainIdentifier: '0xfaba6f8e4a5e8ab82f62fe7c39859fa577269be3' - }, - { - assetType: 'OP', - decimals: 18, - name: 'Oasis', - networkId: 'ETH', - onchainIdentifier: '0x898157afb3e158cc835d19b9ecd37c69bf460f8c' - }, - { - assetType: 'ORDER', - decimals: 18, - name: 'Orderly Network', - networkId: 'ETH', - onchainIdentifier: '0xabd4c63d2616a5201454168269031355f4764337' - }, - { - assetType: 'OSMO', - decimals: 6, - name: 'Osmosis', - networkId: 'OSMO' - }, - { - assetType: 'OTHR', - decimals: 18, - name: 'Otherdeed', - networkId: 'ETH', - onchainIdentifier: '0x34d85c9cdeb23fa97cb08333b511ac86e1c4e258' - }, - { - assetType: 'OUSG', - decimals: 18, - name: 'Ondo Short-Term U.S. Government Bond Fund', - networkId: 'ETH', - onchainIdentifier: '0x1b19c19393e2d034d8ff31ff34c81252fcbbee92' - }, - { - assetType: 'OXT', - decimals: 18, - name: 'Orchid', - networkId: 'ETH', - onchainIdentifier: '0x4575f41308ec1483f3d399aa9a2826d74da13deb' - }, - { - assetType: 'PARTY', - decimals: 18, - name: 'PartyDAO', - networkId: 'ETH', - onchainIdentifier: '0x381b31b3905b6d1175da9d216a7581023f1d6145' - }, - { - assetType: 'PATH', - decimals: 18, - name: 'PathDao', - networkId: 'ETH', - onchainIdentifier: '0x2a2550e0a75acec6d811ae3930732f7f3ad67588' - }, - { - assetType: 'PAXG', - decimals: 18, - name: 'Paxos Gold', - networkId: 'ETH', - onchainIdentifier: '0x45804880de22913dafe09f4980848ece6ecbaf78' - }, - { - assetType: 'PDT', - decimals: 18, - name: 'Paragons DAO', - networkId: 'ETH', - onchainIdentifier: '0x375abb85c329753b1ba849a601438ae77eec9893' - }, - { - assetType: 'PEEPS', - decimals: 18, - name: 'PleasrDAO', - networkId: 'ETH', - onchainIdentifier: '0xba962a81f78837751be8a177378d582f337084e6' - }, - { - assetType: 'PENDLE', - decimals: 18, - name: 'Pendle', - networkId: 'ETH', - onchainIdentifier: '0x808507121b80c02388fad14726482e061b8da827' - }, - { - assetType: 'PEPE', - decimals: 18, - name: 'PEPE', - networkId: 'ETH', - onchainIdentifier: '0x6982508145454ce325ddbe47a25d4ec3d2311933' - }, - { - assetType: 'PERP', - decimals: 18, - name: 'Perpetual', - networkId: 'ETH', - onchainIdentifier: '0xbc396689893d065f41bc2c6ecbee5e0085233447' - }, - { - assetType: 'PIRATE', - decimals: 18, - name: 'Pirate Nation Token', - networkId: 'ETH', - onchainIdentifier: '0x7613c48e0cd50e42dd9bf0f6c235063145f6f8dc' - }, - { - assetType: 'PIXEL', - decimals: 18, - name: 'PIXEL', - networkId: 'ETH', - onchainIdentifier: '0x3429d03c6f7521aec737a0bbf2e5ddcef2c3ae31' - }, - { - assetType: 'PIXFI', - decimals: 18, - name: 'Pixelverse', - networkId: 'ETH', - onchainIdentifier: '0xd795eb12034c2b77d787a22292c26fab5f5c70aa' - }, - { - assetType: 'POL', - decimals: 18, - name: 'Polygon Ecosystem Token', - networkId: 'ETH', - onchainIdentifier: '0x455e53cbb86018ac2b8092fdcd39d8444affc3f6' - }, - { - assetType: 'POLY', - decimals: 18, - name: 'Polymath', - networkId: 'ETH', - onchainIdentifier: '0x9992ec3cf6a55b00978cddf2b27bc6882d88d1ec' - }, - { - assetType: 'POL_POLYGON', - decimals: 18, - name: 'Polygon Ecosystem Token on Polygon', - networkId: 'POLYGON' - }, - { - assetType: 'POND', - decimals: 18, - name: 'Pond', - networkId: 'ETH', - onchainIdentifier: '0x57b946008913b82e4df85f501cbaed910e58d26c' - }, - { - assetType: 'PORTAL', - decimals: 18, - name: 'PORTAL', - networkId: 'ETH', - onchainIdentifier: '0x1bbe973bef3a977fc51cbed703e8ffdefe001fed' - }, - { - assetType: 'POWR', - decimals: 6, - name: 'PowerLedger', - networkId: 'ETH', - onchainIdentifier: '0x595832f8fc6bf59c85c527fec3740a1b7a361269' - }, - { - assetType: 'PRIME', - decimals: 18, - name: 'Prime', - networkId: 'ETH', - onchainIdentifier: '0xb23d80f5fefcddaa212212f028021b41ded428cf' - }, - { - assetType: 'PRINTS', - decimals: 18, - name: 'FingerprintsDAO', - networkId: 'ETH', - onchainIdentifier: '0x4dd28568d05f09b02220b09c2cb307bfd837cb95' - }, - { - assetType: 'PSP', - decimals: 18, - name: 'ParaSwap', - networkId: 'ETH', - onchainIdentifier: '0xcafe001067cdef266afb7eb5a286dcfd277f3de5' - }, - { - assetType: 'PSTAKE', - decimals: 18, - name: 'pSTAKE Finance', - networkId: 'ETH', - onchainIdentifier: '0xfb5c6815ca3ac72ce9f5006869ae67f18bf77006' - }, - { - assetType: 'PUFFER', - decimals: 18, - name: 'PUFFER', - networkId: 'ETH', - onchainIdentifier: '0x4d1c297d39c5c1277964d0e3f8aa901493664530' - }, - { - assetType: 'PYUSD', - decimals: 6, - name: 'PayPal USD', - networkId: 'ETH', - onchainIdentifier: '0x6c3ea9036406852006290770bedfcaba0e23a0e8' - }, - { - assetType: 'QF', - decimals: 18, - name: 'quasar fighter', - networkId: 'ETH', - onchainIdentifier: '0x9c9560a06de70df3d8e97c7364f7508ef92b0f83' - }, - { - assetType: 'QNT', - decimals: 18, - name: 'Quant', - networkId: 'ETH', - onchainIdentifier: '0x4a220e6096b25eadb88358cb44068a3248254675' - }, - { - assetType: 'RAD', - decimals: 18, - name: 'Radicle', - networkId: 'ETH', - onchainIdentifier: '0x31c8eacbffdd875c74b94b077895bd78cf1e64a3' - }, - { - assetType: 'RARE', - decimals: 18, - name: 'SuperRare', - networkId: 'ETH', - onchainIdentifier: '0xba5bde662c17e2adff1075610382b9b691296350' - }, - { - assetType: 'RARI', - decimals: 18, - name: 'Rarible', - networkId: 'ETH', - onchainIdentifier: '0xfca59cd816ab1ead66534d82bc21e7515ce441cf' - }, - { - assetType: 'RBN', - decimals: 18, - name: 'Ribbon Finance', - networkId: 'ETH', - onchainIdentifier: '0x6123b0049f904d730db3c36a31167d9d4121fa6b' - }, - { - assetType: 'RCOIN', - decimals: 8, - name: 'ArCoin', - networkId: 'ETH', - onchainIdentifier: '0x252739487c1fa66eaeae7ced41d6358ab2a6bca9' - }, - { - assetType: 'REN', - decimals: 18, - name: 'Ren', - networkId: 'ETH', - onchainIdentifier: '0x408e41876cccdc0f92210600ef50372656052a38' - }, - { - assetType: 'RENBTC', - decimals: 8, - name: 'renBTC', - networkId: 'ETH', - onchainIdentifier: '0xeb4c2781e4eba804ce9a9803c67d0893436bb27d' - }, - { - assetType: 'REP', - decimals: 18, - name: 'Augur', - networkId: 'ETH', - onchainIdentifier: '0x221657776846890989a759ba2973e427dff5c9bb' - }, - { - assetType: 'REZ', - decimals: 18, - name: 'Renzo', - networkId: 'ETH', - onchainIdentifier: '0x3b50805453023a91a8bf641e279401a0b23fa6f9' - }, - { - assetType: 'RLS', - decimals: 18, - name: 'Rayls', - networkId: 'ETH', - onchainIdentifier: '0xb5f7b021a78f470d31d762c1dda05ea549904fbd' - }, - { - assetType: 'RLY', - decimals: 18, - name: 'Rally', - networkId: 'ETH', - onchainIdentifier: '0xf1f955016ecbcd7321c7266bccfb96c68ea5e49b' - }, - { - assetType: 'RMO', - decimals: 6, - name: 'Rarimo', - networkId: 'RMO' - }, - { - assetType: 'RN', - decimals: 18, - name: 'Rio Network', - networkId: 'ETH', - onchainIdentifier: '0x3c61297e71e9bb04b9fbfead72a6d3c70e4f1e4a' - }, - { - assetType: 'RNDR', - decimals: 18, - name: 'Render Token', - networkId: 'ETH', - onchainIdentifier: '0x6de037ef9ad2725eb40118bb1702ebb27e4aeb24' - }, - { - assetType: 'ROSE', - decimals: 9, - name: 'Oasis Network', - networkId: 'OAC' - }, - { - assetType: 'RPL', - decimals: 18, - name: 'Rocket Pool Protocol', - networkId: 'ETH', - onchainIdentifier: '0xd33526068d116ce69f19a9ee46f0bd304f21a51f' - }, - { - assetType: 'RSC', - decimals: 18, - name: 'ResearchCoin', - networkId: 'ETH', - onchainIdentifier: '0xd101dcc414f310268c37eeb4cd376ccfa507f571' - }, - { - assetType: 'RSETH', - decimals: 18, - name: 'rsETH', - networkId: 'ETH', - onchainIdentifier: '0xa1290d69c65a6fe4df752f95823fae25cb99e5a7' - }, - { - assetType: 'RSR', - decimals: 18, - name: 'Reserve Rights', - networkId: 'ETH', - onchainIdentifier: '0x320623b8e4ff03373931769a31fc52a4e78b5d70' - }, - { - assetType: 'RST', - decimals: 18, - name: 'Realio Security Token', - networkId: 'ETH', - onchainIdentifier: '0x1a76bffd6d1fc1660e1d0e0552fde51ddbb120cf' - }, - { - assetType: 'RSV', - decimals: 18, - name: 'Reserve', - networkId: 'ETH', - onchainIdentifier: '0x196f4727526ea7fb1e17b2071b3d8eaa38486988' - }, - { - assetType: 'RVR', - decimals: 18, - name: 'River', - networkId: 'ETH', - onchainIdentifier: '0x53319181e003e7f86fb79f794649a2ab680db244' - }, - { - assetType: 'SAFE', - decimals: 18, - name: 'Safe Token', - networkId: 'ETH', - onchainIdentifier: '0x5afe3855358e112b5647b952709e6165e1c1eeee' - }, - { - assetType: 'SALD', - decimals: 18, - name: 'Salad', - networkId: 'ETH', - onchainIdentifier: '0x5582a479f0c403e207d2578963ccef5d03ba636f' - }, - { - assetType: 'SAND', - decimals: 18, - name: 'Sandbox', - networkId: 'ETH', - onchainIdentifier: '0x3845badade8e6dff049820680d1f14bd3903a5d0' - }, - { - assetType: 'SBTC', - decimals: 18, - name: 'Synth sBTC', - networkId: 'ETH', - onchainIdentifier: '0xfe18be6b3bd88a2d2a7f928d00292e7a9963cfc6' - }, - { - assetType: 'SD', - decimals: 18, - name: 'Stader', - networkId: 'ETH', - onchainIdentifier: '0x30d20208d987713f46dfd34ef128bb16c404d10f' - }, - { - assetType: 'SDL', - decimals: 18, - name: 'Saddle', - networkId: 'ETH', - onchainIdentifier: '0xf1dc500fde233a4055e25e5bbf516372bc4f6871' - }, - { - assetType: 'SEI', - decimals: 6, - name: 'Sei', - networkId: 'SEI' - }, - { - assetType: 'SEI_T', - decimals: 6, - name: 'Sei Testnet', - networkId: 'SEI_T' - }, - { - assetType: 'SFRXETHHOL', - decimals: 18, - name: 'Staked Frax Ether (Holesky Network)', - networkId: 'ETHHOL', - onchainIdentifier: '0xa63f56985f9c7f3bc9ffc5685535649e0c1a55f3' - }, - { - assetType: 'SHIB', - decimals: 18, - name: 'SHIBA INU', - networkId: 'ETH', - onchainIdentifier: '0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce' - }, - { - assetType: 'SHRAP', - decimals: 18, - name: 'SHRAPToken', - networkId: 'ETH', - onchainIdentifier: '0x31e4efe290973ebe91b3a875a7994f650942d28f' - }, - { - assetType: 'SIPHER', - decimals: 18, - name: 'Sipher Token', - networkId: 'ETH', - onchainIdentifier: '0x9f52c8ecbee10e00d9faaac5ee9ba0ff6550f511' - }, - { - assetType: 'SKY', - decimals: 18, - name: 'SKY Governance Token', - networkId: 'ETH', - onchainIdentifier: '0x56072c95faa701256059aa122697b133aded9279' - }, - { - assetType: 'SNX', - decimals: 18, - name: 'Synthetix', - networkId: 'ETH', - onchainIdentifier: '0xc011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f' - }, - { - assetType: 'SOL_TD', - decimals: 9, - name: 'Solana Devnet', - networkId: 'SOL_TD' - }, - { - assetType: 'SPEC', - decimals: 18, - name: 'Spectral Token', - networkId: 'ETH', - onchainIdentifier: '0xadf7c35560035944e805d98ff17d58cde2449389' - }, - { - assetType: 'SRM', - decimals: 6, - name: 'Serum', - networkId: 'ETH', - onchainIdentifier: '0x476c5e26a75bd202a9683ffd34359c0cc15be0ff' - }, - { - assetType: 'SSV', - decimals: 18, - name: 'ssv.network', - networkId: 'ETH', - onchainIdentifier: '0x9d65ff81a3c488d585bbfb0bfe3c7707c7917f54' - }, - { - assetType: 'STG', - decimals: 18, - name: 'Stargate Finance', - networkId: 'ETH', - onchainIdentifier: '0xaf5191b0de278c7286d6c7cc6ab6bb8a73ba2cd6' - }, - { - assetType: 'STKAAVE', - decimals: 18, - name: 'Staked AAVE', - networkId: 'ETH', - onchainIdentifier: '0x4da27a545c0c5b758a6ba100e3a049001de870f5' - }, - { - assetType: 'STORJ', - decimals: 8, - name: 'StorjToken', - networkId: 'ETH', - onchainIdentifier: '0xb64ef51c888972c908cfacf59b47c1afbc0ab8ac' - }, - { - assetType: 'STRD', - decimals: 6, - name: 'Stride', - networkId: 'STRD' - }, - { - assetType: 'STRDY', - decimals: 18, - name: 'Sturdy Token', - networkId: 'ETH', - onchainIdentifier: '0xaeb3607ec434454ceb308f5cd540875efb54309a' - }, - { - assetType: 'STRK', - decimals: 18, - name: 'StarkNet Token', - networkId: 'ETH', - onchainIdentifier: '0xca14007eff0db1f8135f4c25b34de49ab0d42766' - }, - { - assetType: 'STRK_STARKNET', - decimals: 18, - name: 'Starknet', - networkId: 'STARK_STARKNET' - }, - { - assetType: 'STRK_STARKNET_T', - decimals: 18, - name: 'Starknet Testnet', - networkId: 'STRK_STARKNET_T' - }, - { - assetType: 'STRP', - decimals: 18, - name: 'Strips', - networkId: 'ETH', - onchainIdentifier: '0x97872eafd79940c7b24f7bcc1eadb1457347adc9' - }, - { - assetType: 'SUDO', - decimals: 18, - name: 'SUDO GOVERNANCE TOKEN', - networkId: 'ETH', - onchainIdentifier: '0x3446dd70b2d52a6bf4a5a192d9b0a161295ab7f9' - }, - { - assetType: 'SUI_T', - decimals: 9, - name: 'Sui Testnet', - networkId: 'SUI_T' - }, - { - assetType: 'SUSDCSEP', - decimals: 6, - name: 'Sec USD Coin (Sepolia Network)', - networkId: 'ETHSEP', - onchainIdentifier: '0x6612394ea7cfa53ed6522a5ff0fad091a89aaef6' - }, - { - assetType: 'SUSDE', - decimals: 18, - name: 'Staked USDe', - networkId: 'ETH', - onchainIdentifier: '0x9d39a5de30e57443bff2a8307a4256c8797a3497' - }, - { - assetType: 'SUSHI', - decimals: 18, - name: 'SushiSwap', - networkId: 'ETH', - onchainIdentifier: '0x6b3595068778dd592e39a122f4f5a5cf09c90fe2' - }, - { - assetType: 'SWISE', - decimals: 18, - name: 'StakeWise', - networkId: 'ETH', - onchainIdentifier: '0x48c3399719b582dd63eb5aadf12a40b4c3f52fa2' - }, - { - assetType: 'SYN', - decimals: 18, - name: 'Synapse', - networkId: 'ETH', - onchainIdentifier: '0x0f2d719407fdbeff09d87557abb7232601fd9f29' - }, - { - assetType: 'T', - decimals: 18, - name: 'Threshold Network Token', - networkId: 'ETH', - onchainIdentifier: '0xcdf7028ceab81fa0c6971208e83fa7872994bee5' - }, - { - assetType: 'TAIKO', - decimals: 18, - name: 'Taiko Token', - networkId: 'ETH', - onchainIdentifier: '0x10dea67478c5f8c5e2d90e5e9b26dbe60c54d800' - }, - { - assetType: 'TBILL', - decimals: 6, - name: 'OpenEden T-Bills', - networkId: 'ETH', - onchainIdentifier: '0xdd50c053c096cb04a3e3362e2b622529ec5f2e8a' - }, - { - assetType: 'TBTC', - decimals: 18, - name: 'tBTC v2', - networkId: 'ETH', - onchainIdentifier: '0x18084fba666a33d37592fa2633fd49a74dd93a88' - }, - { - assetType: 'TEN', - decimals: 18, - name: 'Tokenomy', - networkId: 'ETH', - onchainIdentifier: '0xdd16ec0f66e54d453e6756713e533355989040e4' - }, - { - assetType: 'THOU', - decimals: 18, - name: 'Thousands', - networkId: 'ETH', - onchainIdentifier: '0x370e83ca976c1deb98803fbccf64c6f0948705ea' - }, - { - assetType: 'TIA', - decimals: 6, - name: 'Celestia', - networkId: 'TIA' - }, - { - assetType: 'TLC', - decimals: 18, - name: 'Liquid Collective', - networkId: 'ETH', - onchainIdentifier: '0xb5fe6946836d687848b5abd42dabf531d5819632' - }, - { - assetType: 'TLM', - decimals: 4, - name: 'Alien Worlds Trilium', - networkId: 'ETH', - onchainIdentifier: '0x888888848b652b3e3a0f34c96e00eec0f3a23f72' - }, - { - assetType: 'TOKE', - decimals: 18, - name: 'Tokemak', - networkId: 'ETH', - onchainIdentifier: '0x2e9d63788249371f1dfc918a52f8d799f4a38c94' - }, - { - assetType: 'TRIBE', - decimals: 18, - name: 'TRIBE Governance', - networkId: 'ETH', - onchainIdentifier: '0xc7283b66eb1eb5fb86327f08e1b5816b0720212b' - }, - { - assetType: 'TRIBL', - decimals: 18, - name: 'Tribal Token', - networkId: 'ETH', - onchainIdentifier: '0x6988a804c74fd04f37da1ea4781cea68c9c00f86' - }, - { - assetType: 'TRU', - decimals: 8, - name: 'TrueFi', - networkId: 'ETH', - onchainIdentifier: '0x4c19596f5aaff459fa38b0f7ed92f11ae6543784' - }, - { - assetType: 'TUSD', - decimals: 18, - name: 'TrueUSD', - networkId: 'ETH', - onchainIdentifier: '0x0000000000085d4780b73119b644ae5ecd22b376' - }, - { - assetType: 'UMA', - decimals: 18, - name: 'UMA', - networkId: 'ETH', - onchainIdentifier: '0x04fa0d235c4abf4bcf4787af4cf447de572ef828' - }, - { - assetType: 'UNI', - decimals: 18, - name: 'Uniswap', - networkId: 'ETH', - onchainIdentifier: '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984' - }, - { - assetType: 'UNIBOT', - decimals: 18, - name: 'Unibot', - networkId: 'ETH', - onchainIdentifier: '0xf819d9cb1c2a819fd991781a822de3ca8607c3c9' - }, - { - assetType: 'USCC', - decimals: 6, - name: 'Superstate Crypto Carry Fund', - networkId: 'ETH', - onchainIdentifier: '0x14d60e7fdc0d71d8611742720e4c50e7a974020c' - }, - { - assetType: 'USD', - decimals: 2, - name: 'US Dollars', - networkId: 'USD' - }, - { - assetType: 'USDANCHOL', - decimals: 6, - name: 'USDAnchor (Holesky Network)', - networkId: 'ETHHOL', - onchainIdentifier: '0xfe246cff3dfed50e032904ac1fbd0da32de6873e' - }, - { - assetType: 'USDC', - decimals: 6, - name: 'USD Coin', - networkId: 'ETH', - onchainIdentifier: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' - }, - { - assetType: 'USDCNOBLEDYDX', - decimals: 6, - name: 'USDC Noble dYdX', - networkId: 'DYDX_CHAIN' - }, - { - assetType: 'USDE', - decimals: 18, - name: 'USDe', - networkId: 'ETH', - onchainIdentifier: '0x4c9edd5852cd905f086c759e8383e09bff1e68b3' - }, - { - assetType: 'USDG', - decimals: 6, - name: 'Global Dollar', - networkId: 'ETH', - onchainIdentifier: '0xe343167631d89b6ffc58b88d6b7fb0228795491d' - }, - { - assetType: 'USDP', - decimals: 18, - name: 'Pax Dollar', - networkId: 'ETH', - onchainIdentifier: '0x8e870d67f660d95d5be530380d0ec0bd388289e1' - }, - { - assetType: 'USDS', - decimals: 18, - name: 'USDS Stablecoin', - networkId: 'ETH', - onchainIdentifier: '0xdc035d45d973e3ec169d2276ddab16f1e407384f' - }, - { - assetType: 'USDT', - decimals: 6, - name: 'Tether', - networkId: 'ETH', - onchainIdentifier: '0xdac17f958d2ee523a2206206994597c13d831ec7' - }, - { - assetType: 'USDT_APTOS', - decimals: 6, - name: 'Tether USD on Aptos', - networkId: 'APT' - }, - { - assetType: 'USDY', - decimals: 18, - name: 'Ondo U.S. Dollar Yield', - networkId: 'ETH', - onchainIdentifier: '0x96f6ef951840721adbf46ac996b59e0235cb985c' - }, - { - assetType: 'USDY_APTOS', - decimals: 6, - name: 'Ondo US Dollar Yield on Aptos', - networkId: 'APT' - }, - { - assetType: 'USD_R', - decimals: 2, - name: 'US dollars test', - networkId: 'USD_R' - }, - { - assetType: 'USTB', - decimals: 6, - name: 'Superstate Short Duration US Government Securities Fund', - networkId: 'ETH', - onchainIdentifier: '0x43415eb6ff9db7e26a15b704e7a3edce97d31c4e' - }, - { - assetType: 'USYC', - decimals: 6, - name: 'US Yield Coin', - networkId: 'ETH', - onchainIdentifier: '0x136471a34f6ef19fe571effc1ca711fdb8e49f2b' - }, - { - assetType: 'VANA_VANA', - decimals: 18, - name: 'Vana', - networkId: 'VANA' - }, - { - assetType: 'VANA_VANA_MOKSHA_T', - decimals: 18, - name: 'VANA Token on Vana Moksha Testnet', - networkId: 'VANA_MOKSHA_TESTNET' - }, - { - assetType: 'VFORT_POLYGON', - decimals: 18, - name: 'FORT Staking Vault', - networkId: 'POLYGON', - onchainIdentifier: '0xf22f690a41d22496496d4959acfff0f3bacc24f1' - }, - { - assetType: 'VIRTUAL', - decimals: 18, - name: 'Virtual Protocol', - networkId: 'ETH', - onchainIdentifier: '0x44ff8620b8ca30902395a7bd3f2407e1a091bf73' - }, - { - assetType: 'VITA', - decimals: 18, - name: 'VitaDAO Token', - networkId: 'ETH', - onchainIdentifier: '0x81f8f0bb1cb2a06649e51913a151f0e7ef6fa321' - }, - { - assetType: 'VRA', - decimals: 18, - name: 'VERA', - networkId: 'ETH', - onchainIdentifier: '0xf411903cbc70a74d22900a5de66a2dda66507255' - }, - { - assetType: 'W', - decimals: 18, - name: 'Wormhole Token', - networkId: 'ETH', - onchainIdentifier: '0xb0ffa8000886e57f86dd5264b9582b2ad87b2b91' - }, - { - assetType: 'WAXL', - decimals: 6, - name: 'Wrapped Axelar', - networkId: 'ETH', - onchainIdentifier: '0x467719ad09025fcc6cf6f8311755809d45a5e5f3' - }, - { - assetType: 'WBTC', - decimals: 8, - name: 'Wrapped Bitcoin', - networkId: 'ETH', - onchainIdentifier: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599' - }, - { - assetType: 'WCELO', - decimals: 18, - name: 'Wrapped Celo', - networkId: 'ETH', - onchainIdentifier: '0xe452e6ea2ddeb012e20db73bf5d3863a3ac8d77a' - }, - { - assetType: 'WCUSD', - decimals: 18, - name: 'Wrapped Celo Dollar', - networkId: 'ETH', - onchainIdentifier: '0xad3e3fc59dff318beceaab7d00eb4f68b1ecf195' - }, - { - assetType: 'WEETH', - decimals: 18, - name: 'Wrapped eETH', - networkId: 'ETH', - onchainIdentifier: '0xcd5fe23c85820f7b72d0926fc9b05b43e359b7ee' - }, - { - assetType: 'WETH', - decimals: 18, - name: 'Wrapped Ether', - networkId: 'ETH', - onchainIdentifier: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2' - }, - { - assetType: 'WETHDYDX', - decimals: 18, - name: 'Wrapped Ethereum DYDX', - networkId: 'ETH', - onchainIdentifier: '0x46b2deae6eff3011008ea27ea36b7c27255ddfa9' - }, - { - assetType: 'WEVMOS', - decimals: 18, - name: 'Wrapped Evmos', - networkId: 'ETH', - onchainIdentifier: '0x93581991f68dbae1ea105233b67f7fa0d6bdee7b' - }, - { - assetType: 'WEXIT', - decimals: 8, - name: 'Wrapped Exit', - networkId: 'ETH', - onchainIdentifier: '0xc12799bf6c139f269439675454267644d5c7aca3' - }, - { - assetType: 'WEXOD', - decimals: 8, - name: 'Wrapped EXOD', - networkId: 'ETH', - onchainIdentifier: '0x10ef8b469f47a3167505e2f46b57aa3c708ec3c8' - }, - { - assetType: 'WFIL', - decimals: 18, - name: 'Wrapped Filecoin', - networkId: 'ETH', - onchainIdentifier: '0x6e1a19f235be7ed8e3369ef73b196c07257494de' - }, - { - assetType: 'WFLOW', - decimals: 18, - name: 'Wrapped Flow', - networkId: 'ETH', - onchainIdentifier: '0x5c147e74d63b1d31aa3fd78eb229b65161983b2b' - }, - { - assetType: 'WLD', - decimals: 18, - name: 'Worldcoin', - networkId: 'ETH', - onchainIdentifier: '0x163f8c2467924be0ae7b5347228cabf260318753' - }, - { - assetType: 'WM', - decimals: 6, - name: 'WrappedM by M^0', - networkId: 'ETH', - onchainIdentifier: '0x437cc33344a0b27a429f795ff6b469c72698b291' - }, - { - assetType: 'WNXM', - decimals: 18, - name: 'Wrapped NXM', - networkId: 'ETH', - onchainIdentifier: '0x0d438f3b5175bebc262bf23753c1e53d03432bde' - }, - { - assetType: 'WOO', - decimals: 18, - name: 'Woo Network', - networkId: 'ETH', - onchainIdentifier: '0x4691937a7508860f876c9c0a2a617e7d9e945d4b' - }, - { - assetType: 'WOW', - decimals: 18, - name: 'World of Women', - networkId: 'ETH', - onchainIdentifier: '0xe785e82358879f061bc3dcac6f0444462d4b5330' - }, - { - assetType: 'WPUNKS', - decimals: 18, - name: 'Wrapped CryptoPunks', - networkId: 'ETH', - onchainIdentifier: '0xb7f7f6c52f2e2fdb1963eab30438024864c313f6' - }, - { - assetType: 'WQUIL', - decimals: 8, - name: 'Wrapped QUIL', - networkId: 'ETH', - onchainIdentifier: '0x8143182a775c54578c8b7b3ef77982498866945d' - }, - { - assetType: 'WSTETH', - decimals: 18, - name: 'Wrapped Staked ETH', - networkId: 'ETH', - onchainIdentifier: '0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0' - }, - { - assetType: 'WSTR', - decimals: 18, - name: 'WrappedStar', - networkId: 'ETH', - onchainIdentifier: '0xf0dc76c22139ab22618ddfb498be1283254612b1' - }, - { - assetType: 'WTAO', - decimals: 9, - name: 'Wrapped TAO', - networkId: 'ETH', - onchainIdentifier: '0x77e06c9eccf2e797fd462a92b6d7642ef85b0a44' - }, - { - assetType: 'WUSDM', - decimals: 18, - name: 'Wrapped Mountain Protocol USD', - networkId: 'ETH', - onchainIdentifier: '0x57f5e098cad7a3d1eed53991d4d66c45c9af7812' - }, - { - assetType: 'WZEC', - decimals: 18, - name: 'Wrapped Zcash', - networkId: 'ETH', - onchainIdentifier: '0x4a64515e5e1d1073e83f30cb97bed20400b66e10' - }, - { - assetType: 'XAV', - decimals: 18, - name: 'Xave Token', - networkId: 'ETH', - onchainIdentifier: '0x40370aed88933021e20cf7c4d67e00417cda2202' - }, - { - assetType: 'XJ_ZKSYNC_T', - decimals: 18, - name: 'xjToken', - networkId: 'ZKSYNC_SEPOLIA', - onchainIdentifier: '0x69e5dc39e2bcb1c17053d2a4ee7caeaac5d36f96' - }, - { - assetType: 'XMPL', - decimals: 18, - name: 'XMPL', - networkId: 'ETH', - onchainIdentifier: '0x4937a209d4cdbd3ecd48857277cfd4da4d82914c' - }, - { - assetType: 'XRP', - decimals: 6, - name: 'Ripple', - networkId: 'XRP' - }, - { - assetType: 'XSUSHI', - decimals: 18, - name: 'SushiBar', - networkId: 'ETH', - onchainIdentifier: '0x8798249c2e607446efb7ad49ec89dd1865ff4272' - }, - { - assetType: 'XYLB', - decimals: 0, - name: 'XY Labs', - networkId: 'ETH', - onchainIdentifier: '0x00d61c23ba36001603f1fcb4981e2d13ef9f0923' - }, - { - assetType: 'YFI', - decimals: 18, - name: 'yearn.finance', - networkId: 'ETH', - onchainIdentifier: '0x0bc529c00c6401aef6d220be8c6ea1667f6ad93e' - }, - { - assetType: 'YGG', - decimals: 18, - name: 'Yield Guild Games', - networkId: 'ETH', - onchainIdentifier: '0x25f8087ead173b73d6e8b84329989a8eea16cf73' - }, - { - assetType: 'ZBU', - decimals: 18, - name: 'ZEEBU', - networkId: 'ETH', - onchainIdentifier: '0x8f9b4525681f3ea6e43b8e0a57bfff86c0a1dd2e' - }, - { - assetType: 'ZENT', - decimals: 18, - name: 'Zentry', - networkId: 'ETH', - onchainIdentifier: '0xdbb7a34bf10169d6d2d0d02a6cbb436cf4381bfa' - }, - { - assetType: 'ZERO', - decimals: 6, - name: 'Zero by M^0', - networkId: 'ETH', - onchainIdentifier: '0x988567fe094570cce1ffda29d1f2d842b70492be' - }, - { - assetType: 'ZRO', - decimals: 18, - name: 'LayerZero', - networkId: 'ETH', - onchainIdentifier: '0x6985884c4392d348587b19cb9eaaf157f13271cd' - }, - { - assetType: 'ZRX', - decimals: 18, - name: '0x', - networkId: 'ETH', - onchainIdentifier: '0xe41d2489571d322189246dafa5ebde1f4699f498' - }, - { - assetType: 'cEUR_TB', - decimals: 18, - name: 'Celo EUR Testnet (baklava)', - networkId: 'CELO_TB', - onchainIdentifier: '0xf9ece301247ad2ce21894941830a2470f4e774ca' - }, - { - assetType: 'cUSD_TB', - decimals: 18, - name: 'Celo USD Testnet (baklava)', - networkId: 'CELO_TB', - onchainIdentifier: '0x62492a644a588fd904270bed06ad52b9abfea1ae' - } -] - -@Injectable() -export class AnchorageAssetService { - constructor( - private readonly networkRepository: NetworkRepository, - private readonly logger: LoggerService - ) {} - - private mapAnchorageAsset(network: Network, anchorageAsset: AnchorageAsset): Asset { - return { - decimals: anchorageAsset.decimals, - externalId: anchorageAsset.assetType, - name: anchorageAsset.name, - networkId: network.networkId, - onchainId: anchorageAsset.onchainIdentifier - } - } - - async findByExternalId(externalId: string): Promise { - for (const anchorageAsset of ANCHORAGE_ASSETS) { - if (anchorageAsset.assetType === externalId) { - const network = await this.networkRepository.findByExternalId(Provider.ANCHORAGE, anchorageAsset.networkId) - - if (network) { - return this.mapAnchorageAsset(network, anchorageAsset) - } - } - } - - return null - } - - async findAll(): Promise { - const networkExternalIdIndex = await this.networkRepository.buildProviderExternalIdIndex(Provider.ANCHORAGE) - const assets: Asset[] = [] - - for (const anchorageAsset of ANCHORAGE_ASSETS) { - const network = networkExternalIdIndex.get(anchorageAsset.networkId) - - if (network) { - assets.push(this.mapAnchorageAsset(network, anchorageAsset)) - } else { - this.logger.warn('Anchorage asset network not found', { anchorageAsset }) - } - } - - return assets - } - - async findByOnchainId(networkId: string, onchainId: string): Promise { - for (const anchorageAsset of ANCHORAGE_ASSETS) { - if (anchorageAsset.onchainIdentifier?.toLowerCase() === onchainId.toLowerCase()) { - const network = await this.networkRepository.findByExternalId(Provider.ANCHORAGE, anchorageAsset.assetType) - - if (network?.networkId === networkId) { - return this.mapAnchorageAsset(network, anchorageAsset) - } - } - } - - return null - } - - async findNativeAsset(networkId: string): Promise { - const network = await this.networkRepository.findById(networkId) - - if (network) { - const externalNetwork = getExternalNetwork(network, Provider.ANCHORAGE) - - for (const anchorageAsset of ANCHORAGE_ASSETS) { - // If network matches and asset doesn't has an address, it must be the - // native asset. - if (externalNetwork?.externalId === anchorageAsset.networkId && !anchorageAsset.onchainIdentifier) { - return this.mapAnchorageAsset(network, anchorageAsset) - } - } - } - - return null - } -} diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts index 6d3694e4b..020be6ab3 100644 --- a/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts @@ -6,8 +6,8 @@ import { NetworkRepository } from '../../../persistence/repository/network.repos import { TransferRepository } from '../../../persistence/repository/transfer.repository' import { BrokerException } from '../../exception/broker.exception' import { AccountService } from '../../service/account.service' +import { AssetService } from '../../service/asset.service' import { WalletService } from '../../service/wallet.service' -import { Asset } from '../../type/asset.type' import { ConnectionWithCredentials } from '../../type/connection.type' import { Provider, ProviderTransferService } from '../../type/provider.type' import { @@ -17,20 +17,19 @@ import { SendTransfer, Source, Transfer, - TransferAsset, TransferPartyType, TransferStatus, isAddressDestination, isProviderSpecific } from '../../type/transfer.type' -import { AnchorageAssetService } from './anchorage-asset.service' +import { getExternalAsset } from '../../util/asset.util' import { transferPartyTypeToAnchorageResourceType, validateConnection } from './anchorage.util' @Injectable() export class AnchorageTransferService implements ProviderTransferService { constructor( - private readonly anchorageAssetService: AnchorageAssetService, private readonly anchorageClient: AnchorageClient, + private readonly assetService: AssetService, private readonly networkRepository: NetworkRepository, private readonly accountService: AccountService, private readonly walletService: WalletService, @@ -114,32 +113,6 @@ export class AnchorageTransferService implements ProviderTransferService { }) } - private async resolveAsset(asset: TransferAsset): Promise { - if (asset.externalAssetId) { - return this.anchorageAssetService.findByExternalId(asset.externalAssetId) - } - - if (asset.assetId) { - // TODO: Look up by the narval assetId; for now we just treat it as the - // same as the anchorage one. - return this.anchorageAssetService.findByExternalId(asset.assetId) - } - - if (!asset.networkId) { - throw new BrokerException({ - message: 'Cannot resolve asset without networkId', - suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, - context: { asset } - }) - } - - if (asset.address) { - return this.anchorageAssetService.findByOnchainId(asset.networkId, asset.address) - } - - return this.anchorageAssetService.findNativeAsset(asset.networkId) - } - async send(connection: ConnectionWithCredentials, sendTransfer: SendTransfer): Promise { const { clientId, connectionId } = connection const context = { clientId, connectionId } @@ -148,37 +121,48 @@ export class AnchorageTransferService implements ProviderTransferService { validateConnection(connection) - const asset = await this.resolveAsset(sendTransfer.asset) + const asset = await this.assetService.findTransferAsset(Provider.ANCHORAGE, sendTransfer.asset) if (!asset) { throw new BrokerException({ - message: 'Cannot resolve asset', - suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, + message: 'Transfer asset not found', + suggestedHttpStatusCode: HttpStatus.NOT_FOUND, context: { asset: sendTransfer.asset } }) } + const externalAsset = getExternalAsset(asset, Provider.ANCHORAGE) + if (!externalAsset) { + throw new BrokerException({ + message: 'Unsupported asset by Anchorage', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, + context: { asset } + }) + } + const network = await this.networkRepository.findById(asset.networkId) if (!network) { throw new BrokerException({ - message: 'Cannot resolve Narval networkId from Anchorage networkId', + message: 'Cannot find asset network', suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, context: { asset } }) } const source = await this.getSource(clientId, sendTransfer.source) + const destination = await this.getDestination(clientId, sendTransfer.destination) - this.logger.log('Resolved Anchorage source and destination', { ...context, source, destination }) + this.logger.log('Resolved Anchorage transfer source and destination', { ...context, source, destination }) // NOTE: Because Anchorage defaults `deductFeeFromAmountIfSameType` to // false, we default the fee attribution to ON_TOP to match their API's // behaviour. const networkFeeAttribution = sendTransfer.networkFeeAttribution || NetworkFeeAttribution.ON_TOP + const data = { source, destination, - assetType: asset.externalId, + assetType: externalAsset.externalId, amount: sendTransfer.amount, transferMemo: sendTransfer.memo || null, idempotentId: sendTransfer.idempotenceId, @@ -198,8 +182,7 @@ export class AnchorageTransferService implements ProviderTransferService { this.logger.log('Anchorage transfer created', context) const internalTransfer: InternalTransfer = { - // TODO: switch this to the Narval assetId once that is a real thing. - assetId: asset.externalId, + assetId: asset.assetId, clientId: clientId, createdAt: new Date(), customerRefId: null, diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-transfer.service.spec.ts b/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-transfer.service.spec.ts index 569c994b9..2b631f693 100644 --- a/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-transfer.service.spec.ts +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-transfer.service.spec.ts @@ -18,6 +18,7 @@ import { AddressRepository } from '../../../../../persistence/repository/address import { ConnectionRepository } from '../../../../../persistence/repository/connection.repository' import { TransferRepository } from '../../../../../persistence/repository/transfer.repository' import { WalletRepository } from '../../../../../persistence/repository/wallet.repository' +import { AssetSeed } from '../../../../../persistence/seed/asset.seed' import { NetworkSeed } from '../../../../../persistence/seed/network.seed' import { setupMockServer, useRequestSpy } from '../../../../../shared/__test__/mock-server' import { Connection, ConnectionStatus, ConnectionWithCredentials } from '../../../../type/connection.type' @@ -38,14 +39,15 @@ describe(FireblocksTransferService.name, () => { let testPrismaService: TestPrismaService let accountRepository: AccountRepository - let fireblocksTransferService: FireblocksTransferService + let addressRepository: AddressRepository + let assetSeed: AssetSeed let clientService: ClientService let connectionRepository: ConnectionRepository + let fireblocksTransferService: FireblocksTransferService let networkSeed: NetworkSeed let provisionService: ProvisionService let transferRepository: TransferRepository let walletRepository: WalletRepository - let addressRepository: AddressRepository const mockServer = setupMockServer(getHandlers()) @@ -184,15 +186,15 @@ describe(FireblocksTransferService.name, () => { app = module.createNestApplication() - testPrismaService = module.get(TestPrismaService) - fireblocksTransferService = module.get(FireblocksTransferService) - provisionService = module.get(ProvisionService) - clientService = module.get(ClientService) - accountRepository = module.get(AccountRepository) addressRepository = module.get(AddressRepository) + assetSeed = module.get(AssetSeed) + clientService = module.get(ClientService) connectionRepository = module.get(ConnectionRepository) + fireblocksTransferService = module.get(FireblocksTransferService) networkSeed = module.get(NetworkSeed) + provisionService = module.get(ProvisionService) + testPrismaService = module.get(TestPrismaService) transferRepository = module.get(TransferRepository) walletRepository = module.get(WalletRepository) @@ -211,6 +213,7 @@ describe(FireblocksTransferService.name, () => { await provisionService.provision() await clientService.save(testClient) await networkSeed.seed() + await assetSeed.seed() await connectionRepository.create(connection) await walletRepository.bulkCreate([walletOne, walletTwo]) diff --git a/apps/vault/src/broker/core/provider/fireblocks/fireblocks-asset.service.ts b/apps/vault/src/broker/core/provider/fireblocks/fireblocks-asset.service.ts deleted file mode 100644 index f74b9d2e1..000000000 --- a/apps/vault/src/broker/core/provider/fireblocks/fireblocks-asset.service.ts +++ /dev/null @@ -1,10720 +0,0 @@ -import { LoggerService } from '@narval/nestjs-shared' -import { Injectable } from '@nestjs/common' -import { NetworkRepository } from '../../../persistence/repository/network.repository' -import { Asset } from '../../type/asset.type' -import { Network } from '../../type/network.type' -import { Provider } from '../../type/provider.type' -import { getExternalNetwork } from '../../util/network.util' - -type FireblocksAsset = { - contractAddress: string - decimals: number - id: string - issuerAddress?: string - name: string - nativeAsset: string - type: string -} - -const FIREBLOCKS_ASSETS: FireblocksAsset[] = [ - { - contractAddress: '0xEA6A3E367e96521fD9E8296425a44EFa6aee82da', - decimals: 0, - id: '$ACM_$CHZ', - name: 'AC Milan ($CHZ)', - nativeAsset: 'CHZ_$CHZ', - type: 'ERC20' - }, - { - contractAddress: '0x235639F72E127bBdd1509BFC9DC6e2caeb3FB741', - decimals: 0, - id: '$ASR_$CHZ', - name: 'AS Roma ($CHZ)', - nativeAsset: 'CHZ_$CHZ', - type: 'ERC20' - }, - { - contractAddress: '0x4c3E460b8e8285DE57c8B1B2B688847B995B71D6', - decimals: 0, - id: '$ATM_$CHZ', - name: 'Atlético de Madrid ($CHZ)', - nativeAsset: 'CHZ_$CHZ', - type: 'ERC20' - }, - { - contractAddress: '0xECc000EBd318bee2a052EB174A71fAF2C3c9e898', - decimals: 0, - id: '$BAR_$CHZ', - name: 'FC Barcelona ($CHZ)', - nativeAsset: 'CHZ_$CHZ', - type: 'ERC20' - }, - { - contractAddress: '0xf30D150250F5301ef34A0E4a64aaFa93F242d87A', - decimals: 0, - id: '$CITY_$CHZ', - name: 'Manchester City FC ($CHZ)', - nativeAsset: 'CHZ_$CHZ', - type: 'ERC20' - }, - { - contractAddress: '0xEE06A81a695750E71a662B51066F2c74CF4478a0', - decimals: 18, - id: '$DG', - name: 'Decentral.games', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x67e410B0e722ff2eec6dDCC7AefD3EdBC2B9078d', - decimals: 0, - id: '$INTER_$CHZ', - name: 'Inter Milan ($CHZ)', - nativeAsset: 'CHZ_$CHZ', - type: 'ERC20' - }, - { - contractAddress: '0x14A5750B0e54b57D12767B84A326C9fE59472Da5', - decimals: 0, - id: '$JUV_$CHZ', - name: 'Juventus ($CHZ)', - nativeAsset: 'CHZ_$CHZ', - type: 'ERC20' - }, - { - contractAddress: '0xd44fC47dBe5751ed36C3f549e217Dab749Aa4039', - decimals: 0, - id: '$LEG_$CHZ', - name: 'Legia Warsaw ($CHZ)', - nativeAsset: 'CHZ_$CHZ', - type: 'ERC20' - }, - { - contractAddress: '0xC7456e8f7CE7BDdBcbF719d0a90811a35dD3d363', - decimals: 0, - id: '$NAP_$CHZ', - name: 'Napoli ($CHZ)', - nativeAsset: 'CHZ_$CHZ', - type: 'ERC20' - }, - { - contractAddress: '0x6fc212cdE3b420733A88496CbdbB15d85beAb1Ca', - decimals: 0, - id: '$PSG_$CHZ', - name: 'Paris Saint-Germain ($CHZ)', - nativeAsset: 'CHZ_$CHZ', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: '$WIF_SOL', - issuerAddress: 'EKpQGSJtjMFqKZ9KQanSqYXRcF8fBopzLHYxdM65zcjm', - name: 'dogwifhat', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x111111111117dC0aa78b770fA6A738034120C302', - decimals: 18, - id: '1INCH', - name: '1INCH Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x111111111117dC0aa78b770fA6A738034120C302', - decimals: 18, - id: '1INCH_BSC', - name: '1INCH Token (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0xfDBc1aDc26F0F8f8606a5d63b7D3a3CD21c22B23', - decimals: 8, - id: '1WO', - name: '1World', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xC96c1609A1a45CcC667B2b7FA6508e29617f7b69', - decimals: 18, - id: '2GT', - name: '2GT_token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xde50da7f5966eFe1869349ff2242D7AD932Eb785', - decimals: 18, - id: '7UT', - name: '7EVEN Utility Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xe8272210954eA85DE6D2Ae739806Ab593B5d9c51', - decimals: 18, - id: 'A5T', - name: 'Alpha5Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xFFC97d72E13E01096502Cb8Eb52dEe56f74DAD7B', - decimals: 18, - id: 'AAAVE', - name: 'Aave interest bearing AAVE', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9', - decimals: 18, - id: 'AAVE', - name: 'Aave Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xfb6115445Bff7b52FeB98650C87f44907E58f802', - decimals: 18, - id: 'AAVE_BSC', - name: 'Binance-Peg Aave Token (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0x63a72806098Bd3D9520cC43356dD78afe5D386D9', - decimals: 18, - id: 'AAVE_E_AVAX', - name: 'Aave Token (Avalanche)', - nativeAsset: 'AVAX', - type: 'ERC20' - }, - { - contractAddress: '0xD6DF932A45C0f255f85145f286eA0b292B21C90B', - decimals: 18, - id: 'AAVE_POLYGON', - name: 'Aave (Polygon)', - nativeAsset: 'MATIC_POLYGON', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 2, - id: 'ABA_USD', - name: 'USD (ABA)', - nativeAsset: 'ABA_USD', - type: 'FIAT' - }, - { - contractAddress: '0xE1BA0FB44CCb0D11b80F92f4f8Ed94CA3fF51D00', - decimals: 18, - id: 'ABAT', - name: 'Aave BAT', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x0E8d6b471e332F140e7d9dbB99E5E3822F728DA6', - decimals: 18, - id: 'ABYSS', - name: 'The Abyss', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xEd04915c23f00A313a544955524EB7DBD823143d', - decimals: 8, - id: 'ACH', - name: 'Alchemy Pay', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 9, - id: 'ACM_SOL', - issuerAddress: 'ACUMENkbnxQPAsN8XrNA11sY3NmXDNKVCqS82EiDqMYB', - name: 'Acumen Governance Token (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '', - decimals: 6, - id: 'ADA', - name: 'ADA (Cardano)', - nativeAsset: 'ADA', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x3EE2200Efb3400fAbB9AacF31297cBdD1d435D47', - decimals: 18, - id: 'ADA_BSC', - name: 'Binance-Peg Cardano (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '', - decimals: 6, - id: 'ADA_TEST', - name: 'ADA Test', - nativeAsset: 'ADA_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x028171bCA77440897B824Ca71D1c56caC55b68A3', - decimals: 18, - id: 'ADAI', - name: 'Aave interest bearing DAI', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xfC1E690f61EFd961294b3e1Ce3313fBD8aa4f85d', - decimals: 18, - id: 'ADAI_OLD', - name: 'Aave Interest bearing DAI (Old)', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xc3FdbadC7c795EF1D6Ba111e06fF8F16A20Ea539', - decimals: 18, - id: 'ADDY_POLYGON', - name: 'Adamant', - nativeAsset: 'MATIC_POLYGON', - type: 'ERC20' - }, - { - contractAddress: '0xE69a353b3152Dd7b706ff7dD40fe1d18b7802d31', - decimals: 18, - id: 'ADH', - name: 'AdHive', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xADE00C28244d5CE17D72E40330B1c318cD12B7c3', - decimals: 18, - id: 'ADX', - name: 'AdEx Network', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x3a3A65aAb0dd2A17E3F1947bA16138cd37d08c04', - decimals: 18, - id: 'AETH', - name: 'Aave Interest bearing ETH', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'AEVO', - name: 'Aevo', - nativeAsset: 'AEVO', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x8eB24319393716668D768dCEC29356ae9CfFe285', - decimals: 8, - id: 'AGI', - name: 'SingularityNET', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x5B7533812759B45C2B44C19e320ba2cD2681b542', - decimals: 8, - id: 'AGIX', - name: 'SingularityNET Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x32353A6C91143bfd6C7d363B546e62a9A2489A20', - decimals: 18, - id: 'AGLD', - name: 'Adventure Gold', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'AGNG_TEST', - name: 'Agung (Testnet)', - nativeAsset: 'AGNG_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x69CF1e63090Acf1e1E16ec0066055f8973fc9Ec8', - decimals: 18, - id: 'AGX', - name: 'AGX Coin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x8Ab7404063Ec4DBcfd4598215992DC3F8EC853d7', - decimals: 18, - id: 'AKRO', - name: 'Akropolis', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xdBdb4d16EdA451D0503b854CF79D55697F90c8DF', - decimals: 18, - id: 'ALCX', - name: 'Alchemix', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xb26C4B3Ca601136Daf98593feAeff9E0CA702a8D', - decimals: 18, - id: 'ALD', - name: 'Aladdin Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xB5495A8D85EE18cfD0d2816993658D88aF08bEF4', - decimals: 0, - id: 'ALDDAO', - name: 'Aladdin DAO Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x27702a26126e0B3702af63Ee09aC4d1A084EF628', - decimals: 18, - id: 'ALEPH', - name: 'aleph.im v2', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'ALEPH_ZERO_EVM', - name: 'Aleph Zero EVM', - nativeAsset: 'ALEPH_ZERO_EVM', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x0100546F2cD4C9D97f798fFC9755E47865FF7Ee6', - decimals: 18, - id: 'ALETH', - name: 'Alchemix ETH', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x16B0a1a87ae8aF5C792faBC429C4FE248834842B', - decimals: 18, - id: 'ALG', - name: 'Algory', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'ALGO', - name: 'Algorand', - nativeAsset: 'ALGO', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 6, - id: 'ALGO_TEST', - name: 'Algorand Test', - nativeAsset: 'ALGO_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 6, - id: 'ALGO_USDC_2V6G', - issuerAddress: '10458941', - name: 'USDC Test on Algorand', - nativeAsset: 'ALGO_TEST', - type: 'ALGO_ASSET' - }, - { - contractAddress: '', - decimals: 6, - id: 'ALGO_USDC_UV4I', - issuerAddress: '31566704', - name: 'USDC on Algorand', - nativeAsset: 'ALGO', - type: 'ALGO_ASSET' - }, - { - contractAddress: '', - decimals: 6, - id: 'ALGO_USDT_I3ZH', - issuerAddress: '312769', - name: 'USDT on Algorand', - nativeAsset: 'ALGO', - type: 'ALGO_ASSET' - }, - { - contractAddress: '0x6B0b3a982b4634aC68dD83a4DBF02311cE324181', - decimals: 18, - id: 'ALI', - name: 'Artificial Liquid Intelligence Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xAC51066d7bEC65Dc4589368da368b212745d63E8', - decimals: 6, - id: 'ALICE', - name: 'ALICE', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xA64BD6C70Cb9051F6A9ba1F163Fdc07E0DfB5F84', - decimals: 18, - id: 'ALINK', - name: 'Aave Interest bearing LINK', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xa06bC25B5805d5F8d82847D191Cb4Af5A3e873E0', - decimals: 18, - id: 'ALINK_V2', - name: 'Aave interest bearing LINK v2', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x6C16119B20fa52600230F074b349dA3cb861a7e3', - decimals: 18, - id: 'ALK', - name: 'Alkemi_Network_DAO_Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x7cA4408137eb639570F8E647d9bD7B7E8717514A', - decimals: 18, - id: 'ALPA', - name: 'AlpaToken', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x8F0528cE5eF7B51152A59745bEfDD91D97091d2F', - decimals: 18, - id: 'ALPACA_BSC', - name: 'AlpacaToken (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0xa1faa113cbE53436Df28FF0aEe54275c13B40975', - decimals: 18, - id: 'ALPHA', - name: 'AlphaToken', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x8263CD1601FE73C066bf49cc09841f35348e3be0', - decimals: 18, - id: 'ALU_BSC', - name: 'Altura', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0xBC6DA0FE9aD5f3b0d58160288917AA56653660E9', - decimals: 18, - id: 'ALUSD', - name: 'Alchemix USD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x4DC3643DbC642b72C158E7F3d2ff232df61cb6CE', - decimals: 18, - id: 'AMB', - name: 'Ambrosus', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xCA0e7269600d353F70b14Ad118A49575455C0f2f', - decimals: 18, - id: 'AMLT', - name: 'AMLT', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x737F98AC8cA59f2C68aD658E3C3d8C8963E40a4c', - decimals: 18, - id: 'AMN', - name: 'Amon', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'AMOY_POLYGON_TEST', - name: 'Matic Gas Token (Polygon Test Amoy)', - nativeAsset: 'AMOY_POLYGON_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xfF20817765cB7f73d4bde2e66e067E58D11095C2', - decimals: 18, - id: 'AMP', - name: 'Amp', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xD46bA6D942050d489DBd938a2C909A5d5039A161', - decimals: 9, - id: 'AMPL', - name: 'Ampleforth', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x0F3ADC247E91c3c50bC08721355A41037E89Bc20', - decimals: 18, - id: 'ANC', - name: 'Wrapped ANC Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x8290333ceF9e6D528dD5618Fb97a76f268f3EDD4', - decimals: 18, - id: 'ANKR', - name: 'Ankr Network', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xa117000000f279D81A1D3cc75430fAA017FA5A2e', - decimals: 18, - id: 'ANT', - name: 'Aragon', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x9ab165D795019b6d8B3e971DdA91071421305e5a', - decimals: 18, - id: 'AOA', - name: 'Aurora.io (Ethereum)', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x4d224452801ACEd8B2F0aebE155379bb5D594381', - decimals: 18, - id: 'APE_ETH', - name: 'ApeCoin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x0b38210ea11411557c13457D4dA7dC6ea731B88a', - decimals: 18, - id: 'API3', - name: 'API3', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x4104b135DBC9609Fc1A9490E61369036497660c8', - decimals: 18, - id: 'APW', - name: 'APWine Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x95a4492F028aa1fd432Ea71146b433E7B4446611', - decimals: 18, - id: 'APY', - name: 'APY Governance Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x912CE59144191C1204E64559FE8253a0e49E6548', - decimals: 18, - id: 'ARB_ARB_FRK9', - name: 'Arbitrum', - nativeAsset: 'ETH-AETH', - type: 'ERC20' - }, - { - contractAddress: '0x319190E3Bbc595602A9E63B2bCfB61c6634355b1', - decimals: 18, - id: 'ARC_AETH', - name: 'Aave Arc Interest bearing ETH', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x89eFaC495C65d43619c661df654ec64fc10C0A75', - decimals: 18, - id: 'ARC-AAAVE', - name: 'Aave Arc Interest bearing AAVE', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x62A6738d887F47e297676FaB05b902709B106C64', - decimals: 18, - id: 'ARCA', - name: 'ARCA', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x1F3f9D3068568F8040775be2e8C03C103C61f3aF', - decimals: 18, - id: 'ARCH', - name: 'Archer DAO Governance Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xBA50933C268F567BDC86E1aC131BE072C6B0b71a', - decimals: 18, - id: 'ARPA', - name: 'ARPA Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x64D91f12Ece7362F91A6f8E7940Cd55F05060b92', - decimals: 18, - id: 'ASH', - name: 'Burn', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x2565ae0385659badCada1031DB704442E1b69982', - decimals: 18, - id: 'ASM', - name: 'ASSEMBLE', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x27054b13b1B798B345b591a4d22e6562d47eA75a', - decimals: 4, - id: 'AST', - name: 'AirSwap', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'ASTR_ASTR', - name: 'Astar', - nativeAsset: 'ASTR_ASTR', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'ASTR_TEST', - name: 'Shibuya (Astar Test)', - nativeAsset: 'ASTR_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xA2120b9e674d3fC3875f415A7DF52e382F141225', - decimals: 18, - id: 'ATA', - name: 'Automata', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xF69709C4c6F3F2b17978280dCe8b7b7a2CbcbA8b', - decimals: 18, - id: 'ATD', - name: 'ATD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 8, - id: 'ATLAS_SOL', - issuerAddress: 'ATLASXmbPQxBUYbxPsV97usA3fPQYEqzQBUHgiFCUsXx', - name: 'Star Atlas (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x0Eb3a705fc54725037CC9e008bDede697f62F335', - decimals: 18, - id: 'ATOM', - name: 'Cosmos Token (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '', - decimals: 6, - id: 'ATOM_COS', - name: 'Cosmos Hub', - nativeAsset: 'ATOM_COS', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 6, - id: 'ATOM_COS_TEST', - name: 'Cosmos Hub Test', - nativeAsset: 'ATOM_COS_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xdacD69347dE42baBfAEcD09dC88958378780FB62', - decimals: 0, - id: 'ATRI', - name: 'AtariToken', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x101cc05f4A51C0319f570d5E146a8C625198e636', - decimals: 18, - id: 'ATUSD', - name: 'Aave interest bearing TUSD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xA9B1Eb5908CfC3cdf91F9B8B3a74108598009096', - decimals: 18, - id: 'AUCTION', - name: 'Bounce Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x18aAA7115705e8be94bfFEBDE57Af9BFc265B998', - decimals: 18, - id: 'AUDIO', - name: 'Audius', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'AURORA_DEV', - name: 'Aurora.dev', - nativeAsset: 'AURORA_DEV', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x9bA00D6856a4eDF4665BcA2C2309936572473B7E', - decimals: 6, - id: 'AUSDC', - name: 'Aave Interest bearing USDC', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xd35f648C3C7f17cd1Ba92e5eac991E3EfcD4566d', - decimals: 6, - id: 'AUSDC_D35F6_ETH', - name: 'Aave Arc Interest bearing USDC', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xBcca60bB61934080951369a648Fb03DF4F96263C', - decimals: 6, - id: 'AUSDC_ETH', - name: 'Aave interest bearing USDC (V2)', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xab60CcAC0d4157c2b03e5D883bDbe60317992f58', - decimals: 18, - id: 'AUX', - name: 'AUX Coin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'AVAX', - name: 'Avalanche (C-Chain)', - nativeAsset: 'AVAX', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x1CE0c2827e2eF14D5C4f29a091d735A204794041', - decimals: 18, - id: 'AVAX_BSC', - name: 'Avalanche (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '', - decimals: 18, - id: 'AVAXTEST', - name: 'Avalanche Fuji', - nativeAsset: 'AVAXTEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x46A51127C3ce23fb7AB1DE06226147F446e4a857', - decimals: 6, - id: 'AVUSDC', - name: 'Aave Avalanche Market USDC', - nativeAsset: 'AVAX', - type: 'ERC20' - }, - { - contractAddress: '0x9ff58f4fFB29fA2266Ab25e75e2A8b3503311656', - decimals: 8, - id: 'AWBTC', - name: 'Aave interest bearing WBTC', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x030bA81f1c18d280636F32af80b9AAd02Cf0854e', - decimals: 18, - id: 'AWETH', - name: 'Aave interest bearing WETH', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x32950db2a7164aE833121501C797D79E7B79d74C', - decimals: 0, - id: 'AXIE_RON', - name: 'Axie (Ronin)', - nativeAsset: 'RON', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'AXL', - name: 'Axelar', - nativeAsset: 'AXL', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 6, - id: 'AXL_TEST', - name: 'Axelar Test', - nativeAsset: 'AXL_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xBB0E17EF65F82Ab018d8EDd776e8DD940327B28b', - decimals: 18, - id: 'AXS', - name: 'Axie Infinity Shard', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x715D400F88C167884bbCc41C5FeA407ed4D2f8A0', - decimals: 18, - id: 'AXS_BSC', - name: 'Axie Infinity Shard (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0xF5D669627376EBd411E34b98F19C868c8ABA5ADA', - decimals: 18, - id: 'AXS_L', - name: 'Axie Infinity Shard (Old)', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x97a9107C1793BC407d6F527b77e7fff4D812bece', - decimals: 18, - id: 'AXS_RON', - name: 'Axie Infinity Shard (Ronin)', - nativeAsset: 'RON', - type: 'ERC20' - }, - { - contractAddress: '0xd7c302fc3ac829C7E896a32c4Bd126f3e8Bd0a1f', - decimals: 18, - id: 'B2M_ERC20', - name: 'Bit2Me Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x6Faa826aF0568d1866Fca570dA79B318ef114dAb', - decimals: 18, - id: 'B21', - name: 'B21 Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x3472A5A71965499acd81997a54BBA8D852C6E53d', - decimals: 18, - id: 'BADGER', - name: 'Badger', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xe7Bf3aEE922367c10c8acEc3793fE7D809A38eef', - decimals: 18, - id: 'BAGS', - name: 'BAGS', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xE02dF9e3e622DeBdD69fb838bB799E3F168902c5', - decimals: 18, - id: 'BAKE', - name: 'BAKE', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0xba100000625a3754423978a60c9317c58a424e3D', - decimals: 18, - id: 'BAL', - name: 'Balancer', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x603c7f932ED1fc6575303D8Fb018fDCBb0f39a95', - decimals: 18, - id: 'BANANA_BSC', - name: 'ApeSwapFinance Banana', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0xBA11D00c5f74255f56a5E366F4F77f5A186d7f55', - decimals: 18, - id: 'BAND', - name: 'BandToken', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x24A6A37576377F63f194Caa5F518a60f45b42921', - decimals: 18, - id: 'BANK', - name: 'Float Bank', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'BASECHAIN_ETH', - name: 'Ethereum (Base)', - nativeAsset: 'BASECHAIN_ETH', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'BASECHAIN_ETH_TEST5', - name: 'Base Sepolia', - nativeAsset: 'BASECHAIN_ETH_TEST5', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x0D8775F648430679A709E98d2b0Cb6250d2887EF', - decimals: 18, - id: 'BAT', - name: 'Basic Attn.', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x19D97D8fA813EE2f51aD4B4e04EA08bAf4DFfC28', - decimals: 18, - id: 'BBADGER', - name: 'Badger Sett Badger', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xF4b5470523cCD314C6B9dA041076e7D79E0Df267', - decimals: 18, - id: 'BBANK', - name: 'BlockBank', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x9BE89D2a4cd102D8Fecc6BF9dA793be995C22541', - decimals: 8, - id: 'BBTC', - name: 'Binance Wrapped BTC', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x1f41E42D0a9e3c0Dd3BA15B527342783B43200A9', - decimals: 0, - id: 'BCAP', - name: 'BCAP', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 8, - id: 'BCH', - name: 'Bitcoin Cash', - nativeAsset: 'BCH', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x8fF795a6F4D97E7887C79beA79aba5cc76444aDf', - decimals: 18, - id: 'BCH_BSC', - name: 'Binance-Peg Bitcoin Cash Token (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '', - decimals: 8, - id: 'BCH_TEST', - name: 'Bitcoin Cash Test', - nativeAsset: 'BCH_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x72e203a17adD19A3099137c9d7015fD3e2b7DBa9', - decimals: 18, - id: 'BCP', - name: 'BlockchainPoland', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x1c4481750daa5Ff521A2a7490d9981eD46465Dbd', - decimals: 18, - id: 'BCPT', - name: 'BlackMason', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x8D717AB5eaC1016b64C2A7fD04720Fd2D27D1B86', - decimals: 18, - id: 'BCVT', - name: 'BitcoinVend', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x7e7E112A68d8D2E221E11047a72fFC1065c38e1a', - decimals: 18, - id: 'BDIGG', - name: 'Badger Sett Digg', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x7884F51dC1410387371ce61747CB6264E1dAeE0B', - decimals: 10, - id: 'BDOT', - name: 'Binance Wrapped DOT', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x593114f03A0A575aece9ED675e52Ed68D2172B8c', - decimals: 18, - id: 'BDP', - name: 'BidiPass', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xDC59ac4FeFa32293A95889Dc396682858d52e5Db', - decimals: 6, - id: 'BEAN', - name: 'Beanstalk', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xA91ac63D040dEB1b7A5E4d4134aD23eb0ba07e14', - decimals: 18, - id: 'BEL', - name: 'Bella', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xE0e514c71282b6f4e823703a39374Cf58dc3eA4f', - decimals: 18, - id: 'BELT_BSC', - name: 'BELT Token (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '', - decimals: 18, - id: 'BERACHAIN_ARTIO_TEST', - name: 'Berachain Artio Test', - nativeAsset: 'BERACHAIN_ARTIO_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x1B073382E63411E3BcfFE90aC1B9A43feFa1Ec6F', - decimals: 8, - id: 'BEST', - name: 'Bitpanda Ecosystem Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xBe1a001FE942f96Eea22bA08783140B9Dcc09D28', - decimals: 18, - id: 'BETA', - name: 'Beta Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x250632378E573c6Be1AC2f97Fcdf00515d0Aa91B', - decimals: 18, - id: 'BETH_BSC', - name: 'Binance Beacon ETH (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0x14C926F2290044B647e1Bf2072e67B495eff1905', - decimals: 18, - id: 'BETHER', - name: 'Bethereum', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x01fF50f8b7f74E4f00580d9596cd3D0d6d6E326f', - decimals: 18, - id: 'BFT', - name: 'Bnk to the future', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xF17e65822b568B3903685a7c9F496CF7656Cc6C2', - decimals: 18, - id: 'BICO', - name: 'Biconomy Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x25e1474170c4c0aA64fa98123bdc8dB49D7802fa', - decimals: 18, - id: 'BID', - name: 'Bidao', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x6e8908cfa881C9f6f2C64d3436E7b80b1bf0093F', - decimals: 18, - id: 'BIST', - name: 'Bistroo Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x1A4b46696b2bB4794Eb3D4c26f1c55F9170fa4C5', - decimals: 18, - id: 'BIT', - name: 'BitDAO', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xb3104b4B9Da82025E8b9F8Fb28b3553ce2f67069', - decimals: 18, - id: 'BIX', - name: 'Bibox Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xCa1bedEd9720289eb20D9449DE872d28ADa27476', - decimals: 10, - id: 'BK', - name: 'Blockkoin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x3AcF9680b5d57994B6570C0eA97bc4d8b25E3F5b', - decimals: 10, - id: 'BK_OLD', - name: 'Blockkoin (OLD)', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x45245bc59219eeaAF6cD3f382e078A461FF9De7B', - decimals: 18, - id: 'BKX', - name: 'BANKEX', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'BLAST', - name: 'Blast Ethereum', - nativeAsset: 'BLAST', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 2, - id: 'BLINC_CAD', - name: 'Blinc CAD', - nativeAsset: 'BLINC_CAD', - type: 'FIAT' - }, - { - contractAddress: '', - decimals: 2, - id: 'BLINC_CHF', - name: 'Blinc CHF', - nativeAsset: 'BLINC_CHF', - type: 'FIAT' - }, - { - contractAddress: '', - decimals: 2, - id: 'BLINC_EUR', - name: 'Blinc EUR', - nativeAsset: 'BLINC_EUR', - type: 'FIAT' - }, - { - contractAddress: '', - decimals: 2, - id: 'BLINC_GBP', - name: 'Blinc GBP', - nativeAsset: 'BLINC_GBP', - type: 'FIAT' - }, - { - contractAddress: '', - decimals: 2, - id: 'BLINC_JPY', - name: 'Blinc JPY', - nativeAsset: 'BLINC_JPY', - type: 'FIAT' - }, - { - contractAddress: '', - decimals: 2, - id: 'BLINC_SGD', - name: 'Blinc SGD', - nativeAsset: 'BLINC_SGD', - type: 'FIAT' - }, - { - contractAddress: '', - decimals: 2, - id: 'BLINC_TEST_CAD', - name: 'Blinc CAD Test', - nativeAsset: 'BLINC_TEST_CAD', - type: 'FIAT' - }, - { - contractAddress: '', - decimals: 2, - id: 'BLINC_TEST_CHF', - name: 'Blinc CHF Test', - nativeAsset: 'BLINC_TEST_CHF', - type: 'FIAT' - }, - { - contractAddress: '', - decimals: 2, - id: 'BLINC_TEST_EUR', - name: 'Blinc EUR Test', - nativeAsset: 'BLINC_TEST_EUR', - type: 'FIAT' - }, - { - contractAddress: '', - decimals: 2, - id: 'BLINC_TEST_GBP', - name: 'Blinc GBP Test', - nativeAsset: 'BLINC_TEST_GBP', - type: 'FIAT' - }, - { - contractAddress: '', - decimals: 2, - id: 'BLINC_TEST_JPY', - name: 'Blinc JPY Test', - nativeAsset: 'BLINC_TEST_JPY', - type: 'FIAT' - }, - { - contractAddress: '', - decimals: 2, - id: 'BLINC_TEST_SGD', - name: 'Blinc SGD Test', - nativeAsset: 'BLINC_TEST_SGD', - type: 'FIAT' - }, - { - contractAddress: '0x20d37E84Ad91436B0F4380D29c2bc192AA05920B', - decimals: 8, - id: 'BLL', - name: 'BELLCOIN', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 8, - id: 'BLT_SOL', - issuerAddress: 'BLT1noyNr3GttckEVrtcfC6oyK6yV1DpPgSyXbncMwef', - name: 'Blocto Token', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x5732046A883704404F284Ce41FfADd5b007FD668', - decimals: 18, - id: 'BLZ', - name: 'Bluzelle', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x725C263e32c72dDC3A19bEa12C5a0479a81eE688', - decimals: 18, - id: 'BMI', - name: 'Bridge Mutual', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'BNB_BSC', - name: 'BNB Smart Chain', - nativeAsset: 'BNB_BSC', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xB8c77482e45F1F44dE1745F52C74426C631bDD52', - decimals: 18, - id: 'BNB_ERC20', - name: 'BNB (Ethereum)', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'BNB_TEST', - name: 'BNB Smart Chain Testnet', - nativeAsset: 'BNB_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C', - decimals: 18, - id: 'BNT', - name: 'Bancor', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xDF347911910b6c9A4286bA8E2EE5ea4a39eB2134', - decimals: 18, - id: 'BOB', - name: 'BOB Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x0391D2021f89DC339F60Fff84546EA23E337750f', - decimals: 18, - id: 'BOND', - name: 'BarnBridge Governance Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xD2dDa223b2617cB616c1580db421e4cFAe6a8a85', - decimals: 18, - id: 'BONDLY', - name: 'Bondly Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x9813037ee2218799597d83D4a5B6F3b6778218d9', - decimals: 18, - id: 'BONE', - name: 'BONE SHIBASWAP', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 5, - id: 'BONK_SOL', - issuerAddress: 'DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263', - name: 'Bonk_Solana_', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x841FAD6EAe12c286d1Fd18d1d525DFfA75C7EFFE', - decimals: 18, - id: 'BOO_FANTOM', - name: 'SpookyToken (Fantom)', - nativeAsset: 'FTM_FANTOM', - type: 'ERC20' - }, - { - contractAddress: '0x3c9d6c1C73b31c837832c72E04D3152f051fc1A9', - decimals: 18, - id: 'BOR', - name: 'BoringDAO', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xC477D038d5420C6A9e0b031712f61c5120090de9', - decimals: 18, - id: 'BOSON', - name: 'Boson Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x68B55024aD32523c95aaA0A235e1d78E9191168e', - decimals: 8, - id: 'BOSSC', - name: 'BOSSC', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x5bEaBAEBB3146685Dd74176f68a0721F91297D37', - decimals: 18, - id: 'BOT', - name: 'Bounce Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 8, - id: 'BOT_SOL', - issuerAddress: 'AkhdZGVbJXPuQZ53u2LrimCjkRP6ZyxG1SoM85T98eE1', - name: 'Starbots Token', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x780116D91E5592E58a3b3c76A351571b39abCEc6', - decimals: 15, - id: 'BOXX', - name: 'BOXX Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x440CD83C160De5C96Ddb20246815eA44C7aBBCa8', - decimals: 18, - id: 'BPRO_RBTC', - name: 'BitPro (RSK)', - nativeAsset: 'RBTC', - type: 'ERC20' - }, - { - contractAddress: '0xe969991CE475bCF817e01E1AAd4687dA7e1d6F83', - decimals: 18, - id: 'BPT_ETHUSDC_7', - name: 'Balancer: ETH/USDC 50/50 #7', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x24D97EEd6E171E70c82bc60aFd37c7d1E549A0AD', - decimals: 18, - id: 'BPT_LPTETH_2', - name: 'Balancer: LPT/ETH 50/50 #2', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x558EC3152e2eb2174905cd19AeA4e34A23DE9aD6', - decimals: 18, - id: 'BRD', - name: 'Bread', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x420412E765BFa6d85aaaC94b4f7b708C89be2e2B', - decimals: 4, - id: 'BRZ', - name: 'BRZ Token (ETH)', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 8, - id: 'BSV', - name: 'Bitcoin SV', - nativeAsset: 'BSV', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 8, - id: 'BSV_TEST', - name: 'Bitcoin SV Test', - nativeAsset: 'BSV_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 8, - id: 'BTC', - name: 'Bitcoin', - nativeAsset: 'BTC', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x321162Cd933E2Be498Cd2267a90534A804051b11', - decimals: 8, - id: 'BTC_FTM', - name: 'Bitcoin (Fantom)', - nativeAsset: 'FTM_FANTOM', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 8, - id: 'BTC_TEST', - name: 'Bitcoin Test', - nativeAsset: 'BTC_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x7130d2A12B9BCbFAe4f2634d864A1Ee1Ce3Ead9c', - decimals: 18, - id: 'BTCB_BSC', - name: 'Binance-Peg BTCB Token (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0x78650B139471520656b9E7aA7A5e9276814a38e9', - decimals: 17, - id: 'BTCST_BSC', - name: 'StandardBTCHashrateToken (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0x799ebfABE77a6E34311eeEe9825190B9ECe32824', - decimals: 18, - id: 'BTRST', - name: 'BTRST token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x8595F9dA7b868b1822194fAEd312235E43007b49', - decimals: 18, - id: 'BTT_BSC', - name: 'BitTorrent (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0x7712c34205737192402172409a8F7ccef8aA2AEc', - decimals: 6, - id: 'BUIDL_ETH_X3N7', - name: 'BlackRock USD Institutional Digital Liquidity Fund', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xAe9269f27437f0fcBC232d39Ec814844a51d6b8f', - decimals: 18, - id: 'BURGER_BSC', - name: 'Burger Swap (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0x33f391F4c4fE802b70B77AE37670037A92114A7c', - decimals: 18, - id: 'BURP', - name: 'Burp', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x4Fabb145d64652a948d72533023f6E7A623C7C53', - decimals: 18, - id: 'BUSD', - name: 'Binance USD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56', - decimals: 18, - id: 'BUSD_BSC', - name: 'Binance-Peg BUSD (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0xeD24FC36d5Ee211Ea25A80239Fb8C4Cfd80f12Ee', - decimals: 18, - id: 'BUSD_BSC_TEST', - name: 'Binance USD (BSC Test)', - nativeAsset: 'BNB_TEST', - type: 'BEP20' - }, - { - contractAddress: '0x54F9b4B4485543A815c51c412a9E20436A06491d', - decimals: 18, - id: 'BXX', - name: 'Baanx', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x4Bb3205bf648B7F59EF90Dee0F1B62F6116Bc7ca', - decimals: 18, - id: 'BYN', - name: 'Beyond Finance (ERC-20)', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x56d811088235F11C8920698a204A5010a788f4b3', - decimals: 18, - id: 'BZRX', - name: 'bZx Protocol Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x19062190B1925b5b6689D7073fDfC8c2976EF8Cb', - decimals: 16, - id: 'BZZ', - name: 'BZZ', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x26E75307Fc0C021472fEb8F727839531F112f317', - decimals: 18, - id: 'C20', - name: 'Crypto20', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xe65cdB6479BaC1e22340E4E755fAE7E509EcD06c', - decimals: 8, - id: 'CAAVE', - name: 'Compound Aave Token', - nativeAsset: 'ETH', - type: 'COMPOUND' - }, - { - contractAddress: '0x7d4b8Cce0591C9044a22ee543533b72E976E36C3', - decimals: 18, - id: 'CAG', - name: 'ChangeBank', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82', - decimals: 18, - id: 'CAKE_BSC', - name: 'PancakeSwap Token (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '', - decimals: 18, - id: 'CAMINO', - name: 'Camino', - nativeAsset: 'CAMINO', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'CAMINO_COLUMBUS_TEST', - name: 'Camino Columbus Test', - nativeAsset: 'CAMINO_COLUMBUS_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'CANTO', - name: 'Canto', - nativeAsset: 'CANTO', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'CANTO_TEST', - name: 'Canto Test', - nativeAsset: 'CANTO_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x03Be5C903c727Ee2C8C4e9bc0AcC860Cca4715e2', - decimals: 18, - id: 'CAPS', - name: 'Capsule Coin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x6894CDe390a3f51155ea41Ed24a33A4827d3063D', - decimals: 18, - id: 'CAT_B71VABWJ_BY1A', - name: 'Simons Cat', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '', - decimals: 6, - id: 'CAVE_SOL', - issuerAddress: '4SZjjNABoqhbd4hnapbvoEPEqT8mnNkfbEoAwALf1V8t', - name: 'Crypto Cavemen (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x6C8c6b02E7b2BE14d4fA6022Dfd6d75921D90E4E', - decimals: 8, - id: 'CBAT', - name: 'cBAT', - nativeAsset: 'ETH', - type: 'COMPOUND' - }, - { - contractAddress: '0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf', - decimals: 8, - id: 'CBBTC_B6QT1TZK_9XC8', - name: 'Coinbase Wrapped BTC', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf', - decimals: 8, - id: 'CBBTC_B609K9QB_0N6V', - name: 'Coinbase Wrapped BTC', - nativeAsset: 'BASECHAIN_ETH', - type: 'ERC20' - }, - { - contractAddress: '0x0E2b41eA957624A314108cc4E33703e9d78f4b3C', - decimals: 18, - id: 'CBD_BSC', - name: 'Greenheart (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0xD85a6Ae55a7f33B0ee113C234d2EE308EdeAF7fD', - decimals: 18, - id: 'CBK', - name: 'Cobak Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xA6FA6531acDf1f9F96EDdD66a0F9481E35c2e42A', - decimals: 6, - id: 'CBRL', - name: 'Crypto BRL', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x70e36f6BF80a52b3B46b3aF8e106CC0ed743E8e4', - decimals: 8, - id: 'CCOMP', - name: 'Compound Collateral', - nativeAsset: 'ETH', - type: 'COMPOUND' - }, - { - contractAddress: '0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643', - decimals: 8, - id: 'CDAI', - name: 'cDAI', - nativeAsset: 'ETH', - type: 'COMPOUND' - }, - { - contractAddress: '0x177d39AC676ED1C67A2b268AD7F1E58826E5B0af', - decimals: 18, - id: 'CDT', - name: 'Blox', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xaaAEBE6Fe48E54f431b0C390CfaF0b017d09D42d', - decimals: 4, - id: 'CEL', - name: 'Celsius', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'CELESTIA', - name: 'Celestia', - nativeAsset: 'CELESTIA', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 6, - id: 'CELESTIA_TEST', - name: 'Celestia Test', - nativeAsset: 'CELESTIA_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xA2F26a3AF6a2C5Bc1d64e176F3BB42BF6e9c6c61', - decimals: 18, - id: 'CELLDOGE_CELO', - name: 'Cell Doge (Celo)', - nativeAsset: 'CELO', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'CELO', - name: 'Celo', - nativeAsset: 'CELO', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'CELO_ALF', - name: 'Celo Alfajores', - nativeAsset: 'CELO_ALF', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'CELO_BAK', - name: 'Celo Baklava', - nativeAsset: 'CELO_BAK', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x4F9254C83EB525f9FCf346490bbb3ed28a81C667', - decimals: 18, - id: 'CELR', - name: 'CelerToken', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x1122B6a0E00DCe0563082b6e2953f3A943855c1F', - decimals: 18, - id: 'CENNZ', - name: 'Centrality Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x2dA719DB753dFA10a62E140f436E1d67F2ddB0d6', - decimals: 10, - id: 'CERE_ERC20', - name: 'CERE Network', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x4Ddc2D193948926D02f9B1fE9e1daa0718270ED5', - decimals: 8, - id: 'CETH', - name: 'cEther', - nativeAsset: 'ETH', - type: 'COMPOUND' - }, - { - contractAddress: '0xD8763CBa276a3738E6DE85b4b3bF5FDed6D6cA73', - decimals: 18, - id: 'CEUR_CELO', - name: 'Celo Euro', - nativeAsset: 'CELO', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'CFG', - name: 'Centrifuge', - nativeAsset: 'CFG', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x12FEF5e57bF45873Cd9B62E9DBd7BFb99e32D73e', - decimals: 18, - id: 'CFI', - name: 'CFI', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xAdA0A1202462085999652Dc5310a7A9e2BF3eD42', - decimals: 18, - id: 'CGI', - name: 'CoinShares Gold and Cryptoassets Index Lite', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xC4C2614E694cF534D407Ee49F8E44D125E4681c4', - decimals: 18, - id: 'CHAIN', - name: 'Chain Games', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x20de22029ab63cf9A7Cf5fEB2b737Ca1eE4c82A6', - decimals: 18, - id: 'CHESS_BSC', - name: 'Tranchess (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0x0000000000004946c0e9F43F4Dee607b0eF1fA1c', - decimals: 0, - id: 'CHI', - name: 'Chi Gastoken by 1inch', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 9, - id: 'CHICKS_SOL', - issuerAddress: 'cxxShYRVcepDudXhe7U62QHvw8uBJoKFifmzggGKVC2', - name: 'SolChicks', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0xDF98E4306efF7E3d839f9Ca54C56959E578CEa04', - decimals: 18, - id: 'CHLI', - name: 'Chilli Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x8A2279d4A90B6fe1C4B30fa660cC9f926797bAA2', - decimals: 6, - id: 'CHR', - name: 'Chromia', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xf9CeC8d50f6c8ad3Fb6dcCEC577e05aA32B224FE', - decimals: 6, - id: 'CHR_BSC', - name: 'Chroma (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0xba9d4199faB4f26eFE3551D490E3821486f135Ba', - decimals: 8, - id: 'CHSB', - name: 'SwissBorg Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x159dC1C54D409BD694bC1e756d6e17a02D6BF167', - decimals: 7, - id: 'CHT', - name: 'CHATTY', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x3506424F91fD33084466F402d5D97f05F8e3b4AF', - decimals: 18, - id: 'CHZ', - name: 'Chiliz (ETH)', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'CHZ_$CHZ', - name: 'Chiliz ($CHZ)', - nativeAsset: 'CHZ_$CHZ', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'CHZ_CHZ2', - name: 'Chiliz', - nativeAsset: 'CHZ_CHZ2', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'CHZ_CHZ2_TEST', - name: 'Chiliz Test', - nativeAsset: 'CHZ_CHZ2_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xFAce851a4921ce59e912d19329929CE6da6EB0c7', - decimals: 8, - id: 'CLINK', - name: 'Compound ChainLink Token', - nativeAsset: 'ETH', - type: 'COMPOUND' - }, - { - contractAddress: '0x2001f2A0Cf801EcFda622f6C28fb6E10d803D969', - decimals: 8, - id: 'CLT', - name: 'CoinLoan', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x80C62FE4487E1351b47Ba49809EBD60ED085bf52', - decimals: 18, - id: 'CLV', - name: 'Clover', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x47bc01597798DCD7506DCCA36ac4302fc93a8cFb', - decimals: 8, - id: 'CMCT', - name: 'Crowd Machine Compute Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x95b4eF2869eBD94BEb4eEE400a99824BF5DC325b', - decimals: 8, - id: 'CMKR', - name: 'Compound Maker', - nativeAsset: 'ETH', - type: 'COMPOUND' - }, - { - contractAddress: '0xd4c435F5B09F855C3317c8524Cb1F586E42795fa', - decimals: 18, - id: 'CND', - name: 'Cindicator', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x6E109E9dD7Fa1a58BC3eff667e8e41fC3cc07AEF', - decimals: 6, - id: 'CNHT_ERC20', - name: 'Tether CNH (ERC20)', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xc00e94Cb662C3520282E6f5717214004A7f26888', - decimals: 18, - id: 'COMP', - name: 'Compound Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x52CE071Bd9b1C4B00A0b92D298c512478CaD67e8', - decimals: 18, - id: 'COMP_BSC', - name: 'Binance-Peg Compound Coin (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0xc834Fa996fA3BeC7aAD3693af486ae53D8aA8B50', - decimals: 18, - id: 'CONV_ETH', - name: 'Convergence', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x62359Ed7505Efc61FF1D56fEF82158CcaffA23D7', - decimals: 18, - id: 'CORE', - name: 'cVault.finance', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'CORE_COREDAO', - name: 'Core DAO', - nativeAsset: 'CORE_COREDAO', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'CORE_COREDAO_TEST', - name: 'Core DAO Test', - nativeAsset: 'CORE_COREDAO_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x589891a198195061Cb8ad1a75357A3b7DbaDD7Bc', - decimals: 18, - id: 'COS', - name: 'Contentos', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 2, - id: 'COS_TEST_USD', - name: 'Cross River USD Test', - nativeAsset: 'COS_TEST_USD', - type: 'FIAT' - }, - { - contractAddress: '', - decimals: 2, - id: 'COS_USD', - name: 'Cross River USD', - nativeAsset: 'COS_USD', - type: 'FIAT' - }, - { - contractAddress: '0xDDB3422497E61e13543BeA06989C0789117555c5', - decimals: 18, - id: 'COTI', - name: 'COTI Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xB37a769B37224449d92AAc57dE379E1267Cd3B00', - decimals: 18, - id: 'COVA', - name: 'Covalent', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x4688a8b1F292FDaB17E9a90c8Bc379dC1DBd8713', - decimals: 18, - id: 'COVER', - name: 'Cover Protocol', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x66761Fa41377003622aEE3c7675Fc7b5c1C2FaC5', - decimals: 18, - id: 'CPOOL', - name: 'Clearpool', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xD417144312DbF50465b1C641d016962017Ef6240', - decimals: 18, - id: 'CQT', - name: 'Covalent Query Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x115eC79F1de567eC68B7AE7eDA501b406626478e', - decimals: 18, - id: 'CRE', - name: 'CarryToken', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x2ba592F78dB6436527729929AAf6c908497cB200', - decimals: 18, - id: 'CREAM', - name: 'Cream', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x158079Ee67Fce2f58472A96584A73C7Ab9AC95c1', - decimals: 8, - id: 'CREP', - name: 'cAugur', - nativeAsset: 'ETH', - type: 'COMPOUND' - }, - { - contractAddress: '0xA0b73E1Ff0B80914AB6fe0444E65848C4C34450b', - decimals: 8, - id: 'CRO', - name: 'Crypto.com', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 9, - id: 'CRP_SOL', - issuerAddress: 'DubwWZNWiNGMMeeQHPnMATNj77YZPZSAz2WVR5WjLJqz', - name: 'CropperFinance (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x08389495D7456E1951ddF7c3a1314A4bfb646d8B', - decimals: 18, - id: 'CRPT', - name: 'Crypterium', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x80A7E048F37A50500351C204Cb407766fA3baE7f', - decimals: 18, - id: 'CRPT_OLD', - name: 'Crypterium (Old)', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x32a7C02e79c4ea1008dD6564b35F131428673c41', - decimals: 18, - id: 'CRU', - name: 'CRUST', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x44fbeBd2F576670a6C33f6Fc0B00aA8c5753b322', - decimals: 8, - id: 'CRUSDC', - name: 'Cream USD Coin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xD533a949740bb3306d119CC777fa900bA034cd52', - decimals: 18, - id: 'CRV', - name: 'Curve DAO Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xF5DCe57282A584D2746FaF1593d3121Fcac444dC', - decimals: 8, - id: 'CSAI', - name: 'cSAI', - nativeAsset: 'ETH', - type: 'COMPOUND' - }, - { - contractAddress: '', - decimals: 9, - id: 'CSOL_SOL', - issuerAddress: '5h6ssFpeDeRbzsEHDbTQNH7nVGgsKrZydxdSTnLm6QdV', - name: 'Solend SOL (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0xA6446D655a0c34bC4F05042EE88170D056CBAf45', - decimals: 18, - id: 'CSP', - name: 'Caspian', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x4B0181102A0112A2ef11AbEE5563bb4a3176c9d7', - decimals: 8, - id: 'CSUSHI', - name: 'Compound Sushi Token', - nativeAsset: 'ETH', - type: 'COMPOUND' - }, - { - contractAddress: '0xa3EE21C306A700E682AbCdfe9BaA6A08F3820419', - decimals: 18, - id: 'CTC', - name: 'Gluwa Creditcoin Vesting Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x8c18D6a985Ef69744b9d57248a45c0861874f244', - decimals: 18, - id: 'CTI', - name: 'ClinTex', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x96A65609a7B84E8842732DEB08f56C3E21aC6f8a', - decimals: 18, - id: 'CTR', - name: 'Centra', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x491604c0FDF08347Dd1fa4Ee062a822A5DD06B5D', - decimals: 18, - id: 'CTSI', - name: 'Cartesi Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x12392F67bdf24faE0AF363c24aC620a2f67DAd86', - decimals: 8, - id: 'CTUSD', - name: 'Compound TrueUSD', - nativeAsset: 'ETH', - type: 'COMPOUND' - }, - { - contractAddress: '0x321C2fE4446C7c963dc41Dd58879AF648838f98D', - decimals: 18, - id: 'CTX', - name: 'Cryptex', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xDf801468a808a32656D2eD2D2d80B72A129739f4', - decimals: 8, - id: 'CUBE', - name: 'Somnium Space Cubes', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x817bbDbC3e8A1204f3691d14bB44992841e3dB35', - decimals: 18, - id: 'CUDOS', - name: 'CudosToken', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x35A18000230DA775CAc24873d00Ff85BccdeD550', - decimals: 8, - id: 'CUNI', - name: 'Compound Uniswap', - nativeAsset: 'ETH', - type: 'COMPOUND' - }, - { - contractAddress: '0x1410d4eC3D276C0eBbf16ccBE88A4383aE734eD0', - decimals: 18, - id: 'CUSD', - name: 'CarbonUSD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x765DE816845861e75A25fCA122bb6898B8B1282a', - decimals: 18, - id: 'CUSD_CELO', - name: 'Celo Dollar', - nativeAsset: 'CELO', - type: 'ERC20' - }, - { - contractAddress: '0x39AA39c021dfbaE8faC545936693aC917d5E7563', - decimals: 8, - id: 'CUSDC', - name: 'Compound USD Coin', - nativeAsset: 'ETH', - type: 'COMPOUND' - }, - { - contractAddress: '0xf650C3d88D12dB855b8bf7D11Be6C55A4e07dCC9', - decimals: 8, - id: 'CUSDT_ERC20', - name: 'cTether', - nativeAsset: 'ETH', - type: 'COMPOUND' - }, - { - contractAddress: '0x41e5560054824eA6B0732E656E3Ad64E20e94E45', - decimals: 8, - id: 'CVC', - name: 'Civic', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B', - decimals: 18, - id: 'CVX', - name: 'CVX', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x62B9c7356A2Dc64a1969e19C23e4f579F9810Aa7', - decimals: 18, - id: 'CVXCRV', - name: 'cvxCRV', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 9, - id: 'CWAR_SOL', - issuerAddress: 'HfYFjMKNZygfMC8LsQ8LtpPsPxEJoXJx4M6tqi75Hajo', - name: 'Cryowar Token (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0xC11b1268C1A384e55C48c2391d8d480264A3A7F4', - decimals: 8, - id: 'CWBTC', - name: 'cWBTC', - nativeAsset: 'ETH', - type: 'COMPOUND' - }, - { - contractAddress: '0xaC0104Cca91D167873B8601d2e71EB3D4D8c33e0', - decimals: 18, - id: 'CWS', - name: 'Crowns', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x7ABc8A5768E6bE61A6c693a6e4EAcb5B60602C4D', - decimals: 18, - id: 'CXT_B6QT1TZK_3BEN', - name: 'Covalent X Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x80a2AE356fc9ef4305676f7a3E2Ed04e12C33946', - decimals: 8, - id: 'CYFI', - name: 'Compound yearn.finance', - nativeAsset: 'ETH', - type: 'COMPOUND' - }, - { - contractAddress: '', - decimals: 6, - id: 'CYS_SOL', - issuerAddress: 'BRLsMczKuaR5w9vSubF4j8HwEGGprVAyyVgS4EX7DKEg', - name: 'Cyclos', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0xB3319f5D18Bc0D84dD1b4825Dcde5d5f7266d407', - decimals: 8, - id: 'CZRX', - name: 'Compound 0x', - nativeAsset: 'ETH', - type: 'COMPOUND' - }, - { - contractAddress: '0xA31108E5BAB5494560Db34c95492658AF239357C', - decimals: 18, - id: 'DACS', - name: 'DACSEE', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x5B322514FF727253292637D9054301600c2C81e8', - decimals: 9, - id: 'DAD', - name: 'DAD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xFc979087305A826c2B2a0056cFAbA50aad3E6439', - decimals: 18, - id: 'DAFI', - name: 'DAFI Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x6B175474E89094C44Da98b954EedeAC495271d0F', - decimals: 18, - id: 'DAI', - name: 'Dai', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3', - decimals: 18, - id: 'DAI_BSC', - name: 'Dai BSC Token', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0xd586E7F844cEa2F87f50152665BCbc2C279D8d70', - decimals: 18, - id: 'DAI_E', - name: 'Dai Stablecoin (Avalanche)', - nativeAsset: 'AVAX', - type: 'ERC20' - }, - { - contractAddress: '0x8D11eC38a3EB5E956B052f67Da8Bdc9bef8Abf3E', - decimals: 18, - id: 'DAI_FANTOM', - name: 'Dai Stablecoin (Fantom)', - nativeAsset: 'FTM_FANTOM', - type: 'ERC20' - }, - { - contractAddress: '0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063', - decimals: 18, - id: 'DAI_POLYGON', - name: '(PoS) Dai Stablecoin (Polygon)', - nativeAsset: 'MATIC_POLYGON', - type: 'ERC20' - }, - { - contractAddress: '0x0f51bb10119727a7e5eA3538074fb341F56B09Ad', - decimals: 18, - id: 'DAO', - name: 'DAO Maker', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 8, - id: 'DASH', - name: 'Dash', - nativeAsset: 'DASH', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 8, - id: 'DASH_TEST', - name: 'Dash Test', - nativeAsset: 'DASH_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x0Cf0Ee63788A0849fE5297F3407f701E122cC023', - decimals: 18, - id: 'DATA', - name: 'Streamr Data', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x8f693ca8D21b157107184d29D398A8D082b38b76', - decimals: 18, - id: 'DATA_ERC20', - name: 'Streamr', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x0B4BdC478791897274652DC15eF5C135cae61E60', - decimals: 18, - id: 'DAX', - name: 'DAEX Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'DCFG_TEST', - name: 'Centrifuge Test', - nativeAsset: 'DCFG_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x88EF27e69108B2633F8E1C184CC37940A075cC02', - decimals: 18, - id: 'DEGO', - name: 'dego.finance', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x3597bfD533a99c9aa083587B074434E61Eb0A258', - decimals: 8, - id: 'DENT', - name: 'DENT', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x1A3496C18d558bd9C6C8f609E1B129f67AB08163', - decimals: 18, - id: 'DEP', - name: 'DEAPCOIN', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xaB93dF617F51E1E415b5b4f8111f122d6b48e55C', - decimals: 18, - id: 'DETO', - name: 'Delta Exchange Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xfB7B4564402E5500dB5bB6d63Ae671302777C75a', - decimals: 18, - id: 'DEXT', - name: 'DEXTools', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x431ad2ff6a9C365805eBaD47Ee021148d6f7DBe0', - decimals: 18, - id: 'DF', - name: 'dForce', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x20c36f062a31865bED8a5B1e512D9a1A20AA333A', - decimals: 18, - id: 'DFD', - name: 'DefiDollar DAO', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x7CCC863EcE2E15bC45ac0565D410da7A3340aD98', - decimals: 18, - id: 'DFY', - name: 'Dotify Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x9695e0114e12C0d3A3636fAb5A18e6b737529023', - decimals: 18, - id: 'DFYN', - name: 'DFYN Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xC168E40227E4ebD8C1caE80F7a55a4F0e6D66C97', - decimals: 18, - id: 'DFYN_POLYGON', - name: 'DFYN Token (Polygon)', - nativeAsset: 'MATIC_POLYGON', - type: 'ERC20' - }, - { - contractAddress: '0x1C83501478f1320977047008496DACBD60Bb15ef', - decimals: 18, - id: 'DGTX', - name: 'Digitex', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xc666081073E8DfF8D3d1c2292A29aE1A2153eC09', - decimals: 18, - id: 'DGTX_ETH', - name: 'DigitexFutures', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x4f3AfEC4E5a3F2A6a1A411DEF7D7dFe50eE057bF', - decimals: 9, - id: 'DGX', - name: 'Digix Gold Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xca1207647Ff814039530D7d35df0e1Dd2e91Fa84', - decimals: 18, - id: 'DHT', - name: 'dHedge DAO', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x84cA8bc7997272c7CfB4D0Cd3D55cd942B3c9419', - decimals: 18, - id: 'DIA', - name: 'DIAToken', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xefA64D3d5431dBcE85eBCb87e51a5625243d1A55', - decimals: 5, - id: 'DIFX', - name: 'DigitalFinancialExch', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x798D1bE841a82a273720CE31c822C61a67a601C3', - decimals: 9, - id: 'DIGG', - name: 'Digg', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xAa9654BECca45B5BDFA5ac646c939C62b527D394', - decimals: 18, - id: 'DINO_POLYGON', - name: 'DinoSwap (Polygon)', - nativeAsset: 'MATIC_POLYGON', - type: 'ERC20' - }, - { - contractAddress: '0xc1411567d2670e24d9C4DaAa7CdA95686e1250AA', - decimals: 18, - id: 'DLLR_RSK_OYHI', - name: 'Sovryn Dollar', - nativeAsset: 'RBTC', - type: 'ERC20' - }, - { - contractAddress: '0x07e3c70653548B04f0A75970C1F81B4CBbFB606f', - decimals: 18, - id: 'DLT', - name: 'Agrello', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x0000000DE40dfa9B17854cBC7869D80f9F98D823', - decimals: 18, - id: 'DLTA', - name: 'delta.theta', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xEd91879919B71bB6905f23af0A68d231EcF87b14', - decimals: 18, - id: 'DMG', - name: 'DMM: Governance', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x82b0E50478eeaFde392D45D1259Ed1071B6fDa81', - decimals: 18, - id: 'DNA', - name: 'DNA', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x0AbdAce70D3790235af448C88547603b945604ea', - decimals: 18, - id: 'DNT', - name: 'district0x', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xe700691dA7b9851F2F35f8b8182c69c53CcaD9Db', - decimals: 18, - id: 'DOC_RBTC', - name: 'Dollar on Chain (RSK)', - nativeAsset: 'RBTC', - type: 'ERC20' - }, - { - contractAddress: '0xE5Dada80Aa6477e85d09747f2842f7993D0Df71C', - decimals: 18, - id: 'DOCK', - name: 'Dock', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x43Dfc4159D86F3A37A5A4B3D4580b888ad7d4DDd', - decimals: 18, - id: 'DODO', - name: 'DODO bird', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x67ee3Cb086F8a16f34beE3ca72FAD36F7Db929e2', - decimals: 18, - id: 'DODO_BSC', - name: 'DODO bird (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '', - decimals: 8, - id: 'DOGE', - name: 'Doge Coin', - nativeAsset: 'DOGE', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xbA2aE424d960c26247Dd6c32edC70B295c744C43', - decimals: 8, - id: 'DOGE_BSC', - name: 'Binance-Peg Dogecoin (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '', - decimals: 8, - id: 'DOGE_TEST', - name: 'Doge Coin Test', - nativeAsset: 'DOGE_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 9, - id: 'DOGS_TON', - issuerAddress: 'EQCvxJy4eG8hyHBFsZ7eePxrRsUQSFE_jpptRAYBmcG_DOGS', - name: 'Dogs (Ton)', - nativeAsset: 'TON', - type: 'TON_ASSET' - }, - { - contractAddress: '0xa2b5C6d877Ae7eb964E5E7c79F721D1c0085Ec0F', - decimals: 18, - id: 'DOPEX', - name: 'Dopex Governance Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 10, - id: 'DOT', - name: 'Polkadot', - nativeAsset: 'DOT', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x7083609fCE4d1d8Dc0C979AAb8c869Ea2C873402', - decimals: 18, - id: 'DOT_BSC', - name: 'Binance-Peg Polkadot (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0x1494CA1F11D487c2bBe4543E90080AeBa4BA3C2b', - decimals: 18, - id: 'DPI', - name: 'DefiPulse Index', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x9d561d63375672ABd02119b9Bc4FB90EB9E307Ca', - decimals: 18, - id: 'DRCT_ERC20', - name: 'Ally Direct Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x9400Aa8eb5126d20CDE45C7822836BFB70F19878', - decimals: 18, - id: 'DRF_BSC', - name: 'DRIFE', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0x814F67fA286f7572B041D041b1D99b432c9155Ee', - decimals: 8, - id: 'DRG', - name: 'Dragon Coins', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xBD2F0Cd039E0BFcf88901C98c0bFAc5ab27566e3', - decimals: 18, - id: 'DSD', - name: 'Dynamic Set Dollar', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'DSETH_DEV', - name: 'dSETH (Dev)', - nativeAsset: 'DSETH_DEV', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x940a2dB1B7008B6C776d4faaCa729d6d4A4AA551', - decimals: 18, - id: 'DUSK', - name: 'Dusk Network', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'DV4TNT_TEST', - name: 'DYDX Test', - nativeAsset: 'DV4TNT_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xDDdddd4301A082e62E84e43F474f044423921918', - decimals: 18, - id: 'DVF', - name: 'DeversiFi Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x10633216E7E8281e33c86F02Bf8e565a635D9770', - decimals: 18, - id: 'DVI', - name: 'Dvision', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xa1d65E8fB6e87b60FECCBc582F7f97804B725521', - decimals: 18, - id: 'DXD', - name: 'DXdao', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'DXL_SOL', - issuerAddress: 'GsNzxJfFn6zQdJGeYsupJWzUAm57Ba7335mfhWvFiE9Z', - name: 'Dexlab (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x92D6C1e31e14520e676a687F0a93788B716BEff5', - decimals: 18, - id: 'DYDX', - name: 'dYdX', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'DYDX_DYDX', - name: 'DYDX', - nativeAsset: 'DYDX_DYDX', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 8, - id: 'DYDX_SOL', - issuerAddress: '4Hx6Bj56eGyw8EJrrheM6LBQAvVYRikYCWsALeTrwyRU', - name: 'dYdX (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x900b4449236a7bb26b286601dD14d2bDe7a6aC6c', - decimals: 8, - id: 'EARTH', - name: 'Earth Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x913D8ADf7CE6986a8CbFee5A54725D9Eea4F0729', - decimals: 18, - id: 'EASY', - name: 'EASY', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x9eaD0844ea0e890CD0eC6A01e4b65288E6FB20B3', - decimals: 2, - id: 'EAUD', - name: 'FX-T0 eAUD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x9872E14A43482098c400050D21293778AbA28EDf', - decimals: 2, - id: 'ECAD', - name: 'FX-T0 eCAD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xcEcB588AF34B1573e87ef66f612329d12BD3D902', - decimals: 2, - id: 'ECHF', - name: 'FX-T0 eCHF', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x1559FA1b8F28238FD5D76D9f434ad86FD20D1559', - decimals: 18, - id: 'EDEN', - name: 'Eden', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xc528c28FEC0A90C083328BC45f587eE215760A0F', - decimals: 18, - id: 'EDR', - name: 'Endor', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x847a5c271421d53872C559e37F525A73057eCA5e', - decimals: 2, - id: 'EEUR', - name: 'FX-T0 eEUR', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x656C00e1BcD96f256F224AD9112FF426Ef053733', - decimals: 18, - id: 'EFI', - name: 'Efinity Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x575990152169e1C1a4867E81C6AE662caEf068fd', - decimals: 18, - id: 'EFRONTIERUSD', - name: 'EfrontierUSD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x99445865D67B7F15Be5a7DA5D6461a4cbF7803CD', - decimals: 2, - id: 'EGBP', - name: 'FX-T0 eGBP', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xF29F7F4159AD97DEBDd4b187cA48966555e4A723', - decimals: 0, - id: 'EJPY', - name: 'FX-T0 eJPY', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xbf2179859fc6D5BEE9Bf9158632Dc51678a4100e', - decimals: 18, - id: 'ELF', - name: 'aelf', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x761D38e5ddf6ccf6Cf7c55759d5210750B5D60F3', - decimals: 18, - id: 'ELON_ETH', - name: 'Dogelon', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xd6A5aB46ead26f49b03bBB1F9EB1Ad5c1767974a', - decimals: 18, - id: 'EMON', - name: 'EthermonToken', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x95dAaaB98046846bF4B2853e23cba236fa394A31', - decimals: 8, - id: 'EMONT', - name: 'EtheremonToken', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xbdbC2a5B32F3a5141ACd18C39883066E4daB9774', - decimals: 8, - id: 'EMRX', - name: 'Emirex Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x074699497F924682229f2Beee64aaC6F6e05F5c4', - decimals: 2, - id: 'EMXN', - name: 'FX-T0 eMXN', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x6eCD91444f3570E28608B718c31bF3C111Ea5D8F', - decimals: 18, - id: 'ENDEREDGEUSD', - name: 'EnderEdgeUSD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xf0Ee6b27b759C9893Ce4f094b49ad28fd15A23e4', - decimals: 8, - id: 'ENG', - name: 'Enigma', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xF629cBd94d3791C9250152BD8dfBDF380E2a3B9c', - decimals: 18, - id: 'ENJ', - name: 'Enjin Coin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xC18360217D8F7Ab5e7c516566761Ea12Ce7F9D72', - decimals: 18, - id: 'ENS2', - name: 'Ethereum Name Service', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x9A24B8E8A6D4563c575A707b1275381119298E60', - decimals: 18, - id: 'ENVY', - name: 'EVNY Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x1067756c6d6292651B33ba9e4586f5d2893A08d4', - decimals: 2, - id: 'ENZD', - name: 'FX-T0 eNZD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 4, - id: 'EOS', - name: 'EOS', - nativeAsset: 'EOS', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 4, - id: 'EOS_TEST', - name: 'EOS Test', - nativeAsset: 'EOS_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xDaF88906aC1DE12bA2b1D2f7bfC94E9638Ac40c4', - decimals: 18, - id: 'EPK', - name: 'EpiK Protocol', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xA7f552078dcC247C2684336020c03648500C6d9F', - decimals: 18, - id: 'EPS_BSC', - name: 'Ellipsis (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0x8eCb1cA966b6804B129D3c0F9771e079cbF48EFe', - decimals: 18, - id: 'EPT', - name: 'e-Pocket', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xF9986D445ceD31882377b5D6a5F58EaEa72288c3', - decimals: 18, - id: 'ERD', - name: 'Elrond', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xBBc2AE13b23d715c30720F079fcd9B4a74093505', - decimals: 18, - id: 'ERN', - name: 'EthernityChain Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x92A5B04D0ED5D94D7a193d1d334D3D16996f4E13', - decimals: 18, - id: 'ERT', - name: 'Eristica', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xE4Cfc3259c678Cc4d69D18E90E9A52764D8725ea', - decimals: 2, - id: 'ERUB', - name: 'FX-T0 eRUB', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x36F3FD68E7325a35EB768F1AedaAe9EA0689d723', - decimals: 18, - id: 'ESD', - name: 'Empty Set Dollar', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'ETC', - name: 'Ethereum Classic', - nativeAsset: 'ETC', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'ETC_TEST', - name: 'Ethereum Classic Test', - nativeAsset: 'ETC_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'ETH', - name: 'Ethereum', - nativeAsset: 'ETH', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x2170Ed0880ac9A755fd29B2688956BD959F933F8', - decimals: 18, - id: 'ETH_BSC', - name: 'Binance-Peg Ethereum (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0x74b23882a30290451A17c44f4F05243b6b58C76d', - decimals: 18, - id: 'ETH_FTM', - name: 'Multichain Bridged WETH', - nativeAsset: 'FTM_FANTOM', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 8, - id: 'ETH_SOL', - issuerAddress: '7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs', - name: 'Ether (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'ETH_TEST5', - name: 'Ethereum Test (Sepolia)', - nativeAsset: 'ETH_TEST5', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'ETH_TEST6', - name: 'Ethereum Test (Holesky)', - nativeAsset: 'ETH_TEST6', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'ETH_ZKEVM', - name: 'Ethereum (zkEVM)', - nativeAsset: 'ETH_ZKEVM', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'ETH_ZKEVM_TEST', - name: 'Ethereum (zkEVM Test)', - nativeAsset: 'ETH_ZKEVM_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'ETH_ZKSYNC_ERA', - name: 'Ethereum (zkSync Era)', - nativeAsset: 'ETH_ZKSYNC_ERA', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'ETH_ZKSYNC_ERA_SEPOLIA', - name: 'Ethereum (zkSync Era Sepolia)', - nativeAsset: 'ETH_ZKSYNC_ERA_SEPOLIA', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'ETH_ZKSYNC_ERA_TEST', - name: 'Ethereum (zkSync Era Test)', - nativeAsset: 'ETH_ZKSYNC_ERA_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'ETH-AETH', - name: 'Ethereum (Arbitrum)', - nativeAsset: 'ETH-AETH', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'ETH-AETH_RIN', - name: 'Arbitrum Rinkeby', - nativeAsset: 'ETH-AETH_RIN', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'ETH-AETH_SEPOLIA', - name: 'Arbitrum Sepolia', - nativeAsset: 'ETH-AETH_SEPOLIA', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'ETH-OPT', - name: 'Optimistic Ethereum', - nativeAsset: 'ETH-OPT', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'ETH-OPT_KOV', - name: 'Optimistic Ethereum (Kovan)', - nativeAsset: 'ETH-OPT_KOV', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'ETH-OPT_SEPOLIA', - name: 'Optimistic Ethereum (Sepolia)', - nativeAsset: 'ETH-OPT_SEPOLIA', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'ETHW', - name: 'EthereumPoW', - nativeAsset: 'ETHW', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xdBd4d868854575867b9403e751837c9957A016ab', - decimals: 2, - id: 'ETRY', - name: 'FX-T0 eTRY', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x6aB4A7d75B0A42B6Bc83E852daB9E121F9C610Aa', - decimals: 18, - id: 'EUM', - name: 'Elitium', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 7, - id: 'EURC_XLM', - issuerAddress: 'GDHU6WRG4IEQXM5NZ4BMPKOXHW76MZM4Y2IEMFDVXBSDP6SJY4ITNPP2', - name: 'EURC (Stellar)', - nativeAsset: 'XLM', - type: 'XLM_ASSET' - }, - { - contractAddress: '0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c', - decimals: 6, - id: 'EUROC_ETH_F5NG', - name: 'EURC', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xdB25f211AB05b1c97D595516F45794528a807ad8', - decimals: 2, - id: 'EURS', - name: 'STASIS EURS Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xC581b735A1688071A1746c968e0798D642EDE491', - decimals: 6, - id: 'EURT_ERC20', - name: 'Tether EUR (ERC20)', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xf756b5A7209D905d3897A2efB41e2C94b60d1149', - decimals: 2, - id: 'EUSD', - name: 'FX-T0 eUSD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'EVMOS', - name: 'Evmos', - nativeAsset: 'EVMOS', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x9aF15D7B8776fa296019979E70a5BE53c714A7ec', - decimals: 18, - id: 'EVN', - name: 'Evn Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xf3Db5Fa2C66B7aF3Eb0C0b782510816cbe4813b8', - decimals: 4, - id: 'EVX', - name: 'Everex', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x1E8D772EC5085578bDA258b696453e323296e048', - decimals: 8, - id: 'EXD', - name: 'Escada', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x6468e79A80C0eaB0F9A2B574c8d5bC374Af59414', - decimals: 18, - id: 'EXRD', - name: 'E-RADIX', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x5512014efa6Cd57764Fa743756F7a6Ce3358cC83', - decimals: 18, - id: 'EZ_BSC', - name: 'EASY V2 (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0xED18EA36382838ED0039b3a197EB6BAa4B59BE7F', - decimals: 2, - id: 'EZAR', - name: 'FX-T0 eZAR', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x1D3E6CC37b930977dFF8452cEE7b5db870e71679', - decimals: 18, - id: 'FALCONXUSD', - name: 'FalconXUSD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'FANT_SOL', - issuerAddress: 'FANTafPFBAt93BNJVpdu25pGPmca3RfwdsDsRrT3LX1r', - name: 'Phantasia (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'FASTEX_BAHAMUT', - name: 'Fastex Bahamut', - nativeAsset: 'FASTEX_BAHAMUT', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 8, - id: 'FB_ATHENA_TEST', - name: 'FB Private Test', - nativeAsset: 'FB_ATHENA_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xF4d861575ecC9493420A3f5a14F85B13f0b50EB3', - decimals: 18, - id: 'FCL', - name: 'Fractal Protocol Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x956F47F50A910163D8BF957Cf5846D573E7f87CA', - decimals: 18, - id: 'FEI', - name: 'Fei USD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xaea46A60368A7bD060eec7DF8CBa43b7EF41Ad85', - decimals: 18, - id: 'FET', - name: 'Fetch', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x0D8Ce2A99Bb6e3B7Db580eD848240e4a0F9aE153', - decimals: 18, - id: 'FIL_BSC', - name: 'Binance-Peg Filecoin (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0xef3A930e1FfFFAcd2fc13434aC81bD278B0ecC8d', - decimals: 18, - id: 'FIS', - name: 'StaFi', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x3a3Df212b7AA91Aa0402B9035b098891d276572B', - decimals: 18, - id: 'FISH_POLYGON', - name: 'Polycat Finance (Polygon)', - nativeAsset: 'MATIC_POLYGON', - type: 'ERC20' - }, - { - contractAddress: '0xFcF8eda095e37A41e002E266DaAD7efC1579bc0A', - decimals: 18, - id: 'FLEX', - name: 'FLEX Coin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x98Dd7eC28FB43b3C4c770AE532417015fa939Dd3', - decimals: 18, - id: 'FLEX_SMARTBCH', - name: 'FLEX Coin (SmartBCH)', - nativeAsset: 'SMARTBCH', - type: 'ERC20' - }, - { - contractAddress: '0x2B93824ad1c8c2DD79351FaCaE9473eAEf062366', - decimals: 18, - id: 'FLEXBTC', - name: 'flexBTC', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x40fB4096E0ACbf97D0087C3b7e4c6794Aa24a32f', - decimals: 18, - id: 'FLEXETH', - name: 'flexETH', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xa774FFB4AF6B0A91331C084E1aebAE6Ad535e6F3', - decimals: 18, - id: 'FLEXUSD', - name: 'flexUSD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x7b2B3C5308ab5b2a1d9a94d20D35CCDf61e05b72', - decimals: 18, - id: 'FLEXUSD_SMARTBCH', - name: 'flexUSD (SmartBCH)', - nativeAsset: 'SMARTBCH', - type: 'ERC20' - }, - { - contractAddress: '0x43f11c02439e2736800433b4594994Bd43Cd066D', - decimals: 9, - id: 'FLOKI', - name: 'FLOKI old', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x2B3F34e9D4b127797CE6244Ea341a83733ddd6E4', - decimals: 9, - id: 'FLOKI_BSC', - name: 'FLOKI old (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '', - decimals: 18, - id: 'FLR', - name: 'Flare', - nativeAsset: 'FLR', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x6243d8CEA23066d098a15582d81a598b4e8391F4', - decimals: 18, - id: 'FLX', - name: 'Flex Ungovernance Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x7bf3B1922F00C106865fE97a9767b445975D0f71', - decimals: 18, - id: 'FLY', - name: 'Fly Coin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x85f6eB2BD5a062f5F8560BE93FB7147e16c81472', - decimals: 4, - id: 'FLY_1', - name: 'Franklin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x314f951d144b397a088EA9eAc5218bdC7db2Ed4a', - decimals: 18, - id: 'FLY_OLD', - name: 'Fly Coin (Old)', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x67c4729aD44201972E8Bf5Ad2addaBE9DFea4e37', - decimals: 18, - id: 'FLY_SMARTBCH', - name: 'Fly Coin (SmartBCH)', - nativeAsset: 'SMARTBCH', - type: 'ERC20' - }, - { - contractAddress: '0x4946Fcea7C692606e8908002e55A582af44AC121', - decimals: 18, - id: 'FOAM', - name: 'FOAM', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x4C2e59D098DF7b6cBaE0848d66DE2f8A4889b9C3', - decimals: 18, - id: 'FODL', - name: 'Fodl', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xe14026c2f4EdD463791DA1991c74Cf16975942f6', - decimals: 18, - id: 'FOLKVANGUSD', - name: 'FolkvangUSD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x1FCdcE58959f536621d76f5b7FfB955baa5A672F', - decimals: 18, - id: 'FOR', - name: 'The Force Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xDb298285FE4C5410B05390cA80e8Fbe9DE1F259B', - decimals: 18, - id: 'FOREX', - name: 'handleFOREX', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x77FbA179C79De5B7653F68b5039Af940AdA60ce0', - decimals: 18, - id: 'FORTH', - name: 'Ampleforth Governance', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d', - decimals: 18, - id: 'FOX', - name: 'FOX', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x853d955aCEf822Db058eb8505911ED77F175b99e', - decimals: 18, - id: 'FRAX', - name: 'Frax', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xD24C2Ad096400B6FBcd2ad8B24E7acBc21A1da64', - decimals: 18, - id: 'FRAX_AVAX', - name: 'Frax (Avalanche)', - nativeAsset: 'AVAX', - type: 'ERC20' - }, - { - contractAddress: '0xf8C3527CC04340b208C854E985240c02F7B7793f', - decimals: 18, - id: 'FRONT', - name: 'Frontier Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xD0352a019e9AB9d757776F532377aAEbd36Fd541', - decimals: 18, - id: 'FSN', - name: 'Fusion', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x0E192d382a36De7011F795Acc4391Cd302003606', - decimals: 18, - id: 'FST', - name: 'Futureswap Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x274AA8B58E8C57C4e347C8768ed853Eb6D375b48', - decimals: 18, - id: 'FSUSHI', - name: 'FARM_SUSHI', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x4E15361FD6b4BB609Fa63C81A2be19d873717870', - decimals: 18, - id: 'FTM', - name: 'Fantom Token (ERC20)', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xAD29AbB318791D579433D831ed122aFeAf29dcfe', - decimals: 18, - id: 'FTM_BSC', - name: 'Fantom (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '', - decimals: 18, - id: 'FTM_FANTOM', - name: 'Fantom', - nativeAsset: 'FTM_FANTOM', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x50D1c9771902476076eCFc8B2A83Ad6b9355a4c9', - decimals: 18, - id: 'FTT', - name: 'FTX Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 8, - id: 'FTT_SOL', - issuerAddress: 'EzfgjvkSwthhgHaceR3LnKXUoRkP6NUhfghdaHAj1tUv', - name: 'FTX Token (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', - decimals: 8, - id: 'FUN', - name: 'FunFair', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x35bD01FC9d6D5D81CA9E055Db88Dc49aa2c699A8', - decimals: 18, - id: 'FWB', - name: 'Friends With Benefits Pro', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x8a40c222996f9F3431f63Bf80244C36822060f12', - decimals: 18, - id: 'FXF', - name: 'Finxflo', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0', - decimals: 18, - id: 'FXS', - name: 'Frax Share', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x214DB107654fF987AD859F34125307783fC8e387', - decimals: 18, - id: 'FXS_AVAX', - name: 'Frax Share (Avalanche)', - nativeAsset: 'AVAX', - type: 'ERC20' - }, - { - contractAddress: '0xaaEfF6C96F952Fc67379dcFa1667fC32AF02069B', - decimals: 18, - id: 'FXTE', - name: 'FutureX Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x15D4c048F83bd7e37d49eA4C83a07267Ec4203dA', - decimals: 8, - id: 'GALA', - name: 'Gala V1', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xd1d2Eb1B1e90B638588728b4130137D262C87cae', - decimals: 8, - id: 'GALA2', - name: 'Gala V2', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x63f88A2298a5c4AEE3c216Aa6D926B184a4b2437', - decimals: 18, - id: 'GAME', - name: 'Game Credits', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 9, - id: 'GARI_SOL', - issuerAddress: 'CKaKtYvz6dKPyMvYq9Rh3UBrnNqYZAyd7iF4hJtjUvks', - name: 'Gari (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x9d7630aDF7ab0b0CB00Af747Db76864df0EC82E4', - decimals: 18, - id: 'GATE', - name: 'GATE', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x86B4dBE5D203e634a12364C0e428fa242A3FbA98', - decimals: 18, - id: 'GBPT_ETH_APNR', - name: 'poundtoken', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xc67B12049c2D0CF6e476BC64c7F82fc6C63cFFc5', - decimals: 8, - id: 'GDT', - name: 'Globe Derivative Exchange', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 9, - id: 'GENE_SOL', - issuerAddress: 'GENEtH5amGSi8kHAtQoezp1XEXwZJ8vcuePYnXdKrMYz', - name: 'Genopets (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x8a854288a5976036A725879164Ca3e91d30c6A1B', - decimals: 18, - id: 'GET', - name: 'GET Protocol', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xAaEf88cEa01475125522e117BFe45cF32044E238', - decimals: 18, - id: 'GF', - name: 'GuildFi Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x7F969C4D388Ca0AE39A4FdDB1A6f89878CA2fBf8', - decimals: 18, - id: 'GGC', - name: 'GGCOIN', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x3F382DbD960E3a9bbCeaE22651E88158d2791550', - decimals: 18, - id: 'GHST', - name: 'Aavegotchi GHST Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x038a68FF68c393373eC894015816e33Ad41BD564', - decimals: 18, - id: 'GLCH', - name: 'Glitch', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x7DD9c5Cba05E151C895FDe1CF355C9A1D5DA6429', - decimals: 18, - id: 'GLM', - name: 'Golem Network Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'GLMR_GLMR', - name: 'Moonbeam', - nativeAsset: 'GLMR_GLMR', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 9, - id: 'GMT_SOL', - issuerAddress: '7i5KKsX2weiTkry7jA4ZwSuXGhs5eJBEjY8vVxR4pfRx', - name: 'GMT _Solana_', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x6810e776880C02933D47DB1b9fc05908e5386b96', - decimals: 18, - id: 'GNO', - name: 'Gnosis', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xa74476443119A942dE498590Fe1f2454d7D4aC0d', - decimals: 18, - id: 'GNT', - name: 'Golem', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 9, - id: 'GOFX_SOL', - issuerAddress: 'GFX1ZjR2P15tmrSwow6FjyDYcEkoFb4p4gJCpLBjaxHD', - name: 'GooseFX', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x0ab87046fBb341D058F17CBC4c1133F25a20a52f', - decimals: 18, - id: 'GOHM', - name: 'Governance OHM', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xeEAA40B28A2d1b0B08f6f97bB1DD4B75316c6107', - decimals: 18, - id: 'GOVI', - name: 'GOVI', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x71dF9Dd3e658f0136c40E2E8eC3988a5226E9A67', - decimals: 18, - id: 'GRAPEFRUITUSD', - name: 'GrapefruitUSD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x09e64c2B61a5f1690Ee6fbeD9baf5D6990F8dFd0', - decimals: 18, - id: 'GRO', - name: 'Growth', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xc944E90C64B2c07662A292be6244BDf05Cda44a7', - decimals: 18, - id: 'GRT', - name: 'Graph Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x228ba514309FFDF03A81a205a6D040E429d6E80C', - decimals: 18, - id: 'GSC', - name: 'Global Social Chain', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xe530441f4f73bDB6DC2fA5aF7c3fC5fD551Ec838', - decimals: 4, - id: 'GSE', - name: 'GSENetwork', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xB70835D7822eBB9426B56543E391846C107bd32C', - decimals: 18, - id: 'GTC', - name: 'Game.com', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xDe30da39c46104798bB5aA3fe8B9e0e1F348163F', - decimals: 18, - id: 'GTC_ETH', - name: 'Gitcoin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'GUN_TEST', - name: 'GUN_TEST', - nativeAsset: 'GUN_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xf7B098298f7C69Fc14610bf71d5e02c60792894C', - decimals: 3, - id: 'GUP', - name: 'Matchpool', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x056Fd409E1d7A124BD7017459dFEa2F387b6d5Cd', - decimals: 2, - id: 'GUSD', - name: 'Gemini USD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xC08512927D12348F6620a698105e1BAac6EcD911', - decimals: 6, - id: 'GYEN', - name: 'GMO JPY', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x4AC00f287f36A6Aad655281fE1cA6798C9cb727b', - decimals: 18, - id: 'GZE', - name: 'GazeCoin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 8, - id: 'HBAR', - name: 'Hedera Hashgraph', - nativeAsset: 'HBAR', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 8, - id: 'HBAR_TEST', - name: 'Hedera Hashgraph Test', - nativeAsset: 'HBAR_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 6, - id: 'HBB_SPL', - issuerAddress: 'HBB111SCo9jkCejsZfz8Ec8nH7T6THF8KEKSnvwT6XK6', - name: 'Hubble Protocol Token (SPL)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x0316EB71485b0Ab14103307bf65a021042c6d380', - decimals: 18, - id: 'HBTC', - name: 'Huobi BTC', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xE34e1944E776f39B9252790a0527eBDa647aE668', - decimals: 18, - id: 'HBZ', - name: 'HBZ coin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xF1290473E210b2108A85237fbCd7b6eb42Cc654F', - decimals: 18, - id: 'HEDG', - name: 'HEDG', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x584bC13c7D411c00c01A62e8019472dE68768430', - decimals: 18, - id: 'HEGIC', - name: 'Hegic', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x49C7295ff86EaBf5bf58C6eBC858DB4805738c01', - decimals: 18, - id: 'HERA_BSC', - name: 'Hero Arena', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0x2b591e99afE9f32eAA6214f7B7629768c40Eeb39', - decimals: 8, - id: 'HEX', - name: 'HEX', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x77087aB5Df23cFB52449A188e80e9096201c2097', - decimals: 18, - id: 'HI_BSC', - name: 'hi Dollar (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0xd1ba9BAC957322D6e8c07a160a3A8dA11A0d2867', - decimals: 18, - id: 'HMT', - name: 'Human Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 8, - id: 'HNT_SOL', - issuerAddress: 'hntyVP6YFm1Hg25TN9WGLqM12b8TQmcknKrdu1oxWux', - name: 'Helium Network Token (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x6c6EE5e31d828De241282B9606C8e98Ea48526E2', - decimals: 18, - id: 'HOT1', - name: 'Holo', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x9AF839687F6C94542ac5ece2e317dAAE355493A1', - decimals: 18, - id: 'HOT2', - name: 'Hydro Protocol', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x554C20B7c486beeE439277b4540A434566dC4C02', - decimals: 18, - id: 'HST', - name: 'Decision Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x6f259637dcD74C767781E37Bc6133cd6A68aa161', - decimals: 18, - id: 'HT', - name: 'Huobi Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'HT_CHAIN', - name: 'HT Chain', - nativeAsset: 'HT_CHAIN', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'HT_CHAIN_TEST', - name: 'HT Chain Test', - nativeAsset: 'HT_CHAIN_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xdF574c24545E5FfEcb9a659c229253D4111d87e1', - decimals: 8, - id: 'HUSD', - name: 'Huobi USD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x4bD70556ae3F8a6eC6C4080A0C327B24325438f3', - decimals: 18, - id: 'HXRO', - name: 'Hxro', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 2, - id: 'IBAN_CHF', - name: 'CHF (IBAN)', - nativeAsset: 'IBAN_CHF', - type: 'FIAT' - }, - { - contractAddress: '', - decimals: 2, - id: 'IBAN_EUR', - name: 'EUR (IBAN)', - nativeAsset: 'IBAN_EUR', - type: 'FIAT' - }, - { - contractAddress: '', - decimals: 2, - id: 'IBAN_SGD', - name: 'SGD (IBAN)', - nativeAsset: 'IBAN_SGD', - type: 'FIAT' - }, - { - contractAddress: '', - decimals: 2, - id: 'IBAN_USD', - name: 'USD (IBAN)', - nativeAsset: 'IBAN_USD', - type: 'FIAT' - }, - { - contractAddress: '0xf16e81dce15B08F326220742020379B855B87DF9', - decimals: 18, - id: 'ICE', - name: 'Ice Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xB705268213D593B8FD88d3FDEFF93AFF5CbDcfAE', - decimals: 18, - id: 'IDEX', - name: 'IDEX Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x61fd1c62551850D0c04C76FcE614cBCeD0094498', - decimals: 8, - id: 'IDK', - name: 'IDKToken', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x12c5E73Ddb44cD70225669B9F6f0d9DE5455Bc31', - decimals: 18, - id: 'IDON', - name: 'Idoneus Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x998FFE1E43fAcffb941dc337dD0468d52bA5b48A', - decimals: 2, - id: 'IDRT', - name: 'Rupiah', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x66207E39bb77e6B99aaB56795C7c340C08520d83', - decimals: 2, - id: 'IDRTBEP_BSC', - name: 'Rupiah Token (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0x9f059eDcf1C111e9C5987f884abBfEc0F80acFbB', - decimals: 2, - id: 'IDRTBEP_BSC_TEST', - name: 'Rupiah Token (BSC TEST)', - nativeAsset: 'BNB_TEST', - type: 'BEP20' - }, - { - contractAddress: '0xF784682C82526e245F50975190EF0fff4E4fC077', - decimals: 8, - id: 'ILK', - name: 'Inlock Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x767FE9EDC9E0dF98E07454847909b5E959D7ca0E', - decimals: 18, - id: 'ILV', - name: 'Illuvium', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x13119E34E140097a507B07a5564bDe1bC375D9e6', - decimals: 18, - id: 'IMT', - name: 'Moneytoken', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xF57e7e7C23978C3cAEC3C3548E3D615c346e79fF', - decimals: 18, - id: 'IMX_ERC20', - name: 'Immutable X', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'IMX_ZKEVM', - name: 'Immutable zkEVM', - nativeAsset: 'IMX_ZKEVM', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'IMX_ZKEVM_TEST', - name: 'Immutable zkEVM Test', - nativeAsset: 'IMX_ZKEVM_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x17Aa18A4B64A55aBEd7FA543F2Ba4E91f2dcE482', - decimals: 18, - id: 'INB', - name: 'Insight Chain', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x0954906da0Bf32d5479e25f46056d22f08464cab', - decimals: 18, - id: 'INDEX', - name: 'Index', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xe28b3B32B6c345A34Ff64674606124Dd5Aceca30', - decimals: 18, - id: 'INJ', - name: 'Injective Token (Ethereum)', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'INJ_INJ', - name: 'Injective', - nativeAsset: 'INJ_INJ', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'INJ_TEST', - name: 'Injective Test', - nativeAsset: 'INJ_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x5B2e4a700dfBc560061e957edec8F6EeEb74a320', - decimals: 10, - id: 'INS', - name: 'Insolar', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x6f40d4A6237C257fff2dB00FA0510DeEECd303eb', - decimals: 18, - id: 'INST', - name: 'Instadapp', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x544c42fBB96B39B21DF61cf322b5EDC285EE7429', - decimals: 18, - id: 'INSUR', - name: 'InsurAce', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xBBC7f7A6AADAc103769C66CBC69AB720f7F9Eae3', - decimals: 18, - id: 'INX', - name: 'INX token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xa8006C4ca56F24d6836727D106349320dB7fEF82', - decimals: 8, - id: 'INXT', - name: 'Internxt', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x02D3A27Ac3f55d5D91Fb0f52759842696a864217', - decimals: 18, - id: 'IONX', - name: 'Charged Particles - IONX', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xFA1a856Cfa3409CFa145Fa4e20Eb270dF3EB21ab', - decimals: 18, - id: 'IOST', - name: 'IOST', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xd944f1D1e9d5f9Bb90b62f9D45e447D989580782', - decimals: 6, - id: 'IOTA_BSC', - name: 'MIOTAC (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '', - decimals: 18, - id: 'IOTA_EVM', - name: 'IOTA EVM', - nativeAsset: 'IOTA_EVM', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x6fB3e0A217407EFFf7Ca062D46c26E5d60a14d69', - decimals: 18, - id: 'IOTX', - name: 'IoTeX', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'IOTX_IOTEX', - name: 'IoTex', - nativeAsset: 'IOTX_IOTEX', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x001F0aA5dA15585e5b2305DbaB2bac425ea71007', - decimals: 18, - id: 'IPSX', - name: 'IP Exchange', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xF88b137cfa667065955ABD17525e89EDCF4D6426', - decimals: 18, - id: 'ITG', - name: 'iTrust Governance Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x585E7bC75089eD111b656faA7aeb1104F5b96c15', - decimals: 8, - id: 'JLINK_AVAX', - name: 'Banker Joe Link (Avalanche)', - nativeAsset: 'AVAX', - type: 'ERC20' - }, - { - contractAddress: '0xeD8CBD9F0cE3C6986b22002F03c6475CEb7a6256', - decimals: 18, - id: 'JLP_AVAX', - name: 'Joe LP Token (Avalanche)', - nativeAsset: 'AVAX', - type: 'ERC20' - }, - { - contractAddress: '0x6e84a6216eA6dACC71eE8E6b0a5B7322EEbC0fDd', - decimals: 18, - id: 'JOE_AVAX', - name: 'JoeToken (Avalanche)', - nativeAsset: 'AVAX', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 9, - id: 'JTO_SOL', - issuerAddress: 'jtojtomepa8beP8AuQc6eXt5FriJwfFMwQx2v2f9mCL', - name: 'JITO (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x4B1E80cAC91e2216EEb63e29B957eB91Ae9C2Be8', - decimals: 18, - id: 'JUP', - name: 'Jupiter', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'JUP_SOL', - issuerAddress: 'JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN', - name: 'Jupiter (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x16EB2971863587fb93E33619772361ecc013cdcC', - decimals: 18, - id: 'KARD', - name: 'Kard Coin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x2BEb7C3c63Df4C2167839cD7F532338d15beB441', - decimals: 18, - id: 'KATLAUSD', - name: 'KatlaUSD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x08d1E0A7fBd4eDBF56D81Da21D1b0c9c95Fb507F', - decimals: 18, - id: 'KAVA', - name: 'Kava', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'KAVA_KAVA', - name: 'KAVA', - nativeAsset: 'KAVA_KAVA', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xf3586684107CE0859c44aa2b2E0fB8cd8731a15a', - decimals: 7, - id: 'KBC', - name: 'Karatgold Coin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xf34960d9d60be18cC1D5Afc1A6F012A723a28811', - decimals: 6, - id: 'KCS', - name: 'KuCoin Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x95E40E065AFB3059dcabe4aaf404c1F92756603a', - decimals: 18, - id: 'KDAG', - name: 'King DAG', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x85Eee30c52B0b379b046Fb0F85F4f3Dc3009aFEC', - decimals: 18, - id: 'KEEP', - name: 'Keep Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x4ABB9cC67BD3da9Eb966d1159A71a0e68BD15432', - decimals: 18, - id: 'KEL', - name: 'KelVpn Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x4CC19356f2D37338b9802aa8E8fc58B0373296E7', - decimals: 18, - id: 'KEY', - name: 'SelfKey', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xEF53462838000184F35f7D991452e5f25110b207', - decimals: 18, - id: 'KFT', - name: 'Knit Finance', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x818Fc6C2Ec5986bc6E2CBf00939d90556aB12ce5', - decimals: 18, - id: 'KIN', - name: 'Kin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 5, - id: 'KIN_SOL', - issuerAddress: 'kinXdEcpDQeHPEuQnqmUgtYykqKGVFq6CeVX5iAHJq6', - name: 'KIN (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0xCbfef8fdd706cde6F208460f2Bf39Aa9c785F05D', - decimals: 18, - id: 'KINE', - name: 'Kine Governance Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xB1191F691A355b43542Bea9B8847bc73e7Abb137', - decimals: 18, - id: 'KIRO', - name: 'Kirobo', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'KLAY_KAIA', - name: 'Kaia', - nativeAsset: 'KLAY_KAIA', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xdeFA4e8a7bcBA345F687a2f1456F5Edd9CE97202', - decimals: 18, - id: 'KNC', - name: 'Kyber Network Crystal v2', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xdd974D5C2e2928deA5F71b9825b8b646686BD200', - decimals: 18, - id: 'KNC_OLD', - name: 'Kyber Network (Old)', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x7c3E3eAE4d893d11C61E74d5187C962Ba5744A3B', - decimals: 18, - id: 'KOKO', - name: 'Kokoswap Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x7320c128e89bA4584Ab02ed1C9c96285b726443C', - decimals: 18, - id: 'KOKO_BSC', - name: 'Kokoswap Token', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0x1cEB5cB57C4D4E2b2433641b95Dd330A33185A44', - decimals: 18, - id: 'KP3R', - name: 'Keep3rV1', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 12, - id: 'KSM', - name: 'Kusama', - nativeAsset: 'KSM', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x2aa69E8D25C045B659787BC1f03ce47a388DB6E8', - decimals: 18, - id: 'KSM_BSC', - name: 'Kusama (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0xac826952bc30504359a099c3a486d44E97415c77', - decimals: 6, - id: 'KUSDC', - name: 'kUSDCoin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x3a859b9ea4998D344547283C7Ce8EBc4aBb77656', - decimals: 0, - id: 'KVT', - name: 'KinesisVelocityToken', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'LAC', - name: 'LaCoin (LAC)', - nativeAsset: 'LAC', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xfD107B473AB90e8Fbd89872144a3DC92C40Fa8C9', - decimals: 18, - id: 'LALA', - name: 'LALA World', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'LARIX_SOL', - issuerAddress: 'Lrxqnh6ZHKbGy3dcrCED43nsoLkM1LTzU2jRfWe8qUC', - name: 'Larix (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x77d547256A2cD95F32F67aE0313E450Ac200648d', - decimals: 8, - id: 'LAZIO', - name: 'FC Lazio Fan Token', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0xfe5F141Bf94fE84bC28deD0AB966c16B17490657', - decimals: 18, - id: 'LBA', - name: 'Cred', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x5102791cA02FC3595398400BFE0e33d7B6C82267', - decimals: 18, - id: 'LDC', - name: 'Leadcoin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x5A98FcBEA516Cf06857215779Fd812CA3beF1B32', - decimals: 18, - id: 'LDO', - name: 'Lido DAO Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 8, - id: 'LDO_SOL', - issuerAddress: 'HZRCwxP2Vq9PCpPXooayhJ2bxTpo5xfpQrwB1svh332p', - name: 'Lido DAO Token (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x80fB784B7eD66730e8b1DBd9820aFD29931aab03', - decimals: 18, - id: 'LEND', - name: 'ETHLend', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x2AF5D2aD76741191D15Dfe7bF6aC92d4Bd912Ca3', - decimals: 18, - id: 'LEO', - name: 'Bitfinex LEO Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xFA3118B34522580c35Ae27F6cf52da1dBb756288', - decimals: 6, - id: 'LET', - name: 'LinkEye Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x1977A9FE002F6dBfFda79b8459Cb4F7036100d41', - decimals: 6, - id: 'LGCY', - name: 'Legacy Coin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x0a50C93c762fDD6E56D86215C24AaAD43aB629aa', - decimals: 8, - id: 'LGO', - name: 'LGO Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x02F61Fd266DA6E8B102D4121f5CE7b992640CF98', - decimals: 18, - id: 'LIKE', - name: 'LikeCoin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 9, - id: 'LIKE_SOL', - issuerAddress: '3bRTivrVsitbmCTGtqwp7hxXPsybkjn4XLNtPsHqa3zR', - name: 'Only1 (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x9D0B65a76274645B29e4cc41B8f23081fA09f4A3', - decimals: 18, - id: 'LIME', - name: 'iMe Lab', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x3E9BC21C9b189C09dF3eF1B824798658d5011937', - decimals: 18, - id: 'LINA', - name: 'Linear Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'LINEA', - name: 'Ethereum (Linea)', - nativeAsset: 'LINEA', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'LINEA_SEPOLIA_TEST', - name: 'Linea Sepolia Test', - nativeAsset: 'LINEA_SEPOLIA_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'LINEA_TEST', - name: 'Ethereum (Linea Test)', - nativeAsset: 'LINEA_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x514910771AF9Ca656af840dff83E8264EcF986CA', - decimals: 18, - id: 'LINK', - name: 'Chainlink', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xF8A0BF9cF54Bb92F17374d9e9A321E6a111a51bD', - decimals: 18, - id: 'LINK_BSC', - name: 'Binance-Peg ChainLink (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0x5947BB275c521040051D82396192181b413227A3', - decimals: 18, - id: 'LINK_E_AVAX', - name: 'Chainlink Token (Avalanche)', - nativeAsset: 'AVAX', - type: 'ERC20' - }, - { - contractAddress: '0xb3654dc3D10Ea7645f8319668E8F54d2574FBdC8', - decimals: 18, - id: 'LINK_FTM', - name: 'ChainLink (FTM)', - nativeAsset: 'FTM_FANTOM', - type: 'ERC20' - }, - { - contractAddress: '0x53E0bca35eC356BD5ddDFebbD1Fc0fD03FaBad39', - decimals: 18, - id: 'LINK_POLYGON', - name: 'ChainLink Token (Polygon)', - nativeAsset: 'MATIC_POLYGON', - type: 'ERC20' - }, - { - contractAddress: '0x2167FB82309CF76513E83B25123f8b0559d6b48f', - decimals: 18, - id: 'LION', - name: 'LionCoin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'LISK', - name: 'Lisk', - nativeAsset: 'LISK', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xb59490aB09A0f526Cc7305822aC65f2Ab12f9723', - decimals: 18, - id: 'LIT', - name: 'Litentry', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x80CE3027a70e0A928d9268994e9B85d03Bd4CDcf', - decimals: 18, - id: 'LKR', - name: 'Polkalokr', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x25B6325f5BB1c1E03cfbC3e53F470E1F1ca022E3', - decimals: 18, - id: 'LML', - name: 'LML', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x9c23D67AEA7B95D80942e3836BCDF7E708A747C2', - decimals: 18, - id: 'LOCI', - name: 'LOCIcoin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x897f505d9637622219e4687eC1A71b4Acf204816', - decimals: 18, - id: 'LODE', - name: 'LODE Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xf4d2888d29D722226FafA5d9B24F9164c092421E', - decimals: 18, - id: 'LOOKS', - name: 'LooksRare Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x42476F744292107e34519F9c357927074Ea3F75D', - decimals: 18, - id: 'LOOM', - name: 'Loom Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xA4e8C3Ec456107eA67d3075bF9e3DF3A75823DB0', - decimals: 18, - id: 'LOOM_OLD', - name: 'Loom Token(Old)', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x6149C26Cd2f7b5CCdb32029aF817123F6E37Df5B', - decimals: 18, - id: 'LPOOL', - name: 'Launchpool token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x58b6A8A3302369DAEc383334672404Ee733aB239', - decimals: 18, - id: 'LPT', - name: 'Livepeer Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x6DEA81C8171D0bA574754EF6F8b412F2Ed88c54D', - decimals: 18, - id: 'LQTY', - name: 'LQTY', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xBBbbCA6A901c926F240b89EacB641d8Aec7AEafD', - decimals: 18, - id: 'LRC', - name: 'Loopring', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 8, - id: 'LTC', - name: 'Litecoin', - nativeAsset: 'LTC', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x4338665CBB7B2485A8855A139b75D5e34AB0DB94', - decimals: 18, - id: 'LTC_BSC', - name: 'Binance-Peg Litecoin (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '', - decimals: 8, - id: 'LTC_TEST', - name: 'Litecoin Test', - nativeAsset: 'LTC_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x3DB6Ba6ab6F95efed1a6E794caD492fAAabF294D', - decimals: 8, - id: 'LTO', - name: 'LTO Network Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xa393473d64d2F9F026B60b6Df7859A689715d092', - decimals: 8, - id: 'LTX', - name: 'Lattice Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 7, - id: 'LU2426951195_XLM_TEST', - issuerAddress: 'GD4MGD3UZ5QY6NLH2FMXKOUCHH4NA3NRT3H6KUU5UMDWE52PIPETFBY2', - name: 'LU2426951195 (Stellar Test)', - nativeAsset: 'XLM_TEST', - type: 'XLM_ASSET' - }, - { - contractAddress: '', - decimals: 6, - id: 'LUNA2', - name: 'Terra Luna 2.0', - nativeAsset: 'LUNA2', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 6, - id: 'LUNA2_TEST', - name: 'Terra Luna 2.0 Test', - nativeAsset: 'LUNA2_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x5f98805A4E8be255a32880FDeC7F6728C6568bA0', - decimals: 18, - id: 'LUSD', - name: 'LUSD Stablecoin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xA8b919680258d369114910511cc87595aec0be6D', - decimals: 18, - id: 'LYXE', - name: 'LUKSO', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x0F5D2fB29fb7d3CFeE444a200298f468908cC942', - decimals: 18, - id: 'MANA', - name: 'Decentraland', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'MANTLE', - name: 'Mantle', - nativeAsset: 'MANTLE', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'MANTLE_TEST', - name: 'Mantle Sepolia', - nativeAsset: 'MANTLE_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x16CDA4028e9E872a38AcB903176719299beAed87', - decimals: 18, - id: 'MARS4', - name: 'MARS4', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x69af81e73A73B40adF4f3d4223Cd9b1ECE623074', - decimals: 18, - id: 'MASK', - name: 'Mask Network', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0', - decimals: 18, - id: 'MATIC', - name: 'Matic Token (Ethereum)', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xCC42724C6683B7E57334c4E856f4c9965ED682bD', - decimals: 18, - id: 'MATIC_BSC', - name: 'Matic Token (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '', - decimals: 18, - id: 'MATIC_POLYGON', - name: 'Matic Gas Token (Polygon)', - nativeAsset: 'MATIC_POLYGON', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 6, - id: 'MBS_SOL', - issuerAddress: 'Fm9rHUTF5v3hwMLbStjZXqNBBoZyGriQaFM6sTFz3K8A', - name: 'MonkeyBucks (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x949D48EcA67b17269629c7194F4b727d4Ef9E5d6', - decimals: 18, - id: 'MC_ETH', - name: 'Merit Circle', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x4e352cF164E64ADCBad318C3a1e222E9EBa4Ce42', - decimals: 18, - id: 'MCB', - name: 'MCDEX Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xB63B606Ac810a52cCa15e44bB630fd42D8d1d83d', - decimals: 8, - id: 'MCO', - name: 'Crypto.com', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xfC98e825A2264D890F9a1e68ed50E1526abCcacD', - decimals: 18, - id: 'MCO2', - name: 'Moss Carbon Credit', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x51DB5Ad35C671a87207d88fC11d593AC0C8415bd', - decimals: 18, - id: 'MDA', - name: 'Moeda Loyalty Points', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'MDF_SOL', - issuerAddress: 'ALQ9KMWjFmxVbew3vMkJj3ypbAKuorSgGst6svCHEe2z', - name: 'MatrixETF DAO Finance (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x947AEb02304391f8fbE5B25D7D98D649b57b1788', - decimals: 18, - id: 'MDX', - name: 'MANDALA EXCHANGE TOKEN', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'MEAN_SOL', - issuerAddress: 'MEANeD3XDdUmNMsRGjASkSWdC8prLYsoRJ61pPeHctD', - name: 'MEAN (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x42dbBd5ae373FEA2FC320F62d44C058522Bb3758', - decimals: 18, - id: 'MEM', - name: 'Memecoin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xD5525D397898e5502075Ea5E830d8914f6F0affe', - decimals: 8, - id: 'MEME', - name: 'MEME', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xDF2C7238198Ad8B389666574f2d8bc411A4b7428', - decimals: 18, - id: 'MFT', - name: 'Mainframe', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x40395044Ac3c0C57051906dA938B54BD6557F212', - decimals: 8, - id: 'MGO', - name: 'MobileGo', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3', - decimals: 18, - id: 'MIM', - name: 'Magic Internet Money', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xa3Fa99A148fA48D14Ed51d610c367C61876997F1', - decimals: 18, - id: 'MIMATIC_POLYGON', - name: 'miMATIC (Polygon)', - nativeAsset: 'MATIC_POLYGON', - type: 'ERC20' - }, - { - contractAddress: '0x90B831fa3Bebf58E9744A14D638E25B4eE06f9Bc', - decimals: 18, - id: 'MIMO', - name: 'MIMO Parallel Governance Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x09a3EcAFa817268f77BE1283176B946C4ff2E608', - decimals: 18, - id: 'MIR', - name: 'Wrapped MIR Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x68E374F856bF25468D365E539b700b648Bf94B67', - decimals: 18, - id: 'MIST_BSC', - name: 'Mist', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0x3893b9422Cd5D70a81eDeFfe3d5A1c6A978310BB', - decimals: 18, - id: 'MITH', - name: 'Mithril', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x4a527d8fc13C5203AB24BA0944F4Cb14658D1Db6', - decimals: 18, - id: 'MITX', - name: 'Morpheus Labs', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2', - decimals: 18, - id: 'MKR', - name: 'Maker', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x5f0Da599BB2ccCfcf6Fdfd7D81743B6020864350', - decimals: 18, - id: 'MKR_BSC', - name: 'Binance-Peg Maker (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0xec67005c4E498Ec7f55E092bd1d35cbC47C91892', - decimals: 18, - id: 'MLN', - name: 'Melon', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x9506d37f70eB4C3d79C398d326C871aBBf10521d', - decimals: 18, - id: 'MLT_ERC20', - name: 'MILC Platform', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 9, - id: 'MNDE_SOL', - issuerAddress: 'MNDEFzGvMt87ueuHvVU9VcTqsAP5b3fTGPsHuuPA5ey', - name: 'Marinade (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '', - decimals: 6, - id: 'MNGO_SOL', - issuerAddress: 'MangoCzJ36AjZyKwVj3VnYU4GTonjfVEnJmvvWaxLac', - name: 'Mango', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0xb96525143f23F2e9B2B2B260FCcd8AfC260656c8', - decimals: 18, - id: 'MOUNTAIN', - name: 'Mountain', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x4206Fc377c22eB4778B5DAc3C28d0fa92db43AE4', - decimals: 18, - id: 'MOUNTAINVUSD', - name: 'MountainVUSD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'MOVR_MOVR', - name: 'Moonriver', - nativeAsset: 'MOVR_MOVR', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x33349B282065b0284d756F0577FB39c158F935e6', - decimals: 18, - id: 'MPL', - name: 'Maple Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 9, - id: 'MSOL_SOL', - issuerAddress: 'mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So', - name: 'Marinade staked SOL (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0xa3BeD4E1c75D00fa6f4E5E6922DB7261B5E9AcD2', - decimals: 18, - id: 'MTA', - name: 'Meta', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xF501dd45a1198C2E1b5aEF5314A68B9006D842E0', - decimals: 18, - id: 'MTA_POLYGON', - name: 'Meta Polygon', - nativeAsset: 'MATIC_POLYGON', - type: 'ERC20' - }, - { - contractAddress: '0xF433089366899D83a9f26A773D59ec7eCF30355e', - decimals: 8, - id: 'MTL', - name: 'Metal', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xe2f2a5C287993345a840Db3B0845fbC70f5935a5', - decimals: 18, - id: 'MUSD', - name: 'mStable USD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x3564ad35b9E95340E5Ace2D6251dbfC76098669B', - decimals: 6, - id: 'MUSDC', - name: 'DMM: USDC', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x8E766F57F7d16Ca50B4A0b90b88f6468A09b0439', - decimals: 18, - id: 'MXM', - name: 'Maximine Coin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xa645264C5603E96c3b0B078cdab68733794B0A71', - decimals: 8, - id: 'MYST', - name: 'Mysterium', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xDf282f170f3C32AC9c49f3f5Be1D68e5aE6Eb742', - decimals: 8, - id: 'NAKA', - name: 'Nakamoto Debt Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x4a615bB7166210CCe20E6642a6f8Fb5d4D044496', - decimals: 18, - id: 'NAOS', - name: 'NAOSToken', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 4, - id: 'NAXAR_SOL', - issuerAddress: 'Fp4gjLpTsPqBN6xDGpDHwtnuEofjyiZKxxZxzvJnjxV6', - name: 'Naxar (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x809826cceAb68c387726af962713b64Cb5Cb3CCA', - decimals: 18, - id: 'NCASH', - name: 'NucleusVision', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 24, - id: 'NEAR', - name: 'NEAR Protocol', - nativeAsset: 'NEAR', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x1Fa4a73a3F0133f0025378af00236f3aBDEE5D63', - decimals: 18, - id: 'NEAR_BSC', - name: 'Binance-Peg NEAR Protocol', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '', - decimals: 24, - id: 'NEAR_TEST', - name: 'NEAR Protocol Test', - nativeAsset: 'NEAR_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xCc80C051057B774cD75067Dc48f8987C4Eb97A5e', - decimals: 18, - id: 'NEC', - name: 'Ethfinex Nectar Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 9, - id: 'NEST_SOL', - issuerAddress: 'Czt7Fc4dz6BpLh2vKiSYyotNK2uPPDhvbWrrLeD9QxhV', - name: 'Nest Arcade (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0xB62132e35a6c13ee1EE0f84dC5d40bad8d815206', - decimals: 18, - id: 'NEXO', - name: 'Nexo', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xcB8d1260F9c92A3A545d409466280fFdD7AF7042', - decimals: 18, - id: 'NFT', - name: 'NFT Protocol', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xEF40B859D21e4d566a3d713e756197c021BffaAa', - decimals: 6, - id: 'NFT1', - name: 'APENFT', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x87d73E916D7057945c9BcD8cdd94e42A6F47f776', - decimals: 18, - id: 'NFTX', - name: 'NFTX', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xf71982762D141f8679Eb944fAec8cEC415fB5E23', - decimals: 18, - id: 'NIAX', - name: 'NIAXToken', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x25de492f43661Af568f46C0a3F39850Aa1D066A0', - decimals: 18, - id: 'NIBBIOUSD', - name: 'NibbioUSD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x7e291890B01E5181f7ecC98D79ffBe12Ad23df9e', - decimals: 18, - id: 'NIF', - name: 'Unifty', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x7c8155909cd385F120A56eF90728dD50F9CcbE52', - decimals: 15, - id: 'NII', - name: 'Nahmii', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x852e5427c86A3b46DD25e5FE027bb15f53c4BCb8', - decimals: 15, - id: 'NIIFI', - name: 'NiiFiToken', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'NINJA_SOL', - issuerAddress: 'FgX1WD9WzMU3yLwXaFSarPfkgzjLb2DZCqmkx9ExpuvJ', - name: 'NINJA', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0xc813EA5e3b48BEbeedb796ab42A30C5599b01740', - decimals: 4, - id: 'NIOX', - name: 'Autonio', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x5Cf04716BA20127F1E2297AdDCf4B5035000c9eb', - decimals: 18, - id: 'NKN', - name: 'NKN', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x1776e1F26f98b1A5dF9cD347953a26dd3Cb46671', - decimals: 18, - id: 'NMR', - name: 'Numeraire', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xa8c8CfB141A3bB59FEA1E2ea6B79b5ECBCD7b6ca', - decimals: 18, - id: 'NOIA', - name: 'NOIA Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 9, - id: 'NOTCOIN_TON', - issuerAddress: 'EQAvlWFDxGF2lXm67y4yzC17wYKD9A0guwPkMs1gOsM__NOT', - name: 'Notcoin (Ton)', - nativeAsset: 'TON', - type: 'TON_ASSET' - }, - { - contractAddress: '0xCFEAead4947f0705A14ec42aC3D44129E1Ef3eD5', - decimals: 8, - id: 'NOTE_ETH', - name: 'Notional', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x25aE7B9808F6Cc3B5E9b8699b62b0395C3F01BE0', - decimals: 18, - id: 'NOTEUSD', - name: 'noteUSD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x97fB6Fc2AD532033Af97043B563131C5204F8A35', - decimals: 18, - id: 'NPLC', - name: 'Plus-Coin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'NPT_TRX', - issuerAddress: 'TQTShAfjdRztg8id1mrQPaNT6ccdK1HviG', - name: 'NPT (Tron)', - nativeAsset: 'TRX', - type: 'TRON_TRC20' - }, - { - contractAddress: '0xA15C7Ebe1f07CaF6bFF097D8a589fb8AC49Ae5B3', - decimals: 18, - id: 'NPXS', - name: 'Pundi X', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x20945cA1df56D237fD40036d47E866C7DcCD2114', - decimals: 18, - id: 'NSURE', - name: 'Nsure Network Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'NTRN', - name: 'Neutron', - nativeAsset: 'NTRN', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x4fE83213D56308330EC302a8BD641f1d0113A4Cc', - decimals: 18, - id: 'NU', - name: 'NuCypher', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 7, - id: 'NXDB', - issuerAddress: 'GBG4NNAO36LKRDOUE3J3TPZYXGF2J34CW4FRFE5SLL65ED54E7LFBMKK', - name: 'Nicoswap coin (DigitalBits)', - nativeAsset: 'XDB', - type: 'XDB_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'OAS', - name: 'Oasys', - nativeAsset: 'OAS', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'OAS_TEST', - name: 'Oasys Test', - nativeAsset: 'OAS_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x2F109021aFe75B949429fe30523Ee7C0D5B27207', - decimals: 18, - id: 'OCC', - name: 'OCC', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x967da4048cD07aB37855c090aAF366e4ce1b9F48', - decimals: 18, - id: 'OCEAN', - name: 'Ocean Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x4092678e4E78230F46A1534C0fbc8fA39780892B', - decimals: 18, - id: 'OCN', - name: 'Odyssey', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x7240aC91f01233BaAf8b064248E80feaA5912BA3', - decimals: 18, - id: 'OCTO', - name: 'Octo.fi', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x8207c1FfC5B6804F6024322CcF34F29c3541Ae26', - decimals: 18, - id: 'OGN', - name: 'OriginToken', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x383518188C0C6d7730D91b2c03a03C837814a899', - decimals: 9, - id: 'OHM', - name: 'Olympus', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x75231F58b43240C9718Dd58B4967c5114342a86c', - decimals: 18, - id: 'OKB', - name: 'OKB', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x6595b8fD9C920C81500dCa94e53Cdc712513Fb1f', - decimals: 18, - id: 'OLY', - name: 'Olyseum', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x3593D125a4f7849a1B059E64F4517A86Dd60c95d', - decimals: 18, - id: 'OM', - name: 'MANTRA DAO', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x76e63a3E7Ba1e2E61D3DA86a87479f983dE89a7E', - decimals: 18, - id: 'OMEN_POLYGON', - name: 'Augury Finance (Polygon)', - nativeAsset: 'MATIC_POLYGON', - type: 'ERC20' - }, - { - contractAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', - decimals: 18, - id: 'OMG', - name: 'OmiseGO', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xaBc6790673a60b8A7f588450f59D2d256b1aeF7F', - decimals: 18, - id: 'OMN_BSC', - name: 'OMNI Coin', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '', - decimals: 8, - id: 'OMNI_TEST', - name: 'Omni Test', - nativeAsset: 'BTC_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x03fF0ff224f904be3118461335064bB48Df47938', - decimals: 18, - id: 'ONE_BSC', - name: 'Harmony ONE (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0xd341d1680Eeee3255b8C4c75bCCE7EB57f144dAe', - decimals: 18, - id: 'ONG', - name: 'SoMee.Social', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xFd7B3A77848f1C2D67E05E54d78d174a0C850335', - decimals: 18, - id: 'ONT_BSC', - name: 'Binance-Peg Ontology Token (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0x9D86b1B2554ec410ecCFfBf111A6994910111340', - decimals: 8, - id: 'OPENC', - name: 'OPEN Chain', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x888888888889C00c67689029D7856AAC1065eC11', - decimals: 18, - id: 'OPIUM', - name: 'Opium Governance Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x80D55c03180349Fff4a229102F62328220A96444', - decimals: 18, - id: 'OPUL', - name: 'OpulousToken', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xEE1CeA7665bA7aa97e982EdeaeCb26B59a04d035', - decimals: 18, - id: 'ORAO', - name: 'ORAO Network', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xff56Cc6b1E6dEd347aA0B7676C85AB0B3D08B0FA', - decimals: 18, - id: 'ORBS', - name: 'Orbs', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x662b67d00A13FAf93254714DD601F5Ed49Ef2F51', - decimals: 18, - id: 'ORC', - name: 'Orbit Chain', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'ORCA_SOL', - issuerAddress: 'orcaEKTdK7LKz57vaAYr9QeNsVEPfiu6QeMU1kektZE', - name: 'Orca', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x0258F474786DdFd37ABCE6df6BBb1Dd5dfC4434a', - decimals: 8, - id: 'ORN', - name: 'Orion Protocol', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'OSMO', - name: 'Osmosis', - nativeAsset: 'OSMO', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 6, - id: 'OSMO_TEST', - name: 'Osmosis Test', - nativeAsset: 'OSMO_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x2C4e8f2D746113d0696cE89B35F0d8bF88E0AEcA', - decimals: 18, - id: 'OST', - name: 'OST', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x2401D75Bf6E88EF211e51BD3E15415860025fDb9', - decimals: 8, - id: 'OT', - name: 'O Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x2A8e1E676Ec238d8A992307B495b45B3fEAa5e86', - decimals: 18, - id: 'OUSD', - name: 'Origin Dollar', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x4575f41308EC1483f3d399aa9a2826d74Da13Deb', - decimals: 18, - id: 'OXT', - name: 'Orchid', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x46c9757C5497c5B1f2eb73aE79b6B67D119B0B58', - decimals: 18, - id: 'PACT_CELO', - name: 'impactMarket (CELO)', - nativeAsset: 'CELO', - type: 'ERC20' - }, - { - contractAddress: '0x1614F18Fc94f47967A3Fbe5FfcD46d4e7Da3D787', - decimals: 18, - id: 'PAID', - name: 'PAID Network', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xea5f88E54d982Cbb0c441cde4E79bC305e5b43Bc', - decimals: 18, - id: 'PARETO', - name: 'PARETO Rewards', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xeE4458e052B533b1aABD493B5f8c4d85D7B263Dc', - decimals: 6, - id: 'PASS', - name: 'Blockpass', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x8E870D67F660D95d5be530380D0eC0bd388289E1', - decimals: 18, - id: 'PAX', - name: 'PAX Dollar', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x45804880De22913dAFE09f4980848ECE6EcbAf78', - decimals: 18, - id: 'PAXG', - name: 'Paxos Gold', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xB97048628DB6B661D4C2aA833e95Dbe1A905B280', - decimals: 18, - id: 'PAY', - name: 'TenXPay', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x7e9928aFe96FefB820b85B4CE6597B8F660Fe4F4', - decimals: 18, - id: 'PBNB_POLYGON', - name: 'Orbit Bridge Polygon Binance Coin (Polygon)', - nativeAsset: 'MATIC_POLYGON', - type: 'ERC20' - }, - { - contractAddress: '0xD528cf2E081f72908e086F8800977df826B5a483', - decimals: 18, - id: 'PBX_ETH', - name: 'Paribus', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x334cBb5858417Aee161B53Ee0D5349cCF54514CF', - decimals: 18, - id: 'PCDAI', - name: 'PoolTogether Dai Ticket (Compound)', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xD81b1A8B1AD00Baa2D6609E0BAE28A38713872f7', - decimals: 6, - id: 'PCUSDC', - name: 'PoolTogether USDC Ticket (Compound)', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 0, - id: 'PCUST', - name: 'Philanthropic Credit', - nativeAsset: 'BTC', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x56e13ba0b311eDFEA176505B4fB7F2696778913C', - decimals: 0, - id: 'PCUST_ERC20', - name: 'Philanthropic Credit (ERC20)', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'PEAQ', - name: 'Peaq', - nativeAsset: 'PEAQ', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 2, - id: 'PEERACCOUNTTRANSFER_CHF', - name: 'CHF (Peer Transfer)', - nativeAsset: 'PEERACCOUNTTRANSFER_CHF', - type: 'FIAT' - }, - { - contractAddress: '', - decimals: 2, - id: 'PEERACCOUNTTRANSFER_EUR', - name: 'EUR (Peer Transfer)', - nativeAsset: 'PEERACCOUNTTRANSFER_EUR', - type: 'FIAT' - }, - { - contractAddress: '', - decimals: 2, - id: 'PEERACCOUNTTRANSFER_SGD', - name: 'SGD (Peer Transfer)', - nativeAsset: 'PEERACCOUNTTRANSFER_SGD', - type: 'FIAT' - }, - { - contractAddress: '', - decimals: 2, - id: 'PEERACCOUNTTRANSFER_USD', - name: 'USD (Peer Transfer)', - nativeAsset: 'PEERACCOUNTTRANSFER_USD', - type: 'FIAT' - }, - { - contractAddress: '0x808507121B80c02388fAd14726482e061B8da827', - decimals: 18, - id: 'PENDLE', - name: 'Pendle', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xbC396689893D065F41bc2C6EcbeE5e0085233447', - decimals: 18, - id: 'PERP', - name: 'Perpetual', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x3F9BEC82c776c47405BcB38070d2395Fd18F89d3', - decimals: 18, - id: 'PHM', - name: 'Phantom Protocol Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x4399AE7538c33cA24edD4C28C5dd7Ce9a80acF81', - decimals: 18, - id: 'PHM_BSC', - name: 'Phantom Protocol Token (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0xc2D31475a1fbce0725AD71665976F18502a37234', - decimals: 0, - id: 'PKC', - name: 'PKC', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xe3818504c1B32bF1557b16C238B2E01Fd3149C17', - decimals: 18, - id: 'PLR', - name: 'PILLAR', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xD8912C10681D8B21Fd3742244f44658dBA12264E', - decimals: 18, - id: 'PLU', - name: 'Pluton', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x47DA5456bC2e1ce391b645Ce80F2E97192e4976a', - decimals: 18, - id: 'PLUG', - name: 'Plug Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'PLUME', - name: 'Plume', - nativeAsset: 'PLUME', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x846C66cf71C43f80403B51fE3906B3599D63336f', - decimals: 18, - id: 'PMA', - name: 'PumaPay', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x93ED3FBe21207Ec2E8f2d3c3de6e058Cb73Bc04d', - decimals: 18, - id: 'PNK', - name: 'Pinakion', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x89Ab32156e46F46D02ade3FEcbe5Fc4243B9AAeD', - decimals: 18, - id: 'PNT', - name: 'pNetwork Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x455e53CBB86018Ac2B8092FdCd39d8444aFFC3F6', - decimals: 18, - id: 'POL_ETH_9RYQ', - name: 'Polygon Ecosystem Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 8, - id: 'POLIS_SOL', - issuerAddress: 'poLisWXnNRwC6oBu1vHiuKQzFjGL4XDSu4g9qjz9qVk', - name: 'Star Atlas DAO', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x83e6f1E41cdd28eAcEB20Cb649155049Fac3D5Aa', - decimals: 18, - id: 'POLS', - name: 'PolkastarterToken', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x9992eC3cF6A55b00978cdDF2b27BC6882d88D1eC', - decimals: 18, - id: 'POLY', - name: 'Polymath', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x57B946008913B82E4dF85f501cbAeD910e58D26C', - decimals: 18, - id: 'POND', - name: 'Marlin POND', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x0cEC1A9154Ff802e7934Fc916Ed7Ca50bDE6844e', - decimals: 18, - id: 'POOL', - name: 'PoolTogether', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x49f2145d6366099e13B10FbF80646C0F377eE7f6', - decimals: 8, - id: 'PORTO', - name: 'FC Porto Fan Token', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0x595832F8FC6BF59c85C527fEC3740A1b7a361269', - decimals: 6, - id: 'POWR', - name: 'Power Ledger', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x054D64b73d3D8A21Af3D764eFd76bCaA774f3Bb2', - decimals: 18, - id: 'PPAY', - name: 'Plasma', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xd4fa1460F537bb9085d22C7bcCB5DD450Ef28e3a', - decimals: 8, - id: 'PPT', - name: 'Populous', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xEC213F83defB583af3A000B1c0ada660b1902A0F', - decimals: 18, - id: 'PRE', - name: 'Presearch', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x226bb599a12C826476e3A771454697EA52E9E220', - decimals: 8, - id: 'PRO', - name: 'Propy', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xfc82bb4ba86045Af6F327323a46E80412b91b27d', - decimals: 18, - id: 'PROM', - name: 'Token Prometeus Network', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x6fe56C0bcdD471359019FcBC48863d6c3e9d4F41', - decimals: 18, - id: 'PROPS', - name: 'Props Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x8642A849D0dcb7a15a974794668ADcfbe4794B56', - decimals: 18, - id: 'PROS', - name: 'Prosper', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'PRT_SOL', - issuerAddress: 'PRT88RkA4Kg5z7pKnezeNH4mafTvtQdfFgpQTGRjz44', - name: 'Parrot Protocol (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x2bf9671F00643afc813A6623074e0dDF6DB4Fc2B', - decimals: 18, - id: 'PSQ', - name: 'PSQ', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xC57d533c50bC22247d49a368880fb49a1caA39F7', - decimals: 18, - id: 'PTF', - name: 'PowerTrade Fuel Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x22d4002028f537599bE9f666d1c4Fa138522f9c8', - decimals: 18, - id: 'PTP_AVAX', - name: 'Platypus', - nativeAsset: 'AVAX', - type: 'ERC20' - }, - { - contractAddress: '0xC229c69eB3BB51828D0cAA3509A05a51083898dd', - decimals: 18, - id: 'PTU', - name: 'Pintu Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x0FD10b9899882a6f2fcb5c371E17e70FdEe00C38', - decimals: 18, - id: 'PUNDIX', - name: 'Pundi X Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xf418588522d5dd018b425E472991E52EBBeEEEEE', - decimals: 18, - id: 'PUSH', - name: 'Ethereum Push Notification Service', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x47e67BA66b0699500f18A53F94E2b9dB3D47437e', - decimals: 18, - id: 'PXG', - name: 'PlayGame', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x95aA5d2DbD3c16ee3fdea82D5C6EC3E38CE3314f', - decimals: 18, - id: 'PXP', - name: 'PointPay Crypto Banking Token V2', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x430EF9263E76DAE63c84292C3409D61c598E9682', - decimals: 18, - id: 'PYR', - name: 'PYR Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'PYTH_SOL', - issuerAddress: 'HZ1JovNiVvGrGNiiYvEozEVgZ58xaU3RKwX8eACQBCt3', - name: 'Pyth Network (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x6c3ea9036406852006290770BEdFcAbA0e23A0e8', - decimals: 6, - id: 'PYUSD_ETH', - name: 'PayPal USD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'PYUSD_SOL', - issuerAddress: '2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo', - name: 'PayPal USD (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x618E75Ac90b12c6049Ba3b27f5d5F8651b0037F6', - decimals: 6, - id: 'QASH', - name: 'QASH', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x1602af2C782cC03F9241992E243290Fccf73Bb13', - decimals: 18, - id: 'QBIT', - name: 'Qubitica', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x4A16BAf414b8e637Ed12019faD5Dd705735DB2e0', - decimals: 2, - id: 'QCAD', - name: 'QCAD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x9Adc7710E9d1b29d8a78c04d52D32532297C2Ef3', - decimals: 18, - id: 'QDT', - name: 'QuadransToken', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x9e3a9F1612028eeE48F85cA85f8Bed2f37d76848', - decimals: 18, - id: 'QDX_BSC', - name: 'Quidax Token (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0x8729438EB15e2C8B576fCc6AeCdA6A148776C0F5', - decimals: 18, - id: 'QI_AVAX', - name: 'BENQI (Avalanche)', - nativeAsset: 'AVAX', - type: 'ERC20' - }, - { - contractAddress: '0xEA26c4aC16D4a5A106820BC8AEE85fd0b7b2b664', - decimals: 18, - id: 'QKC', - name: 'QuarkChain', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x4a220E6096B25EADb88358cb44068A3248254675', - decimals: 18, - id: 'QNT', - name: 'Quant', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x99ea4dB9EE77ACD40B119BD1dC4E33e1C070b80d', - decimals: 18, - id: 'QSP', - name: 'Quantstamp', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x35aF993EF3E89C076e41e463Fbd4CD00d3105cD1', - decimals: 18, - id: 'QUAKE', - name: 'QuakeCoin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x6c28AeF8977c9B773996d0e8376d2EE379446F2f', - decimals: 18, - id: 'QUICK', - name: 'Quickswap (Old)', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x831753DD7087CaC61aB5644b308642cc1c33Dc13', - decimals: 18, - id: 'QUICK_POLYGON', - name: 'Quickswap (Old Polygon)', - nativeAsset: 'MATIC_POLYGON', - type: 'ERC20' - }, - { - contractAddress: '0x31c8EAcBFFdD875c74b94b077895Bd78CF1E64A3', - decimals: 18, - id: 'RAD', - name: 'Radicle', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x94804dc4948184fFd7355f62Ccbb221c9765886F', - decimals: 18, - id: 'RAGE', - name: 'RageToken', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x33D0568941C0C64ff7e0FB4fbA0B11BD37deEd9f', - decimals: 18, - id: 'RAMP', - name: 'RAMP DEFI', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x8519EA49c997f50cefFa444d240fB655e89248Aa', - decimals: 18, - id: 'RAMP_BSC', - name: 'RAMP DEFI (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0xba5BDe662c17e2aDFF1075610382B9B691296350', - decimals: 18, - id: 'RARE', - name: 'SuperRare', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xFca59Cd816aB1eaD66534D82bc21E7515cE441CF', - decimals: 18, - id: 'RARI', - name: 'Rarible', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x5245C0249e5EEB2A0838266800471Fd32Adb1089', - decimals: 6, - id: 'RAY', - name: 'Raydium', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'RAY_SOL', - issuerAddress: '4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX6R', - name: 'Raydium (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0xFc2C4D8f95002C14eD0a7aA65102Cac9e5953b5E', - decimals: 18, - id: 'RBLX', - name: 'Rublix', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x6123B0049F904d730dB3C36a31167D9d4121fA6B', - decimals: 18, - id: 'RBN', - name: 'Ribbon', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'RBTC', - name: 'RSK Smart Bitcoin', - nativeAsset: 'RBTC', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'RBTC_TEST', - name: 'RSK Smart Bitcoin (Test)', - nativeAsset: 'RBTC_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x431CD3C9AC9Fc73644BF68bF5691f4B83F9E104f', - decimals: 18, - id: 'RBW_POLYGON_UZYB', - name: 'Rainbow Token', - nativeAsset: 'MATIC_POLYGON', - type: 'ERC20' - }, - { - contractAddress: '0xF970b8E36e23F7fC3FD752EeA86f8Be8D83375A6', - decimals: 18, - id: 'RCN', - name: 'Ripio Credit Network', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x252739487C1fa66eaeaE7CED41d6358aB2a6bCa9', - decimals: 8, - id: 'RCOIN', - name: 'ArCoin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x2d919F19D4892381D58edeBeca66D5642Cef1a1f', - decimals: 18, - id: 'RDOC_RBTC', - name: 'RIF Dollar on Chain (RSK)', - nativeAsset: 'RBTC', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 9, - id: 'REAL_SOL', - issuerAddress: 'AD27ov5fVU2XzwsbvnFvb1JpCBaCB5dRXrczV9CqSVGb', - name: 'Realy Token (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'REDBELLY', - name: 'Redbelly', - nativeAsset: 'REDBELLY', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'REDBELLY_TEST', - name: 'Redbelly Test', - nativeAsset: 'REDBELLY_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xFE3E6a25e6b192A42a44ecDDCd13796471735ACf', - decimals: 18, - id: 'REEF', - name: 'Reef.finance', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x408e41876cCCDC0F92210600ef50372656052a38', - decimals: 18, - id: 'REN', - name: 'Republic', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xEB4C2781e4ebA804CE9a9803C67d0893436bB27D', - decimals: 8, - id: 'RENBTC', - name: 'renBTC', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 8, - id: 'RENDER_SOL', - issuerAddress: 'rndrizKT3MK1iimdxRdWabcF7Zg7AR5T4nud4EkHBof', - name: 'Render Token (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x1985365e9f78359a9B6AD760e32412f4a445E862', - decimals: 18, - id: 'REP', - name: 'Augur', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x221657776846890989a759BA2973e427DfF5C9bB', - decimals: 18, - id: 'REPV2', - name: 'Reputation', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x8f8221aFbB33998d8584A2B05749bA73c37a938a', - decimals: 18, - id: 'REQ', - name: 'Request', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x557B933a7C2c45672B610F8954A3deB39a51A8Ca', - decimals: 18, - id: 'REVV', - name: 'REVV', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xa1d6Df714F91DeBF4e0802A542E13067f31b8262', - decimals: 18, - id: 'RFOX', - name: 'RFOX', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xd0929d411954c47438dc1d871dd6081F5C5e149c', - decimals: 4, - id: 'RFR', - name: 'Refereum', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xD291E7a03283640FDc51b121aC401383A46cC623', - decimals: 18, - id: 'RGT', - name: 'Rari Governance Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x168296bb09e24A88805CB9c33356536B980D3fC5', - decimals: 8, - id: 'RHOC', - name: 'RChain', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x2AcC95758f8b5F583470ba265EB685a8F45fC9D5', - decimals: 18, - id: 'RIF_RBTC', - name: 'RIF (RSK)', - nativeAsset: 'RBTC', - type: 'ERC20' - }, - { - contractAddress: '0xf4d27c56595Ed59B66cC7F03CFF5193e4bd74a61', - decimals: 18, - id: 'RIFP_RBTC', - name: 'RIF Pro (RSK)', - nativeAsset: 'RBTC', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 9, - id: 'RIN_SOL', - issuerAddress: 'E5ndSkaB17Dm7CsD22dvcjfrYSDLCxFcMd6z8ddCk5wp', - name: 'Aldrin (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x9469D013805bFfB7D3DEBe5E7839237e535ec483', - decimals: 18, - id: 'RING', - name: 'Darwinia Network Native Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x607F4C5BB672230e8672085532f7e901544a7375', - decimals: 9, - id: 'RLC', - name: 'iExec RLC', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xf1f955016EcbCd7321c7266BccFB96c68ea5E49b', - decimals: 18, - id: 'RLY', - name: 'Rally', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x8D5682941cE456900b12d47ac06a88b47C764CE1', - decimals: 18, - id: 'RMESH', - name: 'RightMesh', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x6De037ef9aD2725EB40118Bb1702EBb27e4Aeb24', - decimals: 18, - id: 'RNDR', - name: 'Render Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'RON', - name: 'Ronin', - nativeAsset: 'RON', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xfA5047c9c78B8877af97BDcb85Db743fD7313d4a', - decimals: 18, - id: 'ROOK', - name: 'ROOK', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x7eaF9C89037e4814DC0d9952Ac7F888C784548DB', - decimals: 18, - id: 'ROYA', - name: 'Royale', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xB4EFd85c19999D84251304bDA99E90B92300Bd93', - decimals: 18, - id: 'RPL', - name: 'Rocket Pool (Old)', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xD33526068D116cE69F19A9ee46F0bd304F21A51f', - decimals: 18, - id: 'RPL2', - name: 'Rocket Pool (New)', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x490c95bE16384E1f28B9e864e98fFEcFCBfF386d', - decimals: 18, - id: 'RPM', - name: 'Repme', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x320623b8E4fF03373931769A31Fc52A4E78B5d70', - decimals: 18, - id: 'RSR', - name: 'Reserve Rights (new contract)', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x8762db106B2c2A0bccB3A80d1Ed41273552616E8', - decimals: 18, - id: 'RSR_OLD', - name: 'Reserve Rights (old)', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x196f4727526eA7FB1e17b2071B3d8eAA38486988', - decimals: 18, - id: 'RSV', - name: 'Reserve', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 9, - id: 'RUN_SOL', - issuerAddress: '6F9XriABHfWhit6zmMUYAQBSy6XK5VF1cHXuW5LDpRtC', - name: 'Run Token (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x3155BA85D5F96b2d030a4966AF206230e46849cb', - decimals: 18, - id: 'RUNE', - name: 'THORChain ETH.RUNE', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xA9776B590bfc2f956711b3419910A5Ec1F63153E', - decimals: 18, - id: 'RUNE_BSC', - name: 'Rune (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '', - decimals: 8, - id: 'RUNE_THOR', - name: 'THORChain Rune', - nativeAsset: 'RUNE_THOR', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 8, - id: 'RUNE_THOR_TEST', - name: 'THORChain Rune Test', - nativeAsset: 'RUNE_THOR_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x8076C74C5e3F5852037F31Ff0093Eeb8c8ADd8D3', - decimals: 9, - id: 'SAFEMOON_BSC', - name: 'SafeMoon (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359', - decimals: 18, - id: 'SAI', - name: 'Sai', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x4156D3342D5c385a87D264F90653733592000581', - decimals: 8, - id: 'SALT', - name: 'SALT', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 9, - id: 'SAMO_SOL', - issuerAddress: '7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU', - name: 'Samoyed Coin (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x3845badAde8e6dFF049820680d1F14bD3903a5d0', - decimals: 18, - id: 'SAND', - name: 'SAND', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x7697B462A7c4Ff5F8b55BDBC2F4076c2aF9cF51A', - decimals: 18, - id: 'SARCO', - name: 'Sarcophagus', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xDf49C9f599A0A9049D97CFF34D0C30E468987389', - decimals: 18, - id: 'SATT', - name: 'Smart Advertising Transaction Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'SB_SOL', - issuerAddress: 'SuperbZyz7TsSdSoFAZ6RYHfAWe9NmjXBLVQpS8hqdx', - name: 'SuperBonds Token (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '', - decimals: 6, - id: 'SBR_SOL', - issuerAddress: 'Saber2gLauYim4Mvftnrasomsv6NvAuncvMEZwcLpD1', - name: 'Saber Protocol Token (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x74FD51a98a4A1ECBeF8Cc43be801cce630E260Bd', - decimals: 18, - id: 'SCC', - name: 'SiaCashCoin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'SCROLL', - name: 'Scroll Ethereum', - nativeAsset: 'SCROLL', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'SCROLL_SEPOLIA_TEST', - name: 'Scroll Sepolia Test', - nativeAsset: 'SCROLL_SEPOLIA_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 9, - id: 'SCT_SOL', - issuerAddress: '4Te4KJgjtnZe4aE2zne8G4NPfrPjCwDmaiEx9rKnyDVZ', - name: 'SolClout (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '', - decimals: 9, - id: 'SCY_SOL', - issuerAddress: 'SCYfrGCw8aDiqdgcpdGjV6jp4UVVQLuphxTDLNWu36f', - name: 'Synchrony (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x993864E43Caa7F7F12953AD6fEb1d1Ca635B875F', - decimals: 18, - id: 'SDAO', - name: 'Singularity Dao', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'SEI', - name: 'Sei', - nativeAsset: 'SEI', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'SEI_TEST', - name: 'Sei', - nativeAsset: 'SEI_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 2, - id: 'SEN_TEST_USD', - name: 'Silvergate SEN Test', - nativeAsset: 'SEN_TEST_USD', - type: 'FIAT' - }, - { - contractAddress: '', - decimals: 2, - id: 'SEN_USD', - name: 'Silvergate SEN', - nativeAsset: 'SEN_USD', - type: 'FIAT' - }, - { - contractAddress: '0x6745fAB6801e376cD24F03572B9C9B0D4EdDDCcf', - decimals: 8, - id: 'SENSE', - name: 'Sense', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xD71eCFF9342A5Ced620049e616c5035F1dB98620', - decimals: 18, - id: 'SEUR', - name: 'Synth sEUR', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xb753428af26E81097e7fD17f40c88aaA3E04902c', - decimals: 18, - id: 'SFI', - name: 'Spice', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xed0849BF46CfB9845a2d900A0A4E593F2dD3673c', - decimals: 18, - id: 'SGA', - name: 'Saga', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'SGB', - name: 'Songbird', - nativeAsset: 'SGB', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'SGB_LEGACY', - name: 'Songbird (Legacy derivation)', - nativeAsset: 'SGB_LEGACY', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xB2135AB9695a7678Dd590B1A996CB0f37BCB0718', - decimals: 9, - id: 'SGN', - name: 'Signals Network', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xAEa8e1b6CB5c05D1dAc618551C76bcD578EA3524', - decimals: 18, - id: 'SGR', - name: 'Sogur', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x232FB065D9d24c34708eeDbF03724f2e95ABE768', - decimals: 18, - id: 'SHEESHA_BSC', - name: 'Sheesha Finance', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0xcba3eAe7f55D0F423AF43cC85E67ab0fBF87B61C', - decimals: 18, - id: 'SHFT', - name: 'Shyft [ Byfrost ]', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xb17C88bDA07D28B3838E0c1dE6a30eAfBCF52D85', - decimals: 18, - id: 'SHFT_WRAPPED', - name: 'Shyft _ Wrapped _', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x95aD61b0a150d79219dCF64E1E6Cc01f0B64C4cE', - decimals: 18, - id: 'SHIB', - name: 'SHIBA INU', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x2859e4544C4bB03966803b044A93563Bd2D0DD4D', - decimals: 18, - id: 'SHIB_BSC', - name: 'SHIBA INU (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '', - decimals: 8, - id: 'SHIB_SOL', - issuerAddress: 'CiKu4eHsVrc1eueVQeHn7qhXTcVu95gSQmBpX4utjL9z', - name: 'SHIBA INU (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '', - decimals: 6, - id: 'SHILL_SOL', - issuerAddress: '6cVgJUqo4nmvQpbgrDZwyfd6RwWw5bfnCamS3M9N1fd', - name: 'Project SEED Token (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0xe25b0BBA01Dc5630312B6A21927E578061A13f55', - decimals: 18, - id: 'SHIP', - name: 'ShipChain', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x7BEF710a5759d197EC0Bf621c3Df802C2D60D848', - decimals: 18, - id: 'SHOPX', - name: 'SPLYT SHOPX', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x7C84e62859D0715eb77d1b1C4154Ecd6aBB21BEC', - decimals: 18, - id: 'SHPING', - name: 'Shping Coin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xd98F75b1A3261dab9eEd4956c93F33749027a964', - decimals: 2, - id: 'SHR', - name: 'ShareToken', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 7, - id: 'SHX_XLM', - issuerAddress: 'GDSTRSHXHGJ7ZIVRBXEYE5Q74XUVCUSEKEBR7UCHEUUEK72N7I7KJ6JH', - name: 'Stronghold SHx (Stellar)', - nativeAsset: 'XLM', - type: 'XLM_ASSET' - }, - { - contractAddress: '0x549020a9Cb845220D66d3E9c6D9F9eF61C981102', - decimals: 18, - id: 'SIDUS', - name: 'SIDUS', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 2, - id: 'SIGNET_TEST_USD', - name: 'Signet Test', - nativeAsset: 'SIGNET_TEST_USD', - type: 'FIAT' - }, - { - contractAddress: '', - decimals: 2, - id: 'SIGNET_USD', - name: 'Signet', - nativeAsset: 'SIGNET_USD', - type: 'FIAT' - }, - { - contractAddress: '0x6D728fF862Bfe74be2aba30537E992A24F259a22', - decimals: 18, - id: 'SIH', - name: 'Salient Investment Holding', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xd38BB40815d2B0c2d2c866e0c72c5728ffC76dd9', - decimals: 18, - id: 'SIS', - name: 'Symbiosis', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x00c83aeCC790e8a4453e5dD3B0B4b3680501a7A7', - decimals: 18, - id: 'SKL', - name: 'SKALE', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'SLC_SOL', - issuerAddress: 'METAmTMXwdb8gYzyCPfXXFmZZw4rUsXX58PNsDg7zjL', - name: 'Solice', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '', - decimals: 6, - id: 'SLIM_SOL', - issuerAddress: 'xxxxa1sKNGwFtw2kFn8XauW9xq8hBZ5kVtcSesTT9fW', - name: 'Solanium (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '', - decimals: 6, - id: 'SLND_SOL', - issuerAddress: 'SLNDpmoWTVADgEdndyvWzroNL7zSi1dF9PC3xHGtPwp', - name: 'Solend (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0xd4e7a6e2D03e4e48DfC27dd3f46DF1c176647E38', - decimals: 18, - id: 'SLP_D4E7A_ETH', - name: 'SushiSwap LP Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xa8754b9Fa15fc18BB59458815510E40a12cD2014', - decimals: 0, - id: 'SLP_RON', - name: 'Smooth Love Potion (Ronin)', - nativeAsset: 'RON', - type: 'ERC20' - }, - { - contractAddress: '0xCC8Fa225D80b9c7D42F96e9570156c65D6cAAa25', - decimals: 0, - id: 'SLP1', - name: 'Smooth Love Potion', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x397FF1542f962076d0BFE58eA045FfA2d347ACa0', - decimals: 18, - id: 'SLPUSDCETH', - name: 'SushiSwap USDC/ETH LP', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'SLRS_SOL', - issuerAddress: 'SLRSSpSLUTP7okbCUBYStWCo1vUgyt775faPqz8HUMr', - name: 'Solrise Finance (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'SMARTBCH', - name: 'SmartBCH', - nativeAsset: 'SMARTBCH', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'SMR_SMR', - name: 'Shimmer', - nativeAsset: 'SMR_SMR', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'SMR_TEST', - name: 'Shimmer Test', - nativeAsset: 'SMR_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xF4134146AF2d511Dd5EA8cDB1C4AC88C57D60404', - decimals: 18, - id: 'SNC', - name: 'SunContract', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xaeC2E87E0A235266D9C5ADc9DEb4b2E29b54D009', - decimals: 0, - id: 'SNGLS', - name: 'SingularDTV', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x983F6d60db79ea8cA4eB9968C6aFf8cfA04B3c63', - decimals: 18, - id: 'SNM', - name: 'SONM', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x744d70FDBE2Ba4CF95131626614a1763DF805B9E', - decimals: 18, - id: 'SNT', - name: 'Status', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F', - decimals: 18, - id: 'SNX', - name: 'Synthetix Network Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x23B608675a2B2fB1890d3ABBd85c5775c51691d5', - decimals: 18, - id: 'SOCKS', - name: 'Unisocks Edition 0', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'SOETH_SOL', - issuerAddress: '2FPyTwcZLUg1MDrwsyoP4D6s1tM7hAkHYRjkNb5w6Pxk', - name: 'Wrapped Ethereum (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x04F2694C8fcee23e8Fd0dfEA1d4f5Bb8c352111F', - decimals: 9, - id: 'SOHM', - name: 'Staked Olympus', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 9, - id: 'SOL', - name: 'Solana', - nativeAsset: 'SOL', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x41848d32f281383F214C69B7b248DC7C2E0a7374', - decimals: 18, - id: 'SOL_BSC', - name: 'Solana (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '', - decimals: 6, - id: 'SOL_MAPS_FD7T', - issuerAddress: 'MAPS41MDahZ9QdKXhVa4dWB9RuyfV4XqhyAZ8XcYepb', - name: 'MAPS (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '', - decimals: 6, - id: 'SOL_OXY_4TTN', - issuerAddress: 'z3dn17yLaGMKffVogeFHQ9zWVcXgqgf3PQnDsNs2g6M', - name: 'Oxygen (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '', - decimals: 6, - id: 'SOL_SRM_R62M', - issuerAddress: 'SRMuApVNdxXokk5GT7XD5cUUgXMBCoAz2LHeuAoKWRt', - name: 'Serum (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '', - decimals: 9, - id: 'SOL_TEST', - name: 'Solana Test', - nativeAsset: 'SOL_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 9, - id: 'SOL_TTOKEN_CHGU', - issuerAddress: 'FYEEA9iZJpad1ZCkigi9BvkCNcW4QNun23hEPrAfELDA', - name: 'Solana Test Token', - nativeAsset: 'SOL_TEST', - type: 'SOL_ASSET' - }, - { - contractAddress: '', - decimals: 6, - id: 'SOL_USDC_PTHX', - issuerAddress: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', - name: 'USD Coin (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '', - decimals: 6, - id: 'SOL_USDT_EWAY', - issuerAddress: 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB', - name: 'USDT (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x570A5D26f7765Ecb712C0924E4De545B89fD43dF', - decimals: 18, - id: 'SOL2_BSC', - name: 'SOLANA BSC (2)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0x446C9033E7516D820cc9a2ce2d0B7328b579406F', - decimals: 8, - id: 'SOLVE', - name: 'Solve.Care', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 9, - id: 'SOLX_SOL', - issuerAddress: 'CH74tuRLTYcxG7qNJCsV9rghfLXJCQJbsu7i52a8F1Gn', - name: 'Soldex (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x3E8FFc8c3Cb0DB3081Df85DeC91B63abBbe99F71', - decimals: 18, - id: 'SOME', - name: 'Mixsome', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 9, - id: 'SONAR_SOL', - issuerAddress: 'sonarX4VtVkQemriJeLm6CKeW3GDMyiBnnAEMw1MRAE', - name: 'Sonar Watch (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'SONEIUM_MINATO_TEST', - name: 'Soneium Minato Test', - nativeAsset: 'SONEIUM_MINATO_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xEFc78fc7d48b64958315949279Ba181c2114ABBd', - decimals: 18, - id: 'SOV_RBTC', - name: 'Sovryn Token (RSK)', - nativeAsset: 'RBTC', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 2, - id: 'SPEI_MXN', - name: 'MXN (SPEI)', - nativeAsset: 'SPEI_MXN', - type: 'FIAT' - }, - { - contractAddress: '0x090185f2135308BaD17527004364eBcC2D37e5F6', - decimals: 18, - id: 'SPELL', - name: 'Spell Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xE11829A7D5d8806BB36E118461a1012588faFD89', - decimals: 18, - id: 'SPICE_SMARTBCH', - name: 'SPICE (SmartBCH)', - nativeAsset: 'SMARTBCH', - type: 'ERC20' - }, - { - contractAddress: '0x1633b7157e7638C4d6593436111Bf125Ee74703F', - decimals: 18, - id: 'SPS_BSC', - name: 'Splintershards (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0xe516D78d784C77D479977BE58905B3f2b1111126', - decimals: 18, - id: 'SPWN', - name: 'BitSpawn Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 9, - id: 'SPWN_SOL', - issuerAddress: '5U9QqCPhqXAJcEv9uyzFJd5zhN93vuPk1aNNkXnUfPnt', - name: 'Bitspawn Token (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x476c5E26a75bd202a9683ffD34359C0CC15be0fF', - decimals: 6, - id: 'SRM', - name: 'Serum', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x68d57c9a1C35f63E2c83eE8e49A64e9d70528D25', - decimals: 18, - id: 'SRN', - name: 'SIRIN LABS Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x624d520BAB2E4aD83935Fa503fB130614374E850', - decimals: 4, - id: 'SSP', - name: 'smartshare token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x0Ae055097C6d159879521C384F1D2123D1f195e6', - decimals: 18, - id: 'STAKE', - name: 'STAKE', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x78474F29aF6D4EB0cfB3168eff1c117cf13569e8', - decimals: 8, - id: 'STDASH', - name: 'stakedDASH', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xD79311EB6c74C408e678b8364B69B4744A5778f4', - decimals: 10, - id: 'STDOT', - name: 'stakedDOT', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 9, - id: 'STEP_SOL', - issuerAddress: 'StepAscQoEioFxxWGnh2sLBDFp9d8rvKz2Yp39iDpyT', - name: 'Step (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0xDFe66B14D37C77F4E9b180cEb433d1b164f0281D', - decimals: 18, - id: 'STETH', - name: 'stakedETH', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84', - decimals: 18, - id: 'STETH_ETH', - name: 'Liquid staked Ether 2_0', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x3F1c547b21f65e10480dE3ad8E19fAAC46C95034', - decimals: 18, - id: 'STETH_ETH_TEST6_DZFA', - name: 'Liquid staked Ether 2_0', - nativeAsset: 'ETH_TEST6', - type: 'ERC20' - }, - { - contractAddress: '0x160B1E5aaBFD70B2FC40Af815014925D71CEEd7E', - decimals: 8, - id: 'STFIRO', - name: 'stakedFiro', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xAf5191B0De278C7286d6C7CC6ab6BB8A73bA2Cd6', - decimals: 18, - id: 'STG', - name: 'StargateToken', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xD309142A629d07B023E5007feeF608d161B01156', - decimals: 18, - id: 'STGFBTC', - name: 'stgfBTC', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xe2ff59F37C3F07100bdEb5F79B98131F18D9D28B', - decimals: 18, - id: 'STGFETH', - name: 'stgfETH', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x8B6327a3050798b7A2843A6Edd0B310E97BEE113', - decimals: 18, - id: 'STGFUSD', - name: 'stgfUSD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x7A4B43dE058073F49774eA527Fc24Abd29e2738D', - decimals: 18, - id: 'STGFUSD_SMARTBCH', - name: 'stgfUSD (SmartBCH)', - nativeAsset: 'SMARTBCH', - type: 'ERC20' - }, - { - contractAddress: '0x4da27a545c0c5B758a6BA100e3a049001de870f5', - decimals: 18, - id: 'STKAAVE', - name: 'Staked Aave', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x19FfA8fc52dF8982cEa39B492E56AbB2f8Abc644', - decimals: 18, - id: 'STMATIC', - name: 'stakedMATIC', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xbE9375C6a420D2eEB258962efB95551A5b722803', - decimals: 18, - id: 'STMX', - name: 'StormX', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xB64ef51C888972c908CFacf59B47C1AfBC0Ab8aC', - decimals: 8, - id: 'STORJ', - name: 'Storj', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xD0a4b8946Cb52f0661273bfbC6fD0E0C75Fc6433', - decimals: 18, - id: 'STORM', - name: 'Storm', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xDe7D85157d9714EADf595045CC12Ca4A5f3E2aDb', - decimals: 18, - id: 'STPT', - name: 'STPT', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 9, - id: 'STR_SOL', - issuerAddress: '9zoqdwEBKWEi9G5Ze8BSkdmppxGgVv1Kw4LuigDiNr9m', - name: 'Solster', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x990f341946A3fdB507aE7e52d17851B87168017c', - decimals: 18, - id: 'STRONG', - name: 'Strong', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 9, - id: 'STSOL_SOL', - issuerAddress: '7dHbWXmci3dT8UFYWYZweBLXgycu7Y3iL6trKn1Y7ARj', - name: 'Lido Staked SOL (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x0371A82e4A9d0A4312f3ee2Ac9c6958512891372', - decimals: 18, - id: 'STU', - name: 'bitJob', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x006BeA43Baa3f7A6f765F14f10A1a1b08334EF45', - decimals: 18, - id: 'STX', - name: 'Stox', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x0C63cAE5fcC2Ca3dDE60a35e50362220651eBEc8', - decimals: 8, - id: 'STXEM', - name: 'stakedXEM', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x31B595e7cfDB624D10A3E7A562eD98c3567e3865', - decimals: 8, - id: 'STZEN', - name: 'stakedZEN', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x8D75959f1E61EC2571aa72798237101F084DE63a', - decimals: 18, - id: 'SUB', - name: 'Substratum', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x0763fdCCF1aE541A5961815C0872A8c5Bc6DE4d7', - decimals: 18, - id: 'SUKU', - name: 'SUKU Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'SUNNY_SOL', - issuerAddress: 'SUNNYWgPQmFxe9wTZzNK7iPnJ3vYDrkgnxJRJm1s3ag', - name: 'Sunny Governance Token (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0xe53EC727dbDEB9E2d5456c3be40cFF031AB40A55', - decimals: 18, - id: 'SUPER', - name: 'SuperVerse', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x57Ab1ec28D129707052df4dF418D58a2D46d5f51', - decimals: 18, - id: 'SUSD', - name: 'Synth sUSD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x6B3595068778DD592e39A122f4f5a5cF09C90fE2', - decimals: 18, - id: 'SUSHI', - name: 'Sushi Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x0b3F868E0BE5597D5DB7fEB59E1CADBb0fdDa50a', - decimals: 18, - id: 'SUSHI_POLYGON', - name: 'SushiSwap (Polygon)', - nativeAsset: 'MATIC_POLYGON', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 8, - id: 'SUSHI_SOL', - issuerAddress: 'ChVzxWRmrTeSgwd3Ui3UumcN8KX7VK3WaD4KGeSKpypj', - name: 'SushiToken (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '', - decimals: 6, - id: 'SVT_SOL', - issuerAddress: 'svtMpL5eQzdmB3uqK9NXaQkq8prGZoKQFNVJghdWCkV', - name: 'Solvent', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'SWEAT_NEAR', - issuerAddress: 'token.sweat', - name: 'SWEAT', - nativeAsset: 'NEAR', - type: 'NEAR_ASSET' - }, - { - contractAddress: '0x48C3399719B582dD63eB5AADf12A40B4C3f52FA2', - decimals: 18, - id: 'SWISE', - name: 'StakeWise', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xB8BAa0e4287890a5F79863aB62b7F175ceCbD433', - decimals: 18, - id: 'SWRV', - name: 'Swerve DAO Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x8CE9137d39326AD0cD6491fb5CC0CbA0e089b6A9', - decimals: 18, - id: 'SXP', - name: 'Swipe', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xf293d23BF2CDc05411Ca0edDD588eb1977e8dcd4', - decimals: 18, - id: 'SYLO', - name: 'Sylo', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x0f2D719407FdBeFF09D87557AbB7232601FD9F29', - decimals: 18, - id: 'SYN', - name: 'Synapse', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 9, - id: 'SYP_SOL', - issuerAddress: 'FnKE9n6aGjQoNWRBZXy4RW6LZVao7qwBonUbiD7edUmZ', - name: 'Sypool (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '', - decimals: 6, - id: 't14_XRP_TEST_YB4D', - issuerAddress: 'rDFUVuBZmdACfEm44ieCu73CE75pdi4fXa', - name: 't14', - nativeAsset: 'XRP_TEST', - type: 'XRP_ASSET' - }, - { - contractAddress: '', - decimals: 7, - id: 'TAB1_XLM_OXFD_YK4G', - issuerAddress: 'GCWAT6HJIHKNCA6UELZCIRLXP44RDVVPN2NOFNVLFOEOXG7GMK7AOSH3', - name: 'TAB1 (Stellar Test)', - nativeAsset: 'XLM_TEST', - type: 'XLM_ASSET' - }, - { - contractAddress: '0xc27A2F05fa577a83BA0fDb4c38443c0718356501', - decimals: 18, - id: 'TAU', - name: 'Lamden Tau', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xdFa3b0019EcF48c753B58908B5A21d11641bA56f', - decimals: 18, - id: 'TAU_BSC', - name: 'Lamden', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0x00006100F7090010005F1bd7aE6122c3C2CF0090', - decimals: 18, - id: 'TAUD', - name: 'TrueAUD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x8dAEBADE922dF735c38C80C7eBD708Af50815fAa', - decimals: 18, - id: 'TBTC', - name: 'tBTC', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x00000100F2A2bd000715001920eB70D229700085', - decimals: 18, - id: 'TCAD', - name: 'TrueCAD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xA72159FC390f0E3C6D415e658264c7c4051E9b87', - decimals: 18, - id: 'TCR_ARB', - name: 'Tracer', - nativeAsset: 'ETH-AETH', - type: 'ERC20' - }, - { - contractAddress: '0x467Bccd9d29f223BcE8043b84E8C8B282827790F', - decimals: 2, - id: 'TEL', - name: 'Telcoin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'TELOS', - name: 'TELOS', - nativeAsset: 'TELOS', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'TELOS_TEST', - name: 'Telos Test', - nativeAsset: 'TELOS_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xDD16eC0F66E54d453e6756713E533355989040E4', - decimals: 18, - id: 'TEN', - name: 'Tokenomy', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x00000000441378008EA67F4284A57932B1c000a5', - decimals: 18, - id: 'TGBP', - name: 'TrueGBP', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x0000852600CEB001E08e00bC008be620d60031F2', - decimals: 18, - id: 'THKD', - name: 'TrueHKD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x1Cb3209D45B2a60B7fBCA1cCDBF87f674237A4aa', - decimals: 4, - id: 'THR', - name: 'ThoreCoin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x29CbD0510EEc0327992CD6006e63F9Fa8E7f33B7', - decimals: 18, - id: 'TIDAL', - name: 'Tidal Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xb54f16fB19478766A268F172C9480f8da1a7c9C3', - decimals: 9, - id: 'TIME_AVAX', - name: 'Time (Avalanche)', - nativeAsset: 'AVAX', - type: 'ERC20' - }, - { - contractAddress: '0x3A8cCCB969a61532d1E6005e2CE12C200caeCe87', - decimals: 18, - id: 'TITAN', - name: 'TitanSwap', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x24E89bDf2f65326b94E36978A7EDeAc63623DAFA', - decimals: 18, - id: 'TKING', - name: 'Tiger King', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x9f589e3eabe42ebC94A44727b3f3531C0c877809', - decimals: 18, - id: 'TKO', - name: 'TKO (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '', - decimals: 18, - id: 'TKX', - name: 'TokenX', - nativeAsset: 'TKX', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x888888848B652B3E3a0f34c96E00EEC0F3a23F72', - decimals: 4, - id: 'TLM1', - name: 'Alien Worlds Trilium', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x08f5a9235B08173b7569F83645d2c7fB55e8cCD8', - decimals: 8, - id: 'TNT', - name: 'Tierion', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x2e9d63788249371f1DFC918a52f8d799F4a38C94', - decimals: 18, - id: 'TOKE', - name: 'Tokemak', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x4507cEf57C46789eF8d1a19EA45f4216bae2B528', - decimals: 9, - id: 'TOKEN_BSC_RLDP', - name: 'TokenFi', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0x4507cEf57C46789eF8d1a19EA45f4216bae2B528', - decimals: 9, - id: 'TOKEN_ETH_JIKQ', - name: 'TokenFi', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 9, - id: 'TON', - name: 'TON', - nativeAsset: 'TON', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 9, - id: 'TON_TEST', - name: 'TON Test', - nativeAsset: 'TON_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xdcD85914b8aE28c1E62f1C488E1D968D5aaFfE2b', - decimals: 18, - id: 'TOP', - name: 'TOP Network', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x3Dd98C8A089dBCFF7e8FC8d4f532BD493501Ab7F', - decimals: 8, - id: 'TOWN', - name: 'TownCoin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xaA7a9CA87d3694B5755f213B5D04094b8d0F0A6F', - decimals: 18, - id: 'TRAC', - name: 'OriginTrail', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x88dF592F8eb5D7Bd38bFeF7dEb0fBc02cf3778a0', - decimals: 18, - id: 'TRB', - name: 'Tellor Tributes', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x0Ba45A8b5d5575935B8158a88C631E9F9C95a2e5', - decimals: 18, - id: 'TRB_L', - name: 'Tellor Tributes (Legacy)', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xc7283b66Eb1EB5FB86327f08e1B5816b0720212B', - decimals: 18, - id: 'TRIBE', - name: 'Tribe', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x4C19596f5aAfF459fA38B0f7eD92F11AE6543784', - decimals: 8, - id: 'TRU', - name: 'TrueFi', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xA4d17AB1eE0efDD23edc2869E7BA96B89eEcf9AB', - decimals: 18, - id: 'TRUE', - name: 'TrueChain', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'TRX', - name: 'Tron', - nativeAsset: 'TRX', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x85EAC5Ac2F758618dFa09bDbe0cf174e7d574D5B', - decimals: 18, - id: 'TRX_BSC', - name: 'TRON (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '', - decimals: 6, - id: 'TRX_TEST', - name: 'Tron Test', - nativeAsset: 'TRX_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 6, - id: 'TRX_USDC_6NU3', - issuerAddress: 'TEkxiTehnzSmSe2XqrBj4w32RUN966rdz8', - name: 'USD Coin (Tron)', - nativeAsset: 'TRX', - type: 'TRON_TRC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'TRX_USDC_SKL5', - issuerAddress: 'TFGBSrddCjLJAwuryZ9DUxtEmKv13BPjnh', - name: 'USD Coin Test (Tron)', - nativeAsset: 'TRX_TEST', - type: 'TRON_TRC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'TRX_USDT_S2UZ', - issuerAddress: 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t', - name: 'USD Tether (Tron)', - nativeAsset: 'TRX', - type: 'TRON_TRC20' - }, - { - contractAddress: '0x2C537E5624e4af88A7ae4060C022609376C8D0EB', - decimals: 6, - id: 'TRYB', - name: 'BiLira', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x564A341Df6C126f90cf3ECB92120FD7190ACb401', - decimals: 6, - id: 'TRYB_AVAX', - name: 'BiLira (Avalanche)', - nativeAsset: 'AVAX', - type: 'ERC20' - }, - { - contractAddress: '0xC1fdbed7Dac39caE2CcC0748f7a80dC446F6a594', - decimals: 6, - id: 'TRYB_BSC', - name: 'BiLira (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '', - decimals: 6, - id: 'TRYB_SOL', - issuerAddress: 'A94X2fRy3wydNShU4dRaDyap2UuoeWJGWyATtyp61WZf', - name: 'BiLira (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0xD9baE39c725A1864b1133Ad0eF1640d02f79B78c', - decimals: 18, - id: 'TST', - name: 'Touch Smart Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xa760e26aA76747020171fCF8BdA108dFdE8Eb930', - decimals: 18, - id: 'TTOKE', - name: 'TokemakTokePool', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x9F599410D207f3D2828a8712e5e543AC2E040382', - decimals: 18, - id: 'TTT', - name: 'Tapcoin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'TTT_SPL', - issuerAddress: 'FNFKRV3V8DtA3gVJN6UshMiLGYA8izxFwkNWmJbFjmRj', - name: 'TabTrader (SOLANA)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x6558392AfdA386d1A6b451640e809a27153151d8', - decimals: 18, - id: 'TTTT_ETH_TEST6', - name: 'TTTT_ETH_TEST6', - nativeAsset: 'ETH_TEST6', - type: 'ERC20' - }, - { - contractAddress: '0x0000000000085d4780B73119b644AE5ecd22b376', - decimals: 18, - id: 'TUSD', - name: 'TrueUSD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x1C20E891Bab6b1727d14Da358FAe2984Ed9B59EB', - decimals: 18, - id: 'TUSD_AVAX', - name: 'TrueUSD (Avalanche)', - nativeAsset: 'AVAX', - type: 'ERC20' - }, - { - contractAddress: '0xd084B83C305daFD76AE3E1b4E1F1fe2eCcCb3988', - decimals: 18, - id: 'TVK', - name: 'Terra Virtua Kolect', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x4463e6A3dEd0dBE3F6e15bC8420dFc55e5FeA830', - decimals: 18, - id: 'TXA', - name: 'TXA', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x547b2F82ceCfAb9C2B1D36fddA96eF9F58C63B8C', - decimals: 18, - id: 'TXT', - name: 'Taxa Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x8400D94A5cb0fa0D041a3788e395285d61c9ee5e', - decimals: 8, - id: 'UBT', - name: 'UniBright', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x8a3d77e9d6968b780564936d15B09805827C21fa', - decimals: 18, - id: 'UCO', - name: 'UnirisToken', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xD1E5b0FF1287aA9f9A268759062E4Ab08b9Dacbe', - decimals: 18, - id: 'UD', - name: '.crypto', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x12f649A9E821F90BB143089a6e56846945892ffB', - decimals: 18, - id: 'UDOO', - name: 'uDOO', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x0202Be363B8a4820f3F4DE7FaF5224fF05943AB1', - decimals: 18, - id: 'UFT', - name: 'UniLend Finance Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x24692791Bc444c5Cd0b81e3CBCaba4b04Acd1F3B', - decimals: 18, - id: 'UKG', - name: 'Unikoin Gold', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x04Fa0d235C4abf4BcF4787aF4CF447DE572eF828', - decimals: 18, - id: 'UMA', - name: 'UMA Voting Token v1', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x5872E64C3f93363822D2B1e4717Be3398FDCEA51', - decimals: 18, - id: 'UMASK', - name: 'Hashmask', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x6fC13EACE26590B80cCCAB1ba5d51890577D83B2', - decimals: 18, - id: 'UMB', - name: 'Umbrella', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984', - decimals: 18, - id: 'UNI', - name: 'Uniswap', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xBf5140A22578168FD562DCcF235E5D43A02ce9B1', - decimals: 18, - id: 'UNI_BSC', - name: 'Binance-Peg Uniswap (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984', - decimals: 18, - id: 'UNI_ETH_TEST5_IXAC', - name: 'Uniswap', - nativeAsset: 'ETH_TEST5', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 8, - id: 'UNI_SOL', - issuerAddress: '8FU95xFJhUUkyyCLU13HSzDLs7oC4QZdXQHL6SCeab36', - name: 'Uniswap (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x9861F7187b58023d89B2C2b0767bdEE43345620A', - decimals: 18, - id: 'UNI-V2-2GT-2', - name: 'Uniswap V2: 2GT 2', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x600Cf1C039e1fD31Bc4762a39D322Dd8977Dd1aB', - decimals: 18, - id: 'UNI-V2-SMOL', - name: 'Uniswap V2: SMOL', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x64060aB139Feaae7f06Ca4E63189D86aDEb51691', - decimals: 18, - id: 'UNIM_POLYGON_LACR', - name: 'Unicorn Milk', - nativeAsset: 'MATIC_POLYGON', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'UNQ_SOL', - issuerAddress: 'UNQtEecZ5Zb4gSSVHCAWUQEoNnSVEbWiKCi1v9kdUJJ', - name: 'UNQ', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0xD13c7342e1ef687C5ad21b27c2b65D772cAb5C8c', - decimals: 4, - id: 'UOS', - name: 'Ultra Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xc7461b398005e50BCc43c8e636378C6722E76c01', - decimals: 8, - id: 'UPBTC', - name: 'Universal Bitcoin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x6C103D85C15107Dce19F5a75fC746227e610AaBd', - decimals: 2, - id: 'UPEUR', - name: 'Universal Euro', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xC86D054809623432210c107af2e3F619DcFbf652', - decimals: 18, - id: 'UPP', - name: 'SENTINEL PROTOCOL', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x6CA88Cc8D9288f5cAD825053B6A1B179B05c76fC', - decimals: 18, - id: 'UPT', - name: 'Universal Protocol Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x86367c0e517622DAcdab379f2de389c3C9524345', - decimals: 2, - id: 'UPUSD', - name: 'Universal US Dollar', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x0557Df767419296474C3f551Bb0A0ED4c2DD3380', - decimals: 5, - id: 'UPXAU', - name: 'Universal Gold', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 2, - id: 'USD_BY_WIRE', - name: 'USD (wire)', - nativeAsset: 'USD_BY_WIRE', - type: 'FIAT' - }, - { - contractAddress: '', - decimals: 2, - id: 'USD_BY_WIRE_TEST', - name: 'USD Test (wire)', - nativeAsset: 'USD_BY_WIRE_TEST', - type: 'FIAT' - }, - { - contractAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', - decimals: 6, - id: 'USDC', - name: 'USD Coin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582', - decimals: 6, - id: 'USDC_AMOY_POLYGON_TEST_7WWV', - name: 'USDC', - nativeAsset: 'AMOY_POLYGON_TEST', - type: 'ERC20' - }, - { - contractAddress: '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', - decimals: 6, - id: 'USDC_ARB', - name: 'Bridged USDC (Arbitrum)', - nativeAsset: 'ETH-AETH', - type: 'ERC20' - }, - { - contractAddress: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', - decimals: 6, - id: 'USDC_ARB_3SBJ', - name: 'USD Coin (Arbitrum)', - nativeAsset: 'ETH-AETH', - type: 'ERC20' - }, - { - contractAddress: '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E', - decimals: 6, - id: 'USDC_AVAX', - name: 'USD Coin (Avalanche)', - nativeAsset: 'AVAX', - type: 'ERC20' - }, - { - contractAddress: '0x5425890298aed601595a70AB815c96711a31Bc65', - decimals: 6, - id: 'USDC_AVAX_FUJI', - name: ' USD Coin (Avalanche Fuji)', - nativeAsset: 'AVAXTEST', - type: 'ERC20' - }, - { - contractAddress: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', - decimals: 6, - id: 'USDC_BASECHAIN_ETH_5I5C', - name: 'USD Coin', - nativeAsset: 'BASECHAIN_ETH', - type: 'ERC20' - }, - { - contractAddress: '0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d', - decimals: 18, - id: 'USDC_BSC', - name: 'Binance-Peg USD Coin (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0xcebA9300f2b948710d2653dD7B07f33A8B32118C', - decimals: 6, - id: 'USDC_CELO_ROI8', - name: 'USDC', - nativeAsset: 'CELO', - type: 'ERC20' - }, - { - contractAddress: '0xA7D7079b0FEaD91F3e65f86E8915Cb59c1a4C664', - decimals: 6, - id: 'USDC_E_AVAX', - name: 'USD Coin (Avalanche)', - nativeAsset: 'AVAX', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'USDC_E_NEAR', - issuerAddress: 'a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48.factory.bridge.near', - name: 'USD Coin Bridged', - nativeAsset: 'NEAR', - type: 'NEAR_ASSET' - }, - { - contractAddress: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238', - decimals: 6, - id: 'USDC_ETH_TEST5_0GER', - name: 'USDC', - nativeAsset: 'ETH_TEST5', - type: 'ERC20' - }, - { - contractAddress: '0x04068DA6C83AFCFA0e13ba15A6696662335D5B75', - decimals: 6, - id: 'USDC_FANTOM', - name: 'USD Coin (Fantom)', - nativeAsset: 'FTM_FANTOM', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'USDC_NEAR', - issuerAddress: '17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a1', - name: 'USD Coin', - nativeAsset: 'NEAR', - type: 'NEAR_ASSET' - }, - { - contractAddress: '', - decimals: 6, - id: 'USDC_NOBLE', - name: 'USDC Noble', - nativeAsset: 'USDC_NOBLE', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 6, - id: 'USDC_NOBLE_TEST', - name: 'USDC Noble Testnet', - nativeAsset: 'USDC_NOBLE_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174', - decimals: 6, - id: 'USDC_POLYGON', - name: 'USD Coin (Polygon)', - nativeAsset: 'MATIC_POLYGON', - type: 'ERC20' - }, - { - contractAddress: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359', - decimals: 6, - id: 'USDC_POLYGON_NXTB', - name: 'USD Coin (Polygon)', - nativeAsset: 'MATIC_POLYGON', - type: 'ERC20' - }, - { - contractAddress: '0xBdbe4D9e43E8f305AfE9462802B8691C45Caf596', - decimals: 18, - id: 'USDD', - name: 'USD Digital', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x1c48f86ae57291F7686349F12601910BD8D470bb', - decimals: 18, - id: 'USDK', - name: 'USDK', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xbdC7c08592Ee4aa51D06C27Ee23D5087D65aDbcD', - decimals: 18, - id: 'USDL_ETH_HYWN', - name: 'Lift Dollar', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x674C6Ad92Fd080e4004b2312b45f796a192D27a0', - decimals: 18, - id: 'USDN', - name: 'Neutrino USD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x3A15461d8aE0F0Fb5Fa2629e9DA7D66A794a6e37', - decimals: 18, - id: 'USDRIF_RSK_14FQ', - name: 'RIF US Dollar', - nativeAsset: 'RBTC', - type: 'ERC20' - }, - { - contractAddress: '0xA4Bdb11dc0a2bEC88d24A3aa1E6Bb17201112eBe', - decimals: 6, - id: 'USDS', - name: 'StableUSD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xc7198437980c041c805A1EDcbA50c1Ce5db95118', - decimals: 6, - id: 'USDT_AVAX', - name: 'Tether USD (Avalanche)', - nativeAsset: 'AVAX', - type: 'ERC20' - }, - { - contractAddress: '0x55d398326f99059fF775485246999027B3197955', - decimals: 18, - id: 'USDT_BSC', - name: 'Binance-Peg Tether (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0x337610d27c682E347C9cD60BD4b3b107C9d34dDd', - decimals: 18, - id: 'USDT_BSC_TEST', - name: 'USDT Token (BSC Test)', - nativeAsset: 'BNB_TEST', - type: 'BEP20' - }, - { - contractAddress: '0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e', - decimals: 6, - id: 'USDT_CELO', - name: 'Tether USD (Celo)', - nativeAsset: 'CELO', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'USDT_E_NEAR', - issuerAddress: 'dac17f958d2ee523a2206206994597c13d831ec7.factory.bridge.near', - name: 'USDT Tether Bridged', - nativeAsset: 'NEAR', - type: 'NEAR_ASSET' - }, - { - contractAddress: '0xdAC17F958D2ee523a2206206994597C13D831ec7', - decimals: 6, - id: 'USDT_ERC20', - name: 'Tether USD (Ethereum)', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'USDT_NEAR', - issuerAddress: 'usdt.tether-token.near', - name: 'USD Tether', - nativeAsset: 'NEAR', - type: 'NEAR_ASSET' - }, - { - contractAddress: '', - decimals: 8, - id: 'USDT_OMNI', - name: 'Tether (Omni)', - nativeAsset: 'BTC', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xc2132D05D31c914a87C6611C10748AEb04B58e8F', - decimals: 6, - id: 'USDT_POLYGON', - name: '(PoS) Tether USD (Polygon)', - nativeAsset: 'MATIC_POLYGON', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'USDT_TON', - issuerAddress: 'EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs', - name: 'Tether USD (Ton)', - nativeAsset: 'TON', - type: 'TON_ASSET' - }, - { - contractAddress: '0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7', - decimals: 6, - id: 'USDT2_AVAX', - name: 'TetherToken _Avalanche_ - USDT2', - nativeAsset: 'AVAX', - type: 'ERC20' - }, - { - contractAddress: '0x4000369AcfA25C8FE5d17fE3312e30C332beF633', - decimals: 9, - id: 'USG', - name: 'US Gold', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xa47c8bf37f92aBed4A126BDA807A7b7498661acD', - decimals: 18, - id: 'UST', - name: 'Wrapped UST Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x23396cF899Ca06c4472205fC903bDB4de249D6fC', - decimals: 18, - id: 'UST_BSC', - name: 'Wrapped UST Token', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0xa693B19d2931d498c5B318dF961919BB4aee87a5', - decimals: 6, - id: 'UST_ETH', - name: 'UST (Wormhole)', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'UST_SOL', - issuerAddress: '9vMJfxuKxXBoEa7rM12mYLMwTacLMLDJqHozw96WQL8i', - name: 'UST (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x340D2bdE5Eb28c1eed91B2f790723E3B160613B7', - decimals: 18, - id: 'VEE', - name: 'BLOCKv', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xcB84d72e61e383767C4DFEb2d8ff7f4FB89abc6e', - decimals: 18, - id: 'VEGA', - name: 'VEGA', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x5F0bc16D50F72d10b719dBF6845DE2E599eb5624', - decimals: 18, - id: 'VENT', - name: 'VENT', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x37F04d2C3AE075Fad5483bB918491F656B12BDB6', - decimals: 8, - id: 'VEST', - name: 'VestChain', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x4D61577d8Fd2208A0afb814ea089fDeAe19ed202', - decimals: 18, - id: 'VFOX_BSC', - name: 'VFOX (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0x3C4B6E6e1eA3D4863700D7F76b36B7f3D3f13E3d', - decimals: 8, - id: 'VGX_ETH', - name: 'Voyager Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x2C974B2d0BA1716E644c1FC59982a89DDD2fF724', - decimals: 18, - id: 'VIB', - name: 'Viberate', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'VICTION', - name: 'Viction', - nativeAsset: 'VICTION', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x2C9023bBc572ff8dc1228c7858A280046Ea8C9E5', - decimals: 18, - id: 'VID', - name: 'VideoCoin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xfeF4185594457050cC9c23980d301908FE057Bb1', - decimals: 18, - id: 'VIDT', - name: 'VIDT Datalink', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xC77b230F31b517F1ef362e59c173C2BE6540B5E8', - decimals: 18, - id: 'VIDY', - name: 'VidyCoin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x3D3D35bb9bEC23b06Ca00fe472b50E7A4c692C30', - decimals: 18, - id: 'VIDYA', - name: 'Vidya', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xF938424F7210f31dF2Aee3011291b658f872e91e', - decimals: 18, - id: 'VISR', - name: 'VISOR', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'VLX_TEST', - name: 'Velas Test (VLX)', - nativeAsset: 'VLX_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'VLX_VLX', - name: 'Velas (VLX)', - nativeAsset: 'VLX_VLX', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xd0258a3fD00f38aa8090dfee343f10A9D4d30D3F', - decimals: 18, - id: 'VOXEL_POLYGON', - name: 'VOXEL Token (Polygon)', - nativeAsset: 'MATIC_POLYGON', - type: 'ERC20' - }, - { - contractAddress: '0xF411903cbC70a74d22900a5DE66A2dda66507255', - decimals: 18, - id: 'VRA', - name: 'VERA', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x1b40183EFB4Dd766f11bDa7A7c3AD8982e998421', - decimals: 18, - id: 'VSP', - name: 'VesperToken', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xB0fFa8000886e57F86dd5264b9582b2Ad87b2b91', - decimals: 18, - id: 'W_ETH_S5P9', - name: 'Wormhole Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'W_SOL', - issuerAddress: '85VBFQZC9TZkfaptBWjvUw7YbZjy52A6mjtPGjstQAmQ', - name: 'Wormhole', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7', - decimals: 18, - id: 'WAVAX_AVAX', - name: 'Wrapped AVAX (Avalanche)', - nativeAsset: 'AVAX', - type: 'ERC20' - }, - { - contractAddress: '0x1cF4592ebfFd730c7dc92c1bdFFDfc3B9EfCf29a', - decimals: 18, - id: 'WAVES', - name: 'WAVES token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c', - decimals: 18, - id: 'WBNB_BSC', - name: 'Wrapped BNB (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', - decimals: 8, - id: 'WBTC', - name: 'Wrapped BTC', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x50b7545627a5162F82A992c33b87aDc75187B218', - decimals: 8, - id: 'WBTC_AVAX', - name: 'Wrapped BTC (Avalanche)', - nativeAsset: 'AVAX', - type: 'ERC20' - }, - { - contractAddress: '0xc221b7E65FfC80DE234bbB6667aBDd46593D34F0', - decimals: 18, - id: 'WCFG', - name: 'Wrapped Centrifuge', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x61cc6aF18C351351148815c5F4813A16DEe7A7E4', - decimals: 18, - id: 'WCT_B6QT1TZK_TZBJ', - name: 'WalletConnect', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xeF4461891DfB3AC8572cCf7C794664A8DD927945', - decimals: 18, - id: 'WCT_B7K5S6PF_H7HU', - name: 'WalletConnect', - nativeAsset: 'ETH-OPT', - type: 'ERC20' - }, - { - contractAddress: '0x123151402076fc819B7564510989e475c9cD93CA', - decimals: 8, - id: 'WDGLD', - name: 'wrapped-DGLD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'WEMIX', - name: 'WEMIX', - nativeAsset: 'WEMIX', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'WEMIX_TEST', - name: 'WEMIX Test', - nativeAsset: 'WEMIX_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', - decimals: 18, - id: 'WETH', - name: 'Wrapped Ether', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB', - decimals: 18, - id: 'WETH_E', - name: 'Wrapped Ether (Avalanche)', - nativeAsset: 'AVAX', - type: 'ERC20' - }, - { - contractAddress: '0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14', - decimals: 18, - id: 'WETH_ETH_TEST5_PU4S', - name: 'Wrapped Ether', - nativeAsset: 'ETH_TEST5', - type: 'ERC20' - }, - { - contractAddress: '0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619', - decimals: 18, - id: 'WETH_POLYGON', - name: 'Wrapped Ether (Polygon)', - nativeAsset: 'MATIC_POLYGON', - type: 'ERC20' - }, - { - contractAddress: '0x21be370D5312f44cB42ce377BC9b8a0cEF1A4C83', - decimals: 18, - id: 'WFTM_FANTOM', - name: 'Wrapped Fantom (Fantom)', - nativeAsset: 'FTM_FANTOM', - type: 'ERC20' - }, - { - contractAddress: '0x9355372396e3F6daF13359B7b607a3374cc638e0', - decimals: 4, - id: 'WHALE', - name: 'WHALE', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x0fa5B0608633c13f4E135F9b1F3570508B4f7046', - decimals: 8, - id: 'WHBAR', - name: 'Wrapped Hbar', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x2a3bFF78B79A009976EeA096a51A948a3dC00e34', - decimals: 18, - id: 'WILD', - name: 'Wilder', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xaeF0d72a118ce24feE3cD1d43d383897D05B4e99', - decimals: 18, - id: 'WIN_BSC', - name: 'WINk', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0x667088b212ce3d06a1b553a7221E1fD19000d9aF', - decimals: 18, - id: 'WINGS', - name: 'Wings', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x971fC3880aD395c165e812b029E7Df76FcB63eD8', - decimals: 18, - id: 'WIRE', - name: 'Airwire', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xDecade1c6Bf2cD9fb89aFad73e4a519C867adcF5', - decimals: 18, - id: 'WIS', - name: 'Experty Wisdom Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xd2877702675e6cEb975b4A1dFf9fb7BAF4C91ea9', - decimals: 18, - id: 'WLUNA', - name: 'Wrapped LUNA Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270', - decimals: 18, - id: 'WMATIC_POLYGON', - name: 'Wrapped Matic (Polygon)', - nativeAsset: 'MATIC_POLYGON', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 12, - id: 'WND', - name: 'Westend', - nativeAsset: 'WND', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x0d438F3b5175Bebc262bF23753C1E53d03432bDE', - decimals: 18, - id: 'WNXM', - name: 'Wrapped NXM', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xBd356a39BFf2cAda8E9248532DD879147221Cf76', - decimals: 18, - id: 'WOM', - name: 'WOM Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x4691937a7508860F876c9c0a2a617E7d9E945D4B', - decimals: 18, - id: 'WOO', - name: 'Wootrade Network (Ethereum)', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x7A8d51b82b36Fa5B50fb77001D6d189E920d2f75', - decimals: 18, - id: 'WOPIUM', - name: 'Wrapped Opium Governance Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'WORLDCHAIN', - name: 'Worldchain', - nativeAsset: 'WORLDCHAIN', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'WORLDCHAIN_TEST', - name: 'Worldchain Test', - nativeAsset: 'WORLDCHAIN_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xd1e2d5085b39B80C9948AeB1b9aA83AF6756bcc5', - decimals: 9, - id: 'WOXEN', - name: 'Wrapped OXEN', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x4CF488387F035FF08c371515562CBa712f9015d4', - decimals: 18, - id: 'WPR', - name: 'WePower', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x542fDA317318eBF1d3DEAf76E0b632741A7e677d', - decimals: 18, - id: 'WRBTC_RSK_VNPH', - name: 'Wrapped BTC', - nativeAsset: 'RBTC', - type: 'ERC20' - }, - { - contractAddress: '0xFF0a024B66739357c4ED231fB3DBC0c8C22749F5', - decimals: 8, - id: 'WRX', - name: 'Wazirx Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x8e17ed70334C87eCE574C9d537BC153d8609e2a3', - decimals: 8, - id: 'WRX_BSC', - name: 'Wazirx Token (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0xa3C22370de5f9544f0c4De126b1e46cEadF0A51B', - decimals: 18, - id: 'WSTRAX', - name: 'WrappedStrax', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xb7cB1C96dB6B22b0D3d9536E0108d062BD488F74', - decimals: 18, - id: 'WTC', - name: 'Waltonchain', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xa02120696c7B8fE16C09C749E4598819b2B0E915', - decimals: 18, - id: 'WXT', - name: 'Wirex Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x68749665FF8D2d112Fa859AA293F07A622782F38', - decimals: 6, - id: 'XAUT2', - name: 'Tether Gold (New)', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x57C09A8de0b0F471F8567609777aDdFfb5c46a08', - decimals: 18, - id: 'XBX', - name: 'Bitex Global XBX Coin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x03678f2c2c762DC63c2Bb738c3a837D366eDa560', - decimals: 18, - id: 'XCASH_POLYGON', - name: 'X-Cash (PoS)', - nativeAsset: 'MATIC_POLYGON', - type: 'ERC20' - }, - { - contractAddress: '0xB4272071eCAdd69d933AdcD19cA99fe80664fc08', - decimals: 18, - id: 'XCHF', - name: 'CryptoFranc', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 18, - id: 'XDAI', - name: 'Gnosis xDAI', - nativeAsset: 'XDAI', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'XDAI_TEST', - name: 'Gnosis xDAI Test', - nativeAsset: 'XDAI_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 7, - id: 'XDB', - name: 'XDB', - nativeAsset: 'XDB', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xB9EefC4b0d472A44be93970254Df4f4016569d27', - decimals: 7, - id: 'XDB_ETH', - name: 'Digitalbits (ETH)', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 7, - id: 'XDB_ROMA_G5H1', - issuerAddress: 'GBJPYIYYLCJED2ETN3YWPG23P77JWIE3SSNHZJPW2FOHKRBXNKF5UEEL', - name: 'ROMA (DigitalBits)', - nativeAsset: 'XDB', - type: 'XDB_ASSET' - }, - { - contractAddress: '', - decimals: 7, - id: 'XDB_TEST', - name: 'XDB Test', - nativeAsset: 'XDB_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 7, - id: 'XDB_USDS_7FSS', - issuerAddress: 'GBFOHHXUNGIYJHPLXAC3AKNDDXWR6NSUJSKBMXY452Y4AQBZEUL7EKAB', - name: 'USDS (DigitalBits)', - nativeAsset: 'XDB', - type: 'XDB_ASSET' - }, - { - contractAddress: '', - decimals: 7, - id: 'XDB_ZUSD_Q74F', - issuerAddress: 'GBFOHHXUNGIYJHPLXAC3AKNDDXWR6NSUJSKBMXY452Y4AQBZEUL7EKAB', - name: 'ZUSD (DigitalBits)', - nativeAsset: 'XDB', - type: 'XDB_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'XDC', - name: 'XDC Network', - nativeAsset: 'XDC', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 2, - id: 'XEC', - name: 'eCash', - nativeAsset: 'XEC', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 2, - id: 'XEC_TEST', - name: 'eCash Test', - nativeAsset: 'XEC_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 6, - id: 'XEM', - name: 'XEM', - nativeAsset: 'XEM', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 6, - id: 'XEM_TEST', - name: 'XEM Test', - nativeAsset: 'XEM_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x4aa41bC1649C9C3177eD16CaaA11482295fC7441', - decimals: 18, - id: 'XFIT', - name: 'XFIT', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xA974c709cFb4566686553a20790685A47acEAA33', - decimals: 18, - id: 'XIN', - name: 'Mixin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 7, - id: 'XLM', - name: 'Stellar', - nativeAsset: 'XLM', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 7, - id: 'XLM_AKN_GNFL', - issuerAddress: 'GACSHAJ2XBNKRNJEVDAII6E2EAASIAMDBCLJ3VKSZEWK3KC7Y7DPXUFX', - name: 'Akoin (Stellar)', - nativeAsset: 'XLM', - type: 'XLM_ASSET' - }, - { - contractAddress: '', - decimals: 7, - id: 'XLM_BRL_LQ3J', - issuerAddress: 'GDVKY2GU2DRXWTBEYJJWSFXIGBZV6AZNBVVSUHEPZI54LIS6BA7DVVSP', - name: 'BRL (Stellar)', - nativeAsset: 'XLM', - type: 'XLM_ASSET' - }, - { - contractAddress: '', - decimals: 7, - id: 'XLM_BRZ_EDTE', - issuerAddress: 'GABMA6FPH3OJXNTGWO7PROF7I5WPQUZOB4BLTBTP4FK6QV7HWISLIEO2', - name: 'BRZ Token (Stellar)', - nativeAsset: 'XLM', - type: 'XLM_ASSET' - }, - { - contractAddress: '', - decimals: 7, - id: 'XLM_BTCE_DP2P', - issuerAddress: 'GBOPFWZZJZUMTS6KVQAHUUNLMXO424ZF7IWHF6GONLAVCDSN4TBBKCLV', - name: 'BTCe Test (Stellar)', - nativeAsset: 'XLM_TEST', - type: 'XLM_ASSET' - }, - { - contractAddress: '', - decimals: 7, - id: 'XLM_BTCEM_T_MVE5', - issuerAddress: 'GBOPFWZZJZUMTS6KVQAHUUNLMXO424ZF7IWHF6GONLAVCDSN4TBBKCLV', - name: 'BTCEM Test (Stellar)', - nativeAsset: 'XLM_TEST', - type: 'XLM_ASSET' - }, - { - contractAddress: '', - decimals: 7, - id: 'XLM_EURE_O4P4', - issuerAddress: 'GBOPFWZZJZUMTS6KVQAHUUNLMXO424ZF7IWHF6GONLAVCDSN4TBBKCLV', - name: 'EURe Test (Stellar)', - nativeAsset: 'XLM_TEST', - type: 'XLM_ASSET' - }, - { - contractAddress: '', - decimals: 7, - id: 'XLM_EUREM_T_B7SB', - issuerAddress: 'GBOPFWZZJZUMTS6KVQAHUUNLMXO424ZF7IWHF6GONLAVCDSN4TBBKCLV', - name: 'EUREM Test (Stellar)', - nativeAsset: 'XLM_TEST', - type: 'XLM_ASSET' - }, - { - contractAddress: '', - decimals: 7, - id: 'XLM_FBTEST_7SNX', - issuerAddress: 'GC3NA75PU6HD5OWCZ7OHCSAL6HZSELNTTBAGHAOCGHBSAQTVI7GCQK2J', - name: 'Fireblocks Test Token (Stellar)', - nativeAsset: 'XLM_TEST', - type: 'XLM_ASSET' - }, - { - contractAddress: '', - decimals: 7, - id: 'XLM_GYEN_TLIE', - issuerAddress: 'GDF6VOEGRWLOZ64PQQGKD2IYWA22RLT37GJKS2EJXZHT2VLAGWLC5TOB', - name: 'GMO JPY (Stellar)', - nativeAsset: 'XLM', - type: 'XLM_ASSET' - }, - { - contractAddress: '', - decimals: 7, - id: 'XLM_GYEN_ZN63', - issuerAddress: 'GAQQSET64FFYJLZB3XIFUVPGRDMETG2USH2R7VPUY2E4YEXH7STKRISN', - name: 'GMO JPY Test (Stellar)', - nativeAsset: 'XLM_TEST', - type: 'XLM_ASSET' - }, - { - contractAddress: '', - decimals: 7, - id: 'XLM_HODL_EFOE', - issuerAddress: 'GAQEDFS2JK6JSQO53DWT23TGOLH5ZUZG4O3MNLF3CFUZWEJ6M7MMGJAV', - name: 'HODL Token (Stellar)', - nativeAsset: 'XLM', - type: 'XLM_ASSET' - }, - { - contractAddress: '', - decimals: 7, - id: 'XLM_IDK_JM2C', - issuerAddress: 'GAVDGVOARGIMZA47POPHGPC2FRDE7I7ZF3NGNNIGDPGEZRMTELFAD6DN', - name: 'IDK (Stellar)', - nativeAsset: 'XLM', - type: 'XLM_ASSET' - }, - { - contractAddress: '', - decimals: 7, - id: 'XLM_LUNA_T_WZ5J', - issuerAddress: 'GBDH4456HKE3BNIMIRWRHQDWN2KSOTY3FZFGUJTRZXY33Y3JEJGGFMCT', - name: 'Luna Test (Stellar)', - nativeAsset: 'XLM_TEST', - type: 'XLM_ASSET' - }, - { - contractAddress: '', - decimals: 7, - id: 'XLM_NTT_PZV2', - issuerAddress: 'GBWFD4RZAEMXLBDLVYTGTRZ53IIGLWOAPEMVRF5V62M7FH76QER5JNMI', - name: 'NTT Test (Stellar)', - nativeAsset: 'XLM_TEST', - type: 'XLM_ASSET' - }, - { - contractAddress: '', - decimals: 7, - id: 'XLM_ROMA_G5H1', - issuerAddress: 'GBJPYIYYLCJED2ETN3YWPG23P77JWIE3SSNHZJPW2FOHKRBXNKF5UEEL', - name: 'ROMA _DigitalBits_', - nativeAsset: 'XDB', - type: 'XDB_ASSET' - }, - { - contractAddress: '', - decimals: 7, - id: 'XLM_SBDD_T_GC74', - issuerAddress: 'GC74OM3VHSTARP2BNCEFFCU5GUNRXGNYZUORHFVZIZJH7IPISKOVDHM4', - name: 'SBDD Issuance Wallet Test (Stellar)', - nativeAsset: 'XLM_TEST', - type: 'XLM_ASSET' - }, - { - contractAddress: '', - decimals: 7, - id: 'XLM_SBDD_T_GD7R', - issuerAddress: 'GD7RN27CQZAAYDZZ5WCIFYRSXSFQCB72IKMFEU2LE6V5M7ILZOONALOK', - name: 'SBDD Distribution Wallet Test (Stellar)', - nativeAsset: 'XLM_TEST', - type: 'XLM_ASSET' - }, - { - contractAddress: '', - decimals: 7, - id: 'XLM_SIX_BIQ4', - issuerAddress: 'GDMS6EECOH6MBMCP3FYRYEVRBIV3TQGLOFQIPVAITBRJUMTI6V7A2X6Z', - name: 'SIX.Network', - nativeAsset: 'XLM', - type: 'XLM_ASSET' - }, - { - contractAddress: '', - decimals: 7, - id: 'XLM_SOLA_T_7WZU', - issuerAddress: 'GDFREACG4LEESEGBBQZKSMS7FS47YNULFKBKFP5WGNKEHXOGNQVGSZHV', - name: 'Sola Test (Stellar)', - nativeAsset: 'XLM_TEST', - type: 'XLM_ASSET' - }, - { - contractAddress: '', - decimals: 7, - id: 'XLM_TEST', - name: 'Stellar Test', - nativeAsset: 'XLM_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 7, - id: 'XLM_TLFTST_UH6X', - issuerAddress: 'GBN54AOKMC6H4Q25Y623IRVUJHVREZJV7DQEJKQ26WISKQZDY4MC6VI3', - name: 'TLFTST Test (Stellar)', - nativeAsset: 'XLM_TEST', - type: 'XLM_ASSET' - }, - { - contractAddress: '', - decimals: 7, - id: 'XLM_USDC_5F3T', - issuerAddress: 'GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN', - name: 'USD Coin (Stellar)', - nativeAsset: 'XLM', - type: 'XLM_ASSET' - }, - { - contractAddress: '', - decimals: 7, - id: 'XLM_USDC_T_CEKS', - issuerAddress: 'GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5', - name: 'USD Coin Test (Stellar)', - nativeAsset: 'XLM_TEST', - type: 'XLM_ASSET' - }, - { - contractAddress: '', - decimals: 7, - id: 'XLM_WXT_DQLC', - issuerAddress: 'GASBLVHS5FOABSDNW5SPPH3QRJYXY5JHA2AOA2QHH2FJLZBRXSG4SWXT', - name: 'Wirex Token (Stellar)', - nativeAsset: 'XLM', - type: 'XLM_ASSET' - }, - { - contractAddress: '', - decimals: 7, - id: 'XLM_ZUSD_VQXC', - issuerAddress: 'GDF6VOEGRWLOZ64PQQGKD2IYWA22RLT37GJKS2EJXZHT2VLAGWLC5TOB', - name: 'Z.com USD (Stellar)', - nativeAsset: 'XLM', - type: 'XLM_ASSET' - }, - { - contractAddress: '', - decimals: 7, - id: 'XLM_ZUSD_XCYQ', - issuerAddress: 'GAQQSET64FFYJLZB3XIFUVPGRDMETG2USH2R7VPUY2E4YEXH7STKRISN', - name: 'Z.com USD Test (Stellar)', - nativeAsset: 'XLM_TEST', - type: 'XLM_ASSET' - }, - { - contractAddress: '0x3aaDA3e213aBf8529606924d8D1c55CbDc70Bf74', - decimals: 18, - id: 'XMON', - name: 'XMON', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'XRP', - name: 'XRP (Ripple)', - nativeAsset: 'XRP', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 6, - id: 'XRP_TEST', - name: 'XRP Test', - nativeAsset: 'XRP_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x70e8dE73cE538DA2bEEd35d14187F6959a8ecA96', - decimals: 6, - id: 'XSGD', - name: 'XSGD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x8798249c2E607446EfB7Ad49eC89dD1865Ff4272', - decimals: 18, - id: 'XSUSHI', - name: 'SushiBar', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x6368e1E18c4C419DDFC608A0BEd1ccb87b9250fc', - decimals: 18, - id: 'XTP', - name: 'TAP', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x9c794f933b4DD8B49031A79b0f924D68BEF43992', - decimals: 18, - id: 'XTRD', - name: 'XTRD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 6, - id: 'XTZ', - name: 'Tezos', - nativeAsset: 'XTZ', - type: 'BASE_ASSET' - }, - { - contractAddress: '0x16939ef78684453bfDFb47825F8a5F714f12623a', - decimals: 18, - id: 'XTZ_BSC', - name: 'Tezos BSC Token', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '', - decimals: 18, - id: 'XTZ_ETHERLINK', - name: 'Tezos (Etherlink)', - nativeAsset: 'XTZ_ETHERLINK', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'XTZ_ETHERLINK_TEST', - name: 'Tezos Test (Etherlink Testnet)', - nativeAsset: 'XTZ_ETHERLINK_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 6, - id: 'XTZ_TEST', - name: 'Tezos Test', - nativeAsset: 'XTZ_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xb5999795BE0EbB5bAb23144AA5FD6A02D080299F', - decimals: 18, - id: 'XUSD_RBTC', - name: 'XUSD Babelfish stablecoin (RSK)', - nativeAsset: 'RBTC', - type: 'ERC20' - }, - { - contractAddress: '0xcF6BB5389c92Bdda8a3747Ddb454cB7a64626C63', - decimals: 18, - id: 'XVS_BSC', - name: 'Venus (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0x55296f69f40Ea6d20E478533C15A6B08B654E758', - decimals: 18, - id: 'XYO', - name: 'XY Oracle', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x618679dF9EfCd19694BB1daa8D00718Eacfa2883', - decimals: 18, - id: 'XYZ', - name: 'XYZ Governance Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x0AaCfbeC6a24756c20D41914F2caba817C0d8521', - decimals: 18, - id: 'YAM', - name: 'YAM', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 9, - id: 'YARD_SOL', - issuerAddress: '8RYSc3rrS4X4bvBCtSJnhcpPpMaAJkXnVKZPzANxQHgz', - name: 'SolYard Finance (Solana)', - nativeAsset: 'SOL', - type: 'SOL_ASSET' - }, - { - contractAddress: '0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e', - decimals: 18, - id: 'YFI', - name: 'Yearn Finance', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xa1d0E215a23d7030842FC67cE582a6aFa3CCaB83', - decimals: 18, - id: 'YFII', - name: 'YFII.finance', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x28cb7e841ee97947a86B06fA4090C8451f64c0be', - decimals: 18, - id: 'YFL', - name: 'YFLink', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x25f8087EAD173b73D6e8B84329989A8eEA16CF73', - decimals: 18, - id: 'YGG', - name: 'Yield Guild Games Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xF94b5C5651c888d928439aB6514B93944eEE6F48', - decimals: 18, - id: 'YLD', - name: 'Yield', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xA26Cbb76156090f4B40A1799A220fc4C946aFB3c', - decimals: 18, - id: 'YNG', - name: 'Young Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xAE1eaAE3F627AAca434127644371b67B18444051', - decimals: 8, - id: 'YOP', - name: 'YOP', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xd6aD7a6750A7593E092a9B218d66C0A814a3436e', - decimals: 6, - id: 'YUSDC', - name: 'iearn USDC', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x7Da96a3891Add058AdA2E826306D812C638D87a7', - decimals: 6, - id: 'YVUSDT', - name: 'USDT yVault', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x2994529C0652D127b7842094103715ec5299bBed', - decimals: 18, - id: 'YYCRV', - name: 'yearn Curve.fi', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xC52C326331E9Ce41F04484d3B5E5648158028804', - decimals: 18, - id: 'ZCX', - name: 'ZEN Exchange Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x6cfDDfeCa2D22F3611E35c4915994472b07Ca315', - decimals: 18, - id: 'ZDC', - name: 'Zodiac', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '', - decimals: 8, - id: 'ZEC', - name: 'ZCash', - nativeAsset: 'ZEC', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 8, - id: 'ZEC_TEST', - name: 'ZCash Test', - nativeAsset: 'ZEC_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xF0939011a9bb95c3B791f0cb546377Ed2693a574', - decimals: 18, - id: 'ZERO', - name: 'Zero.Exchange Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x7BeBd226154E865954A87650FAefA8F485d36081', - decimals: 18, - id: 'ZIG', - name: 'ZigCoin', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x7BeBd226154E865954A87650FAefA8F485d36081', - decimals: 18, - id: 'ZIG_BSC', - name: 'ZigCoin (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '0xb86AbCb37C3A4B64f74f59301AFF131a1BEcC787', - decimals: 12, - id: 'ZIL_BSC', - name: 'Zilliqa (BSC)', - nativeAsset: 'BNB_BSC', - type: 'BEP20' - }, - { - contractAddress: '', - decimals: 18, - id: 'ZIL_MAINNET', - name: 'Zilliqa EVM Mainnet', - nativeAsset: 'ZIL_MAINNET', - type: 'BASE_ASSET' - }, - { - contractAddress: '', - decimals: 18, - id: 'ZIL_TEST', - name: 'Zilliqa EVM Test', - nativeAsset: 'ZIL_TEST', - type: 'BASE_ASSET' - }, - { - contractAddress: '0xA9d2927d3a04309E008B6af6E2e282AE2952e7fD', - decimals: 18, - id: 'ZIP', - name: 'Zipper', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xe4815AE53B124e7263F08dcDBBB757d41Ed658c6', - decimals: 18, - id: 'ZKS', - name: 'Zks Token', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0x69cf3091C91EB72DB05E45C76e58225177dEA742', - decimals: 18, - id: 'ZOOM', - name: 'CoinZoom', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xE41d2489571d322189246DaFA5ebDe1F4699F498', - decimals: 18, - id: 'ZRX', - name: '0x', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xc56c2b7e71B54d38Aab6d52E94a04Cbfa8F604fA', - decimals: 6, - id: 'ZUSD', - name: 'Z.com USD', - nativeAsset: 'ETH', - type: 'ERC20' - }, - { - contractAddress: '0xbf0f3cCB8fA385A287106FbA22e6BB722F94d686', - decimals: 6, - id: 'ZYTARAUSD', - name: 'Zytara USD', - nativeAsset: 'ETH', - type: 'ERC20' - } -] - -@Injectable() -export class FireblocksAssetService { - constructor( - private readonly networkRepository: NetworkRepository, - private readonly logger: LoggerService - ) {} - - private mapFireblocksAsset(network: Network, fireblocksAsset: FireblocksAsset): Asset { - return { - decimals: fireblocksAsset.decimals, - externalId: fireblocksAsset.id, - name: fireblocksAsset.name, - networkId: network.networkId, - onchainId: fireblocksAsset.contractAddress || fireblocksAsset.issuerAddress || undefined - } - } - - async findByExternalId(externalId: string): Promise { - for (const fireblocksAsset of FIREBLOCKS_ASSETS) { - if (fireblocksAsset.id === externalId) { - const network = await this.networkRepository.findByExternalId(Provider.FIREBLOCKS, fireblocksAsset.nativeAsset) - - if (network) { - return this.mapFireblocksAsset(network, fireblocksAsset) - } - } - } - - return null - } - - async findAll(): Promise { - const networkExternalIdIndex = await this.networkRepository.buildProviderExternalIdIndex(Provider.FIREBLOCKS) - const assets: Asset[] = [] - - for (const fireblocksAsset of FIREBLOCKS_ASSETS) { - const network = networkExternalIdIndex.get(fireblocksAsset.nativeAsset) - - if (network) { - assets.push(this.mapFireblocksAsset(network, fireblocksAsset)) - } else { - this.logger.warn('Fireblocks asset network not found', { fireblocksAsset }) - } - } - - return assets - } - - async findByOnchainId(networkId: string, onchainId: string): Promise { - for (const fireblocksAsset of FIREBLOCKS_ASSETS) { - if ( - fireblocksAsset.contractAddress?.toLowerCase() === onchainId.toLowerCase() || - fireblocksAsset.issuerAddress?.toLowerCase() === onchainId.toLowerCase() - ) { - const network = await this.networkRepository.findByExternalId(Provider.FIREBLOCKS, fireblocksAsset.nativeAsset) - - if (network?.networkId === networkId) { - return this.mapFireblocksAsset(network, fireblocksAsset) - } - } - } - - return null - } - - async findNativeAsset(networkId: string): Promise { - const network = await this.networkRepository.findById(networkId) - - if (network) { - const externalNetwork = getExternalNetwork(network, Provider.FIREBLOCKS) - - for (const fireblocksAsset of FIREBLOCKS_ASSETS) { - // If network matches and asset doesn't have a contract address or issuer address, it must be the - // native asset. - if ( - externalNetwork?.externalId === fireblocksAsset.nativeAsset && - !fireblocksAsset.contractAddress && - !fireblocksAsset.issuerAddress - ) { - return this.mapFireblocksAsset(network, fireblocksAsset) - } - } - } - - return null - } -} diff --git a/apps/vault/src/broker/core/provider/fireblocks/fireblocks-transfer.service.ts b/apps/vault/src/broker/core/provider/fireblocks/fireblocks-transfer.service.ts index 3701fb377..42defacec 100644 --- a/apps/vault/src/broker/core/provider/fireblocks/fireblocks-transfer.service.ts +++ b/apps/vault/src/broker/core/provider/fireblocks/fireblocks-transfer.service.ts @@ -7,8 +7,8 @@ import { TransferRepository } from '../../../persistence/repository/transfer.rep import { BrokerException } from '../../exception/broker.exception' import { AccountService } from '../../service/account.service' import { AddressService } from '../../service/address.service' +import { AssetService } from '../../service/asset.service' import { WalletService } from '../../service/wallet.service' -import { Asset } from '../../type/asset.type' import { ConnectionWithCredentials } from '../../type/connection.type' import { Network } from '../../type/network.type' import { Provider, ProviderTransferService } from '../../type/provider.type' @@ -18,19 +18,18 @@ import { NetworkFeeAttribution, SendTransfer, Transfer, - TransferAsset, TransferPartyType, TransferStatus, isAddressDestination, isProviderSpecific } from '../../type/transfer.type' -import { FireblocksAssetService } from './fireblocks-asset.service' +import { getExternalAsset } from '../../util/asset.util' import { validateConnection } from './fireblocks.util' @Injectable() export class FireblocksTransferService implements ProviderTransferService { constructor( - private readonly fireblocksAssetService: FireblocksAssetService, + private readonly assetService: AssetService, private readonly fireblocksClient: FireblocksClient, private readonly networkRepository: NetworkRepository, private readonly walletService: WalletService, @@ -121,28 +120,38 @@ export class FireblocksTransferService implements ProviderTransferService { validateConnection(connection) - const asset = await this.resolveAsset(sendTransfer.asset) + const asset = await this.assetService.findTransferAsset(Provider.FIREBLOCKS, sendTransfer.asset) if (!asset) { throw new BrokerException({ - message: 'Cannot resolve asset', - suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, + message: 'Transfer asset not found', + suggestedHttpStatusCode: HttpStatus.NOT_FOUND, context: { asset: sendTransfer.asset } }) } + const externalAsset = getExternalAsset(asset, Provider.FIREBLOCKS) + if (!externalAsset) { + throw new BrokerException({ + message: 'Unsupported asset by Fireblocks', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, + context: { asset } + }) + } + const network = await this.networkRepository.findById(asset.networkId) if (!network) { throw new BrokerException({ - message: 'Cannot resolve Narval networkId from Anchorage networkId', + message: 'Cannot find asset network', suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, context: { asset } }) } const source = await this.getSource(connection.clientId, sendTransfer) + const destination = await this.getDestination(connection.clientId, network, sendTransfer.destination) - this.logger.log('Resolved source and destination', { + this.logger.log('Resolved Fireblocks transfer source and destination', { ...context, destination, source, @@ -160,12 +169,14 @@ export class FireblocksTransferService implements ProviderTransferService { // // See https://developers.fireblocks.com/reference/createtransaction const networkFeeAttribution = sendTransfer.networkFeeAttribution || NetworkFeeAttribution.DEDUCT + const transferId = sendTransfer.transferId || randomUUID() + const data: CreateTransaction = { source, destination, amount: sendTransfer.amount, - assetId: asset.externalId, + assetId: externalAsset.externalId, customerRefId: sendTransfer.customerRefId, externalTxId: transferId, note: sendTransfer.memo, @@ -186,8 +197,7 @@ export class FireblocksTransferService implements ProviderTransferService { this.logger.log('Fireblocks transaction created', context) const internalTransfer: InternalTransfer = { - // TODO: switch this to the Narval assetId once that is a real thing. - assetId: asset.externalId, + assetId: asset.assetId, clientId: connection.clientId, createdAt: new Date(), customerRefId: sendTransfer.customerRefId || null, @@ -212,32 +222,6 @@ export class FireblocksTransferService implements ProviderTransferService { return internalTransfer } - private async resolveAsset(asset: TransferAsset): Promise { - if (asset.externalAssetId) { - return this.fireblocksAssetService.findByExternalId(asset.externalAssetId) - } - - if (asset.assetId) { - // TODO: Look up by the narval assetId; for now we just treat it as the - // same as the Fireblocks one. - return this.fireblocksAssetService.findByExternalId(asset.assetId) - } - - if (!asset.networkId) { - throw new BrokerException({ - message: 'Cannot resolve asset without networkId', - suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, - context: { asset } - }) - } - - if (asset.address) { - return this.fireblocksAssetService.findByOnchainId(asset.networkId, asset.address) - } - - return this.fireblocksAssetService.findNativeAsset(asset.networkId) - } - /** * When Fireblocks `treatAsGrossAmount` is set to `true`, the fee will be * deducted from the requested amount. diff --git a/apps/vault/src/broker/core/service/__test__/integration/asset.service.spec.ts b/apps/vault/src/broker/core/service/__test__/integration/asset.service.spec.ts new file mode 100644 index 000000000..b6a6761ba --- /dev/null +++ b/apps/vault/src/broker/core/service/__test__/integration/asset.service.spec.ts @@ -0,0 +1,193 @@ +import { ConfigModule } from '@narval/config-module' +import { LoggerModule } from '@narval/nestjs-shared' +import { Test } from '@nestjs/testing' +import { PrismaClientKnownRequestError } from '@prisma/client/vault/runtime/library' +import { load } from '../../../../../main.config' +import { AppModule } from '../../../../../main.module' +import { PersistenceModule } from '../../../../../shared/module/persistence/persistence.module' +import { TestPrismaService } from '../../../../../shared/module/persistence/service/test-prisma.service' +import { AssetRepository } from '../../../../persistence/repository/asset.repository' +import { NetworkRepository } from '../../../../persistence/repository/network.repository' +import { AssetException } from '../../../exception/asset.exception' +import { Asset } from '../../../type/asset.type' +import { Network } from '../../../type/network.type' +import { Provider } from '../../../type/provider.type' +import { TransferAsset } from '../../../type/transfer.type' +import { AssetService } from '../../asset.service' + +describe(AssetService.name, () => { + let testPrismaService: TestPrismaService + let assetService: AssetService + let networkRepository: NetworkRepository + + const ethereum: Network = { + networkId: 'ETHEREUM', + coinType: 60, + name: 'Ethereum', + externalNetworks: [] + } + + const usdc: Asset = { + assetId: 'USDC', + name: 'USD Coin', + symbol: 'USDC', + decimals: 6, + networkId: ethereum.networkId, + onchainId: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', + externalAssets: [ + { + provider: Provider.FIREBLOCKS, + externalId: 'USDC' + } + ] + } + + beforeAll(async () => { + const module = await Test.createTestingModule({ + imports: [ + AppModule, + PersistenceModule.register({ imports: [] }), + LoggerModule.forTest(), + ConfigModule.forRoot({ + load: [load], + isGlobal: true + }) + ], + providers: [AssetService, AssetRepository, NetworkRepository] + }).compile() + + testPrismaService = module.get(TestPrismaService) + assetService = module.get(AssetService) + networkRepository = module.get(NetworkRepository) + + await testPrismaService.truncateAll() + }) + + afterAll(async () => { + await testPrismaService.truncateAll() + }) + + beforeEach(async () => { + await testPrismaService.truncateAll() + await networkRepository.bulkCreate([ethereum]) + }) + + describe('bulkCreate', () => { + it('creates asset with lowercase onchainId', async () => { + const asset: Asset = { + ...usdc, + onchainId: '0XA0B86991C6218B36C1D19D4A2E9EB0CE3606EB48', + externalAssets: [] + } + + const created = await assetService.bulkCreate([asset]) + + expect(created[0].onchainId).toEqual(asset.onchainId?.toLowerCase()) + }) + + it('throws AssetException when native asset already exists', async () => { + const eth: Asset = { + assetId: 'ETH', + name: 'Ethereum', + symbol: 'ETH', + decimals: 18, + networkId: ethereum.networkId, + onchainId: null, + externalAssets: [] + } + + await assetService.bulkCreate([eth]) + + // NOTE: What makes ETH a native asset is the networkId and onchainId + // being null. + const duplicateEth: Asset = { + ...eth, + assetId: 'ETH_2' + } + + await expect(assetService.bulkCreate([duplicateEth])).rejects.toThrow(AssetException) + }) + + it('throws PrismaClientKnownRequestError when networkId and onchainId already exists', async () => { + await assetService.bulkCreate([usdc]) + + // NOTE: Invariant protected by a unique key in the database. + await expect(assetService.bulkCreate([usdc])).rejects.toThrow(PrismaClientKnownRequestError) + }) + }) + + describe('findTransferAsset', () => { + const baseTransferAsset: TransferAsset = { + assetId: usdc.assetId + } + + beforeEach(async () => { + await assetService.bulkCreate([usdc]) + }) + + it('finds by provider and externalId when externalAssetId is present', async () => { + const result = await assetService.findTransferAsset(Provider.FIREBLOCKS, { + ...baseTransferAsset, + externalAssetId: 'USDC' + }) + + expect(result).toEqual({ + ...usdc, + createdAt: expect.any(Date) + }) + }) + + it('finds by assetId when present', async () => { + const result = await assetService.findTransferAsset(Provider.FIREBLOCKS, { + ...baseTransferAsset + }) + + expect(result).toEqual({ + ...usdc, + createdAt: expect.any(Date) + }) + }) + + it('finds by onchainId when address and networkId are set', async () => { + const result = await assetService.findTransferAsset(Provider.FIREBLOCKS, { + address: usdc.onchainId as string, + networkId: ethereum.networkId + }) + + expect(result).toEqual({ + ...usdc, + createdAt: expect.any(Date) + }) + }) + + it('finds native asset when only networkId is set', async () => { + const nativeEth: Asset = { + assetId: 'ETH', + name: 'Ethereum', + symbol: 'ETH', + decimals: 18, + networkId: ethereum.networkId, + onchainId: null, + externalAssets: [] + } + await assetService.bulkCreate([nativeEth]) + + const result = await assetService.findTransferAsset(Provider.FIREBLOCKS, { + networkId: ethereum.networkId + }) + + expect(result).toEqual({ + ...nativeEth, + createdAt: expect.any(Date) + }) + }) + + it('throws AssetException when address is set but networkId is not', async () => { + await expect( + assetService.findTransferAsset(Provider.FIREBLOCKS, { + address: usdc.onchainId as string + }) + ).rejects.toThrow(AssetException) + }) + }) +}) diff --git a/apps/vault/src/broker/core/service/asset.service.ts b/apps/vault/src/broker/core/service/asset.service.ts new file mode 100644 index 000000000..b6dc82c50 --- /dev/null +++ b/apps/vault/src/broker/core/service/asset.service.ts @@ -0,0 +1,97 @@ +import { HttpStatus, Injectable } from '@nestjs/common' +import { AssetRepository } from '../../persistence/repository/asset.repository' +import { AssetException } from '../exception/asset.exception' +import { Asset, ExternalAsset } from '../type/asset.type' +import { Provider } from '../type/provider.type' +import { TransferAsset } from '../type/transfer.type' +import { isNativeAsset } from '../util/asset.util' + +type FindAllOptions = { + filters?: { + provider?: Provider + } +} + +@Injectable() +export class AssetService { + constructor(private readonly assetRepository: AssetRepository) {} + + async bulkCreate(assets: Asset[]): Promise { + const createdAssets: Asset[] = [] + + for (const asset of assets) { + if (isNativeAsset(asset)) { + const native = await this.findNative(asset.networkId) + + if (native) { + throw new AssetException({ + message: 'A native asset for the network already exists', + suggestedHttpStatusCode: HttpStatus.CONFLICT, + context: { asset } + }) + } + } + + createdAssets.push(await this.assetRepository.create(asset)) + } + + return createdAssets + } + + async addExternalAsset(assetId: string, externalAsset: ExternalAsset): Promise { + return this.assetRepository.addExternalAsset(assetId, externalAsset) + } + + async bulkAddExternalAsset( + params: { + assetId: string + externalAsset: ExternalAsset + }[] + ): Promise { + return this.assetRepository.bulkAddExternalAsset(params) + } + + async findAll(options?: FindAllOptions): Promise { + return this.assetRepository.findAll(options) + } + + async findById(assetId: string): Promise { + return this.assetRepository.findById(assetId) + } + + async findByExternalId(provider: Provider, externalId: string): Promise { + return this.assetRepository.findByExternalId(provider, externalId) + } + + async findByOnchainId(networkId: string, onchainId: string): Promise { + return this.assetRepository.findByOnchainId(networkId, onchainId.toLowerCase()) + } + + async findNative(networkId: string): Promise { + return this.assetRepository.findNative(networkId) + } + + async findTransferAsset(provider: Provider, transferAsset: TransferAsset): Promise { + if (transferAsset.externalAssetId) { + return this.findByExternalId(provider, transferAsset.externalAssetId) + } + + if (transferAsset.assetId) { + return this.findById(transferAsset.assetId) + } + + if (!transferAsset.networkId) { + throw new AssetException({ + message: 'Cannot find transfer asset without network ID', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, + context: { asset: transferAsset } + }) + } + + if (transferAsset.address) { + return this.findByOnchainId(transferAsset.networkId, transferAsset.address) + } + + return this.findNative(transferAsset.networkId) + } +} diff --git a/apps/vault/src/broker/core/type/asset.type.ts b/apps/vault/src/broker/core/type/asset.type.ts index eaea7f115..9f780afb0 100644 --- a/apps/vault/src/broker/core/type/asset.type.ts +++ b/apps/vault/src/broker/core/type/asset.type.ts @@ -1,10 +1,20 @@ import { z } from 'zod' +import { Provider } from './provider.type' + +export const ExternalAsset = z.object({ + externalId: z.string(), + provider: z.nativeEnum(Provider) +}) +export type ExternalAsset = z.infer export const Asset = z.object({ + assetId: z.string(), + createdAt: z.date().optional(), decimals: z.number().nullable(), - externalId: z.string(), + externalAssets: z.array(ExternalAsset).default([]), name: z.string(), networkId: z.string(), - onchainId: z.string().optional() + onchainId: z.string().toLowerCase().nullable(), + symbol: z.string().nullable() }) export type Asset = z.infer diff --git a/apps/vault/src/broker/core/type/provider.type.ts b/apps/vault/src/broker/core/type/provider.type.ts index 276a72250..807c07afe 100644 --- a/apps/vault/src/broker/core/type/provider.type.ts +++ b/apps/vault/src/broker/core/type/provider.type.ts @@ -2,7 +2,6 @@ import { HttpStatus } from '@nestjs/common' import { UpdateAccount } from '../../persistence/repository/account.repository' -import { Asset } from './asset.type' import { ConnectionWithCredentials } from './connection.type' import { Account, Address, KnownDestination, UpdateWallet, Wallet } from './indexed-resources.type' import { InternalTransfer, SendTransfer, Transfer } from './transfer.type' @@ -328,15 +327,3 @@ export interface ProviderCredentialService { */ generate>(options?: Options): Promise } - -// -// Asset -// - -// TODO: still thinking.. -export interface ProviderAssetService { - findAll(): Promise - findByExternalId(externalId: string): Promise - findByOnchainId(networkId: string, onchainId: string): Promise - findNativeAsset(networkId: string): Promise -} diff --git a/apps/vault/src/broker/core/util/asset.util.ts b/apps/vault/src/broker/core/util/asset.util.ts new file mode 100644 index 000000000..0262fc88b --- /dev/null +++ b/apps/vault/src/broker/core/util/asset.util.ts @@ -0,0 +1,10 @@ +import { Asset, ExternalAsset } from '../type/asset.type' +import { Provider } from '../type/provider.type' + +export const getExternalAsset = (asset: Asset, provider: Provider): ExternalAsset | null => { + return asset.externalAssets.find((externalAsset) => externalAsset.provider === provider) || null +} + +export const isNativeAsset = (asset: Asset): boolean => { + return asset.onchainId === null +} diff --git a/apps/vault/src/broker/http/rest/controller/asset.controller.ts b/apps/vault/src/broker/http/rest/controller/asset.controller.ts index f7056a128..319a20e27 100644 --- a/apps/vault/src/broker/http/rest/controller/asset.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/asset.controller.ts @@ -1,13 +1,11 @@ import { ApiClientIdHeader } from '@narval/nestjs-shared' -import { BadRequestException, Controller, Get, HttpStatus, Query } from '@nestjs/common' +import { Controller, Get, HttpStatus, Query } from '@nestjs/common' import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' import { PermissionGuard } from '../../../../shared/decorator/permission-guard.decorator' import { VaultPermission } from '../../../../shared/type/domain.type' -import { AnchorageAssetService } from '../../../core/provider/anchorage/anchorage-asset.service' -import { FireblocksAssetService } from '../../../core/provider/fireblocks/fireblocks-asset.service' -import { Asset } from '../../../core/type/asset.type' +import { AssetService } from '../../../core/service/asset.service' import { Provider } from '../../../core/type/provider.type' -import { ProviderAssetDto } from '../dto/response/provider-asset.dto' +import { AssetDto } from '../dto/response/asset.dto' @Controller({ path: 'assets', @@ -16,36 +14,24 @@ import { ProviderAssetDto } from '../dto/response/provider-asset.dto' @ApiClientIdHeader() @ApiTags('Provider Asset') export class AssetController { - constructor( - private readonly anchorageAssetService: AnchorageAssetService, - private readonly fireblocksAssetService: FireblocksAssetService - ) {} + constructor(private readonly assetService: AssetService) {} @Get() @PermissionGuard(VaultPermission.CONNECTION_READ) @ApiOperation({ summary: 'Retrieve all assets', - description: 'This endpoint retrieves a list of all available assets for a specified provider.' + description: 'This endpoint retrieves a list of all available assets.' }) @ApiResponse({ status: HttpStatus.OK, description: 'The assets were successfully retrieved.', - type: ProviderAssetDto + type: AssetDto }) - async list(@Query('provider') provider: Provider): Promise { - const data = await this.findAllByProvider(provider) + async list(@Query('provider') provider?: Provider): Promise { + const data = await this.assetService.findAll({ + filters: { provider } + }) - return ProviderAssetDto.create({ data }) - } - - private findAllByProvider(provider: Provider): Promise { - switch (provider) { - case Provider.ANCHORAGE: - return this.anchorageAssetService.findAll() - case Provider.FIREBLOCKS: - return this.fireblocksAssetService.findAll() - default: - throw new BadRequestException(`Provider ${provider} not implemented`) - } + return AssetDto.create({ data }) } } diff --git a/apps/vault/src/broker/http/rest/controller/network.controller.ts b/apps/vault/src/broker/http/rest/controller/network.controller.ts index d955f236c..8b05542c7 100644 --- a/apps/vault/src/broker/http/rest/controller/network.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/network.controller.ts @@ -5,7 +5,7 @@ import { PermissionGuard } from '../../../../shared/decorator/permission-guard.d import { VaultPermission } from '../../../../shared/type/domain.type' import { Provider } from '../../../core/type/provider.type' import { NetworkRepository } from '../../../persistence/repository/network.repository' -import { ProviderNetworkDto } from '../dto/response/provider-network.dto' +import { NetworkDto } from '../dto/response/network.dto' @Controller({ path: 'networks', @@ -25,11 +25,11 @@ export class NetworkController { @ApiResponse({ status: HttpStatus.OK, description: 'The networks were successfully retrieved.', - type: ProviderNetworkDto + type: NetworkDto }) - async list(@Query('provider') provider: Provider): Promise { + async list(@Query('provider') provider: Provider): Promise { const data = await this.networkRepository.findAll({ filters: { provider } }) - return ProviderNetworkDto.create({ data }) + return NetworkDto.create({ data }) } } diff --git a/apps/vault/src/broker/http/rest/dto/response/provider-asset.dto.ts b/apps/vault/src/broker/http/rest/dto/response/asset.dto.ts similarity index 58% rename from apps/vault/src/broker/http/rest/dto/response/provider-asset.dto.ts rename to apps/vault/src/broker/http/rest/dto/response/asset.dto.ts index 486c793a0..d54332ef0 100644 --- a/apps/vault/src/broker/http/rest/dto/response/provider-asset.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/asset.dto.ts @@ -3,9 +3,13 @@ import { createZodDto } from 'nestjs-zod' import { z } from 'zod' import { Asset } from '../../../../core/type/asset.type' -export class ProviderAssetDto extends createZodDto( +export class AssetDto extends createZodDto( z.object({ - data: z.array(Asset), + data: z.array( + Asset.extend({ + createdAt: z.coerce.date().optional() + }) + ), page: Page }) ) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/provider-network.dto.ts b/apps/vault/src/broker/http/rest/dto/response/network.dto.ts similarity index 85% rename from apps/vault/src/broker/http/rest/dto/response/provider-network.dto.ts rename to apps/vault/src/broker/http/rest/dto/response/network.dto.ts index c289e7b32..82eace55c 100644 --- a/apps/vault/src/broker/http/rest/dto/response/provider-network.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/network.dto.ts @@ -3,7 +3,7 @@ import { createZodDto } from 'nestjs-zod' import { z } from 'zod' import { Network } from '../../../../core/type/network.type' -export class ProviderNetworkDto extends createZodDto( +export class NetworkDto extends createZodDto( z.object({ data: z.array( Network.extend({ diff --git a/apps/vault/src/broker/persistence/repository/asset.repository.ts b/apps/vault/src/broker/persistence/repository/asset.repository.ts new file mode 100644 index 000000000..b84f57281 --- /dev/null +++ b/apps/vault/src/broker/persistence/repository/asset.repository.ts @@ -0,0 +1,196 @@ +import { Injectable } from '@nestjs/common' +import { Prisma } from '@prisma/client/vault' +import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' +import { AssetException } from '../../core/exception/asset.exception' +import { Asset, ExternalAsset } from '../../core/type/asset.type' +import { Provider } from '../../core/type/provider.type' + +type FindAllOptions = { + filters?: { + provider?: Provider + } +} + +@Injectable() +export class AssetRepository { + constructor(private readonly prismaService: PrismaService) {} + + static parseModel( + model: Prisma.AssetGetPayload<{ + include: { + externalAssets: true + } + }> + ): Asset { + return Asset.parse({ + assetId: model.id, + name: model.name, + symbol: model.symbol, + decimals: model.decimals, + networkId: model.networkId, + onchainId: model.onchainId, + createdAt: model.createdAt, + externalAssets: model.externalAssets.map(({ externalId, provider }) => ({ + provider, + externalId + })) + }) + } + + async create(asset: Asset): Promise { + const parse = Asset.parse(asset) + const createdAt = parse.createdAt || new Date() + + await this.prismaService.asset.create({ + data: { + createdAt, + id: parse.assetId, + name: parse.name, + symbol: parse.symbol, + decimals: parse.decimals, + networkId: parse.networkId, + onchainId: parse.onchainId, + externalAssets: { + createMany: { + data: parse.externalAssets.map(({ provider, externalId }) => ({ + provider, + externalId, + createdAt + })) + } + } + }, + include: { + externalAssets: true + } + }) + + return parse + } + + async addExternalAsset(assetId: string, externalAsset: ExternalAsset): Promise { + await this.prismaService.providerAsset.create({ + data: { + ...externalAsset, + assetId + } + }) + + return externalAsset + } + + async bulkAddExternalAsset( + params: { + assetId: string + externalAsset: ExternalAsset + }[] + ): Promise { + await this.prismaService.providerAsset.createMany({ + data: params.map(({ assetId, externalAsset }) => ({ + ...externalAsset, + assetId + })) + }) + + return true + } + + async findAll(options?: FindAllOptions): Promise { + const models = await this.prismaService.asset.findMany({ + where: { + ...(options?.filters?.provider + ? { + externalAssets: { + some: { + provider: options.filters.provider + } + } + } + : {}) + }, + include: { + externalAssets: true + } + }) + + return models.map(AssetRepository.parseModel) + } + + async findById(assetId: string): Promise { + const model = await this.prismaService.asset.findUnique({ + where: { + id: assetId + }, + include: { + externalAssets: true + } + }) + + if (model) { + return AssetRepository.parseModel(model) + } + + return null + } + + async findByExternalId(provider: Provider, externalId: string): Promise { + const model = await this.prismaService.asset.findFirst({ + where: { + externalAssets: { + some: { + provider, + externalId + } + } + }, + include: { + externalAssets: true + } + }) + + if (model) { + return AssetRepository.parseModel(model) + } + + return null + } + + async findByOnchainId(networkId: string, onchainId: string): Promise { + const models = await this.prismaService.asset.findMany({ + where: { + networkId, + onchainId + }, + include: { + externalAssets: true + } + }) + + return models.length ? AssetRepository.parseModel(models[0]) : null + } + + async findNative(networkId: string): Promise { + const models = await this.prismaService.asset.findMany({ + where: { + networkId, + onchainId: null + }, + include: { + externalAssets: true + } + }) + + // NOTE: This invariant is protected at the service level on create. + if (models.length > 1) { + throw new AssetException({ + message: 'Found more than one native asset for network', + context: { + networkId, + modelIds: models.map(({ id }) => id) + } + }) + } + + return models.length ? AssetRepository.parseModel(models[0]) : null + } +} diff --git a/apps/vault/src/broker/persistence/seed/asset.seed.ts b/apps/vault/src/broker/persistence/seed/asset.seed.ts new file mode 100644 index 000000000..d0d09638b --- /dev/null +++ b/apps/vault/src/broker/persistence/seed/asset.seed.ts @@ -0,0 +1,389 @@ +import { ConfigService } from '@narval/config-module' +import { LoggerService } from '@narval/nestjs-shared' +import { Injectable } from '@nestjs/common' +import { Config, Env } from '../../../main.config' +import { AssetService } from '../../core/service/asset.service' +import { Provider } from '../../core/type/provider.type' + +@Injectable() +export class AssetSeed { + constructor( + private readonly assetService: AssetService, + private readonly configService: ConfigService, + private readonly logger: LoggerService + ) {} + + // IMPORTANT: There's already a data migration for base assets. + // See 20250116101514_add_asset_table_and_data/migration.sql + async seed(): Promise { + if (this.configService.get('env') === Env.PRODUCTION) { + throw new Error('You CANNOT seed the production database') + } + + const assets = this.getAssets().map((asset) => ({ + networkId: asset.networkId, + assetId: asset.assetId, + name: asset.name, + decimals: asset.decimals, + symbol: asset.symbol, + onchainId: asset.onchainId, + externalAssets: [ + ...(asset.anchorageId + ? [ + { + provider: Provider.ANCHORAGE, + externalId: asset.anchorageId + } + ] + : []), + ...(asset.fireblocksId + ? [ + { + provider: Provider.FIREBLOCKS, + externalId: asset.fireblocksId + } + ] + : []) + ] + })) + + this.logger.log(`🪙 Seeding ${assets.length} assets`) + + await this.assetService.bulkCreate(assets) + } + + getAssets() { + return [ + { + assetId: 'USDC', + name: 'USD Coin', + symbol: 'USDC', + decimals: 6, + networkId: 'ETHEREUM', + onchainId: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', + anchorageId: 'USDC', + fireblocksId: 'USDC' + }, + { + assetId: 'USDC_POLYGON', + name: 'USD Coin', + symbol: 'USDC', + decimals: 6, + networkId: 'POLYGON', + onchainId: '0x2791bca1f2de4661ed88a30c99a7a9449aa84174', + anchorageId: null, + fireblocksId: 'USDC_POLYGON' + }, + { + assetId: 'USDC_ARBITRUM', + name: 'USD Coin', + symbol: 'USDC', + decimals: 6, + networkId: 'ARBITRUM', + onchainId: '0xaf88d065e77c8cc2239327c5edb3a432268e5831', + anchorageId: null, + fireblocksId: 'USDC_ARB_3SBJ' + }, + { + assetId: 'UNI', + name: 'Uniswap', + symbol: 'UNI', + decimals: 18, + networkId: 'ETHEREUM', + onchainId: '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984', + anchorageId: 'UNI', + fireblocksId: 'UNI' + }, + { + assetId: '1INCH', + name: '1inch', + symbol: '1INCH', + decimals: 18, + networkId: 'ETHEREUM', + onchainId: '0x111111111117dc0aa78b770fa6a738034120c302', + anchorageId: '1INCH', + fireblocksId: '1INCH' + }, + { + assetId: 'AAVE', + name: 'Aave', + symbol: 'AAVE', + decimals: 18, + networkId: 'ETHEREUM', + onchainId: '0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9', + anchorageId: 'AAVE', + fireblocksId: 'AAVE' + }, + { + assetId: 'ATOM', + name: 'Cosmos', + symbol: 'ATOM', + decimals: 6, + networkId: 'ATOM', + onchainId: null, + anchorageId: 'ATOM', + fireblocksId: 'ATOM_COS' + }, + { + assetId: 'XRP', + name: 'Ripple', + symbol: 'XRP', + decimals: 6, + networkId: 'RIPPLE', + onchainId: null, + anchorageId: 'XRP', + fireblocksId: 'XRP' + }, + { + assetId: 'WBTC', + name: 'Wrapped Bitcoin', + symbol: 'WBTC', + decimals: 8, + networkId: 'ETHEREUM', + onchainId: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599', + anchorageId: 'WBTC', + fireblocksId: 'WBTC' + }, + { + assetId: 'USDT', + name: 'Tether', + symbol: 'USDT', + decimals: 6, + networkId: 'ETHEREUM', + onchainId: '0xdac17f958d2ee523a2206206994597c13d831ec7', + anchorageId: 'USDT', + fireblocksId: 'USDT_ERC20' + }, + { + assetId: 'USDT_POLYGON', + name: 'Tether', + symbol: 'USDT', + decimals: 6, + networkId: 'POLYGON', + onchainId: '0xc2132d05d31c914a87c6611c10748aeb04b58e8f', + anchorageId: null, + fireblocksId: 'USDT_POLYGON' + }, + { + assetId: 'SUSHI', + name: 'SushiSwap', + symbol: 'SUSHI', + decimals: 18, + networkId: 'ETHEREUM', + onchainId: '0x6b3595068778dd592e39a122f4f5a5cf09c90fe2', + anchorageId: 'SUSHI', + fireblocksId: 'SUSHI' + }, + { + assetId: 'SUI_TEST', + name: 'Sui Test', + symbol: 'SUI', + decimals: 9, + networkId: 'SUI_TESTNET', + onchainId: null, + anchorageId: 'SUI_T', + fireblocksId: null + }, + { + assetId: 'SOL_DEVNET', + name: 'Solana Devnet', + symbol: 'SOL', + decimals: 9, + networkId: 'SOLANA_DEVNET', + onchainId: null, + anchorageId: 'SOL_TD', + fireblocksId: null + }, + { + assetId: 'SOL_TEST', + name: 'Solana Testnet', + symbol: 'SOL', + decimals: null, + networkId: 'SOLANA_TESTNET', + onchainId: null, + anchorageId: null, + fireblocksId: 'SOL_TEST' + }, + { + assetId: 'SOL', + name: 'Solana', + symbol: 'SOL', + decimals: null, + networkId: 'SOLANA', + onchainId: null, + anchorageId: null, + fireblocksId: 'SOL' + }, + { + assetId: 'PORTAL', + name: 'PORTAL', + symbol: 'PORTAL', + decimals: 18, + networkId: 'ETHEREUM', + onchainId: '0x1bbe973bef3a977fc51cbed703e8ffdefe001fed', + anchorageId: 'PORTAL', + fireblocksId: null + }, + { + assetId: 'POL_POLYGON', + name: 'Polygon', + symbol: 'POL', + decimals: 18, + networkId: 'POLYGON', + onchainId: null, + anchorageId: 'POL_POLYGON', + fireblocksId: 'MATIC_POLYGON' + }, + { + assetId: 'POL', + name: 'Polygon Token', + symbol: 'POL', + decimals: 18, + networkId: 'ETHEREUM', + onchainId: '0x455e53cbb86018ac2b8092fdcd39d8444affc3f6', + anchorageId: 'POL', + fireblocksId: 'POL_ETH_9RYQ' + }, + { + assetId: 'MORPHO', + name: 'Morpho Token', + symbol: 'MORPHO', + decimals: 18, + networkId: 'ETHEREUM', + onchainId: '0x9994e35db50125e0df82e4c2dde62496ce330999', + anchorageId: 'MORPHO', + fireblocksId: null + }, + { + assetId: 'MATIC', + name: 'Matic Token', + symbol: 'MATIC', + decimals: 18, + networkId: 'ETHEREUM', + onchainId: '0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0', + anchorageId: 'MATIC', + fireblocksId: 'MATIC' + }, + { + assetId: 'LTC', + name: 'Litecoin', + symbol: 'LTC', + decimals: 8, + networkId: 'LITECOIN', + onchainId: null, + anchorageId: 'LTC', + fireblocksId: 'LTC' + }, + { + assetId: 'ETH_ZKSYNC_TEST', + name: 'ZKsync Sepolia Testnet', + symbol: 'ETH', + decimals: 18, + networkId: 'ZKSYNC_SEPOLIA', + onchainId: null, + anchorageId: 'ETH_ZKSYNC_T', + fireblocksId: 'ETH_ZKSYNC_ERA_SEPOLIA' + }, + { + assetId: 'ETH_ARBITRUM_TEST', + name: 'Arbitrum Sepolia Testnet', + symbol: 'ETH', + decimals: 18, + networkId: 'ARBITRUM_SEPOLIA', + onchainId: null, + anchorageId: 'ETH_ARBITRUM_T', + fireblocksId: 'ETH-AETH_SEPOLIA' + }, + { + assetId: 'ETH', + name: 'Ethereum', + symbol: 'ETH', + decimals: 18, + networkId: 'ETHEREUM', + onchainId: null, + anchorageId: 'ETH', + fireblocksId: 'ETH' + }, + { + assetId: 'BTC', + name: 'Bitcoin', + symbol: 'BTC', + decimals: 8, + networkId: 'BITCOIN', + onchainId: null, + anchorageId: 'BTC', + fireblocksId: 'BTC' + }, + { + assetId: 'ARB', + name: 'Arbitrum', + symbol: 'ARB', + decimals: 18, + networkId: 'ETHEREUM', + onchainId: '0xb50721bcf8d664c30412cfbc6cf7a15145234ad1', + anchorageId: 'ARB', + fireblocksId: null + }, + { + assetId: 'ETH_OPT', + name: 'Optimistic Ethereum', + symbol: 'ETH', + decimals: 18, + networkId: 'OPTIMISM', + onchainId: null, + anchorageId: null, + fireblocksId: 'ETH-OPT' + }, + { + assetId: 'ETH_OPT_KOVAN', + name: 'Optimistic Ethereum Kovan', + symbol: 'ETH', + decimals: 18, + networkId: 'OPTIMISM_KOVAN', + onchainId: null, + anchorageId: null, + fireblocksId: 'ETH-OPT_KOV' + }, + { + assetId: 'ETH_OPT_SEPOLIA', + name: 'Optimistic Ethereum Sepolia', + symbol: 'ETH', + decimals: 18, + networkId: 'OPTIMISM_SEPOLIA', + onchainId: null, + anchorageId: null, + fireblocksId: 'ETH-OPT_SEPOLIA' + }, + { + assetId: 'DOT', + name: 'Polkadot', + symbol: 'DOT', + decimals: 10, + networkId: 'POLKADOT', + onchainId: null, + anchorageId: null, + fireblocksId: 'DOT' + }, + { + assetId: 'ETH_ARB', + name: 'Arbitrum Ethereum', + symbol: 'ETH', + decimals: 18, + networkId: 'ARBITRUM', + onchainId: null, + anchorageId: null, + fireblocksId: 'ETH-AETH' + }, + { + assetId: 'ARB_ARB', + name: 'Arbitrum', + symbol: 'ARB', + decimals: 18, + networkId: 'ARBITRUM', + onchainId: '0x912ce59144191c1204e64559fe8253a0e49e6548', + anchorageId: null, + fireblocksId: 'ARB_ARB_FRK9' + } + ] + } +} diff --git a/apps/vault/src/broker/persistence/seed/network.seed.ts b/apps/vault/src/broker/persistence/seed/network.seed.ts index 9172d847a..13b2ef33b 100644 --- a/apps/vault/src/broker/persistence/seed/network.seed.ts +++ b/apps/vault/src/broker/persistence/seed/network.seed.ts @@ -1,5 +1,7 @@ +import { ConfigService } from '@narval/config-module' import { LoggerService } from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' +import { Config, Env } from '../../../main.config' import { Provider } from '../../core/type/provider.type' import { NetworkRepository } from '../repository/network.repository' @@ -7,48 +9,58 @@ import { NetworkRepository } from '../repository/network.repository' export class NetworkSeed { constructor( private readonly networkRepository: NetworkRepository, + private readonly configService: ConfigService, private readonly logger: LoggerService ) {} // IMPORTANT: There's already a data migration for base networks. // See 20250115095035_add_network_table_and_data/migration.sql async seed(): Promise { - this.logger.log('🌐 Seeding networks') + if (this.configService.get('env') === Env.PRODUCTION) { + throw new Error('You CANNOT seed the production database') + } - await this.networkRepository.bulkCreate( - this.getNetworks().map((network) => ({ - networkId: network.networkId, - coinType: network.coinType, - name: network.name, - externalNetworks: [ - ...(network.anchorageId - ? [ - { - provider: Provider.ANCHORAGE, - externalId: network.anchorageId - } - ] - : []), - ...(network.fireblocksId - ? [ - { - provider: Provider.FIREBLOCKS, - externalId: network.fireblocksId - } - ] - : []) - ] - })) - ) + const networks = this.getNetworks().map((network) => ({ + networkId: network.networkId, + coinType: network.coinType, + name: network.name, + externalNetworks: [ + ...(network.anchorageId + ? [ + { + provider: Provider.ANCHORAGE, + externalId: network.anchorageId + } + ] + : []), + ...(network.fireblocksId + ? [ + { + provider: Provider.FIREBLOCKS, + externalId: network.fireblocksId + } + ] + : []) + ] + })) + + this.logger.log(`🌐 Seeding ${networks.length} networks`) + + await this.networkRepository.bulkCreate(networks) } getNetworks() { return [ + { + networkId: 'ARBITRUM', + coinType: 9001, + name: 'Arbitrum', + fireblocksId: 'ETH-AETH' + }, { networkId: 'AETH', coinType: 514, - name: 'Aetherius', - fireblocksId: 'ETH-AETH' + name: 'Aetherius' }, { networkId: 'AEVO', @@ -462,9 +474,16 @@ export class NetworkSeed { networkId: 'SOLANA_TESTNET', coinType: 1, name: 'Solana Testnet', - anchorageId: 'SOL_TD', + anchorageId: null, fireblocksId: 'SOL_TEST' }, + { + networkId: 'SOLANA_DEVNET', + coinType: 1, + name: 'Solana Devnet', + anchorageId: 'SOL_TD', + fireblocksId: null + }, { networkId: 'STARKNET', coinType: 9004, diff --git a/apps/vault/src/shared/module/persistence/persistence.module.ts b/apps/vault/src/shared/module/persistence/persistence.module.ts index 644f7f326..3c48f75a6 100644 --- a/apps/vault/src/shared/module/persistence/persistence.module.ts +++ b/apps/vault/src/shared/module/persistence/persistence.module.ts @@ -26,6 +26,7 @@ export class PersistenceModule { exports: [PrismaService, TestPrismaService] } } + static register(config: { imports?: Array } = {}): DynamicModule { return { module: PersistenceModule, diff --git a/apps/vault/src/shared/module/persistence/schema/migrations/20250120095438_add_asset_table_and_data/migration.sql b/apps/vault/src/shared/module/persistence/schema/migrations/20250120095438_add_asset_table_and_data/migration.sql new file mode 100644 index 000000000..d6b70a122 --- /dev/null +++ b/apps/vault/src/shared/module/persistence/schema/migrations/20250120095438_add_asset_table_and_data/migration.sql @@ -0,0 +1,135 @@ +-- CreateTable +CREATE TABLE "asset" ( + "id" TEXT NOT NULL, + "name" TEXT NOT NULL, + "symbol" TEXT, + "decimals" INTEGER, + "network_id" TEXT NOT NULL, + "onchain_id" TEXT, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "asset_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "provider_asset" ( + "asset_id" TEXT NOT NULL, + "provider" TEXT NOT NULL, + "external_id" TEXT NOT NULL, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "provider_asset_pkey" PRIMARY KEY ("provider","external_id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "asset_network_id_onchain_id_key" ON "asset"("network_id", "onchain_id"); + +-- CreateIndex +CREATE UNIQUE INDEX "provider_asset_provider_asset_id_key" ON "provider_asset"("provider", "asset_id"); + +-- AddForeignKey +ALTER TABLE "asset" ADD CONSTRAINT "asset_network_id_fkey" FOREIGN KEY ("network_id") REFERENCES "network"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "provider_asset" ADD CONSTRAINT "provider_asset_asset_id_fkey" FOREIGN KEY ("asset_id") REFERENCES "asset"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- Correct Ethereum Arbitrum external network and Solana Devnet data +INSERT INTO public.network (id,coin_type,name) VALUES + ('ARBITRUM',9001,'Arbitrum'), + ('SOLANA_DEVNET',1,'Solana Devnet'); + +DELETE FROM public.provider_network WHERE external_id = 'SOL_TD' AND network_id = 'SOLANA_TESTNET'; +DELETE FROM public.provider_network WHERE external_id = 'ETH-AETH'; + +INSERT INTO public.provider_network (external_id,network_id,provider) VALUES + ('SOL_TD','SOLANA_DEVNET','anchorage'), + ('ETH-AETH','ARBITRUM','fireblocks'); + +-- Insert initial asset data +INSERT INTO public.asset (id,"name",symbol,decimals,network_id,onchain_id) VALUES + ('1INCH','1inch','1INCH',18,'ETHEREUM','0x111111111117dc0aa78b770fa6a738034120c302'), + ('AAVE','Aave','AAVE',18,'ETHEREUM','0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9'), + ('ARB','Arbitrum','ARB',18,'ETHEREUM','0xb50721bcf8d664c30412cfbc6cf7a15145234ad1'), + ('ARB_ARB','Arbitrum','ARB',18,'ARBITRUM','0x912ce59144191c1204e64559fe8253a0e49e6548'), + ('ATOM','Cosmos','ATOM',6,'ATOM',NULL), + ('BTC','Bitcoin','BTC',8,'BITCOIN',NULL), + ('DOT','Polkadot','DOT',10,'POLKADOT',NULL), + ('ETH','Ethereum','ETH',18,'ETHEREUM',NULL), + ('ETH_ARB','Arbitrum Ethereum','ETH',18,'ARBITRUM',NULL), + ('ETH_ARBITRUM_TEST','Arbitrum Sepolia Testnet','ETH',18,'ARBITRUM_SEPOLIA',NULL), + ('ETH_OPT','Optimistic Ethereum','ETH',18,'OPTIMISM',NULL), + ('ETH_OPT_KOVAN','Optimistic Ethereum Kovan','ETH',18,'OPTIMISM_KOVAN',NULL), + ('ETH_OPT_SEPOLIA','Optimistic Ethereum Sepolia','ETH',18,'OPTIMISM_SEPOLIA',NULL), + ('ETH_ZKSYNC_TEST','ZKsync Sepolia Testnet','ETH',18,'ZKSYNC_SEPOLIA',NULL), + ('LTC','Litecoin','LTC',8,'LITECOIN',NULL), + ('MATIC','Matic Token','MATIC',18,'ETHEREUM','0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0'), + ('MORPHO','Morpho Token','MORPHO',18,'ETHEREUM','0x9994e35db50125e0df82e4c2dde62496ce330999'), + ('POL','Polygon Token','POL',18,'ETHEREUM','0x455e53cbb86018ac2b8092fdcd39d8444affc3f6'), + ('POL_POLYGON','Polygon','POL',18,'POLYGON',NULL), + ('PORTAL','PORTAL','PORTAL',18,'ETHEREUM','0x1bbe973bef3a977fc51cbed703e8ffdefe001fed'), + ('SOL','Solana','SOL',NULL,'SOLANA',NULL), + ('SOL_DEVNET','Solana Devnet','SOL',9,'SOLANA_DEVNET',NULL), + ('SOL_TEST','Solana Testnet','SOL',NULL,'SOLANA_TESTNET',NULL), + ('SUI_TEST','Sui Test','SUI',9,'SUI_TESTNET',NULL), + ('SUSHI','SushiSwap','SUSHI',18,'ETHEREUM','0x6b3595068778dd592e39a122f4f5a5cf09c90fe2'), + ('UNI','Uniswap','UNI',18,'ETHEREUM','0x1f9840a85d5af5bf1d1762f925bdaddc4201f984'), + ('USDC','USD Coin','USDC',6,'ETHEREUM','0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'), + ('USDC_ARBITRUM','USD Coin','USDC',6,'ARBITRUM','0xaf88d065e77c8cc2239327c5edb3a432268e5831'), + ('USDC_POLYGON','USD Coin','USDC',6,'POLYGON','0x2791bca1f2de4661ed88a30c99a7a9449aa84174'), + ('USDT','Tether','USDT',6,'ETHEREUM','0xdac17f958d2ee523a2206206994597c13d831ec7'), + ('USDT_POLYGON','Tether','USDT',6,'POLYGON','0xc2132d05d31c914a87c6611c10748aeb04b58e8f'), + ('WBTC','Wrapped Bitcoin','WBTC',8,'ETHEREUM','0x2260fac5e5542a773aa44fbcfedf7c193bc2c599'), + ('XRP','Ripple','XRP',6,'RIPPLE',NULL); + +-- InsertProviderAsset +INSERT INTO public.provider_asset (asset_id,provider,external_id) VALUES + ('1INCH','anchorage','1INCH'), + ('1INCH','fireblocks','1INCH'), + ('AAVE','anchorage','AAVE'), + ('AAVE','fireblocks','AAVE'), + ('ARB','anchorage','ARB'), + ('ARB_ARB','fireblocks','ARB_ARB_FRK9'), + ('ATOM','anchorage','ATOM'), + ('ATOM','fireblocks','ATOM_COS'), + ('BTC','anchorage','BTC'), + ('BTC','fireblocks','BTC'), + ('DOT','fireblocks','DOT'), + ('ETH','anchorage','ETH'), + ('ETH','fireblocks','ETH'), + ('ETH_ARB','fireblocks','ETH-AETH'), + ('ETH_ARBITRUM_TEST','anchorage','ETH_ARBITRUM_T'), + ('ETH_ARBITRUM_TEST','fireblocks','ETH-AETH_SEPOLIA'), + ('ETH_OPT','fireblocks','ETH-OPT'), + ('ETH_OPT_KOVAN','fireblocks','ETH-OPT_KOV'), + ('ETH_OPT_SEPOLIA','fireblocks','ETH-OPT_SEPOLIA'), + ('ETH_ZKSYNC_TEST','anchorage','ETH_ZKSYNC_T'), + ('ETH_ZKSYNC_TEST','fireblocks','ETH_ZKSYNC_ERA_SEPOLIA'), + ('LTC','anchorage','LTC'), + ('LTC','fireblocks','LTC'), + ('MATIC','anchorage','MATIC'), + ('MATIC','fireblocks','MATIC'), + ('MORPHO','anchorage','MORPHO'), + ('POL','anchorage','POL'), + ('POL','fireblocks','POL_ETH_9RYQ'), + ('POL_POLYGON','anchorage','POL_POLYGON'), + ('POL_POLYGON','fireblocks','MATIC_POLYGON'), + ('PORTAL','anchorage','PORTAL'), + ('SOL','fireblocks','SOL'), + ('SOL_DEVNET','anchorage','SOL_TD'), + ('SOL_TEST','fireblocks','SOL_TEST'), + ('SUI_TEST','anchorage','SUI_T'), + ('SUSHI','anchorage','SUSHI'), + ('SUSHI','fireblocks','SUSHI'), + ('UNI','anchorage','UNI'), + ('UNI','fireblocks','UNI'), + ('USDC','anchorage','USDC'), + ('USDC','fireblocks','USDC'), + ('USDC_ARBITRUM','fireblocks','USDC_ARB_3SBJ'), + ('USDC_POLYGON','fireblocks','USDC_POLYGON'), + ('USDT','anchorage','USDT'), + ('USDT','fireblocks','USDT_ERC20'), + ('USDT_POLYGON','fireblocks','USDT_POLYGON'), + ('WBTC','anchorage','WBTC'), + ('WBTC','fireblocks','WBTC'), + ('XRP','anchorage','XRP'), + ('XRP','fireblocks','XRP'); diff --git a/apps/vault/src/shared/module/persistence/schema/migrations/20250120095738_replace_network_provider_unique_key_by_id/migration.sql b/apps/vault/src/shared/module/persistence/schema/migrations/20250120095738_replace_network_provider_unique_key_by_id/migration.sql new file mode 100644 index 000000000..5eda3166c --- /dev/null +++ b/apps/vault/src/shared/module/persistence/schema/migrations/20250120095738_replace_network_provider_unique_key_by_id/migration.sql @@ -0,0 +1,5 @@ +-- DropIndex +DROP INDEX "provider_network_provider_external_id_key"; + +-- AlterTable +ALTER TABLE "provider_network" ADD CONSTRAINT "provider_network_pkey" PRIMARY KEY ("provider", "external_id"); diff --git a/apps/vault/src/shared/module/persistence/schema/schema.prisma b/apps/vault/src/shared/module/persistence/schema/schema.prisma index feb9c4c5e..a4653ea2b 100644 --- a/apps/vault/src/shared/module/persistence/schema/schema.prisma +++ b/apps/vault/src/shared/module/persistence/schema/schema.prisma @@ -286,6 +286,7 @@ model Network { createdAt DateTime @default(now()) @map("created_at") externalNetworks ProviderNetwork[] + assets Asset[] @@map("network") } @@ -298,9 +299,37 @@ model ProviderNetwork { network Network? @relation(fields: [networkId], references: [id]) - // Prevent duplication of external network by provider. - @@unique([provider, externalId]) + @@id([provider, externalId]) // Prevent duplication of provider supported network. @@unique([provider, networkId]) @@map("provider_network") } + +model Asset { + id String @id + name String + symbol String? + decimals Int? + networkId String @map("network_id") + onchainId String? @map("onchain_id") + createdAt DateTime @default(now()) @map("created_at") + + network Network @relation(fields: [networkId], references: [id]) + externalAssets ProviderAsset[] + + @@unique([networkId, onchainId]) + @@map("asset") +} + +model ProviderAsset { + assetId String @map("asset_id") + provider String + externalId String @map("external_id") + createdAt DateTime @default(now()) @map("created_at") + + asset Asset @relation(fields: [assetId], references: [id]) + + @@id([provider, externalId]) + @@unique([provider, assetId]) + @@map("provider_asset") +} From 797ff5ff3043352d2286fd8bb25c9f9ffc899737 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Wed, 22 Jan 2025 18:13:36 +0100 Subject: [PATCH 099/120] Add LINK asset on ZKsync Sepolia (#100) * Add LINK asset on ZKsync Sepolia * Fix Anchorage ID --- apps/vault/src/broker/persistence/seed/asset.seed.ts | 10 ++++++++++ .../migration.sql | 5 +++++ 2 files changed, 15 insertions(+) create mode 100644 apps/vault/src/shared/module/persistence/schema/migrations/20250122170506_add_asset_chainlink_token_zksync_sepolia/migration.sql diff --git a/apps/vault/src/broker/persistence/seed/asset.seed.ts b/apps/vault/src/broker/persistence/seed/asset.seed.ts index d0d09638b..f99c11936 100644 --- a/apps/vault/src/broker/persistence/seed/asset.seed.ts +++ b/apps/vault/src/broker/persistence/seed/asset.seed.ts @@ -383,6 +383,16 @@ export class AssetSeed { onchainId: '0x912ce59144191c1204e64559fe8253a0e49e6548', anchorageId: null, fireblocksId: 'ARB_ARB_FRK9' + }, + { + assetId: 'LINK_ZKSYNC_SEPOLIA', + name: 'Chainlink', + symbol: 'LINK', + decimals: 18, + networkId: 'ZKSYNC_SEPOLIA', + onchainId: '0x23a1afd896c8c8876af46adc38521f4432658d1e', + anchorageId: 'LINK_ZKSYNC_T', + fireblocksId: null } ] } diff --git a/apps/vault/src/shared/module/persistence/schema/migrations/20250122170506_add_asset_chainlink_token_zksync_sepolia/migration.sql b/apps/vault/src/shared/module/persistence/schema/migrations/20250122170506_add_asset_chainlink_token_zksync_sepolia/migration.sql new file mode 100644 index 000000000..74fe359a1 --- /dev/null +++ b/apps/vault/src/shared/module/persistence/schema/migrations/20250122170506_add_asset_chainlink_token_zksync_sepolia/migration.sql @@ -0,0 +1,5 @@ +INSERT INTO public.asset (id,"name",symbol,decimals,network_id,onchain_id) VALUES + ('LINK_ZKSYNC_SEPOLIA','Chainlink','LINK',18,'ZKSYNC_SEPOLIA','0x23a1afd896c8c8876af46adc38521f4432658d1e'); + +INSERT INTO public.provider_asset (asset_id,provider,external_id) VALUES + ('LINK_ZKSYNC_SEPOLIA','anchorage','LINK_ZKSYNC_T'); From 8faa5efb8ee6b4adac37a0a44adbc145fc3d3f89 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Mon, 27 Jan 2025 13:51:33 +0100 Subject: [PATCH 100/120] Scoped by connection (#93) * Migration, data is persisted per-connection (#88) * schema migration to scope all data per connection * data migration script * fix provider type per connection * unique keys order * fixed failing tests * added connectionId to mock data in transfer and sync tests * handle known destination connections to connectionId * abstract away single tie to connection change from known destinations * filter on correct row in wallet repository * updated migration script to duplicate provider resources * updates existing transfers * Pass through known destination (#90) * Add CSR public key format for FB connection (#92) * Add CSR public key format for FB connection * Add optional CSR format in the public key DTO * Add describe block * Pin node-forge version * Remove wallet connections list (#95) * Scope operations by connection (#96) * Scope operations by connection * Scope sync operations by connection * Fix supertest wrapper to work with query method * Use signed request util in the wallet E2E tests * Fix flaky tests * Add back connection list endpoint * Fix address E2E tests * Bump SDK version * Add network and asset endpoints in the SDK * Adding BitGo connection * ScopedSync by RawAccounts (#84) * duplicated sync, poc working * fixed rebase conflicts and format * cleanup rebase merge, correctly insert connectionId on scope sync * fireblocks scoped-sync updates * use vault label * added updates to anchorage's scoped sync service * add tests on anchorage scoped sync * cleaned up anchorage scope sync tests * map fireblocks assetWallets to network specific accounts * fixed not found test expectation * test fireblocks scoped sync * fixed rebase conflicts * changed externalId standard * Adding Raw Accounts endpoint & Assed/Network bootstrap * Adding includeAddress query param so fireblocks does not always fetch addresses * Cache assets & refactor network cache (#98) * Cache asset Refactor network to use cache manager * Remove draft config * Pin cache-manager version * Lower case cache keys * Fix findAll method * Endpoints to fetch scoped-syncs (#101) * scoped sync persists stringified raw accounts * add status fetching endpoints for scoped syncs * use prismaservice methods to json stringify and parse * Minor fixes before release connection-specific (#102) * Add back the nested wallet and account endpoints in the connection * Minor fix on scope sync logs Connection ID is mandatory in the Vault Client * connect a new connection triggers full sync on anchorage (#103) * connect a new connection triggers full sync on anchorage * fix test excpetation for empty raw accounts on anchorage * Add listProviderRawAccounts method in the Vault SDK * removed references to 'sync' and dropped table * removed syncService from connection test * deleted sync e2e test * re-generated sdk without scoped sync methods * Revert "re-generated sdk without scoped sync methods" This reverts commit 66dccdfa2bd909d2f6c015b153e87c3728004dd2. * Revert "removed references to 'sync' and dropped table" This reverts commit 9c2cd022b95439ce9bc4a45a44d7c67da0cdc535. * Revert "deleted sync e2e test" This reverts commit 2f4a252650fb871662cbe92ba149aa9e2dc5d0c6. * Revert "removed syncService from connection test" This reverts commit 450ece6a34ec5ef04bf170c176f56de4e71b97c9. * removed sync functionality except list * removed deprecated imports --------- Co-authored-by: Ptroger <44851272+Ptroger@users.noreply.github.com> Co-authored-by: Pierre Troger * Feature/nar 2059 make scoped sync quicker (#104) * fireblocks query uniquely scoped accounts, handle duplicated rawAccounts * optimized queries per wallet * anchorage scoped syncs swallow not found errors * batch requests to control rate limiting * removed connection-sync event handler * manage error handling in promiseAllSettled * use httpstatus * expect precisely one account * Asset fallback (#105) * Asset fallback for Anchorage and Fireblocks * Add TransferAssetService * Remove findTransferAsset from AssetService * Remove fallback type * Refactor TransferAssetService * Fix integration test types * Fix E2E tests * Fix provider --------- Co-authored-by: Ptroger <44851272+Ptroger@users.noreply.github.com> Co-authored-by: Matt Schoch Co-authored-by: Pierre Troger --- .../src/broker/__test__/e2e/account.spec.ts | 256 +- .../src/broker/__test__/e2e/address.spec.ts | 191 +- .../src/broker/__test__/e2e/asset.spec.ts | 54 +- .../broker/__test__/e2e/connection.spec.ts | 314 +- .../__test__/e2e/known-destinations.spec.ts | 321 +- .../src/broker/__test__/e2e/network.spec.ts | 26 +- .../src/broker/__test__/e2e/sync.spec.ts | 342 -- .../src/broker/__test__/e2e/transfer.spec.ts | 12 +- .../src/broker/__test__/e2e/wallet.spec.ts | 547 +--- .../__test__/util/map-db-to-returned.ts | 20 +- .../src/broker/__test__/util/mock-data.ts | 50 +- apps/vault/src/broker/broker.module.ts | 54 +- .../anchorage-scoped-sync.service.spec.ts | 196 ++ .../anchorage-sync.service.spec.ts | 538 --- .../anchorage-transfer.service.spec.ts | 28 +- .../server-mock/response/get-wallet-200.json | 36 + .../server-mock/response/get-wallets-200.json | 8 +- .../anchorage/__test__/server-mock/server.ts | 13 + .../anchorage-known-destination.service.ts | 102 + .../anchorage-scoped-sync.service.ts | 287 ++ .../anchorage/anchorage-sync.service.ts | 440 --- .../anchorage/anchorage-transfer.service.ts | 148 +- .../core/provider/anchorage/anchorage.util.ts | 12 +- .../unit/bitgo-credential.service.spec.ts | 81 + .../bitgo/bitgo-credential.service.ts | 44 + .../broker/core/provider/bitgo/bitgo.type.ts | 13 + .../fireblocks-scoped-sync.service.spec.ts | 227 ++ .../fireblocks-transfer.service.spec.ts | 11 +- .../response/get-vault-account-3-200.json | 405 +++ .../response/get-vault-accounts-200.json | 815 +++++ ...=> get-wallet-addresses-ethereum-200.json} | 0 .../get-wallet-addresses-matic-200.json | 5 +- .../fireblocks/__test__/server-mock/server.ts | 19 +- .../fireblocks-credential.service.ts | 29 +- .../fireblocks-known-destination.service.ts | 139 + .../fireblocks-scoped-sync.service.ts | 293 ++ .../fireblocks/fireblocks-sync.service.ts | 497 --- .../fireblocks/fireblocks-transfer.service.ts | 155 +- .../provider/fireblocks/fireblocks.util.ts | 57 +- .../integration/asset.service.spec.ts | 87 +- .../__test__/integration/sync.service.spec.ts | 437 --- .../transfer-asset.service.spec.ts | 242 ++ .../broker/core/service/account.service.ts | 13 +- .../broker/core/service/address.service.ts | 13 +- .../src/broker/core/service/asset.service.ts | 156 +- .../broker/core/service/connection.service.ts | 18 +- .../core/service/known-destination.service.ts | 86 +- .../broker/core/service/network.service.ts | 131 + .../src/broker/core/service/proxy.service.ts | 6 +- .../core/service/raw-account.service.ts | 249 ++ .../core/service/scoped-sync.service.ts | 299 ++ .../src/broker/core/service/sync.service.ts | 368 +-- .../core/service/transfer-asset.service.ts | 264 ++ .../broker/core/service/transfer.service.ts | 7 +- .../src/broker/core/service/wallet.service.ts | 11 +- .../core/type/indexed-resources.type.ts | 22 +- .../core/type/known-destination.type.ts | 15 + .../src/broker/core/type/provider.type.ts | 81 +- apps/vault/src/broker/core/type/scope.type.ts | 7 + .../src/broker/core/type/scoped-sync.type.ts | 46 + apps/vault/src/broker/core/type/sync.type.ts | 5 +- .../src/broker/core/type/transfer.type.ts | 4 +- .../broker/core/util/provider-sync.util.ts | 2 - .../connection-scoped-sync.event-handler.ts | 24 + .../handler/connection-sync.event-handler.ts | 34 - .../broker/http/client/anchorage.client.ts | 120 +- .../broker/http/client/fireblocks.client.ts | 130 +- .../rest/controller/account.controller.ts | 107 +- .../rest/controller/address.controller.ts | 35 +- .../http/rest/controller/asset.controller.ts | 19 +- .../rest/controller/connection.controller.ts | 117 +- .../known-destination.controller.ts | 54 +- .../rest/controller/network.controller.ts | 25 +- .../http/rest/controller/proxy.controller.ts | 17 +- .../rest/controller/scoped-sync.controller.ts | 105 + .../http/rest/controller/sync.controller.ts | 87 +- .../rest/controller/transfer.controller.ts | 14 +- .../http/rest/controller/wallet.controller.ts | 50 +- .../rest/dto/request/start-scoped-sync.dto.ts | 4 + .../dto/response/paginated-accounts.dto.ts | 15 +- .../dto/response/paginated-addresses.dto.ts | 7 +- .../{asset.dto.ts => paginated-assets.dto.ts} | 2 +- .../paginated-known-destinations.dto.ts | 4 +- ...twork.dto.ts => paginated-networks.dto.ts} | 2 +- .../response/paginated-raw-accounts.dto.ts | 11 + .../response/paginated-scoped-syncs.dto.ts | 11 + .../dto/response/paginated-wallets.dto.ts | 21 +- .../rest/dto/response/provider-account.dto.ts | 13 +- .../provider-known-destination.dto.ts | 2 +- .../provider-pending-connection.dto.ts | 6 +- .../rest/dto/response/provider-wallet.dto.ts | 19 +- .../dto/response/scoped-sync-started.dto.ts | 9 + .../http/rest/dto/response/scoped-sync.dto.ts | 9 + .../repository/account.repository.ts | 28 +- .../repository/address.repository.ts | 19 +- .../repository/asset.repository.ts | 46 +- .../known-destination.repository.ts | 296 -- .../repository/network.repository.ts | 176 +- .../repository/scoped-sync.repository.ts | 147 + .../persistence/repository/sync.repository.ts | 11 +- .../repository/transfer.repository.ts | 11 +- .../repository/wallet.repository.ts | 121 +- .../src/broker/persistence/seed/asset.seed.ts | 545 +-- .../broker/persistence/seed/network.seed.ts | 706 ++-- .../src/broker/shared/__test__/fixture.ts | 209 ++ .../src/broker/shared/__test__/request.ts | 118 + .../shared/event/scoped-sync-started.event.ts | 11 + .../broker/shared/event/sync-started.event.ts | 11 - .../migration.sql | 17 + .../migration.sql | 453 +++ .../migration.sql | 6 + .../migration.sql | 11 + .../migration.sql | 8 + .../migration.sql | 3 + .../module/persistence/schema/schema.prisma | 162 +- .../service/test-prisma.service.ts | 5 - examples/unified-api/tsconfig.json | 1 + examples/unified-api/vault.client.ts | 3 +- package-lock.json | 674 ++-- package.json | 3 + packages/armory-sdk/package.json | 2 +- .../src/lib/http/client/vault/api.ts | 2912 ++++++++++++----- .../src/lib/http/client/vault/base.ts | 2 +- .../src/lib/http/client/vault/common.ts | 2 +- .../lib/http/client/vault/configuration.ts | 2 +- .../src/lib/http/client/vault/index.ts | 2 +- packages/armory-sdk/src/lib/vault/client.ts | 226 +- 127 files changed, 10443 insertions(+), 6933 deletions(-) delete mode 100644 apps/vault/src/broker/__test__/e2e/sync.spec.ts create mode 100644 apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-scoped-sync.service.spec.ts delete mode 100644 apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-sync.service.spec.ts create mode 100644 apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/response/get-wallet-200.json create mode 100644 apps/vault/src/broker/core/provider/anchorage/anchorage-known-destination.service.ts create mode 100644 apps/vault/src/broker/core/provider/anchorage/anchorage-scoped-sync.service.ts delete mode 100644 apps/vault/src/broker/core/provider/anchorage/anchorage-sync.service.ts create mode 100644 apps/vault/src/broker/core/provider/bitgo/__test__/unit/bitgo-credential.service.spec.ts create mode 100644 apps/vault/src/broker/core/provider/bitgo/bitgo-credential.service.ts create mode 100644 apps/vault/src/broker/core/provider/bitgo/bitgo.type.ts create mode 100644 apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-scoped-sync.service.spec.ts create mode 100644 apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-vault-account-3-200.json create mode 100644 apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-vault-accounts-200.json rename apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/{get-wallet-addresses-optimism-200.json => get-wallet-addresses-ethereum-200.json} (100%) create mode 100644 apps/vault/src/broker/core/provider/fireblocks/fireblocks-known-destination.service.ts create mode 100644 apps/vault/src/broker/core/provider/fireblocks/fireblocks-scoped-sync.service.ts delete mode 100644 apps/vault/src/broker/core/provider/fireblocks/fireblocks-sync.service.ts delete mode 100644 apps/vault/src/broker/core/service/__test__/integration/sync.service.spec.ts create mode 100644 apps/vault/src/broker/core/service/__test__/integration/transfer-asset.service.spec.ts create mode 100644 apps/vault/src/broker/core/service/network.service.ts create mode 100644 apps/vault/src/broker/core/service/raw-account.service.ts create mode 100644 apps/vault/src/broker/core/service/scoped-sync.service.ts create mode 100644 apps/vault/src/broker/core/service/transfer-asset.service.ts create mode 100644 apps/vault/src/broker/core/type/known-destination.type.ts create mode 100644 apps/vault/src/broker/core/type/scope.type.ts create mode 100644 apps/vault/src/broker/core/type/scoped-sync.type.ts create mode 100644 apps/vault/src/broker/event/handler/connection-scoped-sync.event-handler.ts delete mode 100644 apps/vault/src/broker/event/handler/connection-sync.event-handler.ts create mode 100644 apps/vault/src/broker/http/rest/controller/scoped-sync.controller.ts create mode 100644 apps/vault/src/broker/http/rest/dto/request/start-scoped-sync.dto.ts rename apps/vault/src/broker/http/rest/dto/response/{asset.dto.ts => paginated-assets.dto.ts} (85%) rename apps/vault/src/broker/http/rest/dto/response/{network.dto.ts => paginated-networks.dto.ts} (84%) create mode 100644 apps/vault/src/broker/http/rest/dto/response/paginated-raw-accounts.dto.ts create mode 100644 apps/vault/src/broker/http/rest/dto/response/paginated-scoped-syncs.dto.ts create mode 100644 apps/vault/src/broker/http/rest/dto/response/scoped-sync-started.dto.ts create mode 100644 apps/vault/src/broker/http/rest/dto/response/scoped-sync.dto.ts delete mode 100644 apps/vault/src/broker/persistence/repository/known-destination.repository.ts create mode 100644 apps/vault/src/broker/persistence/repository/scoped-sync.repository.ts create mode 100644 apps/vault/src/broker/shared/__test__/fixture.ts create mode 100644 apps/vault/src/broker/shared/__test__/request.ts create mode 100644 apps/vault/src/broker/shared/event/scoped-sync-started.event.ts delete mode 100644 apps/vault/src/broker/shared/event/sync-started.event.ts create mode 100644 apps/vault/src/shared/module/persistence/schema/migrations/20250116130521_add_provider_sync_table/migration.sql create mode 100644 apps/vault/src/shared/module/persistence/schema/migrations/20250117120539_provider_data_per_connection/migration.sql create mode 100644 apps/vault/src/shared/module/persistence/schema/migrations/20250120144703_add_btc_signet_to_assets/migration.sql create mode 100644 apps/vault/src/shared/module/persistence/schema/migrations/20250121131658_delete_provider_known_destination_table/migration.sql create mode 100644 apps/vault/src/shared/module/persistence/schema/migrations/20250123092543_add_raw_accounts_to_scoped_sync/migration.sql create mode 100644 apps/vault/src/shared/module/persistence/schema/migrations/20250124102305_add_transfer_external_asset_id/migration.sql diff --git a/apps/vault/src/broker/__test__/e2e/account.spec.ts b/apps/vault/src/broker/__test__/e2e/account.spec.ts index 7df2d90d2..56c346fe1 100644 --- a/apps/vault/src/broker/__test__/e2e/account.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/account.spec.ts @@ -1,31 +1,30 @@ import { EncryptionModuleOptionProvider } from '@narval/encryption-module' import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' import { HttpStatus, INestApplication } from '@nestjs/common' +import { EventEmitter2 } from '@nestjs/event-emitter' import { Test, TestingModule } from '@nestjs/testing' -import request from 'supertest' -import { ClientService } from '../../../client/core/service/client.service' +import { mock } from 'jest-mock-extended' import { MainModule } from '../../../main.module' import { ProvisionService } from '../../../provision.service' import { KeyValueRepository } from '../../../shared/module/key-value/core/repository/key-value.repository' import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' -import { getExpectedAccount, getExpectedAddress } from '../util/map-db-to-returned' -import { - TEST_ACCOUNTS, - TEST_ADDRESSES, - TEST_CLIENT_ID, - getJwsd, - testClient, - testUserPrivateJwk -} from '../util/mock-data' +import { PaginatedAccountsDto } from '../../http/rest/dto/response/paginated-accounts.dto' +import { PaginatedAddressesDto } from '../../http/rest/dto/response/paginated-addresses.dto' +import { ProviderAccountDto } from '../../http/rest/dto/response/provider-account.dto' +import { anchorageAccountOne, anchorageConnectionOne, seed, userPrivateKey } from '../../shared/__test__/fixture' +import { signedRequest } from '../../shared/__test__/request' +import { REQUEST_HEADER_CONNECTION_ID } from '../../shared/constant' +import { TEST_ACCOUNTS } from '../util/mock-data' + +import '../../shared/__test__/matcher' describe('Account', () => { let app: INestApplication let module: TestingModule let testPrismaService: TestPrismaService let provisionService: ProvisionService - let clientService: ClientService beforeAll(async () => { module = await Test.createTestingModule({ @@ -39,13 +38,15 @@ describe('Account', () => { .useValue({ keyring: getTestRawAesKeyring() }) + // Mock the event emitter because we don't want to send a + // connection.activated event after the creation. + .overrideProvider(EventEmitter2) + .useValue(mock()) .compile() app = module.createNestApplication() testPrismaService = module.get(TestPrismaService) provisionService = module.get(ProvisionService) - clientService = module.get(ClientService) - await testPrismaService.truncateAll() }) afterAll(async () => { @@ -58,50 +59,30 @@ describe('Account', () => { await testPrismaService.truncateAll() await provisionService.provision() - await clientService.save(testClient) - await testPrismaService.seedBrokerTestData() + await seed(module) await app.init() }) describe('GET /accounts', () => { it('returns the list of accounts with addresses for the client', async () => { - const { status, body } = await request(app.getHttpServer()) + const { status, body } = await signedRequest(app, userPrivateKey) .get('/provider/accounts') - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/accounts', - payload: {}, - htm: 'GET' - }) - ) - - expect(body).toEqual({ - data: TEST_ACCOUNTS.map(getExpectedAccount).reverse(), - page: { - next: null - } - }) + .set(REQUEST_HEADER_CLIENT_ID, anchorageConnectionOne.clientId) + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() + expect(body).toMatchZodSchema(PaginatedAccountsDto.schema) + expect(body.data).toHaveLength(2) expect(status).toEqual(HttpStatus.OK) }) it('returns 404 for unknown client', async () => { - const { status } = await request(app.getHttpServer()) + const { status } = await signedRequest(app, userPrivateKey) .get('/provider/accounts') .set(REQUEST_HEADER_CLIENT_ID, 'unknown-client') - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/accounts', - payload: {}, - htm: 'GET' - }) - ) + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() expect(status).toEqual(HttpStatus.NOT_FOUND) }) @@ -110,18 +91,11 @@ describe('Account', () => { describe('GET /accounts with pagination', () => { it('returns limited number of accounts when limit parameter is provided', async () => { const limit = 1 - const { status, body } = await request(app.getHttpServer()) + const { status, body } = await signedRequest(app, userPrivateKey) .get(`/provider/accounts?limit=${limit}`) - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: `/provider/accounts?limit=${limit}`, - payload: {}, - htm: 'GET' - }) - ) + .set(REQUEST_HEADER_CLIENT_ID, anchorageConnectionOne.clientId) + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() expect(body.data).toHaveLength(limit) expect(body.page).toHaveProperty('next') @@ -131,18 +105,11 @@ describe('Account', () => { it('returns next page of results using cursor', async () => { // First request - const firstResponse = await request(app.getHttpServer()) + const firstResponse = await signedRequest(app, userPrivateKey) .get('/provider/accounts?limit=1') - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/accounts?limit=1', - payload: {}, - htm: 'GET' - }) - ) + .set(REQUEST_HEADER_CLIENT_ID, anchorageConnectionOne.clientId) + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() expect(firstResponse.status).toEqual(HttpStatus.OK) @@ -150,18 +117,11 @@ describe('Account', () => { expect(cursor).toBeDefined() // Second request using the cursor - const secondResponse = await request(app.getHttpServer()) + const secondResponse = await signedRequest(app, userPrivateKey) .get(`/provider/accounts?cursor=${cursor}&limit=1`) - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: `/provider/accounts?cursor=${cursor}&limit=1`, - payload: {}, - htm: 'GET' - }) - ) + .set(REQUEST_HEADER_CLIENT_ID, anchorageConnectionOne.clientId) + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() expect(secondResponse.body.data).toHaveLength(1) expect(secondResponse.body.data[0].accountId).not.toBe(firstResponse.body.data[0].accountId) @@ -170,18 +130,12 @@ describe('Account', () => { }) it('handles ascending createdAt parameter correctly', async () => { - const response = await request(app.getHttpServer()) + const response = await signedRequest(app, userPrivateKey) .get(`/provider/accounts?sortOrder=asc`) - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/accounts?sortOrder=asc', - payload: {}, - htm: 'GET' - }) - ) + .set(REQUEST_HEADER_CLIENT_ID, anchorageConnectionOne.clientId) + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() + expect(response.status).toEqual(HttpStatus.OK) const returnedAccounts = response.body.data @@ -194,57 +148,33 @@ describe('Account', () => { describe('GET /accounts/:accountId', () => { it('returns the account details with addresses', async () => { - const account = TEST_ACCOUNTS[0] - const { status, body } = await request(app.getHttpServer()) - .get(`/provider/accounts/${account.id}`) - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: `/provider/accounts/${account.id}`, - payload: {}, - htm: 'GET' - }) - ) - - expect(body).toEqual({ - data: getExpectedAccount(account) - }) - + const { status, body } = await signedRequest(app, userPrivateKey) + .get(`/provider/accounts/${anchorageAccountOne.accountId}`) + .set(REQUEST_HEADER_CLIENT_ID, anchorageConnectionOne.clientId) + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() + + expect(body).toMatchZodSchema(ProviderAccountDto.schema) + expect(body.data.accountId).toEqual(anchorageAccountOne.accountId) expect(status).toEqual(HttpStatus.OK) }) - it('returns 404 with proper error message for non-existent account', async () => { - const { status } = await request(app.getHttpServer()) - .get(`/provider/accounts/non-existent`) - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: `/provider/accounts/non-existent`, - payload: {}, - htm: 'GET' - }) - ) + it('returns 404 when account does not exist', async () => { + const { status } = await signedRequest(app, userPrivateKey) + .get(`/provider/accounts/does-not-exist`) + .set(REQUEST_HEADER_CLIENT_ID, anchorageConnectionOne.clientId) + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() expect(status).toEqual(HttpStatus.NOT_FOUND) }) - it('returns 404 when accessing account from unknown client', async () => { - const { status } = await request(app.getHttpServer()) - .get(`/provider/accounts/${TEST_ACCOUNTS[0].id}`) - .set(REQUEST_HEADER_CLIENT_ID, 'unknown-client') - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: `/provider/accounts/${TEST_ACCOUNTS[0].id}`, - payload: {}, - htm: 'GET' - }) - ) + it('returns 404 when client does not exist', async () => { + const { status } = await signedRequest(app, userPrivateKey) + .get(`/provider/accounts/${anchorageAccountOne.accountId}`) + .set(REQUEST_HEADER_CLIENT_ID, 'does-not-exist') + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() expect(status).toEqual(HttpStatus.NOT_FOUND) }) @@ -252,63 +182,13 @@ describe('Account', () => { describe('GET /accounts/:accountId/addresses', () => { it('returns the list of addresses for the account', async () => { - const account = TEST_ACCOUNTS[0] - const addresses = TEST_ADDRESSES.filter((addr) => addr.accountId === account.id) - - const { status, body } = await request(app.getHttpServer()) - .get(`/provider/accounts/${account.id}/addresses`) - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: `/provider/accounts/${account.id}/addresses`, - payload: {}, - htm: 'GET' - }) - ) - - expect(body).toEqual({ - data: addresses.map(getExpectedAddress), - page: { - next: null - } - }) - - expect(status).toEqual(HttpStatus.OK) - }) - - it('returns empty addresses array for account with no addresses', async () => { - // Create a new account without addresses - const accountWithoutAddresses = { - ...TEST_ACCOUNTS[0], - externalId: 'test-external-id', - id: 'test-account-without-addresses' - } - await testPrismaService.getClient().providerAccount.create({ - data: accountWithoutAddresses - }) - - const { status, body } = await request(app.getHttpServer()) - .get(`/provider/accounts/${accountWithoutAddresses.id}/addresses`) - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: `/provider/accounts/${accountWithoutAddresses.id}/addresses`, - payload: {}, - htm: 'GET' - }) - ) - - expect(body).toEqual({ - data: [], - page: { - next: null - } - }) + const { status, body } = await signedRequest(app, userPrivateKey) + .get(`/provider/accounts/${anchorageAccountOne.accountId}/addresses`) + .set(REQUEST_HEADER_CLIENT_ID, anchorageConnectionOne.clientId) + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() + expect(body).toMatchZodSchema(PaginatedAddressesDto.schema) expect(status).toEqual(HttpStatus.OK) }) }) diff --git a/apps/vault/src/broker/__test__/e2e/address.spec.ts b/apps/vault/src/broker/__test__/e2e/address.spec.ts index 0080d315c..60c881d68 100644 --- a/apps/vault/src/broker/__test__/e2e/address.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/address.spec.ts @@ -1,24 +1,28 @@ import { EncryptionModuleOptionProvider } from '@narval/encryption-module' import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' import { HttpStatus, INestApplication } from '@nestjs/common' +import { EventEmitter2 } from '@nestjs/event-emitter' import { Test, TestingModule } from '@nestjs/testing' -import request from 'supertest' -import { ClientService } from '../../../client/core/service/client.service' +import { mock } from 'jest-mock-extended' +import { map } from 'lodash' import { MainModule } from '../../../main.module' import { ProvisionService } from '../../../provision.service' import { KeyValueRepository } from '../../../shared/module/key-value/core/repository/key-value.repository' import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' -import { getExpectedAddress } from '../util/map-db-to-returned' -import { TEST_ADDRESSES, TEST_CLIENT_ID, getJwsd, testClient, testUserPrivateJwk } from '../util/mock-data' +import { PaginatedAddressesDto } from '../../http/rest/dto/response/paginated-addresses.dto' +import { anchorageAddressOne, anchorageConnectionOne, seed, userPrivateKey } from '../../shared/__test__/fixture' +import { signedRequest } from '../../shared/__test__/request' +import { REQUEST_HEADER_CONNECTION_ID } from '../../shared/constant' + +import '../../shared/__test__/matcher' describe('Address', () => { let app: INestApplication let module: TestingModule let testPrismaService: TestPrismaService let provisionService: ProvisionService - let clientService: ClientService beforeAll(async () => { module = await Test.createTestingModule({ @@ -32,12 +36,16 @@ describe('Address', () => { .useValue({ keyring: getTestRawAesKeyring() }) + // Mock the event emitter because we don't want to send a + // connection.activated event after the creation. + .overrideProvider(EventEmitter2) + .useValue(mock()) .compile() app = module.createNestApplication() testPrismaService = module.get(TestPrismaService) provisionService = module.get(ProvisionService) - clientService = module.get(ClientService) + await testPrismaService.truncateAll() }) @@ -51,34 +59,21 @@ describe('Address', () => { await testPrismaService.truncateAll() await provisionService.provision() - await clientService.save(testClient) - await testPrismaService.seedBrokerTestData() + await seed(module) await app.init() }) describe('GET /addresses', () => { it('returns the list of addresses for the client', async () => { - const { status, body } = await request(app.getHttpServer()) + const { status, body } = await signedRequest(app, userPrivateKey) .get(`/provider/addresses`) - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/addresses', - payload: {}, - htm: 'GET' - }) - ) - - expect(body).toEqual({ - data: TEST_ADDRESSES.map(getExpectedAddress).reverse(), - page: { - next: null - } - }) + .set(REQUEST_HEADER_CLIENT_ID, anchorageConnectionOne.clientId) + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() + expect(body).toMatchZodSchema(PaginatedAddressesDto.schema) + expect(body.data).toHaveLength(2) expect(status).toEqual(HttpStatus.OK) }) }) @@ -86,142 +81,82 @@ describe('Address', () => { describe('GET /addresses with pagination', () => { it('returns limited number of addresses when limit parameter is provided', async () => { const limit = 1 - const { body } = await request(app.getHttpServer()) - .get(`/provider/addresses?limit=${limit}`) - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: `/provider/addresses?limit=${limit}`, - payload: {}, - htm: 'GET' - }) - ) + const { body } = await signedRequest(app, userPrivateKey) + .get('/provider/addresses') + .query({ limit }) + .set(REQUEST_HEADER_CLIENT_ID, anchorageConnectionOne.clientId) + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() expect(body.data).toHaveLength(limit) expect(body.page).toHaveProperty('next') }) it('returns next page of results using cursor', async () => { - // First request - const firstResponse = await request(app.getHttpServer()) - .get('/provider/addresses?limit=1') - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/addresses?limit=1', - payload: {}, - htm: 'GET' - }) - ) - .expect(HttpStatus.OK) + const firstResponse = await signedRequest(app, userPrivateKey) + .get('/provider/addresses') + .query({ limit: 1 }) + .set(REQUEST_HEADER_CLIENT_ID, anchorageConnectionOne.clientId) + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() const cursor = firstResponse.body.page?.next expect(cursor).toBeDefined() - // Second request using the cursor - const secondResponse = await request(app.getHttpServer()) - .get(`/provider/addresses?cursor=${cursor}&limit=1`) - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: `/provider/addresses?cursor=${cursor}&limit=1`, - payload: {}, - htm: 'GET' - }) - ) - .expect(HttpStatus.OK) + const secondResponse = await signedRequest(app, userPrivateKey) + .get('/provider/addresses') + .query({ cursor, limit: 1 }) + .set(REQUEST_HEADER_CLIENT_ID, anchorageConnectionOne.clientId) + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() expect(secondResponse.body.data).toHaveLength(1) expect(secondResponse.body.data[0].addressId).not.toBe(firstResponse.body.data[0].addressId) }) it('handles descending orderBy createdAt parameter correctly', async () => { - const { status, body } = await request(app.getHttpServer()) - .get('/provider/addresses?orderBy=createdAt&desc=true') - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/addresses?orderBy=createdAt&desc=true', - payload: {}, - htm: 'GET' - }) - ) + const { status, body } = await signedRequest(app, userPrivateKey) + .get('/provider/addresses') + .query({ orderBy: 'createdAt', desc: true }) + .set(REQUEST_HEADER_CLIENT_ID, anchorageConnectionOne.clientId) + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() const addresses = body.data - expect(addresses).toHaveLength(TEST_ADDRESSES.length) - expect(new Date(addresses[1].createdAt).getTime()).toBeGreaterThanOrEqual( - new Date(addresses[0].createdAt).getTime() - ) - + expect(addresses).toHaveLength(2) + expect(map(addresses, 'externalId')).toEqual(['address-external-id-two', 'address-external-id-one']) expect(status).toEqual(HttpStatus.OK) }) }) describe('GET /addresses/:addressId', () => { it('returns the address details', async () => { - const address = TEST_ADDRESSES[0] - const { status, body } = await request(app.getHttpServer()) - .get(`/provider/addresses/${address.id}`) - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: `/provider/addresses/${address.id}`, - payload: {}, - htm: 'GET' - }) - ) + const { status, body } = await signedRequest(app, userPrivateKey) + .get(`/provider/addresses/${anchorageAddressOne.addressId}`) + .set(REQUEST_HEADER_CLIENT_ID, anchorageConnectionOne.clientId) + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() expect(body).toEqual({ - data: getExpectedAddress(address) + data: { + ...anchorageAddressOne, + createdAt: anchorageAddressOne.createdAt.toISOString(), + updatedAt: anchorageAddressOne.updatedAt.toISOString() + } }) - - expect(status).toBe(HttpStatus.OK) + expect(status).toEqual(HttpStatus.OK) }) it('returns 404 with proper error message for non-existent address', async () => { - const { status } = await request(app.getHttpServer()) + const { status } = await signedRequest(app, userPrivateKey) .get('/provider/addresses/non-existent') - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/addresses/non-existent', - payload: {}, - htm: 'GET' - }) - ) - - expect(status).toBe(HttpStatus.NOT_FOUND) - }) + .set(REQUEST_HEADER_CLIENT_ID, anchorageConnectionOne.clientId) + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() - it('returns 404 when accessing address from different client', async () => { - const { status } = await request(app.getHttpServer()) - .get(`/provider/addresses/${TEST_ADDRESSES[0].id}`) - .set(REQUEST_HEADER_CLIENT_ID, 'different-client') - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: `/provider/addresses/${TEST_ADDRESSES[0].id}`, - payload: {}, - htm: 'GET' - }) - ) - - expect(status).toBe(HttpStatus.NOT_FOUND) + expect(status).toEqual(HttpStatus.NOT_FOUND) }) }) }) diff --git a/apps/vault/src/broker/__test__/e2e/asset.spec.ts b/apps/vault/src/broker/__test__/e2e/asset.spec.ts index 00d629ee0..d59d8ed5d 100644 --- a/apps/vault/src/broker/__test__/e2e/asset.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/asset.spec.ts @@ -1,8 +1,9 @@ import { EncryptionModuleOptionProvider } from '@narval/encryption-module' import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' import { HttpStatus, INestApplication } from '@nestjs/common' +import { EventEmitter2 } from '@nestjs/event-emitter' import { Test, TestingModule } from '@nestjs/testing' -import request from 'supertest' +import { mock } from 'jest-mock-extended' import { ClientService } from '../../../client/core/service/client.service' import { MainModule } from '../../../main.module' import { ProvisionService } from '../../../provision.service' @@ -11,11 +12,12 @@ import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/per import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' import { Provider } from '../../core/type/provider.type' -import { AssetDto } from '../../http/rest/dto/response/asset.dto' import { AssetSeed } from '../../persistence/seed/asset.seed' import { NetworkSeed } from '../../persistence/seed/network.seed' -import { TEST_CLIENT_ID, getJwsd, testClient, testUserPrivateJwk } from '../util/mock-data' +import { signedRequest } from '../../shared/__test__/request' +import { TEST_CLIENT_ID, testClient, testUserPrivateJwk } from '../util/mock-data' +import { PaginatedAssetsDto } from '../../http/rest/dto/response/paginated-assets.dto' import '../../shared/__test__/matcher' describe('Asset', () => { @@ -39,6 +41,10 @@ describe('Asset', () => { .useValue({ keyring: getTestRawAesKeyring() }) + // Mock the event emitter because we don't want to send a + // connection.activated event after the creation. + .overrideProvider(EventEmitter2) + .useValue(mock()) .compile() app = module.createNestApplication() @@ -71,52 +77,28 @@ describe('Asset', () => { describe('GET /assets', () => { it('returns the list of assets for the specified provider', async () => { - const { status, body } = await request(app.getHttpServer()) + const { status, body } = await signedRequest(app, testUserPrivateJwk) .get('/provider/assets') .query({ provider: Provider.ANCHORAGE }) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: `/provider/assets?provider=${Provider.ANCHORAGE}`, - payload: {}, - htm: 'GET' - }) - ) - - expect(body).toMatchZodSchema(AssetDto.schema) + .send() + + expect(body).toMatchZodSchema(PaginatedAssetsDto.schema) expect(status).toEqual(HttpStatus.OK) }) it('returns different assets for different providers', async () => { - const anchorageResponse = await request(app.getHttpServer()) + const anchorageResponse = await signedRequest(app, testUserPrivateJwk) .get('/provider/assets') .query({ provider: Provider.ANCHORAGE }) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: `/provider/assets?provider=${Provider.ANCHORAGE}`, - payload: {}, - htm: 'GET' - }) - ) - - const fireblocksResponse = await request(app.getHttpServer()) + .send() + + const fireblocksResponse = await signedRequest(app, testUserPrivateJwk) .get('/provider/assets') .query({ provider: Provider.FIREBLOCKS }) .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: `/provider/assets?provider=${Provider.FIREBLOCKS}`, - payload: {}, - htm: 'GET' - }) - ) + .send() expect(anchorageResponse.status).toEqual(HttpStatus.OK) expect(fireblocksResponse.status).toEqual(HttpStatus.OK) diff --git a/apps/vault/src/broker/__test__/e2e/connection.spec.ts b/apps/vault/src/broker/__test__/e2e/connection.spec.ts index 001da35e1..8fa49af73 100644 --- a/apps/vault/src/broker/__test__/e2e/connection.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/connection.spec.ts @@ -35,17 +35,7 @@ import { ConnectionService } from '../../core/service/connection.service' import { SyncService } from '../../core/service/sync.service' import { ConnectionStatus } from '../../core/type/connection.type' import { Provider } from '../../core/type/provider.type' -import { ConnectionActivatedEvent } from '../../shared/event/connection-activated.event' -import { getExpectedAccount, getExpectedWallet } from '../util/map-db-to-returned' -import { - TEST_ACCOUNTS, - TEST_CONNECTIONS, - TEST_WALLETS, - TEST_WALLET_CONNECTIONS, - getJwsd, - testClient, - testUserPrivateJwk -} from '../util/mock-data' +import { getJwsd, testClient, testUserPrivateJwk } from '../util/mock-data' import '../../shared/__test__/matcher' @@ -67,12 +57,6 @@ describe('Connection', () => { const clientId = testClient.clientId beforeAll(async () => { - // We mock the sync service here to prevent race conditions - // during the tests. This is because the ConnectionService sends a promise - // to start the sync but does not wait for it to complete. - const syncServiceMock = mock() - syncServiceMock.start.mockResolvedValue({ started: true, syncs: [] }) - eventEmitterMock = mock() eventEmitterMock.emit.mockReturnValue(true) @@ -82,8 +66,6 @@ describe('Connection', () => { .overrideModule(LoggerModule) .useModule(LoggerModule.forTest()) .overrideProvider(SyncService) - .useValue(syncServiceMock) - .overrideProvider(EventEmitter2) .useValue(eventEmitterMock) .overrideProvider(KeyValueRepository) .useValue(new InMemoryKeyValueRepository()) @@ -171,99 +153,6 @@ describe('Connection', () => { }) describe('POST /provider/connections', () => { - it('emits connection.activated event on connection create', async () => { - const privateKey = await generateJwk(Alg.EDDSA) - const privateKeyHex = await privateKeyToHex(privateKey) - const connectionId = uuid() - const connection = { - provider: Provider.ANCHORAGE, - connectionId, - label: 'Test Anchorage Connection', - url, - credentials: { - apiKey: 'test-api-key', - privateKey: privateKeyHex - } - } - - await request(app.getHttpServer()) - .post('/provider/connections') - .set(REQUEST_HEADER_CLIENT_ID, clientId) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk, - requestUrl: '/provider/connections', - payload: connection - }) - ) - .send(connection) - - const createdConnectionWithCredentials = await connectionService.findWithCredentialsById( - clientId, - connection.connectionId - ) - - expect(eventEmitterMock.emit).toHaveBeenCalledWith( - ConnectionActivatedEvent.EVENT_NAME, - new ConnectionActivatedEvent(createdConnectionWithCredentials) - ) - }) - - it('emits connection.activated on connection activation', async () => { - const connectionId = uuid() - const provider = Provider.ANCHORAGE - const label = 'Test Anchorage Connection' - const credentials = { apiKey: 'test-api-key' } - - await request(app.getHttpServer()) - .post('/provider/connections/initiate') - .set(REQUEST_HEADER_CLIENT_ID, clientId) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk, - requestUrl: '/provider/connections/initiate', - payload: { connectionId, provider } - }) - ) - .send({ connectionId, provider }) - .expect(HttpStatus.CREATED) - - await request(app.getHttpServer()) - .post('/provider/connections') - .set(REQUEST_HEADER_CLIENT_ID, clientId) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk, - requestUrl: '/provider/connections', - payload: { - connectionId, - credentials, - label, - provider, - url - } - }) - ) - .send({ - connectionId, - credentials, - label, - provider, - url - }) - .expect(HttpStatus.CREATED) - - const createdConnectionWithCredentials = await connectionService.findWithCredentialsById(clientId, connectionId) - - expect(eventEmitterMock.emit).toHaveBeenCalledWith( - ConnectionActivatedEvent.EVENT_NAME, - new ConnectionActivatedEvent(createdConnectionWithCredentials) - ) - }) - it('overrides the existing connection private key when providing a new one on pending connection activation', async () => { const connectionId = uuid() const provider = Provider.ANCHORAGE @@ -336,7 +225,7 @@ describe('Connection', () => { expect(status).toEqual(HttpStatus.CREATED) const createdConnection = await connectionService.findById(clientId, connectionId) - const createdCredential = await connectionService.findCredentials(createdConnection) + const createdCredential = await connectionService.findCredentials({ ...createdConnection, provider }) expect(createdConnection).toMatchObject({ clientId, @@ -654,6 +543,68 @@ describe('Connection', () => { }) }) }) + describe('bitgo', () => { + it('creates a new connection to bitgo with plain credentials', async () => { + const connectionId = uuid() + const connection = { + provider: Provider.BITGO, + connectionId, + label: 'Test Bitgo Connection', + url, + credentials: { + apiKey: 'test-api-key', + walletPassphrase: 'test-wallet-passphrase' + } + } + + const { status, body } = await request(app.getHttpServer()) + .post('/provider/connections') + .set(REQUEST_HEADER_CLIENT_ID, clientId) + .set( + 'detached-jws', + await getJwsd({ + userPrivateJwk, + requestUrl: '/provider/connections', + payload: connection + }) + ) + .send(connection) + + const createdConnection = await connectionService.findById(clientId, connection.connectionId) + const createdCredentials = await connectionService.findCredentials(createdConnection) + + expect(body).toEqual({ + data: { + clientId, + connectionId, + url, + createdAt: expect.any(String), + label: connection.label, + provider: connection.provider, + status: ConnectionStatus.ACTIVE, + updatedAt: expect.any(String) + } + }) + + expect(status).toEqual(HttpStatus.CREATED) + + expect(createdConnection).toMatchObject({ + clientId, + createdAt: expect.any(Date), + connectionId, + label: connection.label, + provider: connection.provider, + status: ConnectionStatus.ACTIVE, + updatedAt: expect.any(Date), + url: connection.url + }) + + expect(createdCredentials).toEqual({ + apiKey: connection.credentials.apiKey, + walletPassphrase: connection.credentials.walletPassphrase + }) + }) + }) }) describe('DELETE /provider/connections/:id', () => { @@ -902,143 +853,14 @@ describe('Connection', () => { expect(status).toEqual(HttpStatus.OK) const updatedConnection = await connectionService.findById(clientId, connection.connectionId) - const updatedCredentials = await connectionService.findCredentials(updatedConnection) + const updatedCredentials = await connectionService.findCredentials({ + ...updatedConnection, + provider: Provider.ANCHORAGE + }) expect(updatedCredentials?.apiKey).toEqual(newCredentials.apiKey) expect(updatedCredentials?.privateKey).toEqual(newPrivateKey) expect(updatedCredentials?.publicKey).toEqual(getPublicKey(newPrivateKey as Ed25519PrivateKey)) }) }) - - describe('GET /provider/connections/:connectionId/wallets', () => { - it('responds with wallets for the specific connection', async () => { - await testPrismaService.seedBrokerTestData() - - const { status, body } = await request(app.getHttpServer()) - .get(`/provider/connections/${TEST_CONNECTIONS[0].id}/wallets`) - .set(REQUEST_HEADER_CLIENT_ID, clientId) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk, - requestUrl: `/provider/connections/${TEST_CONNECTIONS[0].id}/wallets`, - payload: {}, - htm: 'GET' - }) - ) - .send() - - expect(body).toMatchObject({ - data: [getExpectedWallet(TEST_WALLETS[0])], - page: {} - }) - expect(status).toEqual(HttpStatus.OK) - }) - - it('returns empty array when connection has no wallets', async () => { - await testPrismaService.seedBrokerTestData() - - const connection = await connectionService.create(clientId, { - connectionId: uuid(), - label: 'test connection', - provider: Provider.ANCHORAGE, - url, - credentials: { - apiKey: 'test-api-key', - privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) - } - }) - - const { status, body } = await request(app.getHttpServer()) - .get(`/provider/connections/${connection.connectionId}/wallets`) - .set(REQUEST_HEADER_CLIENT_ID, clientId) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk, - requestUrl: `/provider/connections/${connection.connectionId}/wallets`, - payload: {}, - htm: 'GET' - }) - ) - .send() - - expect(body).toMatchObject({ - data: [], - page: {} - }) - expect(status).toEqual(HttpStatus.OK) - }) - }) - - describe('GET /provider/connections/:connectionId/accounts', () => { - it('responds with accounts for the specific connection', async () => { - expect.assertions(2) - await testPrismaService.seedBrokerTestData() - - // Assume connection[0] has some wallets which in turn have accounts. - const connectionId = TEST_CONNECTIONS[0].id - const walletsForConnection = TEST_WALLET_CONNECTIONS.filter((wc) => wc.connectionId === connectionId).map( - (wc) => wc.walletId - ) - - const accountsForConnection = TEST_ACCOUNTS.filter((account) => walletsForConnection.includes(account.walletId)) - - const { status, body } = await request(app.getHttpServer()) - .get(`/provider/connections/${connectionId}/accounts`) - .set(REQUEST_HEADER_CLIENT_ID, clientId) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk, - requestUrl: `/provider/connections/${connectionId}/accounts`, - payload: {}, - htm: 'GET' - }) - ) - .send() - - expect(body).toMatchObject({ - data: accountsForConnection.map(getExpectedAccount).reverse(), - page: {} - }) - expect(status).toEqual(HttpStatus.OK) - }) - - it('returns empty array when connection has no accounts', async () => { - await testPrismaService.seedBrokerTestData() - - // Create a new connection that doesn't have any associated wallets or accounts - const connection = await connectionService.create(clientId, { - connectionId: uuid(), - label: 'test connection', - provider: Provider.ANCHORAGE, - url, - credentials: { - apiKey: 'test-api-key', - privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) - } - }) - - const { status, body } = await request(app.getHttpServer()) - .get(`/provider/connections/${connection.connectionId}/accounts`) - .set(REQUEST_HEADER_CLIENT_ID, clientId) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk, - requestUrl: `/provider/connections/${connection.connectionId}/accounts`, - payload: {}, - htm: 'GET' - }) - ) - .send() - - expect(body).toMatchObject({ - data: [], - page: {} - }) - expect(status).toEqual(HttpStatus.OK) - }) - }) }) diff --git a/apps/vault/src/broker/__test__/e2e/known-destinations.spec.ts b/apps/vault/src/broker/__test__/e2e/known-destinations.spec.ts index f1e96c85c..2a0ee10bc 100644 --- a/apps/vault/src/broker/__test__/e2e/known-destinations.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/known-destinations.spec.ts @@ -14,27 +14,31 @@ import { KeyValueRepository } from '../../../shared/module/key-value/core/reposi import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' -import { ANCHORAGE_TEST_API_BASE_URL } from '../../core/provider/anchorage/__test__/server-mock/server' +import { ANCHORAGE_TEST_API_BASE_URL, getHandlers } from '../../core/provider/anchorage/__test__/server-mock/server' import { ConnectionService } from '../../core/service/connection.service' -import { KnownDestinationService } from '../../core/service/known-destination.service' -import { Connection } from '../../core/type/connection.type' -import { KnownDestination } from '../../core/type/indexed-resources.type' import { Provider } from '../../core/type/provider.type' +import { PaginatedKnownDestinationsDto } from '../../http/rest/dto/response/paginated-known-destinations.dto' +import { AssetSeed } from '../../persistence/seed/asset.seed' +import { NetworkSeed } from '../../persistence/seed/network.seed' +import { setupMockServer } from '../../shared/__test__/mock-server' +import { REQUEST_HEADER_CONNECTION_ID } from '../../shared/constant' import { getJwsd, testClient, testUserPrivateJwk } from '../util/mock-data' -describe('KnownDestination', () => { +import '../../shared/__test__/matcher' + +describe('Known Destination', () => { let app: INestApplication let module: TestingModule let testPrismaService: TestPrismaService let provisionService: ProvisionService let clientService: ClientService - let knownDestinationService: KnownDestinationService let connectionService: ConnectionService + let assetSeed: AssetSeed + let networkSeed: NetworkSeed - let connection1Id: string - let connection2Id: string + let connectionId: string - const now = new Date('2025-01-01T00:00:00Z') + setupMockServer(getHandlers()) beforeAll(async () => { module = await Test.createTestingModule({ @@ -48,17 +52,20 @@ describe('KnownDestination', () => { .useValue({ keyring: getTestRawAesKeyring() }) + // Mock the event emitter because we don't want to send a + // connection.activated event after the creation. .overrideProvider(EventEmitter2) .useValue(mock()) .compile() app = module.createNestApplication() - testPrismaService = module.get(TestPrismaService) - provisionService = module.get(ProvisionService) + assetSeed = module.get(AssetSeed) clientService = module.get(ClientService) connectionService = module.get(ConnectionService) - knownDestinationService = module.get(KnownDestinationService) + networkSeed = module.get(NetworkSeed) + provisionService = module.get(ProvisionService) + testPrismaService = module.get(TestPrismaService) await testPrismaService.truncateAll() }) @@ -69,104 +76,28 @@ describe('KnownDestination', () => { await app.close() }) - let knownDestinations: KnownDestination[] - beforeEach(async () => { await testPrismaService.truncateAll() await provisionService.provision() await clientService.save(testClient) + await networkSeed.seed() + await assetSeed.seed() await app.init() - const connection1 = Connection.parse( - await connectionService.create(testClient.clientId, { - connectionId: uuid(), - provider: Provider.ANCHORAGE, - url: ANCHORAGE_TEST_API_BASE_URL, - createdAt: now, - credentials: { - apiKey: 'test-api-key', - privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) - } - }) - ) - - const connection2 = Connection.parse( - await connectionService.create(testClient.clientId, { - connectionId: uuid(), - provider: Provider.ANCHORAGE, - url: ANCHORAGE_TEST_API_BASE_URL, - createdAt: now, - credentials: { - apiKey: 'test-api-key', - privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) - } - }) - ) - - connection1Id = connection1.connectionId - connection2Id = connection2.connectionId - - knownDestinations = [ - { - clientId: 'test-client-id', - provider: 'anchorage', - externalId: 'neverChanges', - externalClassification: null, - address: 'bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh', - label: null, - assetId: 'BTC', - networkId: 'BTC', - createdAt: now, - updatedAt: now, - connections: [connection1], - knownDestinationId: 'c2f7d2f1-e0b5-4966-a55f-7257420df81f' - }, - { - clientId: 'test-client-id', - provider: 'anchorage', - externalId: 'toBeDeleted', - externalClassification: null, - address: 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', - label: '123456', - assetId: 'XRP', - networkId: 'XRP', - createdAt: now, - updatedAt: now, - connections: [connection1], - knownDestinationId: '9ba64a60-0684-4b7c-9d2d-78bf0a1c6de8' - }, - { - clientId: 'test-client-id', - provider: 'anchorage', - externalId: 'toBeUpdated', - externalClassification: null, - address: '0x8Bc2B8F33e5AeF847B8973Fa669B948A3028D6bd', - label: null, - assetId: 'USDC', - networkId: 'ETH', - createdAt: now, - updatedAt: now, - connections: [connection2], - knownDestinationId: '8d5e8d6f-2836-4d47-821d-80906e1a1448' - }, - { - clientId: 'test-client-id', - provider: 'anchorage', - externalId: 'toBeConnected', - externalClassification: null, - address: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e', - label: null, - assetId: 'ETH', - networkId: 'ETH', - createdAt: now, - updatedAt: now, - connections: [connection2], - knownDestinationId: '04817a66-039d-43e7-ab0a-023997597054' + const connection = await connectionService.create(testClient.clientId, { + connectionId: uuid(), + provider: Provider.ANCHORAGE, + url: ANCHORAGE_TEST_API_BASE_URL, + createdAt: new Date(), + credentials: { + apiKey: 'test-api-key', + privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) } - ] - await knownDestinationService.bulkCreate(knownDestinations) + }) + + connectionId = connection.connectionId }) describe('GET /provider/known-destinations', () => { @@ -174,210 +105,36 @@ describe('KnownDestination', () => { const { status, body } = await request(app.getHttpServer()) .get('/provider/known-destinations') .set(REQUEST_HEADER_CLIENT_ID, testClient.clientId) - .query({ connectionId: connection1Id }) + .set(REQUEST_HEADER_CONNECTION_ID, connectionId) .set( 'detached-jws', await getJwsd({ userPrivateJwk: testUserPrivateJwk, - requestUrl: `/provider/known-destinations?connectionId=${connection1Id}`, + requestUrl: `/provider/known-destinations`, payload: {}, htm: 'GET' }) ) - const expectedDestinations = [knownDestinations[0], knownDestinations[1]] - - expect(body).toEqual({ - data: expectedDestinations.map((knownDestination) => ({ - ...knownDestination, - createdAt: now.toISOString(), - updatedAt: now.toISOString(), - connections: knownDestination.connections.map((connection) => ({ - updatedAt: expect.any(String), - createdAt: expect.any(String), - status: connection.status, - provider: connection.provider, - url: connection.url, - connectionId: connection.connectionId, - clientId: connection.clientId - })) - })), - page: { next: null } - }) + expect(body).toMatchZodSchema(PaginatedKnownDestinationsDto.schema) expect(status).toBe(HttpStatus.OK) }) - it('returns known destinations for another connection', async () => { - const { status, body } = await request(app.getHttpServer()) - .get('/provider/known-destinations') - .set(REQUEST_HEADER_CLIENT_ID, testClient.clientId) - .query({ connectionId: connection2Id }) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: `/provider/known-destinations?connectionId=${connection2Id}`, - payload: {}, - htm: 'GET' - }) - ) - - const expectedDestinations = [knownDestinations[2], knownDestinations[3]] - expect(body).toEqual({ - data: expectedDestinations.map((knownDestination) => ({ - ...knownDestination, - createdAt: now.toISOString(), - updatedAt: now.toISOString(), - connections: knownDestination.connections.map((connection) => ({ - updatedAt: expect.any(String), - createdAt: expect.any(String), - status: connection.status, - provider: connection.provider, - url: connection.url, - connectionId: connection.connectionId, - clientId: connection.clientId - })) - })), - page: { next: null } - }) - expect(status).toBe(HttpStatus.OK) - }) - - it('returns empty if connection is not in the system', async () => { - const { status, body } = await request(app.getHttpServer()) - .get('/provider/known-destinations') - .set(REQUEST_HEADER_CLIENT_ID, testClient.clientId) - .query({ connectionId: 'unknown' }) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/known-destinations?connectionId=unknown', - payload: {}, - htm: 'GET' - }) - ) - - expect(body).toEqual({ data: [], page: { next: null } }) - expect(status).toBe(HttpStatus.OK) - }) - - it('returns all known destinations if connection is not specified', async () => { - const { status, body } = await request(app.getHttpServer()) - .get('/provider/known-destinations') - .set(REQUEST_HEADER_CLIENT_ID, testClient.clientId) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/known-destinations', - payload: {}, - htm: 'GET' - }) - ) - - expect(body).toEqual({ - data: knownDestinations.map((knownDestination) => ({ - ...knownDestination, - createdAt: now.toISOString(), - updatedAt: now.toISOString(), - connections: knownDestination.connections.map((connection) => ({ - updatedAt: expect.any(String), - createdAt: expect.any(String), - status: connection.status, - provider: connection.provider, - url: connection.url, - connectionId: connection.connectionId, - clientId: connection.clientId - })) - })), - page: { next: null } - }) - expect(status).toBe(HttpStatus.OK) - }) - - it('returns known destinations for a connection with pagination', async () => { - const { status, body } = await request(app.getHttpServer()) + it('returns 400 when connection id header is missing', async () => { + const { status } = await request(app.getHttpServer()) .get('/provider/known-destinations') .set(REQUEST_HEADER_CLIENT_ID, testClient.clientId) - .query({ connectionId: connection1Id, limit: 1 }) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: `/provider/known-destinations?connectionId=${connection1Id}&limit=1`, - payload: {}, - htm: 'GET' - }) - ) - - const expectedDestinations = [knownDestinations[0]] - expect(body).toEqual({ - data: expectedDestinations.map((knownDestination) => ({ - ...knownDestination, - createdAt: now.toISOString(), - updatedAt: now.toISOString(), - connections: knownDestination.connections.map((connection) => ({ - updatedAt: expect.any(String), - createdAt: expect.any(String), - status: connection.status, - provider: connection.provider, - url: connection.url, - connectionId: connection.connectionId, - clientId: connection.clientId - })) - })), - page: { next: 'MjAyNS0wMS0wMVQwMDowMDowMC4wMDBafGMyZjdkMmYxLWUwYjUtNDk2Ni1hNTVmLTcyNTc0MjBkZjgxZg==' } - }) - expect(status).toBe(HttpStatus.OK) - }) - }) - - describe('GET /provider/known-destinations/:knownDestinationId', () => { - it('returns known destination', async () => { - const { status, body } = await request(app.getHttpServer()) - .get('/provider/known-destinations/c2f7d2f1-e0b5-4966-a55f-7257420df81f') - .set(REQUEST_HEADER_CLIENT_ID, testClient.clientId) .set( 'detached-jws', await getJwsd({ userPrivateJwk: testUserPrivateJwk, - requestUrl: `/provider/known-destinations/c2f7d2f1-e0b5-4966-a55f-7257420df81f`, + requestUrl: `/provider/known-destinations`, payload: {}, htm: 'GET' }) ) - expect(body.data).toEqual({ - ...knownDestinations[0], - createdAt: now.toISOString(), - updatedAt: now.toISOString(), - connections: knownDestinations[0].connections.map((connection) => ({ - updatedAt: expect.any(String), - createdAt: expect.any(String), - status: connection.status, - provider: connection.provider, - url: connection.url, - connectionId: connection.connectionId, - clientId: connection.clientId - })) - }) - expect(status).toBe(HttpStatus.OK) - }) - it('returns 404 for unknown known destination', async () => { - const { status } = await request(app.getHttpServer()) - .get('/provider/known-destinations/unknown') - .set(REQUEST_HEADER_CLIENT_ID, testClient.clientId) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: `/provider/known-destinations/unknown`, - payload: {}, - htm: 'GET' - }) - ) - expect(status).toBe(HttpStatus.NOT_FOUND) + expect(status).toBe(HttpStatus.BAD_REQUEST) }) }) }) diff --git a/apps/vault/src/broker/__test__/e2e/network.spec.ts b/apps/vault/src/broker/__test__/e2e/network.spec.ts index 411d6bb77..768513618 100644 --- a/apps/vault/src/broker/__test__/e2e/network.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/network.spec.ts @@ -1,8 +1,9 @@ import { EncryptionModuleOptionProvider } from '@narval/encryption-module' import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' import { HttpStatus, INestApplication } from '@nestjs/common' +import { EventEmitter2 } from '@nestjs/event-emitter' import { Test, TestingModule } from '@nestjs/testing' -import request from 'supertest' +import { mock } from 'jest-mock-extended' import { ClientService } from '../../../client/core/service/client.service' import { MainModule } from '../../../main.module' import { ProvisionService } from '../../../provision.service' @@ -10,9 +11,10 @@ import { KeyValueRepository } from '../../../shared/module/key-value/core/reposi import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' -import { NetworkDto } from '../../http/rest/dto/response/network.dto' +import { PaginatedNetworksDto } from '../../http/rest/dto/response/paginated-networks.dto' import { NetworkSeed } from '../../persistence/seed/network.seed' -import { TEST_CLIENT_ID, getJwsd, testClient, testUserPrivateJwk } from '../util/mock-data' +import { signedRequest } from '../../shared/__test__/request' +import { TEST_CLIENT_ID, testClient, testUserPrivateJwk } from '../util/mock-data' import '../../shared/__test__/matcher' @@ -37,6 +39,10 @@ describe('Network', () => { .useValue({ keyring: getTestRawAesKeyring() }) + // Mock the event emitter because we don't want to send a + // connection.activated event after the creation. + .overrideProvider(EventEmitter2) + .useValue(mock()) .compile() app = module.createNestApplication() @@ -67,20 +73,12 @@ describe('Network', () => { describe('GET /networks', () => { it('returns the list of networks', async () => { - const { status, body } = await request(app.getHttpServer()) + const { status, body } = await signedRequest(app, testUserPrivateJwk) .get('/provider/networks') .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/networks', - payload: {}, - htm: 'GET' - }) - ) + .send() - expect(body).toMatchZodSchema(NetworkDto.schema) + expect(body).toMatchZodSchema(PaginatedNetworksDto.schema) expect(body.data).toHaveLength(networkSeed.getNetworks().length) expect(status).toEqual(HttpStatus.OK) }) diff --git a/apps/vault/src/broker/__test__/e2e/sync.spec.ts b/apps/vault/src/broker/__test__/e2e/sync.spec.ts deleted file mode 100644 index 026f24ee1..000000000 --- a/apps/vault/src/broker/__test__/e2e/sync.spec.ts +++ /dev/null @@ -1,342 +0,0 @@ -import { EncryptionModuleOptionProvider } from '@narval/encryption-module' -import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' -import { Alg, generateJwk, privateKeyToHex } from '@narval/signature' -import { HttpStatus, INestApplication } from '@nestjs/common' -import { EventEmitter2 } from '@nestjs/event-emitter' -import { Test, TestingModule } from '@nestjs/testing' -import { MockProxy, mock } from 'jest-mock-extended' -import request from 'supertest' -import { v4 as uuid } from 'uuid' -import { ClientService } from '../../../client/core/service/client.service' -import { MainModule } from '../../../main.module' -import { ProvisionService } from '../../../provision.service' -import { KeyValueRepository } from '../../../shared/module/key-value/core/repository/key-value.repository' -import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' -import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' -import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' -import { ANCHORAGE_TEST_API_BASE_URL, getHandlers } from '../../core/provider/anchorage/__test__/server-mock/server' -import { AnchorageSyncService } from '../../core/provider/anchorage/anchorage-sync.service' -import { ConnectionService } from '../../core/service/connection.service' -import { SyncService } from '../../core/service/sync.service' -import { ConnectionWithCredentials } from '../../core/type/connection.type' -import { Provider } from '../../core/type/provider.type' -import { SyncStatus } from '../../core/type/sync.type' -import { setupMockServer } from '../../shared/__test__/mock-server' -import { SyncStartedEvent } from '../../shared/event/sync-started.event' -import { getJwsd, testClient, testUserPrivateJwk } from '../util/mock-data' - -describe('Sync', () => { - let app: INestApplication - let module: TestingModule - - let eventEmitterMock: MockProxy - let syncService: SyncService - let connectionService: ConnectionService - let testPrismaService: TestPrismaService - let anchorageSyncServiceMock: MockProxy - let provisionService: ProvisionService - let clientService: ClientService - let connection: ConnectionWithCredentials - - const url = ANCHORAGE_TEST_API_BASE_URL - - const apiKey = 'test-api-key' - - const clientId = testClient.clientId - - setupMockServer(getHandlers()) - - beforeAll(async () => { - // NOTE: The sync logic is tested in the provider's sync service and the - // sync service integration tests. - - eventEmitterMock = mock() - eventEmitterMock.emit.mockReturnValue(true) - - module = await Test.createTestingModule({ - imports: [MainModule] - }) - .overrideModule(LoggerModule) - .useModule(LoggerModule.forTest()) - .overrideProvider(KeyValueRepository) - .useValue(new InMemoryKeyValueRepository()) - .overrideProvider(EncryptionModuleOptionProvider) - .useValue({ - keyring: getTestRawAesKeyring() - }) - .overrideProvider(AnchorageSyncService) - .useValue(anchorageSyncServiceMock) - .overrideProvider(EventEmitter2) - .useValue(eventEmitterMock) - .compile() - - app = module.createNestApplication() - - testPrismaService = module.get(TestPrismaService) - provisionService = module.get(ProvisionService) - clientService = module.get(ClientService) - syncService = module.get(SyncService) - connectionService = module.get(ConnectionService) - - await testPrismaService.truncateAll() - }) - - afterAll(async () => { - await testPrismaService.truncateAll() - await module.close() - await app.close() - }) - - beforeEach(async () => { - await testPrismaService.truncateAll() - - await provisionService.provision() - await clientService.save(testClient) - - connection = await connectionService.create(clientId, { - connectionId: uuid(), - provider: Provider.ANCHORAGE, - url, - credentials: { - apiKey, - privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) - } - }) - - await connectionService.initiate(clientId, { - connectionId: uuid(), - provider: Provider.ANCHORAGE - }) - - await app.init() - }) - - describe('POST /syncs', () => { - // This test ensures that the sync process is correctly wired. - // Since the mock is created in the `beforeAll` block, it maintains a - // single state throughout the entire test lifecycle. Therefore, changing - // the order of this test will affect how many times the `sync` function is - // called. - it('emits sync.started event on syncs start', async () => { - await request(app.getHttpServer()) - .post('/provider/syncs') - .set(REQUEST_HEADER_CLIENT_ID, clientId) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/syncs', - payload: {}, - htm: 'POST' - }) - ) - .send() - - const { data: syncs } = await syncService.findAll(clientId) - const credentials = await connectionService.findCredentials(connection) - - expect(eventEmitterMock.emit).toHaveBeenCalledWith( - SyncStartedEvent.EVENT_NAME, - new SyncStartedEvent(syncs[0], { ...connection, credentials }) - ) - }) - - it('starts a sync on every active connection', async () => { - const { status, body } = await request(app.getHttpServer()) - .post('/provider/syncs') - .set(REQUEST_HEADER_CLIENT_ID, clientId) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/syncs', - payload: {}, - htm: 'POST' - }) - ) - .send() - - const syncs = await syncService.findAll(clientId) - const [sync] = syncs.data - - expect(body.data).toMatchObject({ - started: true, - syncs: [ - { - clientId: sync.clientId, - connectionId: sync.connectionId, - createdAt: sync.createdAt.toISOString(), - syncId: sync.syncId, - status: SyncStatus.PROCESSING - } - ] - }) - - expect(status).toEqual(HttpStatus.CREATED) - - expect(syncs.data.length).toEqual(1) - }) - - it('starts a sync on the given connection', async () => { - const { status, body } = await request(app.getHttpServer()) - .post('/provider/syncs') - .set(REQUEST_HEADER_CLIENT_ID, clientId) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/syncs', - payload: { connectionId: connection.connectionId }, - htm: 'POST' - }) - ) - .send({ connectionId: connection.connectionId }) - - const syncs = await syncService.findAll(clientId) - const [sync] = syncs.data - - expect(body.data).toEqual({ - started: true, - syncs: [ - { - clientId: sync.clientId, - connectionId: connection.connectionId, - createdAt: sync.createdAt.toISOString(), - syncId: sync.syncId, - status: SyncStatus.PROCESSING - } - ] - }) - - expect(status).toEqual(HttpStatus.CREATED) - - expect(syncs.data.length).toEqual(1) - }) - }) - - describe('GET /syncs/:syncId', () => { - it('responds with the specific sync', async () => { - const { syncs } = await syncService.start([connection]) - const [sync] = syncs - - const { status, body } = await request(app.getHttpServer()) - .get(`/provider/syncs/${sync.syncId}`) - .set(REQUEST_HEADER_CLIENT_ID, clientId) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: `/provider/syncs/${sync.syncId}`, - payload: {}, - htm: 'GET' - }) - ) - .send() - - expect(body.data).toMatchObject({ - clientId: sync.clientId, - connectionId: sync.connectionId, - createdAt: sync.createdAt.toISOString(), - syncId: sync.syncId, - status: SyncStatus.PROCESSING - }) - - expect(status).toEqual(HttpStatus.OK) - }) - }) - - describe('GET /syncs', () => { - it('responds with a list of syncs', async () => { - const { syncs } = await syncService.start([connection]) - const [sync] = syncs - - const { status, body } = await request(app.getHttpServer()) - .get('/provider/syncs') - .set(REQUEST_HEADER_CLIENT_ID, clientId) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/syncs', - payload: {}, - htm: 'GET' - }) - ) - .send() - - expect(body).toMatchObject({ - data: [ - { - clientId: sync.clientId, - connectionId: sync.connectionId, - createdAt: sync.createdAt.toISOString(), - syncId: sync.syncId, - status: SyncStatus.PROCESSING - } - ] - }) - - expect(status).toEqual(HttpStatus.OK) - - expect(body.data.length).toEqual(1) - }) - - it('responds with the specific sync filter by connection', async () => { - const { syncs } = await syncService.start([connection]) - const [sync] = syncs - - const { status, body } = await request(app.getHttpServer()) - .get('/provider/syncs') - .query({ connectionId: sync.connectionId }) - .set(REQUEST_HEADER_CLIENT_ID, clientId) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: `/provider/syncs?connectionId=${sync.connectionId}`, - payload: {}, - htm: 'GET' - }) - ) - .send() - - expect(body).toMatchObject({ - data: [ - { - clientId: sync.clientId, - connectionId: sync.connectionId, - createdAt: sync.createdAt.toISOString(), - syncId: sync.syncId, - status: SyncStatus.PROCESSING - } - ] - }) - - expect(status).toEqual(HttpStatus.OK) - - expect(body.data.length).toEqual(1) - }) - - it('responds with limited number of syncs when limit is given', async () => { - await syncService.start([connection]) - - const { body } = await request(app.getHttpServer()) - .get('/provider/syncs') - .query({ limit: 1 }) - .set(REQUEST_HEADER_CLIENT_ID, clientId) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/syncs?limit=1', - payload: {}, - htm: 'GET' - }) - ) - .send() - - expect(body.data.length).toEqual(1) - expect(body.page).toHaveProperty('next') - }) - }) -}) diff --git a/apps/vault/src/broker/__test__/e2e/transfer.spec.ts b/apps/vault/src/broker/__test__/e2e/transfer.spec.ts index 1b83a1888..57872f04b 100644 --- a/apps/vault/src/broker/__test__/e2e/transfer.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/transfer.spec.ts @@ -17,7 +17,7 @@ import { TestPrismaService } from '../../../shared/module/persistence/service/te import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' import postAnchorageTransferBadRequest from '../../core/provider/anchorage/__test__/server-mock/response/post-transfer-400.json' import { ANCHORAGE_TEST_API_BASE_URL, getHandlers } from '../../core/provider/anchorage/__test__/server-mock/server' -import { Connection, ConnectionStatus, ConnectionWithCredentials } from '../../core/type/connection.type' +import { ConnectionStatus, ConnectionWithCredentials } from '../../core/type/connection.type' import { Account, Wallet } from '../../core/type/indexed-resources.type' import { Provider } from '../../core/type/provider.type' import { @@ -91,6 +91,7 @@ describe('Transfer', () => { externalId: uuid(), label: 'Account 1', networkId: 'BTC', + connectionId: connection.connectionId, provider: Provider.ANCHORAGE, updatedAt: new Date(), walletId @@ -104,6 +105,7 @@ describe('Transfer', () => { externalId: uuid(), label: 'Account 2', networkId: 'BTC', + connectionId: connection.connectionId, provider: Provider.ANCHORAGE, updatedAt: new Date(), walletId @@ -111,7 +113,7 @@ describe('Transfer', () => { const wallet: Wallet = { clientId, - connections: [Connection.parse(connection)], + connectionId: connection.connectionId, createdAt: new Date(), externalId: uuid(), label: null, @@ -122,6 +124,7 @@ describe('Transfer', () => { const internalTransfer: InternalTransfer = { clientId, + assetExternalId: null, assetId: 'BTC', createdAt: new Date(), customerRefId: null, @@ -133,6 +136,7 @@ describe('Transfer', () => { externalStatus: null, grossAmount: '0.00001', idempotenceId: uuid(), + connectionId: connection.connectionId, memo: 'Test transfer', networkFeeAttribution: NetworkFeeAttribution.DEDUCT, provider: Provider.ANCHORAGE, @@ -244,11 +248,13 @@ describe('Transfer', () => { clientId, externalId, assetId: requiredPayload.asset.assetId, + assetExternalId: requiredPayload.asset.assetId, createdAt: expect.any(String), customerRefId: null, destination: requiredPayload.destination, externalStatus: expect.any(String), grossAmount: requiredPayload.amount, + connectionId: connection.connectionId, idempotenceId: expect.any(String), memo: null, networkFeeAttribution: NetworkFeeAttribution.ON_TOP, @@ -401,6 +407,7 @@ describe('Transfer', () => { describe(`GET ${ENDPOINT}/:transferId`, () => { const internalTransfer = { + assetExternalId: null, assetId: 'BTC', clientId: connection.clientId, createdAt: new Date(), @@ -416,6 +423,7 @@ describe('Transfer', () => { memo: 'Test transfer', networkFeeAttribution: NetworkFeeAttribution.DEDUCT, provider: Provider.ANCHORAGE, + connectionId: connection.connectionId, providerSpecific: null, source: { type: TransferPartyType.ACCOUNT, diff --git a/apps/vault/src/broker/__test__/e2e/wallet.spec.ts b/apps/vault/src/broker/__test__/e2e/wallet.spec.ts index 361369860..fe79247f4 100644 --- a/apps/vault/src/broker/__test__/e2e/wallet.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/wallet.spec.ts @@ -1,34 +1,30 @@ import { EncryptionModuleOptionProvider } from '@narval/encryption-module' import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' import { HttpStatus, INestApplication } from '@nestjs/common' +import { EventEmitter2 } from '@nestjs/event-emitter' import { Test, TestingModule } from '@nestjs/testing' -import request from 'supertest' -import { ClientService } from '../../../client/core/service/client.service' +import { mock } from 'jest-mock-extended' import { MainModule } from '../../../main.module' import { ProvisionService } from '../../../provision.service' import { KeyValueRepository } from '../../../shared/module/key-value/core/repository/key-value.repository' import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' -import { Wallet } from '../../core/type/indexed-resources.type' -import { getExpectedAccount, getExpectedWallet } from '../util/map-db-to-returned' -import { - TEST_ACCOUNTS, - TEST_CLIENT_ID, - TEST_DIFFERENT_CLIENT_ID, - TEST_WALLETS, - getJwsd, - testClient, - testDifferentClient, - testUserPrivateJwk -} from '../util/mock-data' +import { Account, Wallet } from '../../core/type/indexed-resources.type' +import { PaginatedWalletsDto } from '../../http/rest/dto/response/paginated-wallets.dto' +import { ProviderWalletDto } from '../../http/rest/dto/response/provider-wallet.dto' +import { anchorageConnectionOne, anchorageWalletOne, anchorageWalletThree, seed } from '../../shared/__test__/fixture' +import { signedRequest } from '../../shared/__test__/request' +import { REQUEST_HEADER_CONNECTION_ID } from '../../shared/constant' +import { TEST_WALLETS, testUserPrivateJwk } from '../util/mock-data' + +import '../../shared/__test__/matcher' describe('Wallet', () => { let app: INestApplication let module: TestingModule let testPrismaService: TestPrismaService let provisionService: ProvisionService - let clientService: ClientService beforeAll(async () => { module = await Test.createTestingModule({ @@ -42,12 +38,15 @@ describe('Wallet', () => { .useValue({ keyring: getTestRawAesKeyring() }) + // Mock the event emitter because we don't want to send a + // connection.activated event after the creation. + .overrideProvider(EventEmitter2) + .useValue(mock()) .compile() app = module.createNestApplication() testPrismaService = module.get(TestPrismaService) provisionService = module.get(ProvisionService) - clientService = module.get(ClientService) await testPrismaService.truncateAll() }) @@ -62,77 +61,30 @@ describe('Wallet', () => { await testPrismaService.truncateAll() await provisionService.provision() - await clientService.save(testDifferentClient) - await clientService.save(testClient) - await testPrismaService.seedBrokerTestData() + await seed(module) await app.init() }) describe('GET /wallets', () => { - it('returns the list of wallets with accounts for the client', async () => { - const { status, body } = await request(app.getHttpServer()) + it('returns the list of wallets with accounts', async () => { + const { status, body } = await signedRequest(app, testUserPrivateJwk) .get('/provider/wallets') - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/wallets', - payload: {}, - htm: 'GET' - }) - ) + .set(REQUEST_HEADER_CLIENT_ID, anchorageConnectionOne.clientId) + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() - expect(body).toEqual({ - data: TEST_WALLETS.filter((w) => w.clientId === TEST_CLIENT_ID) - .map(getExpectedWallet) - .reverse(), - page: { - next: null - } - }) - - expect(status).toBe(HttpStatus.OK) - }) - - it('does not return private connection information', async () => { - const { status, body } = await request(app.getHttpServer()) - .get('/provider/wallets') - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/wallets', - payload: {}, - htm: 'GET' - }) - ) - - for (const wallet of body.data) { - for (const connection of wallet.connections) { - expect(connection).not.toHaveProperty('credentials') - expect(connection).not.toHaveProperty('revokedAt') - } - } - - expect(status).toBe(HttpStatus.OK) + expect(body).toMatchZodSchema(PaginatedWalletsDto.schema) + expect(body.data).toHaveLength(3) + expect(status).toEqual(HttpStatus.OK) }) it('returns 404 auth error for unknown client', async () => { - const { status, body } = await request(app.getHttpServer()) + const { status, body } = await signedRequest(app, testUserPrivateJwk) .get('/provider/wallets') .set(REQUEST_HEADER_CLIENT_ID, 'unknown-client') - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/wallets', - payload: {}, - htm: 'GET' - }) - ) + .set(REQUEST_HEADER_CONNECTION_ID, 'unknown-connection-id') + .send() expect(body).toEqual({ message: 'Client not found', @@ -140,186 +92,85 @@ describe('Wallet', () => { stack: expect.any(String) }) - expect(status).toBe(HttpStatus.NOT_FOUND) + expect(status).toEqual(HttpStatus.NOT_FOUND) }) }) describe('GET /wallets with pagination', () => { it('returns limited number of wallets when limit parameter is provided', async () => { const limit = 2 - const { status, body } = await request(app.getHttpServer()) - .get(`/provider/wallets?limit=${limit}`) - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: `/provider/wallets?limit=${limit}`, - payload: {}, - htm: 'GET' - }) - ) + const { status, body } = await signedRequest(app, testUserPrivateJwk) + .get('/provider/wallets') + .query({ limit }) + .set(REQUEST_HEADER_CLIENT_ID, anchorageConnectionOne.clientId) + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() expect(body.data).toHaveLength(limit) expect(body.page.next).toBeDefined() // First two wallets should be returned in createdAt descending order - expect(body.data.map((w: Wallet) => w.walletId)).toEqual(['wallet-5', 'wallet-4']) - - expect(status).toBe(HttpStatus.OK) + expect(body.data.map((w: Wallet) => w.label)).toEqual(['wallet 3', 'wallet 2']) + expect(status).toEqual(HttpStatus.OK) }) it('returns all wallets when limit exceeds total count', async () => { const limit = 10 - const { status, body } = await request(app.getHttpServer()) - .get(`/provider/wallets?limit=${limit}`) - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: `/provider/wallets?limit=${limit}`, - payload: {}, - htm: 'GET' - }) - ) - - expect(body.data).toHaveLength(5) // Total wallets for TEST_CLIENT_ID - expect(body.page.next).toBeNull() // No next page + const { status, body } = await signedRequest(app, testUserPrivateJwk) + .get('/provider/wallets') + .query({ limit }) + .set(REQUEST_HEADER_CLIENT_ID, anchorageConnectionOne.clientId) + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() - expect(status).toBe(HttpStatus.OK) + expect(body.data).toHaveLength(3) + expect(body.page.next).toBeNull() + expect(status).toEqual(HttpStatus.OK) }) it('navigates through all pages using cursor', async () => { const limit = 2 - const allWallets = [] - let cursor = null + const wallets = [] + let cursor = undefined do { - const url: string = cursor - ? `/provider/wallets?limit=${limit}&cursor=${cursor}` - : `/provider/wallets?limit=${limit}` - - const { status, body } = await request(app.getHttpServer()) - .get(url) - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: url, - payload: {}, - htm: 'GET' - }) - ) + const { status, body } = await signedRequest(app, testUserPrivateJwk) + .get('/provider/wallets') + .query({ cursor, limit }) + .set(REQUEST_HEADER_CLIENT_ID, anchorageConnectionOne.clientId) + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() expect(status).toBe(HttpStatus.OK) - allWallets.push(...body.data) + wallets.push(...body.data) cursor = body.page.next } while (cursor) - expect(allWallets).toHaveLength(5) // Total wallets for TEST_CLIENT_ID - // Check if wallets are unique - const uniqueWalletIds = new Set(allWallets.map((w) => w.walletId)) - expect(uniqueWalletIds.size).toBe(5) + expect(wallets).toHaveLength(3) + expect(wallets.map((w: Wallet) => w.label)).toEqual(['wallet 3', 'wallet 2', 'wallet 1']) }) it('handles descending order by createdAt parameter correctly', async () => { - const { status, body } = await request(app.getHttpServer()) - .get('/provider/wallets?sortOrder=desc') - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/wallets?sortOrder=desc', - payload: {}, - htm: 'GET' - }) - ) - - expect(body.data.map((w: Wallet) => w.walletId)).toEqual([ - 'wallet-5', - 'wallet-4', - 'wallet-3', - 'wallet-2', - 'wallet-1' - ]) + const { status, body } = await signedRequest(app, testUserPrivateJwk) + .get('/provider/wallets') + .query({ sortOrder: 'desc' }) + .set(REQUEST_HEADER_CLIENT_ID, anchorageConnectionOne.clientId) + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() - expect(status).toBe(HttpStatus.OK) + expect(body.data.map((w: Wallet) => w.label)).toEqual(['wallet 3', 'wallet 2', 'wallet 1']) + expect(status).toEqual(HttpStatus.OK) }) it('handles ascending order by createdAt parameter correctly', async () => { - const { status, body } = await request(app.getHttpServer()) - .get('/provider/wallets?sortOrder=asc') - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/wallets?sortOrder=asc', - payload: {}, - htm: 'GET' - }) - ) - - const wallets = body.data - // Should return wallets in normal order - expect(wallets.map((w: Wallet) => w.walletId)).toEqual([ - 'wallet-1', - 'wallet-2', - 'wallet-3', - 'wallet-4', - 'wallet-5' - ]) - - expect(status).toBe(HttpStatus.OK) - }) - - it('handles asc order when createdAt is same for multiple wallets', async () => { - const { status, body } = await request(app.getHttpServer()) - .get('/provider/wallets?sortOrder=asc') - .set(REQUEST_HEADER_CLIENT_ID, TEST_DIFFERENT_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/wallets?sortOrder=asc', - payload: {}, - htm: 'GET' - }) - ) - - const wallets = body.data - - const walletIds = wallets.map((w: Wallet) => w.walletId) - - // Should return wallets in normal order - expect(walletIds).toEqual(['wallet-6', 'wallet-7', 'wallet-8']) - - expect(status).toBe(HttpStatus.OK) - }) - - it('handles desc order when createdAt is same for multiple wallets', async () => { - const { status, body } = await request(app.getHttpServer()) - .get('/provider/wallets?sortOrder=desc') - .set(REQUEST_HEADER_CLIENT_ID, TEST_DIFFERENT_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/wallets?sortOrder=desc', - payload: {}, - htm: 'GET' - }) - ) - - const wallets = body.data - const walletIds = wallets.map((w: Wallet) => w.walletId) - - // Should return wallets in normal order - expect(walletIds).toEqual(['wallet-8', 'wallet-7', 'wallet-6']) + const { status, body } = await signedRequest(app, testUserPrivateJwk) + .get('/provider/wallets') + .query({ sortOrder: 'asc' }) + .set(REQUEST_HEADER_CLIENT_ID, anchorageConnectionOne.clientId) + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() - expect(status).toBe(HttpStatus.OK) + expect(body.data.map((w: Wallet) => w.label)).toEqual(['wallet 1', 'wallet 2', 'wallet 3']) + expect(status).toEqual(HttpStatus.OK) }) describe('GET /wallets pagination with different directions and sort orders', () => { @@ -327,18 +178,12 @@ describe('Wallet', () => { beforeEach(async () => { // Get initial cursor from latest wallet - const { status, body } = await request(app.getHttpServer()) - .get('/provider/wallets?limit=1&sortOrder=desc') - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/wallets?limit=1&sortOrder=desc', - payload: {}, - htm: 'GET' - }) - ) + const { status, body } = await signedRequest(app, testUserPrivateJwk) + .get('/provider/wallets') + .query({ limit: 1, sortOrder: 'desc' }) + .set(REQUEST_HEADER_CLIENT_ID, anchorageConnectionOne.clientId) + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() expect(status).toBe(HttpStatus.OK) @@ -346,201 +191,143 @@ describe('Wallet', () => { }) it('returns no results when paginating prev in desc order from newest record', async () => { - const { status, body } = await request(app.getHttpServer()) - .get(`/provider/wallets?cursor=${cursor}&direction=prev&limit=2&sortOrder=desc`) - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: `/provider/wallets?cursor=${cursor}&direction=prev&limit=2&sortOrder=desc`, - payload: {}, - htm: 'GET' - }) - ) + const { status, body } = await signedRequest(app, testUserPrivateJwk) + .get('/provider/wallets') + .query({ + cursor, + direction: 'prev', + limit: 2, + sortOrder: 'desc' + }) + .set(REQUEST_HEADER_CLIENT_ID, anchorageConnectionOne.clientId) + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() expect(body.data).toEqual([]) - - expect(status).toBe(HttpStatus.OK) + expect(status).toEqual(HttpStatus.OK) }) it('returns next older records when paginating next in desc order', async () => { - const { status, body } = await request(app.getHttpServer()) - .get(`/provider/wallets?cursor=${cursor}&direction=next&limit=2&sortOrder=desc`) - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: `/provider/wallets?cursor=${cursor}&direction=next&limit=2&sortOrder=desc`, - payload: {}, - htm: 'GET' - }) - ) - - expect(body.data).toHaveLength(2) - expect(body.data.map((w: Wallet) => w.walletId)).toEqual(['wallet-4', 'wallet-3']) + const { status, body } = await signedRequest(app, testUserPrivateJwk) + .get('/provider/wallets') + .query({ + cursor, + direction: 'next', + limit: 2, + sortOrder: 'desc' + }) + .set(REQUEST_HEADER_CLIENT_ID, anchorageConnectionOne.clientId) + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() - expect(status).toBe(HttpStatus.OK) + expect(body.data.map((w: Wallet) => w.label)).toEqual(['wallet 2', 'wallet 1']) + expect(status).toEqual(HttpStatus.OK) }) it('returns next newer records when paginating prev in asc order', async () => { - const { status, body } = await request(app.getHttpServer()) - .get(`/provider/wallets?cursor=${cursor}&direction=prev&limit=2&sortOrder=asc`) - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: `/provider/wallets?cursor=${cursor}&direction=prev&limit=2&sortOrder=asc`, - payload: {}, - htm: 'GET' - }) - ) + const { status, body } = await signedRequest(app, testUserPrivateJwk) + .get('/provider/wallets') + .query({ + cursor, + direction: 'prev', + limit: 2, + sortOrder: 'asc' + }) + .set(REQUEST_HEADER_CLIENT_ID, anchorageConnectionOne.clientId) + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() expect(body.data).toHaveLength(2) - expect(body.data.map((w: Wallet) => w.walletId)).toEqual(['wallet-3', 'wallet-4']) - - expect(status).toBe(HttpStatus.OK) + expect(body.data.map((w: Wallet) => w.label)).toEqual(['wallet 1', 'wallet 2']) + expect(status).toEqual(HttpStatus.OK) }) }) it('returns empty array when cursor points to first wallet and direction is prev', async () => { // First get the earliest wallet - const firstRequest = await request(app.getHttpServer()) - .get('/provider/wallets?limit=1&sortOrder=asc') - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: '/provider/wallets?limit=1&sortOrder=asc', - payload: {}, - htm: 'GET' - }) - ) + const firstRequest = await signedRequest(app, testUserPrivateJwk) + .get('/provider/wallets') + .query({ + limit: 1, + sortOrder: 'asc' + }) + .set(REQUEST_HEADER_CLIENT_ID, anchorageConnectionOne.clientId) + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() const cursor = firstRequest.body.page.next - const { status, body } = await request(app.getHttpServer()) - .get(`/provider/wallets?cursor=${cursor}&sortOrder=asc&direction=prev`) - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: `/provider/wallets?cursor=${cursor}&sortOrder=asc&direction=prev`, - payload: {}, - htm: 'GET' - }) - ) + const { status, body } = await signedRequest(app, testUserPrivateJwk) + .get('/provider/wallets') + .query({ + cursor, + sortOrder: 'asc', + direction: 'prev' + }) + .set(REQUEST_HEADER_CLIENT_ID, anchorageConnectionOne.clientId) + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() expect(body.data).toHaveLength(0) expect(body.page.next).toBeNull() - - expect(status).toBe(HttpStatus.OK) + expect(status).toEqual(HttpStatus.OK) }) }) describe('GET /wallets/:walletId', () => { it('returns the wallet details with accounts and addresses', async () => { - const wallet = TEST_WALLETS[0] - const { status, body } = await request(app.getHttpServer()) - .get(`/provider/wallets/${wallet.id}`) - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: `/provider/wallets/${wallet.id}`, - payload: {}, - htm: 'GET' - }) - ) - - expect(body).toEqual({ - data: getExpectedWallet(wallet) - }) - - expect(status).toBe(HttpStatus.OK) + const { status, body } = await signedRequest(app, testUserPrivateJwk) + .get(`/provider/wallets/${anchorageWalletOne.walletId}`) + .set(REQUEST_HEADER_CLIENT_ID, anchorageConnectionOne.clientId) + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() + + expect(body).toMatchZodSchema(ProviderWalletDto.schema) + expect(body.data.walletId).toEqual(anchorageWalletOne.walletId) + expect(status).toEqual(HttpStatus.OK) }) it('returns 404 with proper error message for non-existent wallet', async () => { - const { status } = await request(app.getHttpServer()) + const { status } = await signedRequest(app, testUserPrivateJwk) .get(`/provider/wallets/non-existent`) - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: `/provider/wallets/non-existent`, - payload: {}, - htm: 'GET' - }) - ) + .set(REQUEST_HEADER_CLIENT_ID, anchorageConnectionOne.clientId) + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() - expect(status).toBe(HttpStatus.NOT_FOUND) + expect(status).toEqual(HttpStatus.NOT_FOUND) }) it('returns 404 when accessing wallet from wrong client', async () => { const wallet = TEST_WALLETS[0] - const { status } = await request(app.getHttpServer()) + const { status } = await signedRequest(app, testUserPrivateJwk) .get(`/provider/wallets/${wallet.id}`) - .set(REQUEST_HEADER_CLIENT_ID, 'wrong-client') - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: `/provider/wallets/${wallet.id}`, - payload: {}, - htm: 'GET' - }) - ) + .set(REQUEST_HEADER_CLIENT_ID, anchorageConnectionOne.clientId) + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() - expect(status).toBe(HttpStatus.NOT_FOUND) + expect(status).toEqual(HttpStatus.NOT_FOUND) }) }) describe('GET /wallets/:walletId/accounts', () => { it('returns the list of accounts for the wallet', async () => { - const wallet = TEST_WALLETS[0] - const accounts = TEST_ACCOUNTS.filter((acc) => acc.walletId === wallet.id) - const { status, body } = await request(app.getHttpServer()) - .get(`/provider/wallets/${wallet.id}/accounts`) - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: `/provider/wallets/${wallet.id}/accounts`, - payload: {}, - htm: 'GET' - }) - ) + const { status, body } = await signedRequest(app, testUserPrivateJwk) + .get(`/provider/wallets/${anchorageWalletOne.walletId}/accounts`) + .set(REQUEST_HEADER_CLIENT_ID, anchorageConnectionOne.clientId) + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() - expect(body).toEqual({ - data: accounts.map(getExpectedAccount).reverse(), - page: { - next: null - } - }) + expect(body.data.map((a: Account) => a.label)).toEqual(['wallet 1 account 2', 'wallet 1 account 1']) - expect(status).toBe(HttpStatus.OK) + expect(status).toEqual(HttpStatus.OK) }) it('returns empty accounts array for wallet with no accounts', async () => { - const { status, body } = await request(app.getHttpServer()) - .get(`/provider/wallets/${TEST_WALLETS[1].id}/accounts`) - .set(REQUEST_HEADER_CLIENT_ID, TEST_CLIENT_ID) - .set( - 'detached-jws', - await getJwsd({ - userPrivateJwk: testUserPrivateJwk, - requestUrl: `/provider/wallets/${TEST_WALLETS[1].id}/accounts`, - payload: {}, - htm: 'GET' - }) - ) + const { status, body } = await signedRequest(app, testUserPrivateJwk) + .get(`/provider/wallets/${anchorageWalletThree.walletId}/accounts`) + .set(REQUEST_HEADER_CLIENT_ID, anchorageConnectionOne.clientId) + .set(REQUEST_HEADER_CONNECTION_ID, anchorageConnectionOne.connectionId) + .send() expect(body).toEqual({ data: [], diff --git a/apps/vault/src/broker/__test__/util/map-db-to-returned.ts b/apps/vault/src/broker/__test__/util/map-db-to-returned.ts index 9be4c7403..2c7cdd6ba 100644 --- a/apps/vault/src/broker/__test__/util/map-db-to-returned.ts +++ b/apps/vault/src/broker/__test__/util/map-db-to-returned.ts @@ -2,7 +2,7 @@ import { ProviderAccount, ProviderAddress, ProviderConnection, ProviderWallet } from '@prisma/client/vault' import { ConnectionRepository } from '../../persistence/repository/connection.repository' -import { TEST_ACCOUNTS, TEST_ADDRESSES, TEST_CONNECTIONS, TEST_WALLET_CONNECTIONS } from './mock-data' +import { TEST_ACCOUNTS, TEST_ADDRESSES, TEST_CONNECTIONS } from './mock-data' // Helper function to get expected connection format for API response export const getExpectedConnection = (model: ProviderConnection) => { @@ -27,7 +27,8 @@ export const getExpectedAddress = (address: ProviderAddress) => { ...addressWithoutId, addressId: address.id, createdAt: new Date(address.createdAt).toISOString(), - updatedAt: new Date(address.updatedAt).toISOString() + updatedAt: new Date(address.updatedAt).toISOString(), + connectionId: address.connectionId } } @@ -48,22 +49,21 @@ export const getExpectedAccount = (account: ProviderAccount) => { // Helper function to get expected wallet format with accounts and connections export const getExpectedWallet = (wallet: ProviderWallet) => { const accounts = TEST_ACCOUNTS.filter((acc) => acc.walletId === wallet.id) - const walletConnections = TEST_WALLET_CONNECTIONS.filter((conn) => conn.walletId === wallet.id) - const connections = TEST_CONNECTIONS.filter((conn) => - walletConnections.some((wc) => wc.connectionId === conn.id) - ).map((c) => ({ + const connections = TEST_CONNECTIONS.filter((conn) => conn.id === wallet.connectionId).map((c) => ({ ...c, credentials: c.credentials ? JSON.stringify(c.credentials) : null, integrity: null })) - const { id, ...walletWithoutId } = wallet + const { id, connectionId, ...walletWithoutId } = wallet - return { + const exp = { ...walletWithoutId, walletId: wallet.id, - accounts: accounts.map(getExpectedAccount), connections: connections.map(getExpectedConnection), createdAt: wallet.createdAt.toISOString(), - updatedAt: wallet.updatedAt.toISOString() + updatedAt: wallet.updatedAt.toISOString(), + accounts: accounts.map(getExpectedAccount) } + + return exp } diff --git a/apps/vault/src/broker/__test__/util/mock-data.ts b/apps/vault/src/broker/__test__/util/mock-data.ts index 3357b6142..c4054281d 100644 --- a/apps/vault/src/broker/__test__/util/mock-data.ts +++ b/apps/vault/src/broker/__test__/util/mock-data.ts @@ -146,21 +146,38 @@ export const TEST_CONNECTIONS = [ createdAt: now, updatedAt: now, revokedAt: null - } -] - -export const TEST_WALLET_CONNECTIONS = [ + }, { + id: 'connection-3', clientId: TEST_CLIENT_ID, - connectionId: 'connection-1', - walletId: 'wallet-1', - createdAt: now + provider: 'anchorage', + url: 'https://api.anchorage.com', + label: 'Test Connection 3', + credentials: { + apiKey: 'test-api-key-1', + privateKey, + publicKey + }, + status: 'active', + createdAt: now, + updatedAt: now, + revokedAt: null }, { + id: 'connection-4', clientId: TEST_CLIENT_ID, - connectionId: 'connection-2', - walletId: 'wallet-2', - createdAt: now + provider: 'anchorage', + url: 'https://api.anchorage.com', + label: 'Test Connection 4', + credentials: { + apiKey: 'test-api-key-1', + privateKey, + publicKey + }, + status: 'active', + createdAt: now, + updatedAt: now, + revokedAt: null } ] @@ -171,6 +188,7 @@ export const TEST_WALLETS_WITH_SAME_TIMESTAMP = [ provider: 'anchorage', label: 'Test Wallet 1', externalId: 'ext-wallet-1', + connectionId: 'connection-3', createdAt: now, updatedAt: now }, @@ -179,6 +197,7 @@ export const TEST_WALLETS_WITH_SAME_TIMESTAMP = [ clientId: TEST_DIFFERENT_CLIENT_ID, provider: 'anchorage', label: 'Test Wallet 2', + connectionId: 'connection-3', externalId: 'ext-wallet-2', createdAt: now, updatedAt: now @@ -187,6 +206,7 @@ export const TEST_WALLETS_WITH_SAME_TIMESTAMP = [ id: 'wallet-8', clientId: TEST_DIFFERENT_CLIENT_ID, provider: 'anchorage', + connectionId: 'connection-3', label: 'Test Wallet 3', externalId: 'ext-wallet-3', createdAt: now, @@ -201,6 +221,7 @@ export const TEST_WALLETS = [ provider: 'anchorage', label: 'Test Wallet 1', externalId: 'ext-wallet-1', + connectionId: 'connection-1', createdAt: now, updatedAt: now }, @@ -210,6 +231,7 @@ export const TEST_WALLETS = [ provider: 'anchorage', label: 'Test Wallet 2', externalId: 'ext-wallet-2', + connectionId: 'connection-2', createdAt: new Date(now.getTime() + 1000), updatedAt: new Date(now.getTime() + 1000) }, @@ -219,6 +241,7 @@ export const TEST_WALLETS = [ provider: 'anchorage', label: 'Test Wallet 3', externalId: 'ext-wallet-3', + connectionId: 'connection-4', createdAt: new Date(now.getTime() + 2000), updatedAt: new Date(now.getTime() + 2000) }, @@ -227,6 +250,7 @@ export const TEST_WALLETS = [ clientId: TEST_CLIENT_ID, provider: 'anchorage', label: 'Test Wallet 4', + connectionId: 'connection-4', externalId: 'ext-wallet-4', createdAt: new Date(now.getTime() + 3000), updatedAt: new Date(now.getTime() + 3000) @@ -235,6 +259,7 @@ export const TEST_WALLETS = [ id: 'wallet-5', clientId: TEST_CLIENT_ID, provider: 'anchorage', + connectionId: 'connection-4', label: 'Test Wallet 5', externalId: 'ext-wallet-5', createdAt: new Date(now.getTime() + 4000), @@ -250,6 +275,7 @@ export const TEST_ACCOUNTS = [ label: 'Test Account 1', externalId: 'ext-account-1', walletId: 'wallet-1', // Linking to wallet-1 + connectionId: 'connection-1', networkId: '1', createdAt: now, updatedAt: now @@ -261,6 +287,7 @@ export const TEST_ACCOUNTS = [ label: 'Test Account 2', externalId: 'ext-account-2', walletId: 'wallet-1', // Linking to wallet-1 + connectionId: 'connection-1', networkId: '60', createdAt: now, updatedAt: now @@ -274,6 +301,7 @@ export const TEST_ADDRESSES = [ provider: 'anchorage', externalId: 'ext-address-1', accountId: 'account-1', // Linking to account-1 + connectionId: 'connection-1', address: '0x1234567890123456789012345678901234567890', // Example ETH address createdAt: now, updatedAt: now @@ -284,6 +312,7 @@ export const TEST_ADDRESSES = [ provider: 'anchorage', externalId: 'ext-address-2', accountId: 'account-1', // Another address for account-1 + connectionId: 'connection-1', address: '0x0987654321098765432109876543210987654321', // Example ETH address createdAt: now, updatedAt: now @@ -294,6 +323,7 @@ export const TEST_ADDRESSES = [ provider: 'anchorage', externalId: 'ext-address-3', accountId: 'account-2', // Linking to account-2 + connectionId: 'connection-2', address: 'bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh', // Example BTC address createdAt: now, updatedAt: now diff --git a/apps/vault/src/broker/broker.module.ts b/apps/vault/src/broker/broker.module.ts index 87e7d6778..80629a778 100644 --- a/apps/vault/src/broker/broker.module.ts +++ b/apps/vault/src/broker/broker.module.ts @@ -1,9 +1,9 @@ import { HttpModule, OpenTelemetryModule } from '@narval/nestjs-shared' -import { Module } from '@nestjs/common' +import { CacheModule } from '@nestjs/cache-manager' +import { Module, OnApplicationBootstrap } from '@nestjs/common' import { APP_FILTER } from '@nestjs/core' import { EventEmitterModule } from '@nestjs/event-emitter' import { ClientModule } from '../client/client.module' -import { Env, getEnv } from '../main.config' import { DEFAULT_HTTP_MODULE_PROVIDERS } from '../shared/constant' import { ProviderHttpExceptionFilter } from '../shared/filter/provider-http-exception.filter' import { PersistenceModule } from '../shared/module/persistence/persistence.module' @@ -11,23 +11,30 @@ import { EncryptionKeyService } from '../transit-encryption/core/service/encrypt import { EncryptionKeyRepository } from '../transit-encryption/persistence/encryption-key.repository' import { TransitEncryptionModule } from '../transit-encryption/transit-encryption.module' import { AnchorageCredentialService } from './core/provider/anchorage/anchorage-credential.service' +import { AnchorageKnownDestinationService } from './core/provider/anchorage/anchorage-known-destination.service' import { AnchorageProxyService } from './core/provider/anchorage/anchorage-proxy.service' -import { AnchorageSyncService } from './core/provider/anchorage/anchorage-sync.service' +import { AnchorageScopedSyncService } from './core/provider/anchorage/anchorage-scoped-sync.service' import { AnchorageTransferService } from './core/provider/anchorage/anchorage-transfer.service' +import { BitgoCredentialService } from './core/provider/bitgo/bitgo-credential.service' import { FireblocksCredentialService } from './core/provider/fireblocks/fireblocks-credential.service' +import { FireblocksKnownDestinationService } from './core/provider/fireblocks/fireblocks-known-destination.service' import { FireblocksProxyService } from './core/provider/fireblocks/fireblocks-proxy.service' -import { FireblocksSyncService } from './core/provider/fireblocks/fireblocks-sync.service' +import { FireblocksScopedSyncService } from './core/provider/fireblocks/fireblocks-scoped-sync.service' import { FireblocksTransferService } from './core/provider/fireblocks/fireblocks-transfer.service' import { AccountService } from './core/service/account.service' import { AddressService } from './core/service/address.service' import { AssetService } from './core/service/asset.service' import { ConnectionService } from './core/service/connection.service' import { KnownDestinationService } from './core/service/known-destination.service' +import { NetworkService } from './core/service/network.service' import { ProxyService } from './core/service/proxy.service' +import { RawAccountService } from './core/service/raw-account.service' +import { ScopedSyncService } from './core/service/scoped-sync.service' import { SyncService } from './core/service/sync.service' +import { TransferAssetService } from './core/service/transfer-asset.service' import { TransferService } from './core/service/transfer.service' import { WalletService } from './core/service/wallet.service' -import { ConnectionSyncEventHandler } from './event/handler/connection-sync.event-handler' +import { ConnectionScopedSyncEventHandler } from './event/handler/connection-scoped-sync.event-handler' import { AnchorageClient } from './http/client/anchorage.client' import { FireblocksClient } from './http/client/fireblocks.client' import { ProviderAccountController } from './http/rest/controller/account.controller' @@ -37,6 +44,7 @@ import { ConnectionController } from './http/rest/controller/connection.controll import { KnownDestinationController } from './http/rest/controller/known-destination.controller' import { NetworkController } from './http/rest/controller/network.controller' import { ProxyController } from './http/rest/controller/proxy.controller' +import { ScopedSyncController } from './http/rest/controller/scoped-sync.controller' import { SyncController } from './http/rest/controller/sync.controller' import { TransferController } from './http/rest/controller/transfer.controller' import { ProviderWalletController } from './http/rest/controller/wallet.controller' @@ -44,18 +52,17 @@ import { AccountRepository } from './persistence/repository/account.repository' import { AddressRepository } from './persistence/repository/address.repository' import { AssetRepository } from './persistence/repository/asset.repository' import { ConnectionRepository } from './persistence/repository/connection.repository' -import { KnownDestinationRepository } from './persistence/repository/known-destination.repository' import { NetworkRepository } from './persistence/repository/network.repository' +import { ScopedSyncRepository } from './persistence/repository/scoped-sync.repository' import { SyncRepository } from './persistence/repository/sync.repository' import { TransferRepository } from './persistence/repository/transfer.repository' import { WalletRepository } from './persistence/repository/wallet.repository' import { AssetSeed } from './persistence/seed/asset.seed' import { NetworkSeed } from './persistence/seed/network.seed' -const SEEDS = [NetworkSeed, AssetSeed] - @Module({ imports: [ + CacheModule.register(), ClientModule, EventEmitterModule.forRoot(), HttpModule.register({ retry: { retries: 3 } }), @@ -73,10 +80,12 @@ const SEEDS = [NetworkSeed, AssetSeed] ProviderWalletController, ProxyController, SyncController, + ScopedSyncController, TransferController ], providers: [ - ...(getEnv() !== Env.PRODUCTION ? SEEDS : []), + NetworkSeed, + AssetSeed, ...DEFAULT_HTTP_MODULE_PROVIDERS, { provide: APP_FILTER, @@ -85,34 +94,51 @@ const SEEDS = [NetworkSeed, AssetSeed] FireblocksCredentialService, AccountRepository, AccountService, + RawAccountService, AddressRepository, AddressService, AnchorageClient, AnchorageCredentialService, + AnchorageKnownDestinationService, AnchorageProxyService, - AnchorageSyncService, + AnchorageScopedSyncService, AnchorageTransferService, AssetRepository, AssetService, + BitgoCredentialService, ConnectionRepository, ConnectionService, - ConnectionSyncEventHandler, + ConnectionScopedSyncEventHandler, EncryptionKeyRepository, EncryptionKeyService, FireblocksClient, + FireblocksKnownDestinationService, FireblocksProxyService, - FireblocksSyncService, FireblocksTransferService, - KnownDestinationRepository, + FireblocksScopedSyncService, KnownDestinationService, NetworkRepository, + NetworkService, ProxyService, + ScopedSyncRepository, + ScopedSyncService, SyncRepository, SyncService, TransferRepository, TransferService, + TransferAssetService, WalletRepository, WalletService ] }) -export class BrokerModule {} +export class BrokerModule implements OnApplicationBootstrap { + constructor( + private networkSeed: NetworkSeed, + private assetSeed: AssetSeed + ) {} + + async onApplicationBootstrap() { + await this.networkSeed.seed() + await this.assetSeed.seed() + } +} diff --git a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-scoped-sync.service.spec.ts b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-scoped-sync.service.spec.ts new file mode 100644 index 000000000..930e97d9b --- /dev/null +++ b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-scoped-sync.service.spec.ts @@ -0,0 +1,196 @@ +import { EncryptionModuleOptionProvider } from '@narval/encryption-module' +import { LoggerModule } from '@narval/nestjs-shared' +import { Alg, generateJwk, privateKeyToHex } from '@narval/signature' +import { INestApplication } from '@nestjs/common' +import { EventEmitter2 } from '@nestjs/event-emitter' +import { Test, TestingModule } from '@nestjs/testing' +import { mock } from 'jest-mock-extended' +import { v4 as uuid } from 'uuid' +import { ClientService } from '../../../../../../client/core/service/client.service' +import { MainModule } from '../../../../../../main.module' +import { ProvisionService } from '../../../../../../provision.service' +import { KeyValueRepository } from '../../../../../../shared/module/key-value/core/repository/key-value.repository' +import { InMemoryKeyValueRepository } from '../../../../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' +import { TestPrismaService } from '../../../../../../shared/module/persistence/service/test-prisma.service' +import { getTestRawAesKeyring } from '../../../../../../shared/testing/encryption.testing' +import { testClient } from '../../../../../__test__/util/mock-data' +import { NetworkSeed } from '../../../../../persistence/seed/network.seed' +import { setupMockServer } from '../../../../../shared/__test__/mock-server' +import { AccountService } from '../../../../service/account.service' +import { AddressService } from '../../../../service/address.service' +import { ConnectionService } from '../../../../service/connection.service' +import { WalletService } from '../../../../service/wallet.service' +import { ConnectionWithCredentials } from '../../../../type/connection.type' +import { Provider, isCreateOperation } from '../../../../type/provider.type' +import { AnchorageScopedSyncService } from '../../anchorage-scoped-sync.service' +import { ANCHORAGE_TEST_API_BASE_URL, getHandlers } from '../server-mock/server' + +describe(AnchorageScopedSyncService.name, () => { + let app: INestApplication + let module: TestingModule + + let anchorageScopedSyncService: AnchorageScopedSyncService + let clientService: ClientService + let connection: ConnectionWithCredentials + let walletService: WalletService + let accountService: AccountService + let addressService: AddressService + let connectionService: ConnectionService + let networkSeed: NetworkSeed + let provisionService: ProvisionService + let testPrismaService: TestPrismaService + + const mockServer = setupMockServer(getHandlers()) + + const clientId = 'test-client-id' + + beforeAll(async () => { + module = await Test.createTestingModule({ + imports: [MainModule] + }) + .overrideModule(LoggerModule) + .useModule(LoggerModule.forTest()) + .overrideProvider(KeyValueRepository) + .useValue(new InMemoryKeyValueRepository()) + .overrideProvider(EncryptionModuleOptionProvider) + .useValue({ + keyring: getTestRawAesKeyring() + }) + // Mock the event emitter because we don't want to send a + // connection.activated event after the creation. + .overrideProvider(EventEmitter2) + .useValue(mock()) + .compile() + + app = module.createNestApplication() + + testPrismaService = module.get(TestPrismaService) + anchorageScopedSyncService = module.get(AnchorageScopedSyncService) + connectionService = module.get(ConnectionService) + walletService = module.get(WalletService) + accountService = module.get(AccountService) + addressService = module.get(AddressService) + provisionService = module.get(ProvisionService) + networkSeed = module.get(NetworkSeed) + clientService = module.get(ClientService) + + await testPrismaService.truncateAll() + }) + + afterAll(async () => { + await testPrismaService.truncateAll() + await module.close() + await app.close() + }) + + beforeEach(async () => { + await testPrismaService.truncateAll() + + await provisionService.provision() + await clientService.save(testClient) + + connection = await connectionService.create(clientId, { + connectionId: uuid(), + provider: Provider.ANCHORAGE, + url: ANCHORAGE_TEST_API_BASE_URL, + label: 'test active connection', + credentials: { + apiKey: 'test-api-key', + privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) + } + }) + + await networkSeed.seed() + + await app.init() + }) + + describe('scoped-syncs', () => { + it('returns scoped sync operations for wallets, accounts and addresses based on an anchorage wallet externalId', async () => { + const rawAccounts = [ + { + provider: Provider.ANCHORAGE, + externalId: '6a46a1977959e0529f567e8e927e3895' + } + ] + const sync = await anchorageScopedSyncService.scopedSync(connection, rawAccounts) + + expect(sync.wallets.length).toBe(1) + expect(sync.accounts.length).toBe(1) + expect(sync.addresses.length).toBe(1) + }) + + // TODO @ptroger: revert that back to 'return empty array' when we completely move towards the scoped connections + it('returns full connection sync when empty rawAccounts are provided', async () => { + const sync = await anchorageScopedSyncService.scopedSync(connection, []) + + expect(sync.wallets.length).toBe(2) + expect(sync.accounts.length).toBe(18) + expect(sync.addresses.length).toBe(2) + }) + + it('returns empty array when no wallets are found for the provided rawAccounts', async () => { + const rawAccounts = [ + { + provider: Provider.ANCHORAGE, + externalId: 'notFound' + } + ] + const sync = await anchorageScopedSyncService.scopedSync(connection, rawAccounts) + + expect(sync.wallets.length).toBe(0) + expect(sync.accounts.length).toBe(0) + expect(sync.addresses.length).toBe(0) + }) + it('skips duplicate for the same connection', async () => { + const rawAccounts = [ + { + provider: Provider.ANCHORAGE, + externalId: '6a46a1977959e0529f567e8e927e3895' + } + ] + const firstSync = await anchorageScopedSyncService.scopedSync(connection, rawAccounts) + + await walletService.bulkCreate(firstSync.wallets.filter(isCreateOperation).map(({ create }) => create)) + await accountService.bulkCreate(firstSync.accounts.filter(isCreateOperation).map(({ create }) => create)) + await addressService.bulkCreate(firstSync.addresses.filter(isCreateOperation).map(({ create }) => create)) + + const secondSync = await anchorageScopedSyncService.scopedSync(connection, rawAccounts) + + expect(secondSync.wallets.length).toBe(0) + expect(secondSync.accounts.length).toBe(0) + expect(secondSync.addresses.length).toBe(0) + }) + + it('duplicates for different connections', async () => { + const rawAccounts = [ + { + provider: Provider.ANCHORAGE, + externalId: '6a46a1977959e0529f567e8e927e3895' + } + ] + const firstSync = await anchorageScopedSyncService.scopedSync(connection, rawAccounts) + + await walletService.bulkCreate(firstSync.wallets.filter(isCreateOperation).map(({ create }) => create)) + await accountService.bulkCreate(firstSync.accounts.filter(isCreateOperation).map(({ create }) => create)) + await addressService.bulkCreate(firstSync.addresses.filter(isCreateOperation).map(({ create }) => create)) + + const secondConnection = await connectionService.create(clientId, { + connectionId: uuid(), + provider: Provider.ANCHORAGE, + url: ANCHORAGE_TEST_API_BASE_URL, + label: 'test active connection', + credentials: { + apiKey: 'test-api-key', + privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) + } + }) + + const secondSync = await anchorageScopedSyncService.scopedSync(secondConnection, rawAccounts) + + expect(secondSync.wallets.length).toBe(1) + expect(secondSync.accounts.length).toBe(1) + expect(secondSync.addresses.length).toBe(1) + }) + }) +}) diff --git a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-sync.service.spec.ts b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-sync.service.spec.ts deleted file mode 100644 index e00d8277a..000000000 --- a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-sync.service.spec.ts +++ /dev/null @@ -1,538 +0,0 @@ -import { EncryptionModuleOptionProvider } from '@narval/encryption-module' -import { LoggerModule } from '@narval/nestjs-shared' -import { Alg, generateJwk, privateKeyToHex } from '@narval/signature' -import { INestApplication } from '@nestjs/common' -import { EventEmitter2 } from '@nestjs/event-emitter' -import { Test, TestingModule } from '@nestjs/testing' -import { mock } from 'jest-mock-extended' -import { v4 as uuid } from 'uuid' -import { ClientService } from '../../../../../../client/core/service/client.service' -import { MainModule } from '../../../../../../main.module' -import { ProvisionService } from '../../../../../../provision.service' -import { KeyValueRepository } from '../../../../../../shared/module/key-value/core/repository/key-value.repository' -import { InMemoryKeyValueRepository } from '../../../../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' -import { TestPrismaService } from '../../../../../../shared/module/persistence/service/test-prisma.service' -import { getTestRawAesKeyring } from '../../../../../../shared/testing/encryption.testing' -import { testClient } from '../../../../../__test__/util/mock-data' -import { WalletRepository } from '../../../../../persistence/repository/wallet.repository' -import { NetworkSeed } from '../../../../../persistence/seed/network.seed' -import { setupMockServer } from '../../../../../shared/__test__/mock-server' -import { AccountService } from '../../../../service/account.service' -import { AddressService } from '../../../../service/address.service' -import { ConnectionService } from '../../../../service/connection.service' -import { KnownDestinationService } from '../../../../service/known-destination.service' -import { WalletService } from '../../../../service/wallet.service' -import { ConnectionWithCredentials } from '../../../../type/connection.type' -import { - Provider, - SyncContext, - SyncOperationType, - isCreateOperation, - isDeleteOperation, - isFailedOperation, - isSkipOperation, - isUpdateOperation -} from '../../../../type/provider.type' -import { buildEmptyContext } from '../../../../util/provider-sync.util' -import { AnchorageSyncService } from '../../../anchorage/anchorage-sync.service' -import { - ANCHORAGE_TEST_API_BASE_URL, - getHandlers, - getTrustedDestinationHandlers, - getVaultHandlers -} from '../server-mock/server' - -const toConnectionAssociation = (connection: ConnectionWithCredentials) => ({ - clientId: connection.clientId, - connectionId: connection.connectionId, - createdAt: connection.createdAt, - label: connection.label, - provider: connection.provider, - revokedAt: connection.revokedAt, - status: connection.status, - updatedAt: connection.updatedAt, - url: connection.url -}) - -describe(AnchorageSyncService.name, () => { - let app: INestApplication - let module: TestingModule - - let accountService: AccountService - let addressService: AddressService - let anchorageSyncService: AnchorageSyncService - let clientService: ClientService - let connection: ConnectionWithCredentials - let connectionService: ConnectionService - let knownDestinationService: KnownDestinationService - let networkSeed: NetworkSeed - let provisionService: ProvisionService - let testPrismaService: TestPrismaService - let walletService: WalletRepository - - const mockServer = setupMockServer(getHandlers()) - - const clientId = 'test-client-id' - - const now = new Date() - - beforeAll(async () => { - module = await Test.createTestingModule({ - imports: [MainModule] - }) - .overrideModule(LoggerModule) - .useModule(LoggerModule.forTest()) - .overrideProvider(KeyValueRepository) - .useValue(new InMemoryKeyValueRepository()) - .overrideProvider(EncryptionModuleOptionProvider) - .useValue({ - keyring: getTestRawAesKeyring() - }) - // Mock the event emitter because we don't want to send a - // connection.activated event after the creation. - .overrideProvider(EventEmitter2) - .useValue(mock()) - .compile() - - app = module.createNestApplication() - - testPrismaService = module.get(TestPrismaService) - anchorageSyncService = module.get(AnchorageSyncService) - connectionService = module.get(ConnectionService) - walletService = module.get(WalletService) - accountService = module.get(AccountService) - addressService = module.get(AddressService) - knownDestinationService = module.get(KnownDestinationService) - provisionService = module.get(ProvisionService) - networkSeed = module.get(NetworkSeed) - clientService = module.get(ClientService) - - await testPrismaService.truncateAll() - }) - - afterAll(async () => { - await testPrismaService.truncateAll() - await module.close() - await app.close() - }) - - beforeEach(async () => { - await testPrismaService.truncateAll() - - await provisionService.provision() - await clientService.save(testClient) - - connection = await connectionService.create(clientId, { - connectionId: uuid(), - provider: Provider.ANCHORAGE, - url: ANCHORAGE_TEST_API_BASE_URL, - label: 'test active connection', - credentials: { - apiKey: 'test-api-key', - privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) - } - }) - - await networkSeed.seed() - - await app.init() - }) - - describe('sync', () => { - it('returns sync operations for wallets, accounts, addresses and known destinations', async () => { - const sync = await anchorageSyncService.sync(connection) - - expect(sync.wallets.length).toBeGreaterThan(0) - expect(sync.accounts.length).toBeGreaterThan(0) - expect(sync.addresses.length).toBeGreaterThan(0) - expect(sync.knownDestinations.length).toBeGreaterThan(0) - }) - }) - - describe('syncWallets', () => { - it('adds create operations into the context', async () => { - const result = await anchorageSyncService.syncWallets(buildEmptyContext({ connection, now })) - - expect(result.wallets).toEqual([ - { - type: SyncOperationType.CREATE, - create: { - accounts: [], - clientId: connection.clientId, - connections: [toConnectionAssociation(connection)], - createdAt: now, - externalId: '084ff57c0984420efac31723579c94fc', - label: 'Vault 1', - provider: connection.provider, - updatedAt: now, - walletId: expect.any(String) - } - }, - { - type: SyncOperationType.CREATE, - create: { - accounts: [], - clientId: connection.clientId, - connections: [toConnectionAssociation(connection)], - createdAt: now, - externalId: '62547351cea99e827bcd43a513c40e7c', - label: 'Vault 2', - provider: connection.provider, - updatedAt: now, - walletId: expect.any(String) - } - } - ]) - }) - - it('skips duplicate wallets', async () => { - const context = buildEmptyContext({ connection, now }) - - const firstSync = await anchorageSyncService.syncWallets(context) - await walletService.bulkCreate(firstSync.wallets.filter(isCreateOperation).map(({ create }) => create)) - - const secondSync = await anchorageSyncService.syncWallets(context) - - expect(secondSync.wallets).toHaveLength(0) - }) - - it('adds update operations to associate wallet with a new connection', async () => { - const secondConnectionWithCredentials = await connectionService.create(clientId, { - connectionId: 'connection-two-id', - provider: Provider.ANCHORAGE, - url: ANCHORAGE_TEST_API_BASE_URL, - credentials: { - apiKey: 'test-api-key', - privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) - } - }) - - // First sync - should create all wallets - mockServer.use(getVaultHandlers(ANCHORAGE_TEST_API_BASE_URL).findAll) - const firstSync = await anchorageSyncService.syncWallets(buildEmptyContext({ connection, now })) - await walletService.bulkCreate(firstSync.wallets.filter(isCreateOperation).map(({ create }) => create)) - - // Second sync with new connection that only finds one wallet and its - // label is changed. - mockServer.use(getVaultHandlers(ANCHORAGE_TEST_API_BASE_URL).update) - const secondSync = await anchorageSyncService.syncWallets( - buildEmptyContext({ - connection: secondConnectionWithCredentials, - now - }) - ) - - expect(secondSync.wallets.filter(isCreateOperation)).toHaveLength(0) - expect(secondSync.wallets.filter(isUpdateOperation)).toHaveLength(1) - expect(secondSync.wallets.filter(isDeleteOperation)).toHaveLength(0) - expect(secondSync.wallets.filter(isSkipOperation)).toHaveLength(0) - expect(secondSync.wallets.filter(isFailedOperation)).toHaveLength(0) - - expect(secondSync.wallets.filter(isUpdateOperation)[0]).toEqual({ - type: SyncOperationType.UPDATE, - update: expect.objectContaining({ - externalId: '084ff57c0984420efac31723579c94fc', - label: 'Vault 1 - renamed', - connections: [toConnectionAssociation(connection), toConnectionAssociation(secondConnectionWithCredentials)] - }) - }) - }) - }) - - describe('syncAccounts', () => { - it('adds create operations into the context', async () => { - const walletOne = { - accounts: [], - clientId: connection.clientId, - connections: [], - createdAt: now, - externalId: '084ff57c0984420efac31723579c94fc', - label: 'Vault 1', - provider: connection.provider, - updatedAt: now, - walletId: '96e7bdc0-d090-42fe-8aaf-f25c2a752e79' - } - const walletTwo = { - accounts: [], - clientId: connection.clientId, - connections: [], - createdAt: now, - externalId: '62547351cea99e827bcd43a513c40e7c', - label: 'Vault 2', - provider: connection.provider, - updatedAt: now, - walletId: 'f22cd7b3-f1af-4312-8c05-25acb7dbb76f' - } - const context = buildEmptyContext({ - connection, - now, - wallets: [ - { type: SyncOperationType.CREATE, create: walletOne }, - { type: SyncOperationType.CREATE, create: walletTwo } - ] - }) - - const result = await anchorageSyncService.syncAccounts(context) - - expect(result.accounts.filter(isCreateOperation)).toHaveLength(18) - expect(result.accounts.filter(isUpdateOperation)).toHaveLength(0) - expect(result.accounts.filter(isDeleteOperation)).toHaveLength(0) - expect(result.accounts.filter(isSkipOperation)).toHaveLength(0) - expect(result.accounts.filter(isFailedOperation)).toHaveLength(0) - - expect(result.accounts.filter(isCreateOperation)[0]).toEqual({ - type: SyncOperationType.CREATE, - create: { - accountId: expect.any(String), - walletId: walletOne.walletId, - label: 'secondWalletThroughApi!', - clientId: connection.clientId, - provider: Provider.ANCHORAGE, - addresses: [], - externalId: '145ff5b10e0e208b9c3adab0a9531f0c', - createdAt: now, - updatedAt: now, - networkId: 'BITCOIN' - } - }) - }) - - it('skips duplicate accounts', async () => { - const walletOne = { - accounts: [], - clientId: connection.clientId, - connections: [], - createdAt: now, - externalId: '084ff57c0984420efac31723579c94fc', - label: 'Vault 1', - provider: connection.provider, - updatedAt: now, - walletId: '96e7bdc0-d090-42fe-8aaf-f25c2a752e79' - } - const walletTwo = { - accounts: [], - clientId: connection.clientId, - connections: [], - createdAt: now, - externalId: '62547351cea99e827bcd43a513c40e7c', - label: 'Vault 2', - provider: connection.provider, - updatedAt: now, - walletId: 'f22cd7b3-f1af-4312-8c05-25acb7dbb76f' - } - const context = buildEmptyContext({ - connection, - now, - wallets: [ - { type: SyncOperationType.CREATE, create: walletOne }, - { type: SyncOperationType.CREATE, create: walletTwo } - ] - }) - - const firstSync = await anchorageSyncService.syncAccounts(context) - - await walletService.bulkCreate(firstSync.wallets.filter(isCreateOperation).map(({ create }) => create)) - await accountService.bulkCreate(firstSync.accounts.filter(isCreateOperation).map(({ create }) => create)) - - const secondSync = await anchorageSyncService.syncAccounts(context) - - expect(secondSync.accounts).toHaveLength(0) - }) - - it.todo('adds failed operations into the context when it does not found the parent wallet') - }) - - describe('syncAddresses', () => { - let context: SyncContext - - beforeEach(async () => { - const walletSyncContext = await anchorageSyncService.syncWallets( - buildEmptyContext({ - connection, - now - }) - ) - - context = await anchorageSyncService.syncAccounts(walletSyncContext) - }) - - it('adds create operations into the context', async () => { - const result = await anchorageSyncService.syncAddresses(context) - - expect(result.addresses.filter(isCreateOperation)).toHaveLength(1) - expect(result.addresses.filter(isUpdateOperation)).toHaveLength(0) - expect(result.addresses.filter(isDeleteOperation)).toHaveLength(0) - expect(result.addresses.filter(isSkipOperation)).toHaveLength(0) - expect(result.addresses.filter(isFailedOperation)).toHaveLength(0) - - expect(result.addresses.filter(isCreateOperation)[0]).toEqual({ - type: SyncOperationType.CREATE, - create: { - accountId: expect.any(String), - address: '2N18VkRep3F2z7Ggm8W94nkKdARMfEM3EWa', - addressId: expect.any(String), - clientId: connection.clientId, - createdAt: now, - externalId: '96bf95f1b59d50d9d1149057e8c0f9fd', - provider: Provider.ANCHORAGE, - updatedAt: now - } - }) - }) - - it('skips duplicate addresses', async () => { - const walletSyncContext = await anchorageSyncService.syncWallets( - buildEmptyContext({ - connection, - now - }) - ) - const accountSyncContext = await anchorageSyncService.syncAccounts(walletSyncContext) - const firstSync = await anchorageSyncService.syncAddresses(accountSyncContext) - - expect(firstSync.addresses.length).toBeGreaterThan(0) - - await walletService.bulkCreate(firstSync.wallets.filter(isCreateOperation).map(({ create }) => create)) - await accountService.bulkCreate(firstSync.accounts.filter(isCreateOperation).map(({ create }) => create)) - await addressService.bulkCreate(firstSync.addresses.filter(isCreateOperation).map(({ create }) => create)) - - const secondSync = await anchorageSyncService.syncAddresses(context) - - expect(secondSync.addresses).toHaveLength(0) - }) - - it.todo('adds failed operations into the context when it does not found the parent account') - }) - - describe('syncKnownDestinations', () => { - it('adds create operations into the context', async () => { - const result = await anchorageSyncService.syncKnownDestinations( - buildEmptyContext({ - connection, - now - }) - ) - - expect(result.knownDestinations.filter(isCreateOperation)).toHaveLength(4) - expect(result.knownDestinations.filter(isUpdateOperation)).toHaveLength(0) - expect(result.knownDestinations.filter(isDeleteOperation)).toHaveLength(0) - expect(result.knownDestinations.filter(isSkipOperation)).toHaveLength(0) - expect(result.knownDestinations.filter(isFailedOperation)).toHaveLength(0) - - expect(result.knownDestinations.filter(isCreateOperation)[0]).toEqual({ - type: SyncOperationType.CREATE, - create: { - address: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e', - assetId: 'ETH', - clientId, - connections: [toConnectionAssociation(connection)], - createdAt: now, - externalId: 'toBeConnected', - knownDestinationId: expect.any(String), - label: undefined, - networkId: 'ETHEREUM', - provider: Provider.ANCHORAGE, - updatedAt: now - } - }) - }) - - it('adds update operations when known destination already exist', async () => { - const context = buildEmptyContext({ connection, now }) - - // First sync, create initial destinations - mockServer.use(getTrustedDestinationHandlers(ANCHORAGE_TEST_API_BASE_URL).findAll) - - const firstSync = await anchorageSyncService.syncKnownDestinations(context) - await knownDestinationService.bulkCreate( - firstSync.knownDestinations.filter(isCreateOperation).map(({ create }) => create) - ) - - // Second sync with updated data - mockServer.use(getTrustedDestinationHandlers(ANCHORAGE_TEST_API_BASE_URL).deleteAndUpdate) - const secondSync = await anchorageSyncService.syncKnownDestinations(context) - - expect(secondSync.knownDestinations.filter(isCreateOperation)).toHaveLength(0) - expect(secondSync.knownDestinations.filter(isUpdateOperation)).toHaveLength(1) - expect(secondSync.knownDestinations.filter(isDeleteOperation)).toHaveLength(1) - expect(secondSync.knownDestinations.filter(isFailedOperation)).toHaveLength(0) - - // Only the modified destination should be in updated - expect(secondSync.knownDestinations.filter(isUpdateOperation)[0]).toEqual({ - type: SyncOperationType.UPDATE, - update: { - clientId, - address: '0x8Bc2B8F33e5AeF847B8973Fa669B948A3028D6bd', - assetId: 'USDC', - connections: expect.arrayContaining([toConnectionAssociation(connection)]), - createdAt: now, - externalClassification: null, - externalId: 'toBeUpdated', - knownDestinationId: expect.any(String), - label: 'new memo', - networkId: 'ETHEREUM', - provider: Provider.ANCHORAGE, - updatedAt: now - } - }) - }) - - it('adds update operations to associate known destinations with a new connection', async () => { - const secondConnectionWithCredentials = await connectionService.create(clientId, { - connectionId: uuid(), - provider: Provider.ANCHORAGE, - url: ANCHORAGE_TEST_API_BASE_URL, - credentials: { - apiKey: 'test-api-key', - privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) - } - }) - - // First sync - should create all destinations - mockServer.use(getTrustedDestinationHandlers(ANCHORAGE_TEST_API_BASE_URL).findAll) - const firstSync = await anchorageSyncService.syncKnownDestinations( - buildEmptyContext({ - connection, - now - }) - ) - await knownDestinationService.bulkCreate( - firstSync.knownDestinations.filter(isCreateOperation).map(({ create }) => create) - ) - - // Second sync with new connection that only finds one destination - mockServer.use(getTrustedDestinationHandlers(ANCHORAGE_TEST_API_BASE_URL).connect) - - const secondSync = await anchorageSyncService.syncKnownDestinations( - buildEmptyContext({ - connection: secondConnectionWithCredentials, - now - }) - ) - - expect(secondSync.knownDestinations.filter(isCreateOperation)).toHaveLength(0) - expect(secondSync.knownDestinations.filter(isUpdateOperation)).toHaveLength(1) - expect(secondSync.knownDestinations.filter(isDeleteOperation)).toHaveLength(3) - expect(secondSync.knownDestinations.filter(isSkipOperation)).toHaveLength(0) - expect(secondSync.knownDestinations.filter(isFailedOperation)).toHaveLength(0) - - expect(secondSync.knownDestinations.filter(isUpdateOperation)[0]).toEqual({ - type: SyncOperationType.UPDATE, - update: { - clientId, - address: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e', - assetId: 'ETH', - connections: [toConnectionAssociation(connection), toConnectionAssociation(secondConnectionWithCredentials)], - createdAt: now, - externalClassification: null, - externalId: 'toBeConnected', - knownDestinationId: expect.any(String), - label: undefined, - networkId: 'ETHEREUM', - provider: Provider.ANCHORAGE, - updatedAt: now - } - }) - }) - }) -}) diff --git a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts index cbfa323de..cc5beeb12 100644 --- a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts +++ b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts @@ -16,14 +16,13 @@ import { testClient } from '../../../../../__test__/util/mock-data' import { AccountRepository } from '../../../../../persistence/repository/account.repository' import { AddressRepository } from '../../../../../persistence/repository/address.repository' import { ConnectionRepository } from '../../../../../persistence/repository/connection.repository' -import { KnownDestinationRepository } from '../../../../../persistence/repository/known-destination.repository' import { TransferRepository } from '../../../../../persistence/repository/transfer.repository' import { WalletRepository } from '../../../../../persistence/repository/wallet.repository' import { AssetSeed } from '../../../../../persistence/seed/asset.seed' import { NetworkSeed } from '../../../../../persistence/seed/network.seed' import { setupMockServer, useRequestSpy } from '../../../../../shared/__test__/mock-server' -import { Connection, ConnectionStatus, ConnectionWithCredentials } from '../../../../type/connection.type' -import { Account, Address, KnownDestination, Wallet } from '../../../../type/indexed-resources.type' +import { ConnectionStatus, ConnectionWithCredentials } from '../../../../type/connection.type' +import { Account, Address, Wallet } from '../../../../type/indexed-resources.type' import { Provider } from '../../../../type/provider.type' import { InternalTransfer, @@ -45,7 +44,6 @@ describe(AnchorageTransferService.name, () => { let assetSeed: AssetSeed let clientService: ClientService let connectionRepository: ConnectionRepository - let knownDestinationRepository: KnownDestinationRepository let networkSeed: NetworkSeed let provisionService: ProvisionService let transferRepository: TransferRepository @@ -88,6 +86,7 @@ describe(AnchorageTransferService.name, () => { addresses: [], clientId, createdAt: new Date(), + connectionId: connection.connectionId, externalId: uuid(), label: 'Account 1', networkId: 'BITCOIN', @@ -100,6 +99,7 @@ describe(AnchorageTransferService.name, () => { accountId: uuid(), addresses: [], clientId, + connectionId: connection.connectionId, createdAt: new Date(), externalId: uuid(), label: 'Account 2', @@ -112,6 +112,7 @@ describe(AnchorageTransferService.name, () => { const address: Address = { accountId: accountTwo.accountId, address: '0x2c4895215973cbbd778c32c456c074b99daf8bf1', + connectionId: connection.connectionId, addressId: uuid(), clientId, createdAt: new Date(), @@ -122,7 +123,7 @@ describe(AnchorageTransferService.name, () => { const wallet: Wallet = { clientId, - connections: [Connection.parse(connection)], + connectionId: connection.connectionId, createdAt: new Date(), externalId: uuid(), label: null, @@ -131,18 +132,6 @@ describe(AnchorageTransferService.name, () => { walletId } - const knownDestination: KnownDestination = { - address: '0x04b12f0863b83c7162429f0ebb0dfda20e1aa97b', - clientId, - connections: [], - createdAt: new Date(), - externalId: uuid(), - knownDestinationId: uuid(), - networkId: 'BITCOIN', - provider: Provider.ANCHORAGE, - updatedAt: new Date() - } - const internalTransfer: InternalTransfer = { clientId, customerRefId: null, @@ -154,6 +143,8 @@ describe(AnchorageTransferService.name, () => { externalId, externalStatus: null, assetId: 'BTC', + assetExternalId: null, + connectionId: connection.connectionId, memo: 'Test transfer', grossAmount: '0.00001', networkFeeAttribution: NetworkFeeAttribution.DEDUCT, @@ -191,7 +182,6 @@ describe(AnchorageTransferService.name, () => { addressRepository = module.get(AddressRepository) assetSeed = module.get(AssetSeed) connectionRepository = module.get(ConnectionRepository) - knownDestinationRepository = module.get(KnownDestinationRepository) networkSeed = module.get(NetworkSeed) transferRepository = module.get(TransferRepository) walletRepository = module.get(WalletRepository) @@ -218,7 +208,6 @@ describe(AnchorageTransferService.name, () => { await accountRepository.bulkCreate([accountOne, accountTwo]) await addressRepository.bulkCreate([address]) await transferRepository.bulkCreate([internalTransfer]) - await knownDestinationRepository.bulkCreate([knownDestination]) await app.init() }) @@ -231,6 +220,7 @@ describe(AnchorageTransferService.name, () => { assetId: internalTransfer.assetId, clientId: internalTransfer.clientId, customerRefId: internalTransfer.customerRefId, + connectionId: connection.connectionId, destination: internalTransfer.destination, externalId: internalTransfer.externalId, idempotenceId: internalTransfer.idempotenceId, diff --git a/apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/response/get-wallet-200.json b/apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/response/get-wallet-200.json new file mode 100644 index 000000000..5ea634ac0 --- /dev/null +++ b/apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/response/get-wallet-200.json @@ -0,0 +1,36 @@ +{ + "data": { + "assets": [ + { + "assetType": "BTC_S", + "availableBalance": { + "assetType": "BTC_S", + "currentPrice": "105552.083758084", + "currentUSDValue": "372.77", + "quantity": "0.00353165" + }, + "totalBalance": { + "assetType": "BTC_S", + "currentPrice": "105552.083758084", + "currentUSDValue": "372.77", + "quantity": "0.00353165" + } + } + ], + "depositAddress": { + "address": "2N85qduq5HGsQkAUsUGyouAE8YKz4we6y2h", + "addressId": "7ca733da4a4a665bbb26163c31058a95", + "addressSignaturePayload": "7b225465787441646472657373223a22324e38357164757135484773516b4155735547796f75414538594b7a34776536793268227d", + "addressID": "7ca733da4a4a665bbb26163c31058a95", + "signature": "2339b329a3bc43815b50d5cca805b4f3e87c081068ef5d397763e0095651afa066788f7ab60f0b705d2cf4b0366d31a2f2b2417ae3c78c973c8888be4b7a0f04" + }, + "isArchived": false, + "isDefault": true, + "networkId": "BTC_S", + "type": "WALLET", + "vaultId": "084ff57c0984420efac31723579c94fc", + "vaultName": "Vault 1", + "walletId": "6a46a1977959e0529f567e8e927e3895", + "walletName": "Bitcoin Signet Wallet 1" + } +} diff --git a/apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/response/get-wallets-200.json b/apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/response/get-wallets-200.json index cabc8d153..3e1faa25d 100644 --- a/apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/response/get-wallets-200.json +++ b/apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/response/get-wallets-200.json @@ -29,7 +29,7 @@ }, "isArchived": false, "isDefault": true, - "networkId": "ZKSYNC_SEPOLIA", + "networkId": "ETH_ZKSYNC_T", "type": "WALLET", "vaultId": "084ff57c0984420efac31723579c94fc", "vaultName": "Vault 1", @@ -65,7 +65,7 @@ }, "isArchived": false, "isDefault": true, - "networkId": "ARBITRUM_SEPOLIA", + "networkId": "ETH_ARBITRUM_T", "type": "WALLET", "vaultId": "084ff57c0984420efac31723579c94fc", "vaultName": "Vault 1", @@ -153,7 +153,7 @@ }, "isArchived": false, "isDefault": true, - "networkId": "POLYGON", + "networkId": "POL_POLYGON", "type": "WALLET", "vaultId": "084ff57c0984420efac31723579c94fc", "vaultName": "Vault 1", @@ -225,7 +225,7 @@ }, "isArchived": false, "isDefault": false, - "networkId": "POLYGON", + "networkId": "POL_POLYGON", "type": "WALLET", "vaultId": "084ff57c0984420efac31723579c94fc", "vaultName": "Vault 1", diff --git a/apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/server.ts b/apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/server.ts index faceeb7fa..70a90ab9b 100644 --- a/apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/server.ts +++ b/apps/vault/src/broker/core/provider/anchorage/__test__/server-mock/server.ts @@ -1,3 +1,4 @@ +import { HttpStatus } from '@nestjs/common' import { HttpResponse, http } from 'msw' import getTransferOk from './response/get-transfer-200.json' import trustedDestinationsSecond from './response/get-trusted-destinations-200-second.json' @@ -6,6 +7,7 @@ import trustedDestinationsFirst from './response/get-trusted-destinations-200.js import getVaultsOkSecond from './response/get-vaults-200-second.json' import getVaultsOk from './response/get-vaults-200.json' import getVaultAddressesOk from './response/get-vaults-addresses-200.json' +import getWalletOk from './response/get-wallet-200.json' import getWalletsOk from './response/get-wallets-200.json' import postTransferCreated from './response/post-transfer-201.json' @@ -47,6 +49,17 @@ export const getHandlers = (baseUrl = ANCHORAGE_TEST_API_BASE_URL) => [ return new HttpResponse(JSON.stringify(getWalletsOk)) }), + http.get(`${baseUrl}/v2/wallets/6a46a1977959e0529f567e8e927e3895`, () => { + return new HttpResponse(JSON.stringify(getWalletOk)) + }), + + http.get(`${baseUrl}/v2/wallets/notFound`, () => { + return new HttpResponse(JSON.stringify({ errorType: 'NotFound', message: 'Wallet not found' }), { + status: HttpStatus.NOT_FOUND + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } as unknown as any) + }), + http.get(`${baseUrl}/v2/transfers/:transferId`, () => { return new HttpResponse(JSON.stringify(getTransferOk)) }), diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage-known-destination.service.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage-known-destination.service.ts new file mode 100644 index 000000000..9cfe5d455 --- /dev/null +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage-known-destination.service.ts @@ -0,0 +1,102 @@ +import { LoggerService, PaginatedResult } from '@narval/nestjs-shared' +import { Injectable } from '@nestjs/common' +import { AnchorageClient } from '../../../http/client/anchorage.client' +import { AssetService } from '../../service/asset.service' +import { NetworkService } from '../../service/network.service' +import { Asset } from '../../type/asset.type' +import { ConnectionWithCredentials } from '../../type/connection.type' +import { KnownDestination } from '../../type/known-destination.type' +import { + Provider, + ProviderKnownDestinationPaginationOptions, + ProviderKnownDestinationService +} from '../../type/provider.type' +import { validateConnection } from './anchorage.util' + +@Injectable() +export class AnchorageKnownDestinationService implements ProviderKnownDestinationService { + constructor( + private readonly anchorageClient: AnchorageClient, + private readonly networkService: NetworkService, + private readonly assetService: AssetService, + private readonly logger: LoggerService + ) {} + + async findAll( + connection: ConnectionWithCredentials, + options?: ProviderKnownDestinationPaginationOptions | undefined + ): Promise> { + validateConnection(connection) + + const anchorageTrustedDestinations = await this.anchorageClient.getTrustedDestinations({ + url: connection.url, + limit: options?.limit, + afterId: options?.cursor, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey + }) + + const assetsIndexedByExternalId = await this.assetService.buildProviderExternalIdIndex(Provider.ANCHORAGE) + + const networksIndexedByExternalId = await this.networkService.buildProviderExternalIdIndex(Provider.ANCHORAGE) + + const knownDestinations: KnownDestination[] = [] + + for (const anchorageTrustedDestination of anchorageTrustedDestinations.data) { + const externalId = anchorageTrustedDestination.id + const network = networksIndexedByExternalId.get(anchorageTrustedDestination.crypto.networkId) + + let asset: Asset | undefined + + if (anchorageTrustedDestination.crypto.assetType) { + this.logger.log('Lookup Anchorage trusted destination asset type', { + clientId: connection.clientId, + connectionId: connection.connectionId, + trustedDestination: anchorageTrustedDestination + }) + + asset = assetsIndexedByExternalId.get(anchorageTrustedDestination.crypto.assetType) + } + + if (network) { + const knownDestination = KnownDestination.parse({ + externalId, + address: anchorageTrustedDestination.crypto.address.toLowerCase(), + assetId: asset?.assetId, + externalClassification: null, + clientId: connection.clientId, + connectionId: connection.connectionId, + // NOTE: Anchorage doesn't return a label for trusted destinations. + label: null, + networkId: network.networkId, + provider: Provider.ANCHORAGE + }) + + knownDestinations.push(knownDestination) + } else { + this.logger.warn('Skip Anchorage known destination due to network not found', { + externalId, + externalNetworkId: anchorageTrustedDestination.crypto.networkId, + address: anchorageTrustedDestination.crypto.address, + clientId: connection.clientId, + connectionId: connection.connectionId + }) + } + } + + const last = knownDestinations[knownDestinations.length - 1] + + if (anchorageTrustedDestinations.page.next && last) { + return { + data: knownDestinations, + page: { + next: last.externalId + } + } + } + + return { + data: knownDestinations + } + } +} diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage-scoped-sync.service.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage-scoped-sync.service.ts new file mode 100644 index 000000000..c4cfbf0b4 --- /dev/null +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage-scoped-sync.service.ts @@ -0,0 +1,287 @@ +import { LoggerService } from '@narval/nestjs-shared' +import { HttpStatus, Injectable } from '@nestjs/common' +import { randomUUID } from 'crypto' +import { filter, find, flatMap, flow, groupBy, isEmpty, map, uniqBy } from 'lodash/fp' +import { AnchorageClient, Wallet as AnchorageWallet } from '../../../http/client/anchorage.client' +import { UpdateAccount } from '../../../persistence/repository/account.repository' +import { NetworkRepository } from '../../../persistence/repository/network.repository' +import { WalletRepository } from '../../../persistence/repository/wallet.repository' +import { ConnectionWithCredentials } from '../../type/connection.type' +import { Account, Address, UpdateWallet, Wallet } from '../../type/indexed-resources.type' +import { + CreateScopedSyncOperation, + Provider, + ProviderScopedSyncService, + ScopedSyncOperation, + ScopedSyncOperationType, + ScopedSyncResult +} from '../../type/provider.type' +import { RawAccount } from '../../type/scoped-sync.type' +import { CONCURRENT_ANCHORAGE_REQUESTS, validateConnection } from './anchorage.util' + +@Injectable() +export class AnchorageScopedSyncService implements ProviderScopedSyncService { + constructor( + private readonly anchorageClient: AnchorageClient, + private readonly networkRepository: NetworkRepository, + private readonly walletRepository: WalletRepository, + private readonly logger: LoggerService + ) {} + + private async fetchRawAccountWallets( + connection: ConnectionWithCredentials, + rawAccounts: RawAccount[] + ): Promise { + validateConnection(connection) + + const wallets: AnchorageWallet[] = [] + + for (let i = 0; i < rawAccounts.length; i += CONCURRENT_ANCHORAGE_REQUESTS) { + const batch = rawAccounts.slice(i, i + CONCURRENT_ANCHORAGE_REQUESTS) + const batchPromises = batch.map((rawAccount) => + this.anchorageClient.getWallet({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey, + walletId: rawAccount.externalId + }) + ) + + const batchResults = await Promise.allSettled(batchPromises) + + const validWallets = batchResults + .map((result, index) => { + if (result.status === 'fulfilled') { + return result.value + } else { + // Handle rejected promises + const error = result.reason + const rawAccount = batch[index] + + if (error.response?.status === HttpStatus.NOT_FOUND) { + this.logger.warn('Anchorage wallet not found', { + connectionId: connection.connectionId, + clientId: connection.clientId, + url: connection.url, + externalId: rawAccount.externalId + }) + return null + } + throw error + } + }) + .filter((wallet): wallet is AnchorageWallet => wallet !== null) as AnchorageWallet[] + + wallets.push(...validWallets) + } + + return wallets + } + + async scopedSync(connection: ConnectionWithCredentials, rawAccounts: RawAccount[]): Promise { + const now = new Date() + + this.logger.log('Sync Anchorage accounts', { + connectionId: connection.connectionId, + clientId: connection.clientId, + url: connection.url + }) + + validateConnection(connection) + + const existingWallets = await this.walletRepository.findAll( + { clientId: connection.clientId, connectionId: connection.connectionId }, + { pagination: { disabled: true } } + ) + + const existingWalletMap = new Map(existingWallets.data.map((wallet) => [wallet.externalId, wallet])) + const existingAccountMap = new Map( + existingWallets.data.flatMap( + (wallet) => + wallet.accounts?.map((account) => [account.externalId, { ...account, walletId: wallet.walletId }]) ?? [] + ) + ) + + // TODO @ptroger: revert that back to 'return empty array' when we completely move towards the scoped connections + const scopedAnchorageWallets = isEmpty(rawAccounts) + ? await this.anchorageClient.getWallets({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey + }) + : await this.fetchRawAccountWallets(connection, rawAccounts) + + const walletsByVault = groupBy('vaultId', scopedAnchorageWallets) + const vaultAndWallets = Object.entries(walletsByVault).map(([vaultId, wallets]) => ({ + id: vaultId, + // All wallets in a vault should have the same vault name + name: wallets[0].vaultName, + wallets: wallets.map((wallet) => ({ + walletId: wallet.walletId, + walletName: wallet.walletName, + address: { + address: wallet.depositAddress.address, + addressId: wallet.depositAddress.addressId + }, + assets: wallet.assets.map((asset) => ({ + assetType: asset.assetType, + availableBalance: asset.availableBalance, + totalBalance: asset.totalBalance, + stakedBalance: asset.stakedBalance, + unclaimedBalance: asset.unclaimedBalance + })), + networkId: wallet.networkId + })) + })) + + const walletOperations: ScopedSyncOperation[] = [] + const accountOperations: ScopedSyncOperation[] = [] + const addressOperations: ScopedSyncOperation[] = [] + + for (const vault of vaultAndWallets) { + const existingWallet = existingWalletMap.get(vault.id) + const walletId = existingWallet?.walletId || randomUUID() + + if (existingWallet) { + // Check if wallet needs update + if (existingWallet.label !== vault.name) { + walletOperations.push({ + type: ScopedSyncOperationType.UPDATE, + update: { + clientId: connection.clientId, + walletId, + label: vault.name, + updatedAt: now + } + }) + } + } else { + // Create new wallet + walletOperations.push({ + type: ScopedSyncOperationType.CREATE, + create: { + accounts: [], + clientId: connection.clientId, + connectionId: connection.connectionId, + createdAt: now, + externalId: vault.id, + label: vault.name, + provider: Provider.ANCHORAGE, + updatedAt: now, + walletId + } + }) + } + + const vaultAssetTypes = flow(flatMap('assets'), uniqBy('assetType'), map('assetType'))(vault.wallets) + + for (const anchorageWallet of vault.wallets) { + const existingAccount = existingAccountMap.get(anchorageWallet.walletId) + const accountId = existingAccount?.accountId || randomUUID() + const network = await this.networkRepository.findByExternalId(Provider.ANCHORAGE, anchorageWallet.networkId) + + if (network) { + if (existingAccount) { + // Check if account needs update + if (existingAccount.label !== anchorageWallet.walletName) { + accountOperations.push({ + type: ScopedSyncOperationType.UPDATE, + update: { + clientId: connection.clientId, + accountId: existingAccount.accountId, + label: anchorageWallet.walletName, + updatedAt: now + } + }) + } + } else { + accountOperations.push({ + type: ScopedSyncOperationType.CREATE, + create: { + externalId: anchorageWallet.walletId, + accountId, + addresses: [], + clientId: connection.clientId, + connectionId: connection.connectionId, + createdAt: now, + label: anchorageWallet.walletName, + networkId: network.networkId, + provider: Provider.ANCHORAGE, + updatedAt: now, + walletId + } + }) + } + } else { + accountOperations.push({ + type: ScopedSyncOperationType.FAILED, + externalId: anchorageWallet.walletId, + message: 'Unknown Anchorage wallet network ID', + context: { + externalId: anchorageWallet.walletId, + anchorageNetworkId: anchorageWallet.networkId + } + }) + } + } + + // Process addresses - Anchorage only creates, no updates + for (const assetType of vaultAssetTypes) { + const addresses = await this.anchorageClient.getVaultAddresses({ + signKey: connection.credentials.privateKey, + apiKey: connection.credentials.apiKey, + assetType, + url: connection.url, + vaultId: vault.id + }) + + for (const address of addresses) { + const account = flow( + filter((op: ScopedSyncOperation) => op.type === ScopedSyncOperationType.CREATE), + find((op: CreateScopedSyncOperation) => op.create.externalId === address.walletId) + )(accountOperations) + + const existingAccount = existingAccountMap.get(address.walletId) + const skipAddress = existingAccount?.addresses?.some((a) => a.externalId === address.addressId) + + const tiedAccount = account?.create?.accountId || existingAccount?.accountId + if (!skipAddress && tiedAccount) { + if (account?.create?.accountId || existingAccount?.accountId) { + addressOperations.push({ + type: ScopedSyncOperationType.CREATE, + create: { + accountId: tiedAccount, + address: address.address, + addressId: randomUUID(), + clientId: connection.clientId, + connectionId: connection.connectionId, + createdAt: now, + externalId: address.addressId, + provider: Provider.ANCHORAGE, + updatedAt: now + } + }) + } else { + addressOperations.push({ + type: ScopedSyncOperationType.FAILED, + externalId: address.addressId, + message: 'Unknown Anchorage wallet address', + context: { + externalId: address.addressId, + address: address.address, + walletId: address.walletId + } + }) + } + } + } + } + } + + return { + wallets: walletOperations, + accounts: accountOperations, + addresses: addressOperations + } + } +} diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage-sync.service.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage-sync.service.ts deleted file mode 100644 index 10f957412..000000000 --- a/apps/vault/src/broker/core/provider/anchorage/anchorage-sync.service.ts +++ /dev/null @@ -1,440 +0,0 @@ -import { LoggerService } from '@narval/nestjs-shared' -import { Injectable } from '@nestjs/common' -import { randomUUID } from 'crypto' -import { uniq } from 'lodash' -import { AnchorageClient } from '../../../http/client/anchorage.client' -import { UpdateAccount } from '../../../persistence/repository/account.repository' -import { NetworkRepository } from '../../../persistence/repository/network.repository' -import { AccountService } from '../../service/account.service' -import { AddressService } from '../../service/address.service' -import { KnownDestinationService } from '../../service/known-destination.service' -import { WalletService } from '../../service/wallet.service' -import { Connection, ConnectionWithCredentials } from '../../type/connection.type' -import { Account, Address, KnownDestination, Wallet } from '../../type/indexed-resources.type' -import { - Provider, - ProviderSyncService, - SyncContext, - SyncOperation, - SyncOperationType, - SyncResult, - isCreateOperation -} from '../../type/provider.type' -import { buildEmptyContext } from '../../util/provider-sync.util' -import { validateConnection } from './anchorage.util' - -@Injectable() -export class AnchorageSyncService implements ProviderSyncService { - constructor( - private readonly anchorageClient: AnchorageClient, - private readonly walletService: WalletService, - private readonly accountService: AccountService, - private readonly addressService: AddressService, - private readonly knownDestinationService: KnownDestinationService, - private readonly networkRepository: NetworkRepository, - private readonly logger: LoggerService - ) {} - - async sync(connection: ConnectionWithCredentials): Promise { - const initialContext = buildEmptyContext({ connection, now: new Date() }) - const syncWalletContext = await this.syncWallets(initialContext) - const syncAccountContext = await this.syncAccounts(syncWalletContext) - const syncAddressContext = await this.syncAddresses(syncAccountContext) - const lastSyncContext = await this.syncKnownDestinations(syncAddressContext) - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { connection: _conn, ...result } = lastSyncContext - - return result - } - - async syncWallets(context: SyncContext): Promise { - const { connection } = context - - this.logger.log('Sync Anchorage wallets', { - connectionId: connection.connectionId, - clientId: connection.clientId, - url: connection.url - }) - - validateConnection(connection) - - const anchorageVaults = await this.anchorageClient.getVaults({ - url: connection.url, - apiKey: connection.credentials.apiKey, - signKey: connection.credentials.privateKey - }) - - const { data: existingWallets } = await this.walletService.findAll(connection.clientId, { - filters: { - externalIds: anchorageVaults.map((vault) => vault.vaultId) - }, - pagination: { disabled: true } - }) - - const existingWalletByExternalId = new Map( - existingWallets.map((wallet) => [wallet.externalId, wallet]) - ) - - const missingAnchorageVaults = anchorageVaults.filter( - (anchorageVault) => !existingWalletByExternalId.has(anchorageVault.vaultId) - ) - - const now = context.now ?? new Date() - - const createOperations = missingAnchorageVaults.map((vault) => { - return { - type: SyncOperationType.CREATE, - create: { - accounts: [], - clientId: connection.clientId, - connections: [Connection.parse(connection)], - createdAt: now, - externalId: vault.vaultId, - label: vault.name, - provider: Provider.ANCHORAGE, - updatedAt: now, - walletId: randomUUID() - } - } - }) - - const updateOperations = anchorageVaults - .reduce((acc, incoming) => { - const existing = existingWalletByExternalId.get(incoming.vaultId) - if (!existing) return acc - - const hasConnection = existing.connections.some((conn) => conn.connectionId === connection.connectionId) - const hasDataChanges = existing.label !== incoming.name - - if (hasDataChanges || !hasConnection) { - acc.push({ - ...existing, - label: incoming.name, - updatedAt: now, - connections: [...existing.connections, Connection.parse(connection)] - }) - } - - return acc - }, []) - .map((update) => ({ type: SyncOperationType.UPDATE, update })) - - return { - ...context, - wallets: [...createOperations, ...updateOperations] - } - } - - async syncAccounts(context: SyncContext): Promise { - const { connection } = context - - this.logger.log('Sync Anchorage accounts', { - connectionId: connection.connectionId, - clientId: connection.clientId, - url: connection.url - }) - - validateConnection(connection) - - const anchorageWallets = await this.anchorageClient.getWallets({ - url: connection.url, - apiKey: connection.credentials.apiKey, - signKey: connection.credentials.privateKey - }) - - const walletExternalIds = uniq(anchorageWallets.map(({ vaultId }) => vaultId)) - - const { data: existingWallets } = await this.walletService.findAll(connection.clientId, { - filters: { - externalIds: walletExternalIds - }, - pagination: { disabled: true } - }) - - const { data: existingAccounts } = await this.accountService.findAll(connection.clientId, { - filters: { - externalIds: uniq(anchorageWallets.map((wallet) => wallet.walletId)) - }, - pagination: { disabled: true } - }) - - const existingAccountsByExternalId = new Map(existingAccounts.map((account) => [account.externalId, account])) - - const missingAnchorageWallets = anchorageWallets.filter( - (anchorageVault) => !existingAccountsByExternalId.has(anchorageVault.walletId) - ) - - const walletsIndexedByExternalId = existingWallets.reduce( - (idx, wallet) => idx.set(wallet.externalId, wallet), - new Map() - ) - - const contextWalletsIndexedByExternalId = new Map( - context.wallets.filter(isCreateOperation).map(({ create }) => [create.externalId, create]) - ) - - const now = context.now ?? new Date() - - const operations: SyncOperation[] = [] - - for (const anchorageWallet of missingAnchorageWallets) { - const externalId = anchorageWallet.walletId - const parentExternalId = anchorageWallet.vaultId - // Either look up the existing wallets in the database or in the sync context. - const wallet = - contextWalletsIndexedByExternalId.get(parentExternalId) || walletsIndexedByExternalId.get(parentExternalId) - - if (wallet) { - const network = await this.networkRepository.findByExternalId(Provider.ANCHORAGE, anchorageWallet.networkId) - - if (network) { - operations.push({ - type: SyncOperationType.CREATE, - create: { - externalId, - accountId: randomUUID(), - addresses: [], - clientId: connection.clientId, - createdAt: now, - label: anchorageWallet.walletName, - networkId: network.networkId, - provider: Provider.ANCHORAGE, - updatedAt: now, - walletId: wallet.walletId - } - }) - } else { - operations.push({ - type: SyncOperationType.SKIP, - externalId, - message: 'Unknown Anchorage wallet network ID', - context: { - externalId, - anchorageNetworkId: anchorageWallet.networkId - } - }) - } - } else { - operations.push({ - type: SyncOperationType.FAILED, - externalId, - message: 'Parent wallet for account not found', - context: { anchorageWalletId: parentExternalId } - }) - } - } - - return { - ...context, - accounts: operations - } - } - - async syncAddresses(context: SyncContext): Promise { - const { connection } = context - - this.logger.log('Sync Anchorage addresses', { - connectionId: connection.connectionId, - clientId: connection.clientId, - url: connection.url - }) - - validateConnection(connection) - - const now = context.now || new Date() - - const signKey = connection.credentials.privateKey - - const anchorageVaults = await this.anchorageClient.getVaults({ - url: connection.url, - apiKey: connection.credentials.apiKey, - signKey - }) - - const getVaultAddressesRequests = anchorageVaults.flatMap((anchorageVault) => - anchorageVault.assets.map((asset) => ({ - signKey, - apiKey: connection.credentials.apiKey, - assetType: asset.assetType, - url: connection.url, - vaultId: anchorageVault.vaultId - })) - ) - - const anchorageAddresses = ( - await Promise.all(getVaultAddressesRequests.map((request) => this.anchorageClient.getVaultAddresses(request))) - ).flat() - - // Query existing accounts to associate them with their children addresses. - const { data: existingAccounts } = await this.accountService.findAll(connection.clientId, { - filters: { - externalIds: anchorageAddresses.map((anchorageAddress) => anchorageAddress.walletId) - } - }) - - const existingAccountsByExternalId = new Map(existingAccounts.map((account) => [account.externalId, account])) - - const { data: existingAddresses } = await this.addressService.findAll(connection.clientId, { - filters: { - externalIds: anchorageAddresses.map((anchorageAddress) => anchorageAddress.addressId) - } - }) - - const existingAddressesByExternalId = new Map(existingAddresses.map((address) => [address.externalId, address])) - - const contextAccountsIndexedByExternalId = new Map( - context.accounts.filter(isCreateOperation).map(({ create }) => [create.externalId, create]) - ) - - const uniqueAnchorageAddresses = Array.from( - new Map(anchorageAddresses.map((anchorageAddress) => [anchorageAddress.addressId, anchorageAddress])).values() - ) - - const missingAnchorageAddresses = uniqueAnchorageAddresses.filter( - (anchorageAddress) => !existingAddressesByExternalId.has(anchorageAddress.addressId) - ) - - const operations = missingAnchorageAddresses.map((anchorageAddress) => { - const externalId = anchorageAddress.addressId - const parentExternalId = anchorageAddress.walletId - const account = - existingAccountsByExternalId.get(parentExternalId) || contextAccountsIndexedByExternalId.get(parentExternalId) - - if (account) { - return { - type: SyncOperationType.CREATE, - create: { - accountId: account.accountId, - address: anchorageAddress.address, - addressId: randomUUID(), - clientId: connection.clientId, - createdAt: now, - externalId, - provider: Provider.ANCHORAGE, - updatedAt: now - } satisfies Address - } - } - - return { - type: SyncOperationType.FAILED, - externalId, - message: 'Anchorage address parent account not found' - } - }) - - return { - ...context, - addresses: operations - } - } - - async syncKnownDestinations(context: SyncContext): Promise { - const { connection } = context - - this.logger.log('Sync Anchorage known destinations', { - connectionId: connection.connectionId, - clientId: connection.clientId, - url: connection.url - }) - - validateConnection(connection) - - // Fetch current state from Anchorage - const anchorageTrustedDestinations = await this.anchorageClient.getTrustedDestinations({ - url: connection.url, - apiKey: connection.credentials.apiKey, - signKey: connection.credentials.privateKey - }) - - const now = context.now || new Date() - - const { data: existingKnownDestinations } = await this.knownDestinationService.findAll(connection.clientId, { - pagination: { disabled: true } - }) - - const incomingMap = new Map(anchorageTrustedDestinations.map((dest) => [dest.id, dest])) - const existingMap = new Map(existingKnownDestinations.map((dest) => [dest.externalId, dest])) - - // TODO: Review this before merge. - // 1. the parse on acc.push - // 2. the error handling on `.parse` - const updateOperations = anchorageTrustedDestinations - .reduce((acc, incoming) => { - const existing = existingMap.get(incoming.id) - if (!existing) return acc - - const hasConnection = existing.connections.some((conn) => conn.connectionId === connection.connectionId) - const hasDataChanges = - (existing.label || undefined) !== incoming.crypto.memo || - (existing.assetId || undefined) !== incoming.crypto.assetType - - if (hasDataChanges || !hasConnection) { - acc.push( - KnownDestination.parse({ - ...existing, - label: incoming.crypto.memo, - assetId: incoming.crypto.assetType, - updatedAt: now, - connections: [...existing.connections, connection] - }) - ) - } - - return acc - }, []) - .map((update) => ({ type: SyncOperationType.UPDATE, update })) - - const missingDestinations = anchorageTrustedDestinations.filter( - (anchorageTrustedAddress) => !existingMap.has(anchorageTrustedAddress.id) - ) - - const createOperations: SyncOperation[] = [] - - for (const anchorageTrustedAddress of missingDestinations) { - const externalId = anchorageTrustedAddress.id - const network = await this.networkRepository.findByExternalId( - Provider.ANCHORAGE, - anchorageTrustedAddress.crypto.networkId - ) - - if (network) { - const knownDestination = KnownDestination.parse({ - externalId, - knownDestinationId: randomUUID(), - address: anchorageTrustedAddress.crypto.address, - clientId: connection.clientId, - label: anchorageTrustedAddress.crypto.memo, - assetId: anchorageTrustedAddress.crypto.assetType, - provider: Provider.ANCHORAGE, - networkId: network.networkId, - createdAt: now, - updatedAt: now, - connections: [connection] - }) - - createOperations.push({ type: SyncOperationType.CREATE, create: knownDestination }) - } else { - createOperations.push({ - type: SyncOperationType.SKIP, - externalId, - message: 'Unknown Anchorage trusted address network ID', - context: { - externalId, - anchorageNetworkId: anchorageTrustedAddress.crypto.networkId - } - }) - } - } - - const deleteOperations = existingKnownDestinations - .filter((dest) => !incomingMap.has(dest.externalId)) - .map((kd) => ({ type: SyncOperationType.DELETE, entityId: kd.knownDestinationId })) - - return { - ...context, - knownDestinations: [...createOperations, ...updateOperations, ...deleteOperations] - } - } -} diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts index 020be6ab3..393ebb9ea 100644 --- a/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage-transfer.service.ts @@ -2,14 +2,17 @@ import { LoggerService } from '@narval/nestjs-shared' import { HttpStatus, Injectable } from '@nestjs/common' import { v4 as uuid } from 'uuid' import { AnchorageClient } from '../../../http/client/anchorage.client' -import { NetworkRepository } from '../../../persistence/repository/network.repository' import { TransferRepository } from '../../../persistence/repository/transfer.repository' +import { AssetException } from '../../exception/asset.exception' import { BrokerException } from '../../exception/broker.exception' import { AccountService } from '../../service/account.service' -import { AssetService } from '../../service/asset.service' +import { NetworkService } from '../../service/network.service' +import { ResolvedTransferAsset, TransferAssetService } from '../../service/transfer-asset.service' import { WalletService } from '../../service/wallet.service' import { ConnectionWithCredentials } from '../../type/connection.type' +import { Network } from '../../type/network.type' import { Provider, ProviderTransferService } from '../../type/provider.type' +import { ConnectionScope } from '../../type/scope.type' import { Destination, InternalTransfer, @@ -17,23 +20,24 @@ import { SendTransfer, Source, Transfer, + TransferAsset, TransferPartyType, TransferStatus, isAddressDestination, isProviderSpecific } from '../../type/transfer.type' -import { getExternalAsset } from '../../util/asset.util' -import { transferPartyTypeToAnchorageResourceType, validateConnection } from './anchorage.util' +import { getExternalNetwork } from '../../util/network.util' +import { ValidConnection, transferPartyTypeToAnchorageResourceType, validateConnection } from './anchorage.util' @Injectable() export class AnchorageTransferService implements ProviderTransferService { constructor( private readonly anchorageClient: AnchorageClient, - private readonly assetService: AssetService, - private readonly networkRepository: NetworkRepository, + private readonly networkService: NetworkService, private readonly accountService: AccountService, private readonly walletService: WalletService, private readonly transferRepository: TransferRepository, + private readonly transferAssetService: TransferAssetService, private readonly logger: LoggerService ) {} @@ -60,6 +64,8 @@ export class AnchorageTransferService implements ProviderTransferService { this.logger.log('Found remote transfer by external ID', { ...context, anchorageTransfer }) const transfer = { + connectionId, + assetExternalId: internalTransfer.assetExternalId, assetId: internalTransfer.assetId, clientId: internalTransfer.clientId, createdAt: new Date(anchorageTransfer.createdAt), @@ -121,8 +127,8 @@ export class AnchorageTransferService implements ProviderTransferService { validateConnection(connection) - const asset = await this.assetService.findTransferAsset(Provider.ANCHORAGE, sendTransfer.asset) - if (!asset) { + const transferAsset = await this.findTransferAsset(connection, sendTransfer.asset) + if (!transferAsset) { throw new BrokerException({ message: 'Transfer asset not found', suggestedHttpStatusCode: HttpStatus.NOT_FOUND, @@ -130,27 +136,9 @@ export class AnchorageTransferService implements ProviderTransferService { }) } - const externalAsset = getExternalAsset(asset, Provider.ANCHORAGE) - if (!externalAsset) { - throw new BrokerException({ - message: 'Unsupported asset by Anchorage', - suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, - context: { asset } - }) - } - - const network = await this.networkRepository.findById(asset.networkId) - if (!network) { - throw new BrokerException({ - message: 'Cannot find asset network', - suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, - context: { asset } - }) - } - - const source = await this.getSource(clientId, sendTransfer.source) + const source = await this.getSource(connection, sendTransfer.source) - const destination = await this.getDestination(clientId, sendTransfer.destination) + const destination = await this.getDestination(connection, sendTransfer.destination) this.logger.log('Resolved Anchorage transfer source and destination', { ...context, source, destination }) @@ -162,7 +150,7 @@ export class AnchorageTransferService implements ProviderTransferService { const data = { source, destination, - assetType: externalAsset.externalId, + assetType: transferAsset.assetExternalId, amount: sendTransfer.amount, transferMemo: sendTransfer.memo || null, idempotentId: sendTransfer.idempotenceId, @@ -182,7 +170,8 @@ export class AnchorageTransferService implements ProviderTransferService { this.logger.log('Anchorage transfer created', context) const internalTransfer: InternalTransfer = { - assetId: asset.assetId, + assetId: transferAsset.assetId, + assetExternalId: transferAsset.assetExternalId, clientId: clientId, createdAt: new Date(), customerRefId: null, @@ -191,6 +180,7 @@ export class AnchorageTransferService implements ProviderTransferService { externalStatus: anchorageTransfer.status, grossAmount: sendTransfer.amount, idempotenceId: sendTransfer.idempotenceId, + connectionId, memo: sendTransfer.memo || null, networkFeeAttribution, provider: Provider.ANCHORAGE, @@ -231,9 +221,9 @@ export class AnchorageTransferService implements ProviderTransferService { return false } - private async getSource(clientId: string, source: Source) { + private async getSource(scope: ConnectionScope, source: Source) { if (source.type === TransferPartyType.WALLET) { - const wallet = await this.walletService.findById(clientId, source.id) + const wallet = await this.walletService.findById(scope, source.id) return { type: transferPartyTypeToAnchorageResourceType(source.type), @@ -242,7 +232,7 @@ export class AnchorageTransferService implements ProviderTransferService { } if (source.type === TransferPartyType.ACCOUNT) { - const wallet = await this.accountService.findById(clientId, source.id) + const wallet = await this.accountService.findById(scope, source.id) return { type: transferPartyTypeToAnchorageResourceType(source.type), @@ -253,11 +243,11 @@ export class AnchorageTransferService implements ProviderTransferService { throw new BrokerException({ message: 'Cannot resolve Anchorage transfer source', suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, - context: { clientId, source } + context: { scope, source } }) } - private async getDestination(clientId: string, destination: Destination) { + private async getDestination(scope: ConnectionScope, destination: Destination) { if (isAddressDestination(destination)) { // IMPORTANT: For both known and unknown addresses, we pass them directly // to Anchorage without validating their existence on our side. If the @@ -270,7 +260,7 @@ export class AnchorageTransferService implements ProviderTransferService { } if (destination.type === TransferPartyType.WALLET) { - const wallet = await this.walletService.findById(clientId, destination.id) + const wallet = await this.walletService.findById(scope, destination.id) return { type: transferPartyTypeToAnchorageResourceType(destination.type), @@ -279,7 +269,7 @@ export class AnchorageTransferService implements ProviderTransferService { } if (destination.type === TransferPartyType.ACCOUNT) { - const account = await this.accountService.findById(clientId, destination.id) + const account = await this.accountService.findById(scope, destination.id) return { type: transferPartyTypeToAnchorageResourceType(destination.type), @@ -290,7 +280,89 @@ export class AnchorageTransferService implements ProviderTransferService { throw new BrokerException({ message: 'Cannot resolve Anchorage transfer destination', suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, - context: { clientId, destination } + context: { scope, destination } + }) + } + + private async findTransferAsset( + connection: ValidConnection, + transferAsset: TransferAsset + ): Promise { + const findByExternalIdFallback = async (externalAssetId: string): Promise => { + const anchorageAssetTypes = await this.anchorageClient.getAssetTypes({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey + }) + + const anchorageAssetType = anchorageAssetTypes.find( + ({ assetType }) => assetType.toLowerCase() === externalAssetId.toLowerCase() + ) + if (!anchorageAssetType) { + throw new AssetException({ + message: 'Anchorage asset type not found', + suggestedHttpStatusCode: HttpStatus.NOT_FOUND, + context: { transferAsset } + }) + } + + const network = await this.networkService.findByExternalId(Provider.ANCHORAGE, anchorageAssetType.networkId) + if (!network) { + throw new AssetException({ + message: 'Anchorage asset type network not found', + suggestedHttpStatusCode: HttpStatus.NOT_FOUND, + context: { transferAsset, anchorageAssetType } + }) + } + + return { + network, + assetExternalId: externalAssetId, + assetId: null + } + } + + const findByOnchainIdFallback = async (network: Network, onchainId: string): Promise => { + const externalNetwork = getExternalNetwork(network, Provider.ANCHORAGE) + if (!externalNetwork) { + throw new AssetException({ + message: 'Network does not support Anchorage', + suggestedHttpStatusCode: HttpStatus.NOT_IMPLEMENTED, + context: { transferAsset, network } + }) + } + + const anchorageAssetTypes = await this.anchorageClient.getAssetTypes({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey + }) + + const anchorageAssetType = anchorageAssetTypes.find( + ({ onchainIdentifier, networkId }) => + onchainIdentifier?.toLowerCase() === onchainId.toLowerCase() && + networkId.toLowerCase() === externalNetwork.externalId.toLowerCase() + ) + if (!anchorageAssetType) { + throw new AssetException({ + message: 'Anchorage asset type not found', + suggestedHttpStatusCode: HttpStatus.NOT_FOUND, + context: { transferAsset } + }) + } + + return { + network, + assetId: null, + assetExternalId: anchorageAssetType.assetType + } + } + + return this.transferAssetService.resolve({ + findByExternalIdFallback, + findByOnchainIdFallback, + transferAsset, + provider: Provider.ANCHORAGE }) } } diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage.util.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage.util.ts index 42bc84ed4..5703365af 100644 --- a/apps/vault/src/broker/core/provider/anchorage/anchorage.util.ts +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage.util.ts @@ -7,15 +7,19 @@ import { Provider } from '../../type/provider.type' import { TransferPartyType } from '../../type/transfer.type' import { AnchorageCredentials, AnchorageResourceType } from './anchorage.type' -export function validateConnection( - connection: ConnectionWithCredentials -): asserts connection is ConnectionWithCredentials & { +export const CONCURRENT_ANCHORAGE_REQUESTS = 5 + +export type ValidConnection = { url: string credentials: { apiKey: string privateKey: Ed25519PrivateKey } -} { +} + +export function validateConnection( + connection: ConnectionWithCredentials +): asserts connection is ConnectionWithCredentials & ValidConnection { const context = { clientId: connection.clientId, connectionId: connection.connectionId, diff --git a/apps/vault/src/broker/core/provider/bitgo/__test__/unit/bitgo-credential.service.spec.ts b/apps/vault/src/broker/core/provider/bitgo/__test__/unit/bitgo-credential.service.spec.ts new file mode 100644 index 000000000..7bd7e87ff --- /dev/null +++ b/apps/vault/src/broker/core/provider/bitgo/__test__/unit/bitgo-credential.service.spec.ts @@ -0,0 +1,81 @@ +import { Test } from '@nestjs/testing' +import '../../../../../shared/__test__/matcher' +import { ConnectionInvalidCredentialsException } from '../../../../exception/connection-invalid-credentials.exception' +import { BitgoCredentialService } from '../../bitgo-credential.service' +import { BitgoCredentials, BitgoInputCredentials } from '../../bitgo.type' + +describe(BitgoCredentialService.name, () => { + let service: BitgoCredentialService + + beforeEach(async () => { + const module = await Test.createTestingModule({ + providers: [BitgoCredentialService] + }).compile() + + service = module.get(BitgoCredentialService) + }) + + describe('parse', () => { + it('validates and parses raw credentials into typed BitgoCredentials', async () => { + const validCredentials: BitgoCredentials = { + apiKey: 'test-api-key', + walletPassphrase: 'test-wallet-passphrase' + } + + const result = service.parse(validCredentials) + expect(result).toStrictEqual(validCredentials) + }) + + it('handles everything being undefined', () => { + const invalidCredentials = {} + + expect(() => service.parse(invalidCredentials)).not.toThrow() + }) + }) + + describe('build', () => { + it('transforms input credentials into provider-ready format', async () => { + const input: BitgoInputCredentials = { + apiKey: 'test-api-key', + walletPassphrase: 'test-wallet-passphrase' + } + + const credentials = await service.build(input) + + expect(credentials).toEqual({ + apiKey: input.apiKey, + walletPassphrase: input.walletPassphrase + }) + }) + + it('accepts undefined walletPassphrase', async () => { + const input: BitgoInputCredentials = { + apiKey: 'test-api-key' + } + + const credentials = await service.build(input) + + expect(credentials).toEqual({ + apiKey: input.apiKey + }) + }) + + it('throws error when input api key is undefined', async () => { + const input = { + apiKey: undefined + } + + await expect(service.build(input as unknown as BitgoInputCredentials)).rejects.toThrow( + ConnectionInvalidCredentialsException + ) + }) + }) + + describe('generate', () => { + it('is a noop & returns empty object', async () => { + const credentials = await service.generate() + + expect(credentials).toEqual({}) + }) + }) +}) diff --git a/apps/vault/src/broker/core/provider/bitgo/bitgo-credential.service.ts b/apps/vault/src/broker/core/provider/bitgo/bitgo-credential.service.ts new file mode 100644 index 000000000..9b8baf8a8 --- /dev/null +++ b/apps/vault/src/broker/core/provider/bitgo/bitgo-credential.service.ts @@ -0,0 +1,44 @@ +import { Injectable } from '@nestjs/common' +import { ParseException } from '../../../../shared/module/persistence/exception/parse.exception' +import { ConnectionInvalidCredentialsException } from '../../exception/connection-invalid-credentials.exception' +import { ProviderCredentialService } from '../../type/provider.type' +import { BitgoCredentials, BitgoInputCredentials } from './bitgo.type' + +@Injectable() +export class BitgoCredentialService implements ProviderCredentialService { + parse(value: unknown): BitgoCredentials { + const parse = BitgoCredentials.safeParse(value) + + if (parse.success) { + return parse.data + } + + throw new ParseException(parse.error) + } + + parseInput(value: unknown): BitgoInputCredentials { + const parse = BitgoInputCredentials.safeParse(value) + + if (parse.success) { + return parse.data + } + + throw new ParseException(parse.error) + } + + async build(input: BitgoInputCredentials): Promise { + if (input.apiKey) { + return { + apiKey: input.apiKey, + walletPassphrase: input.walletPassphrase + } + } + + throw new ConnectionInvalidCredentialsException() + } + + async generate(): Promise { + // noop, you can't generate bitgo credentials + return {} + } +} diff --git a/apps/vault/src/broker/core/provider/bitgo/bitgo.type.ts b/apps/vault/src/broker/core/provider/bitgo/bitgo.type.ts new file mode 100644 index 000000000..6f8e0be7e --- /dev/null +++ b/apps/vault/src/broker/core/provider/bitgo/bitgo.type.ts @@ -0,0 +1,13 @@ +import { z } from 'zod' + +export const BitgoInputCredentials = z.object({ + apiKey: z.string(), + walletPassphrase: z.string().optional() +}) +export type BitgoInputCredentials = z.infer + +export const BitgoCredentials = z.object({ + apiKey: z.string().optional(), + walletPassphrase: z.string().optional() +}) +export type BitgoCredentials = z.infer diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-scoped-sync.service.spec.ts b/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-scoped-sync.service.spec.ts new file mode 100644 index 000000000..ae5d81f90 --- /dev/null +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-scoped-sync.service.spec.ts @@ -0,0 +1,227 @@ +import { EncryptionModuleOptionProvider } from '@narval/encryption-module' +import { LoggerModule } from '@narval/nestjs-shared' +import { INestApplication } from '@nestjs/common' +import { EventEmitter2 } from '@nestjs/event-emitter' +import { Test, TestingModule } from '@nestjs/testing' +import { mock } from 'jest-mock-extended' +import { v4 as uuid } from 'uuid' +import { ClientService } from '../../../../../../client/core/service/client.service' +import { MainModule } from '../../../../../../main.module' +import { ProvisionService } from '../../../../../../provision.service' +import { KeyValueRepository } from '../../../../../../shared/module/key-value/core/repository/key-value.repository' +import { InMemoryKeyValueRepository } from '../../../../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' +import { TestPrismaService } from '../../../../../../shared/module/persistence/service/test-prisma.service' +import { getTestRawAesKeyring } from '../../../../../../shared/testing/encryption.testing' +import { testClient } from '../../../../../__test__/util/mock-data' +import { NetworkSeed } from '../../../../../persistence/seed/network.seed' +import { setupMockServer } from '../../../../../shared/__test__/mock-server' +import { AccountService } from '../../../../service/account.service' +import { AddressService } from '../../../../service/address.service' +import { ConnectionService } from '../../../../service/connection.service' +import { WalletService } from '../../../../service/wallet.service' +import { ConnectionWithCredentials } from '../../../../type/connection.type' +import { Provider, isCreateOperation } from '../../../../type/provider.type' +import { FIREBLOCKS_TEST_API_BASE_URL, getHandlers } from '../../../fireblocks/__test__/server-mock/server' +import { FireblocksScopedSyncService } from '../../fireblocks-scoped-sync.service' +import { getFireblocksAssetWalletExternalId } from '../../fireblocks.util' + +describe(FireblocksScopedSyncService.name, () => { + let app: INestApplication + let module: TestingModule + + let fireblocksScopedSyncService: FireblocksScopedSyncService + let clientService: ClientService + let connection: ConnectionWithCredentials + let walletService: WalletService + let accountService: AccountService + let addressService: AddressService + let connectionService: ConnectionService + let networkSeed: NetworkSeed + let provisionService: ProvisionService + let testPrismaService: TestPrismaService + + const mockServer = setupMockServer(getHandlers()) + + const privateKeyPem = `-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDVORyUbWt/yuW4 +29mXtJBC3PEisQN3BQhtKp6jHa89YeWBct43g6tUTwcvdj7HXJOmp1FLbbPzE/pe +HMHtlx2ZTHIcz2nU4c4k6PiN//xGHze7aY8e3G+tVSJLQKRBFXiXWuUjDM5/OYWj +YwCjJptulOjzU6zwc/LW0KNBYQb4VuElJeV2mp17YOwUaLxyR+1I2+6aN5wCK8+M +VHHbo5y4nSNUClK0TdAWP3ZKu6DKZveKCmbY5X3V/mVS52LgvFlVHrSLMUQUkH1Y +ob4vBcw4QT7lAcyo4YKno1Q8mZKNivkWMpw+6R3c2hjPzHdiqYjPkPiMPDC6hJGi +7rh2iG3jAgMBAAECggEAB7wyKrpLd4/bRJkJLEU7JInSX6FPUF6I3zj4F0/I3y+x +fUA3ComGyiCx0Il4HpBftOCGBPf+WrejUg22BVIBm2GYFC58FuJ4MYOYHMKoGr0g +LvbV39c8X+viOhumucu3G7qK7HoW9auXCwXY7JJGej0BtG4ZLIHwUdWwznrgH1sq +ig/mdHy3SWVl0/c7PbLaD+IoHLqVmGgq4ylDdRyNfbvjLFzDptaois0kfZ0JMTF8 ++l0n30ib3Vmv1T/sZaLKj33LY7moQHk/FYp4uAP/5CAfSJQaUWQDDrc3WN7LwE0o +ALeIfAN2KltEcTouCDgBqTD5y72c6IsAIyDlkOxX/QKBgQDysS48botXSH3dF8/2 +gxRhVqYYGx2mU6pqQDOQk8z0Cg5qjs5H7U+xSX1vyaGNfPLKrMXLjJSDKtKT5TN1 +sHXHKjL88I5gGODf4vJncCD7m5wTt1JPzm4mIVZcLILmD3buAn8qMXz64i4tus1e +heVJZBUt360B/iEsJtlS7WsZLwKBgQDg6kGT/jBa6hP5JKVZWbyk5tOxCZsHSaNx +iXzSmKX6bld+b9qlxBsZGOs74lSeSaps8pLO0+Hy+WRvnJF0UNPSJpNT8ppHaHBn +KPWtX1yPj+JWqHLSx5JgsxCAiHSAHpRcR0Yh77WpAHCAstYm+pa2tCZ1sbzSOa3j +jz8L3FuhjQKBgBYTCZqTj3cD7/bROKg6afskj3z30m2ThJefeVE4MFcuJvuIO7kN +G8eLYK5vT5N3/vlyV5dZFRUNKxQqr9CPmVbhPrwFAV46RRH4KYZBC673C247qW/6 +3cf4FkvR/KICXBXwAjMLR0vmkL62FAH5+c4AHXELvEfHHqtOaUwCrlAfAoGBAJ9u +br3xWWWYuD/Lcko8CjT6SuUb4gDweiNpSkoeWsmCnhLKRztqH6tStqzkawcpQN2p +tddW6rvJfSCA47qH8R7uqVDAkAw+RC9cIYqcJoi9fbvf/ETdoy1YwUHbeHm5M4GW +JGi5+xOpdBZGrvdCesNYQEr9itOaf2DnkdFeirWhAoGAMlyskZWy2EW9T4tJgxVz +474FlWrtmVZNXMHO8pgd++JrR8Tgb1maoxENNsIxcWwMRgGLL0FA7sGf+wcxQjHT +l6Yb3VB/SnVMOOLTsE1SvCywjJ8vl8tEmbCoTFlDCJHh+IEB5a2NC4403tL7yPWS +iYDlTZ/pWsEotE2yCl/8krs= +-----END PRIVATE KEY-----` + + const privateKey = Buffer.from(privateKeyPem).toString('base64') + + const clientId = 'test-client-id' + + beforeAll(async () => { + module = await Test.createTestingModule({ + imports: [MainModule] + }) + .overrideModule(LoggerModule) + .useModule(LoggerModule.forTest()) + .overrideProvider(KeyValueRepository) + .useValue(new InMemoryKeyValueRepository()) + .overrideProvider(EncryptionModuleOptionProvider) + .useValue({ + keyring: getTestRawAesKeyring() + }) + // Mock the event emitter because we don't want to send a + // connection.activated event after the creation. + .overrideProvider(EventEmitter2) + .useValue(mock()) + .compile() + + app = module.createNestApplication() + + testPrismaService = module.get(TestPrismaService) + fireblocksScopedSyncService = module.get(FireblocksScopedSyncService) + connectionService = module.get(ConnectionService) + walletService = module.get(WalletService) + accountService = module.get(AccountService) + addressService = module.get(AddressService) + provisionService = module.get(ProvisionService) + networkSeed = module.get(NetworkSeed) + clientService = module.get(ClientService) + + await testPrismaService.truncateAll() + }) + + afterAll(async () => { + await testPrismaService.truncateAll() + await module.close() + await app.close() + }) + + beforeEach(async () => { + await testPrismaService.truncateAll() + + await provisionService.provision() + await clientService.save(testClient) + + connection = await connectionService.create(clientId, { + connectionId: uuid(), + provider: Provider.FIREBLOCKS, + url: FIREBLOCKS_TEST_API_BASE_URL, + label: 'test active connection', + credentials: { + apiKey: 'test-api-key', + privateKey + } + }) + + await networkSeed.seed() + + await app.init() + }) + + describe('scoped-syncs', () => { + it('returns scoped sync operations for wallets, accounts and addresses based on an fireblocks wallet externalId', async () => { + const rawAccounts = [ + { + provider: Provider.FIREBLOCKS, + externalId: getFireblocksAssetWalletExternalId({ vaultId: '3', networkId: 'ETHEREUM' }) + } + ] + const sync = await fireblocksScopedSyncService.scopedSync(connection, rawAccounts) + + expect(sync.wallets.length).toBe(1) + expect(sync.accounts.length).toBe(1) + expect(sync.addresses.length).toBe(1) + }) + + it('returns empty array when no rawAccounts are provided', async () => { + const sync = await fireblocksScopedSyncService.scopedSync(connection, []) + + expect(sync.wallets.length).toBe(0) + expect(sync.accounts.length).toBe(0) + expect(sync.addresses.length).toBe(0) + }) + + it('returns empty array when no wallets are found for the provided rawAccounts', async () => { + const rawAccounts = [ + { + provider: Provider.FIREBLOCKS, + externalId: getFireblocksAssetWalletExternalId({ vaultId: 'notfound', networkId: 'ETHEREUM' }) + } + ] + const sync = await fireblocksScopedSyncService.scopedSync(connection, rawAccounts) + + expect(sync.wallets.length).toBe(0) + expect(sync.accounts.length).toBe(0) + expect(sync.addresses.length).toBe(0) + }) + + it('skips duplicate for the same connection', async () => { + const rawAccounts = [ + { + provider: Provider.FIREBLOCKS, + externalId: getFireblocksAssetWalletExternalId({ vaultId: '3', networkId: 'ETHEREUM' }) + } + ] + const firstSync = await fireblocksScopedSyncService.scopedSync(connection, rawAccounts) + + await walletService.bulkCreate(firstSync.wallets.filter(isCreateOperation).map(({ create }) => create)) + await accountService.bulkCreate(firstSync.accounts.filter(isCreateOperation).map(({ create }) => create)) + await addressService.bulkCreate(firstSync.addresses.filter(isCreateOperation).map(({ create }) => create)) + + const secondSync = await fireblocksScopedSyncService.scopedSync(connection, rawAccounts) + + expect(secondSync.wallets.length).toBe(0) + expect(secondSync.accounts.length).toBe(0) + expect(secondSync.addresses.length).toBe(0) + }) + + it('duplicates for different connections', async () => { + const rawAccounts = [ + { + provider: Provider.FIREBLOCKS, + externalId: getFireblocksAssetWalletExternalId({ vaultId: '3', networkId: 'ETHEREUM' }) + } + ] + const firstSync = await fireblocksScopedSyncService.scopedSync(connection, rawAccounts) + + await walletService.bulkCreate(firstSync.wallets.filter(isCreateOperation).map(({ create }) => create)) + await accountService.bulkCreate(firstSync.accounts.filter(isCreateOperation).map(({ create }) => create)) + await addressService.bulkCreate(firstSync.addresses.filter(isCreateOperation).map(({ create }) => create)) + + const secondConnection = await connectionService.create(clientId, { + connectionId: uuid(), + provider: Provider.FIREBLOCKS, + url: FIREBLOCKS_TEST_API_BASE_URL, + label: 'test active connection', + credentials: { + apiKey: 'test-api-key', + privateKey + } + }) + + const secondSync = await fireblocksScopedSyncService.scopedSync(secondConnection, rawAccounts) + + expect(secondSync.wallets.length).toBe(1) + expect(secondSync.accounts.length).toBe(1) + expect(secondSync.addresses.length).toBe(1) + }) + }) +}) diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-transfer.service.spec.ts b/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-transfer.service.spec.ts index 2b631f693..e5623281a 100644 --- a/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-transfer.service.spec.ts +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-transfer.service.spec.ts @@ -21,7 +21,7 @@ import { WalletRepository } from '../../../../../persistence/repository/wallet.r import { AssetSeed } from '../../../../../persistence/seed/asset.seed' import { NetworkSeed } from '../../../../../persistence/seed/network.seed' import { setupMockServer, useRequestSpy } from '../../../../../shared/__test__/mock-server' -import { Connection, ConnectionStatus, ConnectionWithCredentials } from '../../../../type/connection.type' +import { ConnectionStatus, ConnectionWithCredentials } from '../../../../type/connection.type' import { Account, Address, Wallet } from '../../../../type/indexed-resources.type' import { Provider } from '../../../../type/provider.type' import { @@ -94,6 +94,7 @@ describe(FireblocksTransferService.name, () => { clientId, createdAt: new Date(), externalId: randomUUID(), + connectionId: connection.connectionId, label: 'Account 1', networkId: 'POLYGON', provider: Provider.FIREBLOCKS, @@ -105,6 +106,7 @@ describe(FireblocksTransferService.name, () => { accountId: randomUUID(), addresses: [], clientId, + connectionId: connection.connectionId, createdAt: new Date(), externalId: randomUUID(), label: 'Account 2', @@ -116,7 +118,7 @@ describe(FireblocksTransferService.name, () => { const walletOne: Wallet = { clientId, - connections: [Connection.parse(connection)], + connectionId: connection.connectionId, createdAt: new Date(), externalId: randomUUID(), label: null, @@ -127,7 +129,7 @@ describe(FireblocksTransferService.name, () => { const walletTwo: Wallet = { clientId, - connections: [Connection.parse(connection)], + connectionId: connection.connectionId, createdAt: new Date(), externalId: randomUUID(), label: null, @@ -141,6 +143,7 @@ describe(FireblocksTransferService.name, () => { address: '0x2c4895215973cbbd778c32c456c074b99daf8bf1', addressId: randomUUID(), clientId, + connectionId: connection.connectionId, createdAt: new Date(), externalId: randomUUID(), provider: Provider.FIREBLOCKS, @@ -160,8 +163,10 @@ describe(FireblocksTransferService.name, () => { customerRefId: null, idempotenceId: null, externalId: randomUUID(), + connectionId: connection.connectionId, externalStatus: null, assetId: 'MATIC', + assetExternalId: null, memo: 'Test transfer', grossAmount: '0.00001', networkFeeAttribution: NetworkFeeAttribution.DEDUCT, diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-vault-account-3-200.json b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-vault-account-3-200.json new file mode 100644 index 000000000..82ad474b6 --- /dev/null +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-vault-account-3-200.json @@ -0,0 +1,405 @@ +{ + "id": "3", + "name": "dev-1", + "hiddenOnUI": false, + "customerRefId": "dev-guild-id-1", + "autoFuel": false, + "assets": [ + { + "id": "MATIC_POLYGON", + "total": "0.092436133514242454", + "balance": "0.092436133514242454", + "lockedAmount": "0", + "available": "0.092436133514242454", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "66650299", + "blockHash": "0x62c064832c4a2ff9cc1e00c236427015cda4f639fd03ed62b0e7374bf652807a" + }, + { + "id": "RBW_POLYGON_UZYB", + "total": "1.4", + "balance": "1.4", + "lockedAmount": "0", + "available": "1.4", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "48669610", + "blockHash": "0x9788f6b916527311e53c169f4ef0fafca6d10626862ee473a72144837ed0edc1" + }, + { + "id": "ETH", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "-1" + }, + { + "id": "ETH-AETH", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "117377373" + }, + { + "id": "AVAX", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "33392936" + }, + { + "id": "BNB_BSC", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "30498105" + }, + { + "id": "ETH-OPT", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "107685647" + }, + { + "id": "SGB", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "40869531" + }, + { + "id": "RBTC", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "5656136" + }, + { + "id": "FTM_FANTOM", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "68378879" + }, + { + "id": "GLMR_GLMR", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "4476463" + }, + { + "id": "MOVR_MOVR", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "5151851" + }, + { + "id": "BASECHAIN_ETH", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "4216404" + }, + { + "id": "CELO", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "23357363", + "blockHash": "0x69338c41b8c8a0d10e23356c1463065ebce05f6db554ffcb387eef4a666eca32" + }, + { + "id": "SMARTBCH", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "15805300" + }, + { + "id": "ASIANXT_BESU", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0" + }, + { + "id": "OAS", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "3669391" + }, + { + "id": "LINEA", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "6079647" + }, + { + "id": "SMR_SMR", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "5106465" + }, + { + "id": "ETH_ZKSYNC_ERA", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "37704404" + }, + { + "id": "FLR", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "26085228" + }, + { + "id": "EVMOS", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "21794920" + }, + { + "id": "RON", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "35909496" + }, + { + "id": "SX_NETWORK", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0" + }, + { + "id": "KAVA_KAVA", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "10496720" + }, + { + "id": "AURORA_DEV", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "119522841" + }, + { + "id": "CANTO", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "10283806" + }, + { + "id": "ASTR_ASTR", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "6486323" + }, + { + "id": "WEMIX", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "53327498" + }, + { + "id": "ETH_ZKEVM", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "13758502" + }, + { + "id": "XDAI", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0" + }, + { + "id": "BLAST", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "5376321" + }, + { + "id": "SEI", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "85852495" + }, + { + "id": "CORE_COREDAO", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "15420531" + }, + { + "id": "BTC", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "872488" + }, + { + "id": "USDC", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "21294609" + } + ] +} diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-vault-accounts-200.json b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-vault-accounts-200.json new file mode 100644 index 000000000..e948cbda5 --- /dev/null +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-vault-accounts-200.json @@ -0,0 +1,815 @@ +{ + "accounts": [ + { + "id": "3", + "name": "dev-1", + "hiddenOnUI": false, + "customerRefId": "dev-guild-id-1", + "autoFuel": false, + "assets": [ + { + "id": "MATIC_POLYGON", + "total": "0.092436133514242454", + "balance": "0.092436133514242454", + "lockedAmount": "0", + "available": "0.092436133514242454", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "66650299", + "blockHash": "0x62c064832c4a2ff9cc1e00c236427015cda4f639fd03ed62b0e7374bf652807a" + }, + { + "id": "RBW_POLYGON_UZYB", + "total": "1.4", + "balance": "1.4", + "lockedAmount": "0", + "available": "1.4", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "48669610", + "blockHash": "0x9788f6b916527311e53c169f4ef0fafca6d10626862ee473a72144837ed0edc1" + }, + { + "id": "ETH", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "-1" + }, + { + "id": "ETH-AETH", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "117377373" + }, + { + "id": "AVAX", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "33392936" + }, + { + "id": "BNB_BSC", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "30498105" + }, + { + "id": "ETH-OPT", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "107685647" + }, + { + "id": "SGB", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "40869531" + }, + { + "id": "RBTC", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "5656136" + }, + { + "id": "FTM_FANTOM", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "68378879" + }, + { + "id": "GLMR_GLMR", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "4476463" + }, + { + "id": "MOVR_MOVR", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "5151851" + }, + { + "id": "BASECHAIN_ETH", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "4216404" + }, + { + "id": "CELO", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "23357363", + "blockHash": "0x69338c41b8c8a0d10e23356c1463065ebce05f6db554ffcb387eef4a666eca32" + }, + { + "id": "SMARTBCH", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "15805300" + }, + { + "id": "ASIANXT_BESU", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0" + }, + { + "id": "OAS", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "3669391" + }, + { + "id": "LINEA", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "6079647" + }, + { + "id": "SMR_SMR", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "5106465" + }, + { + "id": "ETH_ZKSYNC_ERA", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "37704404" + }, + { + "id": "FLR", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "26085228" + }, + { + "id": "EVMOS", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "21794920" + }, + { + "id": "RON", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "35909496" + }, + { + "id": "SX_NETWORK", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0" + }, + { + "id": "KAVA_KAVA", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "10496720" + }, + { + "id": "AURORA_DEV", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "119522841" + }, + { + "id": "CANTO", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "10283806" + }, + { + "id": "ASTR_ASTR", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "6486323" + }, + { + "id": "WEMIX", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "53327498" + }, + { + "id": "ETH_ZKEVM", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "13758502" + }, + { + "id": "XDAI", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0" + }, + { + "id": "BLAST", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "5376321" + }, + { + "id": "SEI", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "85852495" + }, + { + "id": "CORE_COREDAO", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "15420531" + }, + { + "id": "BTC", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "872488" + }, + { + "id": "USDC", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "21294609" + } + ] + }, + { + "id": "3", + "name": "dev-1", + "hiddenOnUI": false, + "customerRefId": "dev-guild-id-1", + "autoFuel": false, + "assets": [ + { + "id": "MATIC_POLYGON", + "total": "0.092436133514242454", + "balance": "0.092436133514242454", + "lockedAmount": "0", + "available": "0.092436133514242454", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "66650299", + "blockHash": "0x62c064832c4a2ff9cc1e00c236427015cda4f639fd03ed62b0e7374bf652807a" + }, + { + "id": "RBW_POLYGON_UZYB", + "total": "1.4", + "balance": "1.4", + "lockedAmount": "0", + "available": "1.4", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "48669610", + "blockHash": "0x9788f6b916527311e53c169f4ef0fafca6d10626862ee473a72144837ed0edc1" + }, + { + "id": "ETH", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "-1" + }, + { + "id": "ETH-AETH", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "117377373" + }, + { + "id": "AVAX", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "33392936" + }, + { + "id": "BNB_BSC", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "30498105" + }, + { + "id": "ETH-OPT", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "107685647" + }, + { + "id": "SGB", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "40869531" + }, + { + "id": "RBTC", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "5656136" + }, + { + "id": "FTM_FANTOM", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "68378879" + }, + { + "id": "GLMR_GLMR", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "4476463" + }, + { + "id": "MOVR_MOVR", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "5151851" + }, + { + "id": "BASECHAIN_ETH", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "4216404" + }, + { + "id": "CELO", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "23357363", + "blockHash": "0x69338c41b8c8a0d10e23356c1463065ebce05f6db554ffcb387eef4a666eca32" + }, + { + "id": "SMARTBCH", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "15805300" + }, + { + "id": "ASIANXT_BESU", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0" + }, + { + "id": "OAS", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "3669391" + }, + { + "id": "LINEA", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "6079647" + }, + { + "id": "SMR_SMR", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "5106465" + }, + { + "id": "ETH_ZKSYNC_ERA", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "37704404" + }, + { + "id": "FLR", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "26085228" + }, + { + "id": "EVMOS", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "21794920" + }, + { + "id": "RON", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "35909496" + }, + { + "id": "SX_NETWORK", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0" + }, + { + "id": "KAVA_KAVA", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "10496720" + }, + { + "id": "AURORA_DEV", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "119522841" + }, + { + "id": "CANTO", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "10283806" + }, + { + "id": "ASTR_ASTR", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "6486323" + }, + { + "id": "WEMIX", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "53327498" + }, + { + "id": "ETH_ZKEVM", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "13758502" + }, + { + "id": "XDAI", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0" + }, + { + "id": "BLAST", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "5376321" + }, + { + "id": "SEI", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "85852495" + }, + { + "id": "CORE_COREDAO", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "15420531" + }, + { + "id": "BTC", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "872488" + }, + { + "id": "USDC", + "total": "0", + "balance": "0", + "lockedAmount": "0", + "available": "0", + "pending": "0", + "frozen": "0", + "staked": "0", + "blockHeight": "21294609" + } + ] + } + ], + "paging": {} +} diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-wallet-addresses-optimism-200.json b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-wallet-addresses-ethereum-200.json similarity index 100% rename from apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-wallet-addresses-optimism-200.json rename to apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-wallet-addresses-ethereum-200.json diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-wallet-addresses-matic-200.json b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-wallet-addresses-matic-200.json index 0167e0b52..89e7e557d 100644 --- a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-wallet-addresses-matic-200.json +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-wallet-addresses-matic-200.json @@ -2,7 +2,7 @@ "addresses": [ { "assetId": "MATIC_POLYGON", - "address": "0x5748EA5ca075734bc7ADc9D8046e897c24829A80", + "address": "0x6b1c79dBF7a7D90d6F4fD623393aFa3DfFd6bE4E", "description": "", "tag": "", "type": "Permanent", @@ -11,6 +11,5 @@ "bip44AddressIndex": 0, "userDefined": false } - ], - "paging": {} + ] } diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/server.ts b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/server.ts index bab2c993e..958d9ab7f 100644 --- a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/server.ts +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/server.ts @@ -1,20 +1,21 @@ import { HttpResponse, http } from 'msw' import getTransactionOk from './response/get-transaction-200.json' +import vaultAccount3 from './response/get-vault-account-3-200.json' +import getWalletAddressesEthOk from './response/get-wallet-addresses-ethereum-200.json' import getWalletAddressesMaticOk from './response/get-wallet-addresses-matic-200.json' -import getWalletAddressesOptOk from './response/get-wallet-addresses-optimism-200.json' import postTransactionCreated from './response/post-transaction-201.json' export const FIREBLOCKS_TEST_API_BASE_URL = 'https://test-mock-api.fireblocks.com' -export const getAddressesHandlers = (baseUrl = FIREBLOCKS_TEST_API_BASE_URL) => { +export const getVaultAccount3AddressesHandlers = (baseUrl = FIREBLOCKS_TEST_API_BASE_URL) => { return { getMatic: http.get( - `${baseUrl}vault/accounts/:vaultAccountId/:assetId/addresses_paginated`, + `${baseUrl}/v1/vault/accounts/:vaultAccountId/:assetId/addresses_paginated`, () => new HttpResponse(JSON.stringify(getWalletAddressesMaticOk)) ), - getOptimism: http.get( - `${baseUrl}vault/accounts/:vaultAccountId/:assetId/addresses_paginated`, - () => new HttpResponse(JSON.stringify(getWalletAddressesOptOk)) + getEth: http.get( + `${baseUrl}/v1/vault/accounts/:vaultAccountId/:assetId/addresses_paginated`, + () => new HttpResponse(JSON.stringify(getWalletAddressesEthOk)) ) } } @@ -28,5 +29,9 @@ export const getHandlers = (baseUrl = FIREBLOCKS_TEST_API_BASE_URL) => [ return new HttpResponse(JSON.stringify(postTransactionCreated)) }), - getAddressesHandlers(baseUrl).getMatic + http.get(`${baseUrl}/v1/vault/accounts/:vaultAccountId`, () => { + return new HttpResponse(JSON.stringify(vaultAccount3)) + }), + + getVaultAccount3AddressesHandlers(baseUrl).getMatic ] diff --git a/apps/vault/src/broker/core/provider/fireblocks/fireblocks-credential.service.ts b/apps/vault/src/broker/core/provider/fireblocks/fireblocks-credential.service.ts index 6bf91f8de..7a6fe43f7 100644 --- a/apps/vault/src/broker/core/provider/fireblocks/fireblocks-credential.service.ts +++ b/apps/vault/src/broker/core/provider/fireblocks/fireblocks-credential.service.ts @@ -1,5 +1,14 @@ -import { Alg, DEFAULT_RSA_MODULUS_LENGTH, generateJwk, getPublicKey, privateRsaPemToJwk } from '@narval/signature' +import { + Alg, + DEFAULT_RSA_MODULUS_LENGTH, + RsaPrivateKey, + generateJwk, + getPublicKey, + privateKeyToPem, + privateRsaPemToJwk +} from '@narval/signature' import { Injectable } from '@nestjs/common' +import * as forge from 'node-forge' import { ParseException } from '../../../../shared/module/persistence/exception/parse.exception' import { ConnectionInvalidPrivateKeyException } from '../../exception/connection-invalid-private-key.exception' import { ProviderCredentialService } from '../../type/provider.type' @@ -63,4 +72,22 @@ export class FireblocksCredentialService publicKey: getPublicKey(privateKey) } } + + static async signCertificateRequest(privateKey: RsaPrivateKey, organizationName: string): Promise { + const pem = await privateKeyToPem(privateKey, Alg.RS256) + const forgePrivateKey = forge.pki.privateKeyFromPem(pem) + const forgePublicKey = forge.pki.rsa.setPublicKey(forgePrivateKey.n, forgePrivateKey.e) + const csr = forge.pki.createCertificationRequest() + + csr.publicKey = forgePublicKey + csr.setSubject([ + { + name: 'organizationName', + value: organizationName + } + ]) + csr.sign(forgePrivateKey) + + return Buffer.from(forge.pki.certificationRequestToPem(csr)).toString('base64') + } } diff --git a/apps/vault/src/broker/core/provider/fireblocks/fireblocks-known-destination.service.ts b/apps/vault/src/broker/core/provider/fireblocks/fireblocks-known-destination.service.ts new file mode 100644 index 000000000..4f860cfb0 --- /dev/null +++ b/apps/vault/src/broker/core/provider/fireblocks/fireblocks-known-destination.service.ts @@ -0,0 +1,139 @@ +import { LoggerService, PaginatedResult } from '@narval/nestjs-shared' +import { HttpStatus, Injectable } from '@nestjs/common' +import { FireblocksClient, WhitelistedWallet } from '../../../http/client/fireblocks.client' +import { BrokerException } from '../../exception/broker.exception' +import { AssetService } from '../../service/asset.service' +import { Asset } from '../../type/asset.type' +import { ConnectionWithCredentials } from '../../type/connection.type' +import { KnownDestination } from '../../type/known-destination.type' +import { + Provider, + ProviderKnownDestinationPaginationOptions, + ProviderKnownDestinationService +} from '../../type/provider.type' +import { WhitelistClassification } from './fireblocks.type' +import { validateConnection } from './fireblocks.util' + +@Injectable() +export class FireblocksKnownDestinationService implements ProviderKnownDestinationService { + constructor( + private readonly fireblocksClient: FireblocksClient, + private readonly assetService: AssetService, + private readonly logger: LoggerService + ) {} + + async findAll( + connection: ConnectionWithCredentials, + // NOTE: Fireblocks doesn't provide pagination on whitelisted resource + // endpoints. + // + // eslint-disable-next-line @typescript-eslint/no-unused-vars + _options?: ProviderKnownDestinationPaginationOptions | undefined + ): Promise> { + validateConnection(connection) + + const fireblocksWhitelistedInternalsWallets = await this.fireblocksClient.getWhitelistedInternalWallets({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey + }) + + const fireblocksWhitelistedExternalWallets = await this.fireblocksClient.getWhitelistedExternalWallets({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey + }) + + const fireblocksWhitelistedContracts = await this.fireblocksClient.getWhitelistedContracts({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey + }) + + const assetsIndexedByExternalId = await this.assetService.buildProviderExternalIdIndex(Provider.FIREBLOCKS) + + const knownDestinations: KnownDestination[] = [ + ...this.buildKnownDestinations({ + connection, + assetsIndexedByExternalId, + classification: WhitelistClassification.INTERNAL, + resources: fireblocksWhitelistedInternalsWallets + }), + ...this.buildKnownDestinations({ + connection, + assetsIndexedByExternalId, + classification: WhitelistClassification.EXTERNAL, + resources: fireblocksWhitelistedExternalWallets + }), + ...this.buildKnownDestinations({ + connection, + assetsIndexedByExternalId, + classification: WhitelistClassification.CONTRACT, + resources: fireblocksWhitelistedContracts + }) + ] + + return { data: knownDestinations } + } + + private buildKnownDestinations(params: { + connection: ConnectionWithCredentials + resources: WhitelistedWallet[] + classification: WhitelistClassification + assetsIndexedByExternalId: Map + }): KnownDestination[] { + const { connection, resources, classification, assetsIndexedByExternalId } = params + const knownDestinations: KnownDestination[] = [] + + for (const resource of resources) { + for (const fireblocksAsset of resource.assets) { + // NOTE: We only include assets ready to be used with 'APPROVED' status + // since we don't have any UX to display asset status to users. + if (fireblocksAsset.status === 'APPROVED') { + const asset = assetsIndexedByExternalId.get(fireblocksAsset.id) + const externalId = this.getExternalId(classification, resource.id, fireblocksAsset.id) + + if (asset) { + knownDestinations.push({ + externalId, + address: fireblocksAsset.address.toLowerCase(), + externalClassification: classification, + clientId: connection.clientId, + connectionId: connection.connectionId, + provider: Provider.FIREBLOCKS, + assetId: asset.assetId, + networkId: asset.networkId + }) + } else { + this.logger.warn('Skip Fireblocks known destination due to asset not found', { + externalId, + classification, + clientId: connection.clientId, + connectionId: connection.connectionId, + externalAssetId: fireblocksAsset.id + }) + } + } + } + } + + return knownDestinations + } + + private getExternalId(classification: WhitelistClassification, resourceId: string, assetId: string): string { + switch (classification) { + case WhitelistClassification.INTERNAL: + return `fireblocks/whitelisted-internal-wallet/${resourceId}/asset/${assetId}` + case WhitelistClassification.EXTERNAL: + return `fireblocks/whitelisted-external-wallet/${resourceId}/asset/${assetId}` + case WhitelistClassification.CONTRACT: + return `fireblocks/whitelisted-contract/${resourceId}/asset/${assetId}` + default: + throw new BrokerException({ + message: `Unknown Fireblocks classification ${classification}`, + suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, + context: { resourceId, assetId } + }) + } + } +} diff --git a/apps/vault/src/broker/core/provider/fireblocks/fireblocks-scoped-sync.service.ts b/apps/vault/src/broker/core/provider/fireblocks/fireblocks-scoped-sync.service.ts new file mode 100644 index 000000000..ae7347d40 --- /dev/null +++ b/apps/vault/src/broker/core/provider/fireblocks/fireblocks-scoped-sync.service.ts @@ -0,0 +1,293 @@ +import { LoggerService } from '@narval/nestjs-shared' +import { Injectable } from '@nestjs/common' +import { randomUUID } from 'crypto' +import { uniqBy } from 'lodash/fp' +import { FIREBLOCKS_API_ERROR_CODES, FireblocksClient, VaultAccount } from '../../../http/client/fireblocks.client' +import { UpdateAccount } from '../../../persistence/repository/account.repository' +import { NetworkRepository } from '../../../persistence/repository/network.repository' +import { WalletRepository } from '../../../persistence/repository/wallet.repository' +import { ConnectionWithCredentials } from '../../type/connection.type' +import { Account, Address, UpdateWallet, Wallet } from '../../type/indexed-resources.type' +import { + Provider, + ProviderScopedSyncService, + ScopedSyncOperation, + ScopedSyncOperationType, + ScopedSyncResult +} from '../../type/provider.type' +import { RawAccount } from '../../type/scoped-sync.type' +import { + CONCURRENT_FIREBLOCKS_REQUESTS, + FireblocksAssetWalletId, + getFireblocksAssetAddressExternalId, + getFireblocksAssetWalletExternalId, + toFireblocksAssetWalletExternalId, + validateConnection +} from './fireblocks.util' + +@Injectable() +export class FireblocksScopedSyncService implements ProviderScopedSyncService { + constructor( + private readonly fireblocksClient: FireblocksClient, + private readonly networkRepository: NetworkRepository, + private readonly walletRepository: WalletRepository, + private readonly logger: LoggerService + ) {} + + private async buildVaultNetworkMap( + assetWalletIds: FireblocksAssetWalletId[] + ): Promise>> { + const result: Record> = {} + + for (const { vaultId, networkId } of assetWalletIds) { + if (!vaultId || !networkId) continue + + try { + const network = await this.networkRepository.findById(networkId) + + if (!network) { + this.logger.log('Network not found', { networkId }) + continue + } + + const fireblocksNetwork = network.externalNetworks?.find((n) => n.provider === Provider.FIREBLOCKS) + if (!fireblocksNetwork) { + this.logger.log('Network not supported', { networkId, provider: Provider.FIREBLOCKS }) + continue + } + + if (!result[vaultId]) { + result[vaultId] = new Set() + } + result[vaultId].add({ + narvalNetworkId: networkId, + fireblocksNetworkId: fireblocksNetwork.externalId + }) + } catch (error) { + this.logger.log('Error processing network', { networkId, error: String(error) }) + } + } + + return result + } + + async scopedSync(connection: ConnectionWithCredentials, rawAccounts: RawAccount[]): Promise { + const now = new Date() + validateConnection(connection) + + const existingWallets = await this.walletRepository.findAll( + { clientId: connection.clientId, connectionId: connection.connectionId }, + { pagination: { disabled: true } } + ) + + const existingWalletMap = new Map(existingWallets.data.map((wallet) => [wallet.externalId, wallet])) + const existingAccountMap = new Map( + existingWallets.data.flatMap( + (wallet) => + wallet.accounts?.map((account) => [account.externalId, { ...account, walletId: wallet.walletId }]) ?? [] + ) + ) + + const assetWalletIds = uniqBy('externalId', rawAccounts).map((account) => + toFireblocksAssetWalletExternalId(account.externalId) + ) + + const vaultToNetworkMap = await this.buildVaultNetworkMap(assetWalletIds) + const requestedVaultIds = Object.keys(vaultToNetworkMap) + + const vaults: VaultAccount[] = [] + for (let i = 0; i < Object.keys(vaultToNetworkMap).length; i += CONCURRENT_FIREBLOCKS_REQUESTS) { + const batch = Object.keys(vaultToNetworkMap).slice(i, i + CONCURRENT_FIREBLOCKS_REQUESTS) + const batchPromises = batch.map((vaultId) => + this.fireblocksClient.getVaultAccount({ + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey, + url: connection.url, + vaultAccountId: vaultId + }) + ) + + const batchResults = await Promise.allSettled(batchPromises) + + const validVaults = batchResults + .map((result, index) => { + if (result.status === 'fulfilled') { + return result.value + } else { + const error = result.reason + const vaultId = batch[index] + + if (error?.response?.body?.code === FIREBLOCKS_API_ERROR_CODES.INVALID_SPECIFIED_VAULT_ACCOUNT) { + this.logger.warn('Vault not found', { + vaultId, + provider: Provider.FIREBLOCKS + }) + return null + } else { + throw error + } + } + }) + .filter((vault): vault is VaultAccount => vault !== null) + + vaults.push(...validVaults) + } + + // Filter to only get the vaults we need based on vaultToNetworkMap + const relevantVaults = vaults.filter((vault) => vault.id in vaultToNetworkMap) + const vaultMap = Object.fromEntries(relevantVaults.map((vault) => [vault.id, vault])) + + // Log each missing vault + const foundVaultIds = relevantVaults.map((vault) => vault.id) + requestedVaultIds.forEach((vaultId) => { + if (!foundVaultIds.includes(vaultId)) { + this.logger.warn('Vault not found', { + vaultId, + networks: vaultToNetworkMap[vaultId] + }) + } + }) + + const walletOperations: ScopedSyncOperation[] = [] + const accountOperations: ScopedSyncOperation[] = [] + const addressOperations: ScopedSyncOperation[] = [] + + for (const [vaultId, networkIds] of Object.entries(vaultToNetworkMap)) { + const vault = vaultMap[vaultId] + if (!vault) { + this.logger.warn('raw account was not found', { vaultId }) + continue + } + const existingWallet = existingWalletMap.get(vaultId) + const walletId = existingWallet?.walletId || randomUUID() + + if (existingWallet) { + if (existingWallet.label !== vault.name) { + walletOperations.push({ + type: ScopedSyncOperationType.UPDATE, + update: { + clientId: connection.clientId, + walletId, + label: vault.name, + updatedAt: now + } + }) + } + } else { + walletOperations.push({ + type: ScopedSyncOperationType.CREATE, + create: { + accounts: [], + clientId: connection.clientId, + connectionId: connection.connectionId, + createdAt: now, + externalId: vaultId, + label: vault.name, + provider: Provider.FIREBLOCKS, + updatedAt: now, + walletId + } + }) + } + + // Create accounts for each network + for (const { fireblocksNetworkId, narvalNetworkId } of networkIds) { + const accountExternalId = getFireblocksAssetWalletExternalId({ + vaultId: vault.id, + networkId: fireblocksNetworkId + }) + + const existingAccount = existingAccountMap.get(accountExternalId) + const accountId = existingAccount?.accountId || randomUUID() + const accountLabel = `${vault.name} - ${fireblocksNetworkId}` + + try { + if (existingAccount) { + if (existingAccount.label !== accountLabel) { + accountOperations.push({ + type: ScopedSyncOperationType.UPDATE, + update: { + clientId: connection.clientId, + accountId: existingAccount.accountId, + label: accountLabel, + updatedAt: now + } + }) + } + } else { + accountOperations.push({ + type: ScopedSyncOperationType.CREATE, + create: { + externalId: accountExternalId, + accountId, + addresses: [], + clientId: connection.clientId, + createdAt: now, + connectionId: connection.connectionId, + label: accountLabel, + networkId: narvalNetworkId, + provider: Provider.FIREBLOCKS, + updatedAt: now, + walletId + } + }) + } + + // Fetch and process addresses + try { + const addresses = await this.fireblocksClient.getAddresses({ + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey, + url: connection.url, + vaultAccountId: vault.id, + assetId: fireblocksNetworkId + }) + addresses.forEach((address) => { + const addressExternalId = getFireblocksAssetAddressExternalId({ + vaultId: vault.id, + networkId: fireblocksNetworkId, + address: address.address + }) + if (!existingAccount?.addresses?.some((a) => a.externalId === addressExternalId)) { + addressOperations.push({ + type: ScopedSyncOperationType.CREATE, + create: { + accountId, + address: address.address, + addressId: randomUUID(), + clientId: connection.clientId, + createdAt: now, + connectionId: connection.connectionId, + externalId: addressExternalId, + provider: Provider.FIREBLOCKS, + updatedAt: now + } + }) + } + }) + } catch (error) { + addressOperations.push({ + type: ScopedSyncOperationType.FAILED, + externalId: accountExternalId, + message: 'Failed to fetch addresses', + context: { error: error.message } + }) + } + } catch (error) { + accountOperations.push({ + type: ScopedSyncOperationType.FAILED, + externalId: accountExternalId, + message: 'Failed to process account', + context: { error: error.message } + }) + } + } + } + + return { + wallets: walletOperations, + accounts: accountOperations, + addresses: addressOperations + } + } +} diff --git a/apps/vault/src/broker/core/provider/fireblocks/fireblocks-sync.service.ts b/apps/vault/src/broker/core/provider/fireblocks/fireblocks-sync.service.ts deleted file mode 100644 index 45c42e968..000000000 --- a/apps/vault/src/broker/core/provider/fireblocks/fireblocks-sync.service.ts +++ /dev/null @@ -1,497 +0,0 @@ -import { LoggerService } from '@narval/nestjs-shared' -import { Injectable } from '@nestjs/common' -import { randomUUID } from 'crypto' -import { uniq } from 'lodash/fp' -import { FireblocksClient, WhitelistedWallet } from '../../../http/client/fireblocks.client' -import { UpdateAccount } from '../../../persistence/repository/account.repository' -import { NetworkRepository } from '../../../persistence/repository/network.repository' -import { AccountService } from '../../service/account.service' -import { KnownDestinationService } from '../../service/known-destination.service' -import { WalletService } from '../../service/wallet.service' -import { Connection, ConnectionWithCredentials } from '../../type/connection.type' -import { Account, Address, KnownDestination, UpdateWallet, Wallet } from '../../type/indexed-resources.type' -import { - Provider, - ProviderSyncService, - SyncContext, - SyncOperation, - SyncOperationType, - SyncResult, - isCreateOperation -} from '../../type/provider.type' -import { buildEmptyContext } from '../../util/provider-sync.util' -import { WhitelistClassification } from './fireblocks.type' -import { getFireblocksAssetWalletExternalId, validateConnection } from './fireblocks.util' - -@Injectable() -export class FireblocksSyncService implements ProviderSyncService { - constructor( - private readonly fireblocksClient: FireblocksClient, - private readonly walletService: WalletService, - private readonly accountService: AccountService, - private readonly knownDestinationService: KnownDestinationService, - private readonly networkRepository: NetworkRepository, - private readonly logger: LoggerService - ) {} - - async sync(connection: ConnectionWithCredentials): Promise { - const initialContext = buildEmptyContext({ connection, now: new Date() }) - const syncWalletContext = await this.syncWallets(initialContext) - const syncAccountContext = await this.syncAccounts(syncWalletContext) - // const syncAddressContext = await this.syncAddresses(syncAccountContext) - const lastSyncContext = await this.syncKnownDestinations(syncAccountContext) - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { connection: _conn, ...result } = lastSyncContext - - return result - } - - async syncWallets(context: SyncContext): Promise { - const { connection } = context - - this.logger.log('Sync Fireblocks wallets', { - connectionId: connection.connectionId, - clientId: connection.clientId, - url: connection.url - }) - - validateConnection(connection) - - const now = context.now ?? new Date() - - const fireblocksVaultAccounts = await this.fireblocksClient.getVaultAccounts({ - url: connection.url, - apiKey: connection.credentials.apiKey, - signKey: connection.credentials.privateKey - }) - - const { data: existingWallets } = await this.walletService.findAll(connection.clientId, { - filters: { - externalIds: uniq(fireblocksVaultAccounts.map((account) => account.id)) - }, - pagination: { disabled: true } - }) - - const operations: SyncOperation[] = [] - - for (const account of fireblocksVaultAccounts) { - const existingAccount = existingWallets.find((w) => w.externalId === account.id) - if (!existingAccount) { - operations.push({ - type: SyncOperationType.CREATE, - create: { - externalId: account.id, - clientId: connection.clientId, - createdAt: now, - accounts: [], - label: account.name, - connections: [Connection.parse(connection)], - provider: Provider.FIREBLOCKS, - updatedAt: now, - walletId: randomUUID() - } - }) - continue - } - - const hasConnection = existingAccount.connections.some((conn) => conn.connectionId === connection.connectionId) - const hasDataChanges = existingAccount.label !== account.name - - if (hasConnection || hasDataChanges) { - operations.push({ - type: SyncOperationType.UPDATE, - update: { - ...existingAccount, - label: account.name, - updatedAt: now - } - }) - } - } - - return { - ...context, - wallets: operations - } - } - - async syncAccounts(context: SyncContext): Promise { - const { connection } = context - - this.logger.log('Sync Fireblocks accounts', { - connectionId: connection.connectionId, - clientId: connection.clientId, - url: connection.url - }) - - validateConnection(connection) - - const fireblocksAssetWallets = await this.fireblocksClient.getAssetWallets({ - url: connection.url, - apiKey: connection.credentials.apiKey, - signKey: connection.credentials.privateKey - }) - - const walletExternalIds = uniq(fireblocksAssetWallets.map(({ vaultId }) => vaultId)) - - const { data: existingWallets } = await this.walletService.findAll(connection.clientId, { - filters: { - externalIds: walletExternalIds - }, - pagination: { disabled: true } - }) - - const { data: existingAccounts } = await this.accountService.findAll(connection.clientId, { - filters: { - externalIds: uniq( - fireblocksAssetWallets.map((wallet) => - getFireblocksAssetWalletExternalId({ - vaultId: wallet.vaultId, - assetId: wallet.assetId - }) - ) - ) - }, - pagination: { disabled: true } - }) - - const existingAccountsByExternalId = new Map(existingAccounts.map((account) => [account.externalId, account])) - - const missingFireblocksWallets = fireblocksAssetWallets.filter( - (fireblocksVault) => - !existingAccountsByExternalId.has( - getFireblocksAssetWalletExternalId({ - vaultId: fireblocksVault.vaultId, - assetId: fireblocksVault.assetId - }) - ) - ) - - const walletsIndexedByExternalId = new Map(existingWallets.map((wallet) => [wallet.externalId, wallet])) - - const contextWalletsIndexedByExternalId = new Map( - context.wallets.filter(isCreateOperation).map(({ create }) => [create.externalId, create]) - ) - - const now = context.now ?? new Date() - - const operations: SyncOperation[] = [] - - for (const fireblocksAssetWallet of missingFireblocksWallets) { - const externalId = getFireblocksAssetWalletExternalId({ - vaultId: fireblocksAssetWallet.vaultId, - assetId: fireblocksAssetWallet.assetId - }) - const parentExternalId = fireblocksAssetWallet.vaultId - - // Either look up the existing wallets in the database or in the sync context. - const contextWallet = contextWalletsIndexedByExternalId.get(parentExternalId) - const indexedWallet = walletsIndexedByExternalId.get(parentExternalId) - - const wallet = contextWallet || indexedWallet - - if (wallet) { - const network = await this.networkRepository.findByExternalId( - Provider.FIREBLOCKS, - fireblocksAssetWallet.assetId - ) - - if (network) { - operations.push({ - type: SyncOperationType.CREATE, - create: { - // Fireblocks 'assetWallet' ID is not unique. It's the networkID used per vault Account - // In our system, each provider account has a unique external ID per client. - // This is a specific problem from Fireblocks, so we need to be aware of the way we store the externalID in order to know how to query per ID - externalId, - accountId: randomUUID(), - addresses: [], - clientId: connection.clientId, - createdAt: now, - networkId: network.networkId, - provider: Provider.FIREBLOCKS, - updatedAt: now, - walletId: wallet.walletId - } - }) - } else { - operations.push({ - type: SyncOperationType.SKIP, - externalId, - message: 'Unknown Fireblocks wallet network ID', - context: { - externalId, - fireblocksNetworkId: fireblocksAssetWallet.assetId - } - }) - } - } else { - operations.push({ - type: SyncOperationType.FAILED, - externalId, - - message: 'Parent wallet for account not found', - context: { - fireblocksWalletId: parentExternalId, - totalLength: existingWallets.length, - contextWallet, - indexedWallet - } - }) - } - } - - return { - ...context, - accounts: operations - } - } - - async syncAddresses(context: SyncContext): Promise { - const { connection } = context - - this.logger.log('Sync Fireblocks addresses', { - connectionId: connection.connectionId, - clientId: connection.clientId, - url: connection.url - }) - - validateConnection(connection) - - const vaultAccounts = await this.fireblocksClient.getVaultAccounts({ - url: connection.url, - apiKey: connection.credentials.apiKey, - signKey: connection.credentials.privateKey - }) - - const now = context.now ?? new Date() - - const accountOperations = await Promise.all( - vaultAccounts.map(async (account) => { - this.logger.log('Sync Fireblocks addresses for account', { - clientId: connection.clientId, - url: connection.url, - accountId: account.id - }) - - const assetOperations = await Promise.all( - account.assets.map(async (asset) => { - try { - const addresses = await this.fireblocksClient.getAddresses({ - url: connection.url, - apiKey: connection.credentials.apiKey, - signKey: connection.credentials.privateKey, - vaultAccountId: account.id, - assetId: asset.id - }) - - return addresses.map( - (fireblocksAddress): SyncOperation => ({ - type: SyncOperationType.CREATE, - create: { - externalId: fireblocksAddress.address, - addressId: fireblocksAddress.address, - accountId: account.id, - address: fireblocksAddress.address, - clientId: connection.clientId, - createdAt: now, - provider: Provider.FIREBLOCKS, - updatedAt: now - } - }) - ) - } catch (error) { - const failedOperation: SyncOperation = { - type: SyncOperationType.FAILED, - externalId: `${account.id}:${asset.id}`, - message: `Failed to fetch addresses for account/asset: ${error.message}`, - context: { - accountId: account.id, - assetId: asset.id, - error: error.message - } - } - - this.logger.error('Failed to fetch addresses for account/asset', { - accountId: account.id, - assetId: asset.id, - error: error.message - }) - - return [failedOperation] - } - }) - ) - - return assetOperations.flat() - }) - ) - const operations = accountOperations.flat() - - return { - ...context, - addresses: operations - } - } - - async syncKnownDestinations(context: SyncContext): Promise { - const { connection } = context - - this.logger.log('Sync Fireblocks known destinations', { - connectionId: connection.connectionId, - clientId: connection.clientId, - url: connection.url - }) - - validateConnection(connection) - - const fireblocksWhitelistedInternalsWallets = await this.fireblocksClient.getWhitelistedInternalWallets({ - url: connection.url, - apiKey: connection.credentials.apiKey, - signKey: connection.credentials.privateKey - }) - - const fireblocksWhitelistedExternals = await this.fireblocksClient.getWhitelistedExternalWallets({ - url: connection.url, - apiKey: connection.credentials.apiKey, - signKey: connection.credentials.privateKey - }) - - const fireblocksWhitelistedContracts = await this.fireblocksClient.getWhitelistedContracts({ - url: connection.url, - apiKey: connection.credentials.apiKey, - signKey: connection.credentials.privateKey - }) - - const fireblocksKnownDestinations = [ - ...this.transformWhitelistedAddresses({ - whitelistedWallets: fireblocksWhitelistedContracts, - classification: WhitelistClassification.CONTRACT - }), - ...this.transformWhitelistedAddresses({ - whitelistedWallets: fireblocksWhitelistedExternals, - classification: WhitelistClassification.EXTERNAL - }), - ...this.transformWhitelistedAddresses({ - whitelistedWallets: fireblocksWhitelistedInternalsWallets, - classification: WhitelistClassification.INTERNAL - }) - ] - - const { data: existingKnownDestinations } = await this.knownDestinationService.findAll(connection.clientId, { - filters: { - providers: [Provider.FIREBLOCKS] - }, - pagination: { disabled: true } - }) - - const now = context.now ?? new Date() - - const incomingMap = new Map(fireblocksKnownDestinations.map((dest) => [dest.externalId, dest])) - const existingMap = new Map(existingKnownDestinations.map((dest) => [dest.externalId, dest])) - - const updateOperations = fireblocksKnownDestinations - .reduce((acc, incoming) => { - const existing = existingMap.get(incoming.externalId) - if (!existing) return acc - - const hasConnection = existing.connections.some((conn) => conn.connectionId === connection.connectionId) - const hasDataChanges = (existing.label || undefined) !== incoming.label - - if (hasDataChanges || !hasConnection) { - acc.push( - KnownDestination.parse({ - ...existing, - label: incoming.label, - updatedAt: now, - connections: [...existing.connections, connection] - }) - ) - } - - return acc - }, []) - .map((update) => ({ type: SyncOperationType.UPDATE, update })) - - const missingDestinations = fireblocksKnownDestinations.filter( - (fireblocksTrustedAddress) => !existingMap.has(fireblocksTrustedAddress.externalId) - ) - - const createOperations: SyncOperation[] = [] - - for (const fireblocksTrustedAddress of missingDestinations) { - const externalId = fireblocksTrustedAddress.externalId - const network = await this.networkRepository.findByExternalId( - Provider.FIREBLOCKS, - fireblocksTrustedAddress.assetId - ) - - if (network) { - const knownDestination = KnownDestination.parse({ - externalId, - knownDestinationId: randomUUID(), - address: fireblocksTrustedAddress.address, - externalClassification: fireblocksTrustedAddress.externalClassification, - clientId: connection.clientId, - label: fireblocksTrustedAddress.label, - assetId: fireblocksTrustedAddress.assetId, - provider: Provider.FIREBLOCKS, - networkId: fireblocksTrustedAddress.assetId, - createdAt: now, - updatedAt: now, - connections: [connection] - }) - - createOperations.push({ type: SyncOperationType.CREATE, create: knownDestination }) - } else { - createOperations.push({ - type: SyncOperationType.SKIP, - externalId, - message: 'Unknown Fireblocks trusted address network ID', - context: { - externalId, - fireblocksNetworkId: fireblocksTrustedAddress.assetId - } - }) - } - } - - const deleteOperations = existingKnownDestinations - .filter((dest) => !incomingMap.has(dest.externalId)) - .map((kd) => ({ type: SyncOperationType.DELETE, entityId: kd.knownDestinationId })) - - return { - ...context, - knownDestinations: [...createOperations, ...updateOperations, ...deleteOperations] - } - } - - private transformWhitelistedAddresses(opts: { - whitelistedWallets: WhitelistedWallet[] - classification: WhitelistClassification - }) { - const now = new Date() - const destinations = [] - - for (const wallet of opts.whitelistedWallets) { - for (const asset of wallet.assets) { - destinations.push({ - provider: Provider.FIREBLOCKS, - externalId: getFireblocksAssetWalletExternalId({ - vaultId: wallet.id, - assetId: asset.id - }), - externalClassification: opts.classification, - address: asset.address, - label: wallet.name, - assetId: asset.id, - createdAt: now, - updatedAt: now - }) - } - } - - return destinations - } -} diff --git a/apps/vault/src/broker/core/provider/fireblocks/fireblocks-transfer.service.ts b/apps/vault/src/broker/core/provider/fireblocks/fireblocks-transfer.service.ts index 42defacec..ae141445b 100644 --- a/apps/vault/src/broker/core/provider/fireblocks/fireblocks-transfer.service.ts +++ b/apps/vault/src/broker/core/provider/fireblocks/fireblocks-transfer.service.ts @@ -2,28 +2,32 @@ import { LoggerService } from '@narval/nestjs-shared' import { HttpStatus, Injectable } from '@nestjs/common' import { randomUUID } from 'crypto' import { CreateTransaction, FireblocksClient } from '../../../http/client/fireblocks.client' -import { NetworkRepository } from '../../../persistence/repository/network.repository' import { TransferRepository } from '../../../persistence/repository/transfer.repository' +import { AssetException } from '../../exception/asset.exception' import { BrokerException } from '../../exception/broker.exception' import { AccountService } from '../../service/account.service' import { AddressService } from '../../service/address.service' import { AssetService } from '../../service/asset.service' +import { NetworkService } from '../../service/network.service' +import { ResolvedTransferAsset, TransferAssetService } from '../../service/transfer-asset.service' import { WalletService } from '../../service/wallet.service' import { ConnectionWithCredentials } from '../../type/connection.type' import { Network } from '../../type/network.type' import { Provider, ProviderTransferService } from '../../type/provider.type' +import { ConnectionScope } from '../../type/scope.type' import { Destination, InternalTransfer, NetworkFeeAttribution, SendTransfer, Transfer, + TransferAsset, TransferPartyType, TransferStatus, isAddressDestination, isProviderSpecific } from '../../type/transfer.type' -import { getExternalAsset } from '../../util/asset.util' +import { getExternalNetwork } from '../../util/network.util' import { validateConnection } from './fireblocks.util' @Injectable() @@ -31,11 +35,12 @@ export class FireblocksTransferService implements ProviderTransferService { constructor( private readonly assetService: AssetService, private readonly fireblocksClient: FireblocksClient, - private readonly networkRepository: NetworkRepository, + private readonly networkService: NetworkService, private readonly walletService: WalletService, private readonly accountService: AccountService, private readonly addressService: AddressService, private readonly transferRepository: TransferRepository, + private readonly transferAssetService: TransferAssetService, private readonly logger: LoggerService ) {} @@ -63,7 +68,9 @@ export class FireblocksTransferService implements ProviderTransferService { this.logger.log('Found Fireblocks transaction by ID', context) - const transfer = { + const transfer: Transfer = { + connectionId, + assetExternalId: internalTransfer.assetExternalId, assetId: internalTransfer.assetId, clientId: internalTransfer.clientId, createdAt: new Date(fireblocksTransaction.createdAt), @@ -120,8 +127,8 @@ export class FireblocksTransferService implements ProviderTransferService { validateConnection(connection) - const asset = await this.assetService.findTransferAsset(Provider.FIREBLOCKS, sendTransfer.asset) - if (!asset) { + const transferAsset = await this.findTransferAsset(connection, sendTransfer.asset) + if (!transferAsset) { throw new BrokerException({ message: 'Transfer asset not found', suggestedHttpStatusCode: HttpStatus.NOT_FOUND, @@ -129,33 +136,15 @@ export class FireblocksTransferService implements ProviderTransferService { }) } - const externalAsset = getExternalAsset(asset, Provider.FIREBLOCKS) - if (!externalAsset) { - throw new BrokerException({ - message: 'Unsupported asset by Fireblocks', - suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, - context: { asset } - }) - } + const source = await this.getSource(connection, sendTransfer) - const network = await this.networkRepository.findById(asset.networkId) - if (!network) { - throw new BrokerException({ - message: 'Cannot find asset network', - suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR, - context: { asset } - }) - } - - const source = await this.getSource(connection.clientId, sendTransfer) - - const destination = await this.getDestination(connection.clientId, network, sendTransfer.destination) + const destination = await this.getDestination(connection, transferAsset.network, sendTransfer.destination) this.logger.log('Resolved Fireblocks transfer source and destination', { ...context, destination, source, - networkId: network.networkId + networkId: transferAsset.network.networkId }) // NOTE: Defaults the `networkFeeAttribution` to deduct to match most @@ -176,7 +165,7 @@ export class FireblocksTransferService implements ProviderTransferService { source, destination, amount: sendTransfer.amount, - assetId: externalAsset.externalId, + assetId: transferAsset.assetExternalId, customerRefId: sendTransfer.customerRefId, externalTxId: transferId, note: sendTransfer.memo, @@ -197,11 +186,14 @@ export class FireblocksTransferService implements ProviderTransferService { this.logger.log('Fireblocks transaction created', context) const internalTransfer: InternalTransfer = { - assetId: asset.assetId, + connectionId, + transferId, + assetId: transferAsset.assetId, clientId: connection.clientId, createdAt: new Date(), customerRefId: sendTransfer.customerRefId || null, destination: sendTransfer.destination, + assetExternalId: transferAsset.assetExternalId, externalId: createTransactionResponse.id, externalStatus: createTransactionResponse.status, grossAmount: sendTransfer.amount, @@ -211,8 +203,7 @@ export class FireblocksTransferService implements ProviderTransferService { provider: Provider.FIREBLOCKS, providerSpecific: sendTransfer.providerSpecific || null, source: sendTransfer.source, - status: this.mapStatus(createTransactionResponse.status), - transferId + status: this.mapStatus(createTransactionResponse.status) } this.logger.log('Create internal transfer', internalTransfer) @@ -249,12 +240,12 @@ export class FireblocksTransferService implements ProviderTransferService { return false } - private async getSource(clientId: string, sendTransfer: SendTransfer) { + private async getSource(scope: ConnectionScope, sendTransfer: SendTransfer) { if (sendTransfer.source.type === TransferPartyType.ACCOUNT) { - const account = await this.accountService.findById(clientId, sendTransfer.source.id) + const account = await this.accountService.findById(scope, sendTransfer.source.id) if (account) { - const wallet = await this.walletService.findById(clientId, account.walletId) + const wallet = await this.walletService.findById(scope, account.walletId) if (wallet) { return { @@ -272,25 +263,25 @@ export class FireblocksTransferService implements ProviderTransferService { }) } - private async getDestination(clientId: string, network: Network, destination: Destination) { + private async getDestination(scope: ConnectionScope, network: Network, destination: Destination) { this.logger.log('Resolved Fireblocks destination', { - clientId, + scope, destination, network: network.networkId }) if (isAddressDestination(destination)) { const address = await this.addressService.findByAddressAndNetwork( - clientId, + scope.clientId, destination.address, network.networkId ) if (address) { - const account = await this.accountService.findById(clientId, address.accountId) + const account = await this.accountService.findById(scope, address.accountId) if (account) { - const wallet = await this.walletService.findById(clientId, account.walletId) + const wallet = await this.walletService.findById(scope, account.walletId) if (wallet) { return { @@ -310,10 +301,10 @@ export class FireblocksTransferService implements ProviderTransferService { } if (destination.type === TransferPartyType.ACCOUNT) { - const account = await this.accountService.findById(clientId, destination.id) + const account = await this.accountService.findById(scope, destination.id) if (account) { - const wallet = await this.walletService.findById(clientId, account.walletId) + const wallet = await this.walletService.findById(scope, account.walletId) if (wallet) { return { @@ -331,6 +322,88 @@ export class FireblocksTransferService implements ProviderTransferService { }) } + private async findTransferAsset( + connection: ConnectionWithCredentials, + transferAsset: TransferAsset + ): Promise { + validateConnection(connection) + + const findByExternalIdFallback = async (externalAssetId: string): Promise => { + const fbSupportedAssets = await this.fireblocksClient.getSupportedAssets({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey + }) + + const fbSupportedAsset = fbSupportedAssets.find(({ id }) => id.toLowerCase() === externalAssetId.toLowerCase()) + if (!fbSupportedAsset) { + throw new AssetException({ + message: 'Fireblocks supported asset not found', + suggestedHttpStatusCode: HttpStatus.NOT_FOUND, + context: { transferAsset } + }) + } + + const network = await this.networkService.findByExternalId(Provider.FIREBLOCKS, fbSupportedAsset.nativeAsset) + if (!network) { + throw new AssetException({ + message: 'Fireblocks supported asset network not found', + suggestedHttpStatusCode: HttpStatus.NOT_FOUND, + context: { transferAsset, fbSupportedAsset } + }) + } + + return { + network, + assetExternalId: externalAssetId, + assetId: null + } + } + + const findByOnchainIdFallback = async (network: Network, onchainId: string): Promise => { + const externalNetwork = getExternalNetwork(network, Provider.FIREBLOCKS) + if (!externalNetwork) { + throw new AssetException({ + message: 'Network does not support Fireblocks', + suggestedHttpStatusCode: HttpStatus.NOT_IMPLEMENTED, + context: { transferAsset, network } + }) + } + + const fbSupportedAssets = await this.fireblocksClient.getSupportedAssets({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey + }) + + const fbSupportedAsset = fbSupportedAssets.find( + ({ contractAddress, nativeAsset }) => + contractAddress.toLowerCase() === onchainId.toLowerCase() && + nativeAsset.toLowerCase() === externalNetwork.externalId.toLowerCase() + ) + if (!fbSupportedAsset) { + throw new AssetException({ + message: 'Fireblocks supported asset not found', + suggestedHttpStatusCode: HttpStatus.NOT_FOUND, + context: { transferAsset } + }) + } + + return { + network, + assetId: null, + assetExternalId: fbSupportedAsset.id + } + } + + return this.transferAssetService.resolve({ + findByExternalIdFallback, + findByOnchainIdFallback, + transferAsset, + provider: Provider.FIREBLOCKS + }) + } + private mapStatus(status: string): TransferStatus { const upperCasedStatus = status.toUpperCase() diff --git a/apps/vault/src/broker/core/provider/fireblocks/fireblocks.util.ts b/apps/vault/src/broker/core/provider/fireblocks/fireblocks.util.ts index abe9f01fb..f6267108e 100644 --- a/apps/vault/src/broker/core/provider/fireblocks/fireblocks.util.ts +++ b/apps/vault/src/broker/core/provider/fireblocks/fireblocks.util.ts @@ -6,6 +6,8 @@ import { ConnectionWithCredentials } from '../../type/connection.type' import { Provider } from '../../type/provider.type' import { FireblocksCredentials } from './fireblocks.type' +export const CONCURRENT_FIREBLOCKS_REQUESTS = 5 + export function validateConnection( connection: ConnectionWithCredentials ): asserts connection is ConnectionWithCredentials & { @@ -54,24 +56,63 @@ export function validateConnection( } } -export type FireblocksAccountExternalId = `fireblocks/vaults/${string}/wallets/${string}` -export function getFireblocksAssetWalletExternalId({ vaultId, assetId }: { vaultId: string; assetId: string }): string { - return `fireblocks/vaults/${vaultId}/wallets/${assetId}` +export type FireblocksAccountExternalId = `${string}-${string}` +export function getFireblocksAssetWalletExternalId({ + vaultId, + networkId +}: { + vaultId: string + networkId: string +}): string { + return `${vaultId.toString()}-${networkId}` } -export type FireblocksAssetWalletId = { vaultId: string; assetId: string } +export type FireblocksAssetWalletId = { vaultId: string; networkId: string } export function toFireblocksAssetWalletExternalId(externalId: string): FireblocksAssetWalletId { - const matches = externalId.match(/^fireblocks\/vaults\/([^/]+)\/wallets\/([^/]+)$/) + const matches = externalId.match(/^([^-]+)-([^-]+)$/) + if (!matches) { + throw new BrokerException({ + message: 'The external ID does not match composed standard for fireblocks', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, + context: { externalId } + }) + } + + const [, vaultId, networkId] = matches + return { + vaultId, + networkId + } +} + +export type FireblocksAddressExternalId = `${string}-${string}-${string}` +export function getFireblocksAssetAddressExternalId({ + vaultId, + networkId, + address +}: { + vaultId: string + networkId: string + address: string +}): string { + return `${vaultId}-${networkId}-${address}` +} + +export type FireblocksAssetAddressId = { vaultId: string; networkId: string; address: string } +export function toFireblocksAssetAddressExternalId(externalId: string): FireblocksAssetAddressId { + const matches = externalId.match(/^([^-]+)-([^-]+)-([^-]+)$/) if (!matches) { throw new BrokerException({ message: 'The external ID does not match composed standard for fireblocks', - suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, + context: { externalId } }) } - const [, vaultId, assetId] = matches + const [, vaultId, networkId, address] = matches return { vaultId, - assetId + networkId, + address } } diff --git a/apps/vault/src/broker/core/service/__test__/integration/asset.service.spec.ts b/apps/vault/src/broker/core/service/__test__/integration/asset.service.spec.ts index b6a6761ba..e3d84ae86 100644 --- a/apps/vault/src/broker/core/service/__test__/integration/asset.service.spec.ts +++ b/apps/vault/src/broker/core/service/__test__/integration/asset.service.spec.ts @@ -1,5 +1,6 @@ import { ConfigModule } from '@narval/config-module' import { LoggerModule } from '@narval/nestjs-shared' +import { CacheModule } from '@nestjs/cache-manager' import { Test } from '@nestjs/testing' import { PrismaClientKnownRequestError } from '@prisma/client/vault/runtime/library' import { load } from '../../../../../main.config' @@ -12,13 +13,13 @@ import { AssetException } from '../../../exception/asset.exception' import { Asset } from '../../../type/asset.type' import { Network } from '../../../type/network.type' import { Provider } from '../../../type/provider.type' -import { TransferAsset } from '../../../type/transfer.type' import { AssetService } from '../../asset.service' +import { NetworkService } from '../../network.service' describe(AssetService.name, () => { let testPrismaService: TestPrismaService let assetService: AssetService - let networkRepository: NetworkRepository + let networkService: NetworkService const ethereum: Network = { networkId: 'ETHEREUM', @@ -47,18 +48,19 @@ describe(AssetService.name, () => { imports: [ AppModule, PersistenceModule.register({ imports: [] }), + CacheModule.register(), LoggerModule.forTest(), ConfigModule.forRoot({ load: [load], isGlobal: true }) ], - providers: [AssetService, AssetRepository, NetworkRepository] + providers: [AssetService, AssetRepository, NetworkService, NetworkRepository] }).compile() testPrismaService = module.get(TestPrismaService) assetService = module.get(AssetService) - networkRepository = module.get(NetworkRepository) + networkService = module.get(NetworkService) await testPrismaService.truncateAll() }) @@ -69,7 +71,7 @@ describe(AssetService.name, () => { beforeEach(async () => { await testPrismaService.truncateAll() - await networkRepository.bulkCreate([ethereum]) + await networkService.bulkCreate([ethereum]) }) describe('bulkCreate', () => { @@ -115,79 +117,4 @@ describe(AssetService.name, () => { await expect(assetService.bulkCreate([usdc])).rejects.toThrow(PrismaClientKnownRequestError) }) }) - - describe('findTransferAsset', () => { - const baseTransferAsset: TransferAsset = { - assetId: usdc.assetId - } - - beforeEach(async () => { - await assetService.bulkCreate([usdc]) - }) - - it('finds by provider and externalId when externalAssetId is present', async () => { - const result = await assetService.findTransferAsset(Provider.FIREBLOCKS, { - ...baseTransferAsset, - externalAssetId: 'USDC' - }) - - expect(result).toEqual({ - ...usdc, - createdAt: expect.any(Date) - }) - }) - - it('finds by assetId when present', async () => { - const result = await assetService.findTransferAsset(Provider.FIREBLOCKS, { - ...baseTransferAsset - }) - - expect(result).toEqual({ - ...usdc, - createdAt: expect.any(Date) - }) - }) - - it('finds by onchainId when address and networkId are set', async () => { - const result = await assetService.findTransferAsset(Provider.FIREBLOCKS, { - address: usdc.onchainId as string, - networkId: ethereum.networkId - }) - - expect(result).toEqual({ - ...usdc, - createdAt: expect.any(Date) - }) - }) - - it('finds native asset when only networkId is set', async () => { - const nativeEth: Asset = { - assetId: 'ETH', - name: 'Ethereum', - symbol: 'ETH', - decimals: 18, - networkId: ethereum.networkId, - onchainId: null, - externalAssets: [] - } - await assetService.bulkCreate([nativeEth]) - - const result = await assetService.findTransferAsset(Provider.FIREBLOCKS, { - networkId: ethereum.networkId - }) - - expect(result).toEqual({ - ...nativeEth, - createdAt: expect.any(Date) - }) - }) - - it('throws AssetException when address is set but networkId is not', async () => { - await expect( - assetService.findTransferAsset(Provider.FIREBLOCKS, { - address: usdc.onchainId as string - }) - ).rejects.toThrow(AssetException) - }) - }) }) diff --git a/apps/vault/src/broker/core/service/__test__/integration/sync.service.spec.ts b/apps/vault/src/broker/core/service/__test__/integration/sync.service.spec.ts deleted file mode 100644 index 3aefff59c..000000000 --- a/apps/vault/src/broker/core/service/__test__/integration/sync.service.spec.ts +++ /dev/null @@ -1,437 +0,0 @@ -import { EncryptionModuleOptionProvider } from '@narval/encryption-module' -import { LoggerModule } from '@narval/nestjs-shared' -import { Alg, generateJwk, privateKeyToHex } from '@narval/signature' -import { INestApplication } from '@nestjs/common' -import { EventEmitter2 } from '@nestjs/event-emitter' -import { Test, TestingModule } from '@nestjs/testing' -import { randomUUID } from 'crypto' -import { mock } from 'jest-mock-extended' -import { v4 as uuid } from 'uuid' -import { ClientService } from '../../../../../client/core/service/client.service' -import { MainModule } from '../../../../../main.module' -import { ProvisionService } from '../../../../../provision.service' -import { KeyValueRepository } from '../../../../../shared/module/key-value/core/repository/key-value.repository' -import { InMemoryKeyValueRepository } from '../../../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' -import { TestPrismaService } from '../../../../../shared/module/persistence/service/test-prisma.service' -import { getTestRawAesKeyring } from '../../../../../shared/testing/encryption.testing' -import { testClient } from '../../../../__test__/util/mock-data' -import { SyncRepository } from '../../../../persistence/repository/sync.repository' -import { WalletRepository } from '../../../../persistence/repository/wallet.repository' -import { ANCHORAGE_TEST_API_BASE_URL } from '../../../provider/anchorage/__test__/server-mock/server' -import { Connection, ConnectionWithCredentials } from '../../../type/connection.type' -import { Account, Address, KnownDestination, Wallet } from '../../../type/indexed-resources.type' -import { Provider, SyncOperationType, SyncResult } from '../../../type/provider.type' -import { Sync, SyncStatus } from '../../../type/sync.type' -import { AccountService } from '../../account.service' -import { AddressService } from '../../address.service' -import { ConnectionService } from '../../connection.service' -import { KnownDestinationService } from '../../known-destination.service' -import { SyncService } from '../../sync.service' -import { WalletService } from '../../wallet.service' - -describe(SyncService.name, () => { - let app: INestApplication - let module: TestingModule - let testPrismaService: TestPrismaService - - let accountService: AccountService - let addressService: AddressService - let clientService: ClientService - let connection: ConnectionWithCredentials - let connectionService: ConnectionService - let knownDestinationService: KnownDestinationService - let provisionService: ProvisionService - let syncRepository: SyncRepository - let syncService: SyncService - let walletService: WalletRepository - - const clientId = 'test-client-id' - - beforeAll(async () => { - module = await Test.createTestingModule({ - imports: [MainModule] - }) - .overrideModule(LoggerModule) - .useModule(LoggerModule.forTest()) - .overrideProvider(KeyValueRepository) - .useValue(new InMemoryKeyValueRepository()) - .overrideProvider(EncryptionModuleOptionProvider) - .useValue({ - keyring: getTestRawAesKeyring() - }) - .overrideProvider(EventEmitter2) - .useValue(mock()) - .compile() - - app = module.createNestApplication() - - accountService = module.get(AccountService) - addressService = module.get(AddressService) - clientService = module.get(ClientService) - connectionService = module.get(ConnectionService) - knownDestinationService = module.get(KnownDestinationService) - provisionService = module.get(ProvisionService) - syncRepository = module.get(SyncRepository) - syncService = module.get(SyncService) - testPrismaService = module.get(TestPrismaService) - walletService = module.get(WalletService) - - await testPrismaService.truncateAll() - }) - - afterAll(async () => { - await testPrismaService.truncateAll() - await module.close() - await app.close() - }) - - beforeEach(async () => { - await testPrismaService.truncateAll() - - await provisionService.provision() - await clientService.save(testClient) - - connection = await connectionService.create(clientId, { - connectionId: uuid(), - provider: Provider.ANCHORAGE, - url: ANCHORAGE_TEST_API_BASE_URL, - credentials: { - apiKey: 'test-api-key', - privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) - } - }) - - await app.init() - }) - - describe('execute', () => { - let sync: Sync - let walletOne: Wallet - let walletTwo: Wallet - let accountOne: Account - let accountTwo: Account - let addressOne: Address - let addressTwo: Address - let kdOne: KnownDestination - let kdTwo: KnownDestination - - const now = new Date() - - beforeEach(async () => { - sync = await syncRepository.create({ - clientId, - syncId: randomUUID(), - connectionId: connection.connectionId, - createdAt: now, - status: SyncStatus.PROCESSING - }) - - walletOne = { - accounts: [], - clientId: connection.clientId, - connections: [Connection.parse(connection)], - createdAt: new Date('2023-01-01T00:00:00Z'), - externalId: 'external-id-one', - label: 'wallet one', - provider: connection.provider, - updatedAt: now, - walletId: randomUUID() - } - walletTwo = { - accounts: [], - clientId: connection.clientId, - connections: [Connection.parse(connection)], - createdAt: new Date('2024-01-01T00:00:00Z'), - externalId: 'external-id-two', - label: 'wallet two', - provider: connection.provider, - updatedAt: now, - walletId: randomUUID() - } - - accountOne = { - accountId: randomUUID(), - addresses: [], - clientId: connection.clientId, - createdAt: new Date('2023-01-01T00:00:00Z'), - externalId: 'account-external-id-one', - label: 'accoutn one', - networkId: 'BTC', - provider: Provider.ANCHORAGE, - updatedAt: now, - walletId: walletOne.walletId - } - accountTwo = { - accountId: randomUUID(), - addresses: [], - clientId: connection.clientId, - createdAt: new Date('2024-01-01T00:00:00Z'), - externalId: 'account-external-id-two', - label: 'accoutn two', - networkId: 'BTC', - provider: Provider.ANCHORAGE, - updatedAt: now, - walletId: walletOne.walletId - } - - addressOne = { - accountId: accountOne.accountId, - address: 'address-one', - addressId: randomUUID(), - clientId: connection.clientId, - createdAt: new Date('2023-01-01T00:00:00Z'), - externalId: 'address-one-external-id', - provider: Provider.ANCHORAGE, - updatedAt: now - } - addressTwo = { - accountId: accountOne.accountId, - address: 'address-two', - addressId: randomUUID(), - clientId: connection.clientId, - createdAt: new Date('2024-01-01T00:00:00Z'), - externalId: 'address-two-external-id', - provider: Provider.ANCHORAGE, - updatedAt: now - } - - kdOne = { - address: 'known-destination-one-address', - assetId: 'USDC', - clientId, - connections: [Connection.parse(connection)], - createdAt: new Date('2023-01-01T00:00:00Z'), - externalClassification: null, - externalId: 'known-destination-one-external-id', - knownDestinationId: randomUUID(), - label: 'known destination one', - networkId: 'ETH', - provider: Provider.ANCHORAGE, - updatedAt: now - } - kdTwo = { - address: 'known-destination-two-address', - assetId: 'USDC', - clientId, - connections: [Connection.parse(connection)], - createdAt: new Date('2024-01-01T00:00:00Z'), - externalClassification: null, - externalId: 'known-destination-two-external-id', - knownDestinationId: randomUUID(), - label: 'known destination two', - networkId: 'ETH', - provider: Provider.ANCHORAGE, - updatedAt: now - } - }) - - it('creates wallets', async () => { - const operations: SyncResult = { - wallets: [ - { type: SyncOperationType.CREATE, create: walletOne }, - { type: SyncOperationType.CREATE, create: walletTwo } - ], - accounts: [], - addresses: [], - knownDestinations: [] - } - - await syncService.execute(sync, operations) - - const { data: wallets } = await walletService.findAll(clientId) - - expect(wallets).toEqual([walletTwo, walletOne]) - }) - - it('updates wallets', async () => { - await walletService.bulkCreate([walletOne, walletTwo]) - - const operations: SyncResult = { - wallets: [ - { - type: SyncOperationType.UPDATE, - update: { - ...walletTwo, - label: 'updated wallet label' - } - } - ], - accounts: [], - addresses: [], - knownDestinations: [] - } - - await syncService.execute(sync, operations) - - const updatedWallet = await walletService.findById(clientId, walletTwo.walletId) - - expect(updatedWallet.label).toEqual('updated wallet label') - }) - - it.todo('deletes wallets') - - it('creates accounts', async () => { - const operations: SyncResult = { - wallets: [{ type: SyncOperationType.CREATE, create: walletOne }], - accounts: [ - { type: SyncOperationType.CREATE, create: accountOne }, - { type: SyncOperationType.CREATE, create: accountTwo } - ], - addresses: [], - knownDestinations: [] - } - - await syncService.execute(sync, operations) - - const { data: accounts } = await accountService.findAll(clientId) - - expect(accounts).toEqual([accountTwo, accountOne]) - }) - - it('update accounts', async () => { - await walletService.bulkCreate([walletOne]) - await accountService.bulkCreate([accountOne, accountTwo]) - - const operations: SyncResult = { - wallets: [], - accounts: [ - { - type: SyncOperationType.UPDATE, - update: { - ...accountOne, - label: 'updated account label' - } - } - ], - addresses: [], - knownDestinations: [] - } - - await syncService.execute(sync, operations) - - const updatedAccount = await accountService.findById(clientId, accountOne.accountId) - - expect(updatedAccount.label).toEqual('updated account label') - }) - - it.todo('deletes accounts') - - it('creates addresses', async () => { - const operations: SyncResult = { - wallets: [{ type: SyncOperationType.CREATE, create: walletOne }], - accounts: [{ type: SyncOperationType.CREATE, create: accountOne }], - addresses: [ - { type: SyncOperationType.CREATE, create: addressOne }, - { type: SyncOperationType.CREATE, create: addressTwo } - ], - knownDestinations: [] - } - - await syncService.execute(sync, operations) - - const { data: addresses } = await addressService.findAll(clientId) - - expect(addresses).toEqual([addressTwo, addressOne]) - }) - - it.todo('deletes addresses') - - it('creates known destinations', async () => { - const operations: SyncResult = { - wallets: [], - accounts: [], - addresses: [], - knownDestinations: [ - { type: SyncOperationType.CREATE, create: kdOne }, - { type: SyncOperationType.CREATE, create: kdTwo } - ] - } - - await syncService.execute(sync, operations) - - const { data: knownDestinations } = await knownDestinationService.findAll(clientId) - - expect(knownDestinations).toEqual([kdTwo, kdOne]) - }) - - it('updates known destinations', async () => { - await knownDestinationService.bulkCreate([kdOne, kdTwo]) - - const operations: SyncResult = { - wallets: [], - accounts: [], - addresses: [], - knownDestinations: [ - { - type: SyncOperationType.UPDATE, - update: { - ...kdTwo, - label: 'updated kown destination label' - } - } - ] - } - - await syncService.execute(sync, operations) - - const updatedKd = await knownDestinationService.findById(clientId, kdTwo.knownDestinationId) - - expect(updatedKd.label).toEqual('updated kown destination label') - }) - - it('deletes known destinations', async () => { - await knownDestinationService.bulkCreate([kdOne, kdTwo]) - - const operations: SyncResult = { - wallets: [], - accounts: [], - addresses: [], - knownDestinations: [ - { type: SyncOperationType.DELETE, entityId: kdOne.knownDestinationId }, - { type: SyncOperationType.DELETE, entityId: kdTwo.knownDestinationId } - ] - } - - await syncService.execute(sync, operations) - - const { data: knownDestinations } = await knownDestinationService.findAll(clientId) - - expect(knownDestinations).toEqual([]) - }) - - it('completes sync on success', async () => { - const operations: SyncResult = { - wallets: [], - accounts: [], - addresses: [], - knownDestinations: [] - } - const successfulSync = await syncService.execute(sync, operations) - - expect(successfulSync).toMatchObject({ - completedAt: expect.any(Date), - status: SyncStatus.SUCCESS - }) - }) - - it('fails sync on error', async () => { - const operations: SyncResult = { - wallets: [{ type: SyncOperationType.CREATE, create: {} as unknown as Wallet }], - accounts: [], - addresses: [], - knownDestinations: [] - } - const failedSync = await syncService.execute(sync, operations) - - expect(failedSync).toMatchObject({ - completedAt: expect.any(Date), - status: SyncStatus.FAILED, - error: { - name: expect.any(String), - message: expect.any(String), - traceId: undefined - } - }) - }) - }) -}) diff --git a/apps/vault/src/broker/core/service/__test__/integration/transfer-asset.service.spec.ts b/apps/vault/src/broker/core/service/__test__/integration/transfer-asset.service.spec.ts new file mode 100644 index 000000000..f4bb4f7fe --- /dev/null +++ b/apps/vault/src/broker/core/service/__test__/integration/transfer-asset.service.spec.ts @@ -0,0 +1,242 @@ +import { ConfigModule } from '@narval/config-module' +import { LoggerModule } from '@narval/nestjs-shared' +import { CacheModule } from '@nestjs/cache-manager' +import { Test } from '@nestjs/testing' +import { load } from '../../../../../main.config' +import { AppModule } from '../../../../../main.module' +import { PersistenceModule } from '../../../../../shared/module/persistence/persistence.module' +import { TestPrismaService } from '../../../../../shared/module/persistence/service/test-prisma.service' +import { AssetRepository } from '../../../../persistence/repository/asset.repository' +import { NetworkRepository } from '../../../../persistence/repository/network.repository' +import { AssetException } from '../../../exception/asset.exception' +import { Asset } from '../../../type/asset.type' +import { Network } from '../../../type/network.type' +import { Provider } from '../../../type/provider.type' +import { TransferAsset } from '../../../type/transfer.type' +import { getExternalAsset } from '../../../util/asset.util' +import { AssetService } from '../../asset.service' +import { NetworkService } from '../../network.service' +import { ResolvedTransferAsset, TransferAssetService } from '../../transfer-asset.service' + +describe(TransferAssetService.name, () => { + let testPrismaService: TestPrismaService + let assetService: AssetService + let networkService: NetworkService + let transferAssetService: TransferAssetService + + const ethereum: Network = { + networkId: 'ETHEREUM', + coinType: 60, + name: 'Ethereum', + externalNetworks: [ + { + provider: Provider.FIREBLOCKS, + externalId: 'FB_ETHEREUM' + } + ] + } + + const usdc: Asset = { + assetId: 'USDC', + name: 'USD Coin', + symbol: 'USDC', + decimals: 6, + networkId: ethereum.networkId, + onchainId: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', + externalAssets: [ + { + provider: Provider.FIREBLOCKS, + externalId: 'FB_USDC' + } + ] + } + + const usdcOnFireblocks = getExternalAsset(usdc, Provider.FIREBLOCKS) + + const ether: Asset = { + assetId: 'ETH', + name: 'Ethereum', + symbol: 'ETH', + decimals: 18, + networkId: ethereum.networkId, + onchainId: null, + externalAssets: [ + { + provider: Provider.FIREBLOCKS, + externalId: 'FB_ETH' + } + ] + } + + const etherOnFireblocks = getExternalAsset(ether, Provider.FIREBLOCKS) + + beforeAll(async () => { + const module = await Test.createTestingModule({ + imports: [ + AppModule, + PersistenceModule.register({ imports: [] }), + CacheModule.register(), + LoggerModule.forTest(), + ConfigModule.forRoot({ + load: [load], + isGlobal: true + }) + ], + providers: [AssetService, AssetRepository, NetworkService, NetworkRepository, TransferAssetService] + }).compile() + + testPrismaService = module.get(TestPrismaService) + assetService = module.get(AssetService) + networkService = module.get(NetworkService) + transferAssetService = module.get(TransferAssetService) + + await testPrismaService.truncateAll() + }) + + afterAll(async () => { + await testPrismaService.truncateAll() + }) + + beforeEach(async () => { + await testPrismaService.truncateAll() + await networkService.bulkCreate([ethereum]) + await assetService.bulkCreate([usdc, ether]) + }) + + describe('resolve', () => { + const baseTransferAsset: TransferAsset = { + assetId: usdc.assetId + } + + it('resolves by provider and externalId when externalAssetId is present', async () => { + const resolvedTransferAsset = await transferAssetService.resolve({ + provider: Provider.FIREBLOCKS, + transferAsset: { + ...baseTransferAsset, + externalAssetId: usdcOnFireblocks?.externalId + } + }) + + expect(resolvedTransferAsset).toEqual({ + network: expect.objectContaining(ethereum), + assetId: usdc.assetId, + assetExternalId: usdcOnFireblocks?.externalId + }) + }) + + it('calls fallback when asset is not found by externalId', async () => { + const unlistedAssetId = 'UNLISTED_ASSET_ID' + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const findByExternalIdFallback = async (_externalAssetId: string): Promise => { + return { + network: ethereum, + assetId: null, + assetExternalId: unlistedAssetId + } + } + + const resolvedTransferAsset = await transferAssetService.resolve({ + provider: Provider.FIREBLOCKS, + findByExternalIdFallback, + transferAsset: { + ...baseTransferAsset, + externalAssetId: 'UNLISTED_ASSET_ID' + } + }) + + expect(resolvedTransferAsset).toEqual({ + network: ethereum, + assetId: null, + assetExternalId: unlistedAssetId + }) + }) + + it('resolves by assetId when present', async () => { + const resolvedTransferAsset = await transferAssetService.resolve({ + provider: Provider.FIREBLOCKS, + transferAsset: baseTransferAsset + }) + + expect(resolvedTransferAsset).toEqual({ + network: expect.objectContaining(ethereum), + assetId: usdc.assetId, + assetExternalId: usdcOnFireblocks?.externalId + }) + }) + + it('resolves by onchainId when address and networkId are set', async () => { + const resolvedTransferAsset = await transferAssetService.resolve({ + provider: Provider.FIREBLOCKS, + transferAsset: { + address: usdc.onchainId as string, + networkId: ethereum.networkId + } + }) + + expect(resolvedTransferAsset).toEqual({ + network: expect.objectContaining(ethereum), + assetId: usdc.assetId, + assetExternalId: usdcOnFireblocks?.externalId + }) + }) + + it('calls fallback when asset is not found by address and networkId', async () => { + const unlistedAssetAddress = 'UNLISTED_ASSET_ADDRESS' + + const findByOnchainIdFallback = async ( + // eslint-disable-next-line @typescript-eslint/no-unused-vars + _network: Network, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + _externalAssetId: string + ): Promise => { + return { + network: ethereum, + assetId: null, + assetExternalId: unlistedAssetAddress + } + } + + const resolvedTransferAsset = await transferAssetService.resolve({ + provider: Provider.FIREBLOCKS, + findByOnchainIdFallback, + transferAsset: { + networkId: ethereum.networkId, + address: unlistedAssetAddress + } + }) + + expect(resolvedTransferAsset).toEqual({ + network: ethereum, + assetId: null, + assetExternalId: unlistedAssetAddress + }) + }) + + it('resolves native asset when only networkId is set', async () => { + const resolvedTransferAsset = await transferAssetService.resolve({ + provider: Provider.FIREBLOCKS, + transferAsset: { + networkId: ethereum.networkId + } + }) + + expect(resolvedTransferAsset).toEqual({ + network: expect.objectContaining(ethereum), + assetId: ether.assetId, + assetExternalId: etherOnFireblocks?.externalId + }) + }) + + it('throws AssetException when address is set but networkId is not', async () => { + await expect( + transferAssetService.resolve({ + provider: Provider.FIREBLOCKS, + transferAsset: { + address: usdc.onchainId as string + } + }) + ).rejects.toThrow(AssetException) + }) + }) +}) diff --git a/apps/vault/src/broker/core/service/account.service.ts b/apps/vault/src/broker/core/service/account.service.ts index 749a0afc6..27837aa06 100644 --- a/apps/vault/src/broker/core/service/account.service.ts +++ b/apps/vault/src/broker/core/service/account.service.ts @@ -2,6 +2,7 @@ import { PaginatedResult, PaginationOptions } from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' import { AccountRepository, FindAllOptions, UpdateAccount } from '../../persistence/repository/account.repository' import { Account, Address } from '../type/indexed-resources.type' +import { ConnectionScope } from '../type/scope.type' @Injectable() export class AccountService { @@ -15,10 +16,6 @@ export class AccountService { return this.accountRepository.findAddressesByAccountId(clientId, AccountId, options) } - async findAllPaginated(clientId: string, options?: FindAllOptions): Promise> { - return this.accountRepository.findAll(clientId, options) - } - async bulkCreate(accounts: Account[]): Promise { return this.accountRepository.bulkCreate(accounts) } @@ -31,11 +28,11 @@ export class AccountService { return this.accountRepository.update(updateAccount) } - async findAll(clientId: string, options?: FindAllOptions): Promise> { - return this.accountRepository.findAll(clientId, options) + async findAll(scope: ConnectionScope, options?: FindAllOptions): Promise> { + return this.accountRepository.findAll(scope, options) } - async findById(clientId: string, accountId: string): Promise { - return this.accountRepository.findById(clientId, accountId) + async findById(scope: ConnectionScope, accountId: string): Promise { + return this.accountRepository.findById(scope, accountId) } } diff --git a/apps/vault/src/broker/core/service/address.service.ts b/apps/vault/src/broker/core/service/address.service.ts index ba3ad4c28..89eaaaa51 100644 --- a/apps/vault/src/broker/core/service/address.service.ts +++ b/apps/vault/src/broker/core/service/address.service.ts @@ -3,6 +3,7 @@ import { HttpStatus, Injectable } from '@nestjs/common' import { AddressRepository, FindAllOptions } from '../../persistence/repository/address.repository' import { BrokerException } from '../exception/broker.exception' import { Address } from '../type/indexed-resources.type' +import { ConnectionScope } from '../type/scope.type' @Injectable() export class AddressService { @@ -12,20 +13,16 @@ export class AddressService { return this.addressRepository.findByClientId(clientId, options) } - async getAddress(clientId: string, AddressId: string): Promise
{ - return this.addressRepository.findById(clientId, AddressId) - } - async bulkCreate(addresses: Address[]): Promise { return this.addressRepository.bulkCreate(addresses) } - async findAll(clientId: string, opts?: FindAllOptions): Promise> { - return this.addressRepository.findAll(clientId, opts) + async findAll(scope: ConnectionScope, opts?: FindAllOptions): Promise> { + return this.addressRepository.findAll(scope, opts) } - async findById(clientId: string, addressId: string): Promise
{ - return this.addressRepository.findById(clientId, addressId) + async findById(scope: ConnectionScope, addressId: string): Promise
{ + return this.addressRepository.findById(scope, addressId) } async findByAddressAndNetwork(clientId: string, address: string, networkId: string): Promise
{ diff --git a/apps/vault/src/broker/core/service/asset.service.ts b/apps/vault/src/broker/core/service/asset.service.ts index b6dc82c50..8ce9ecf49 100644 --- a/apps/vault/src/broker/core/service/asset.service.ts +++ b/apps/vault/src/broker/core/service/asset.service.ts @@ -1,9 +1,11 @@ -import { HttpStatus, Injectable } from '@nestjs/common' +import { LoggerService } from '@narval/nestjs-shared' +import { CACHE_MANAGER, Cache } from '@nestjs/cache-manager' +import { HttpStatus, Inject, Injectable } from '@nestjs/common' +import { uniq } from 'lodash' import { AssetRepository } from '../../persistence/repository/asset.repository' import { AssetException } from '../exception/asset.exception' import { Asset, ExternalAsset } from '../type/asset.type' import { Provider } from '../type/provider.type' -import { TransferAsset } from '../type/transfer.type' import { isNativeAsset } from '../util/asset.util' type FindAllOptions = { @@ -14,14 +16,20 @@ type FindAllOptions = { @Injectable() export class AssetService { - constructor(private readonly assetRepository: AssetRepository) {} + constructor( + private readonly assetRepository: AssetRepository, + private readonly logger: LoggerService, + @Inject(CACHE_MANAGER) private cacheManager: Cache + ) {} async bulkCreate(assets: Asset[]): Promise { const createdAssets: Asset[] = [] for (const asset of assets) { if (isNativeAsset(asset)) { - const native = await this.findNative(asset.networkId) + // Bypass cache and query repository directly to ensure we check the + // source of truth. + const native = await this.assetRepository.findNative(asset.networkId) if (native) { throw new AssetException({ @@ -35,6 +43,18 @@ export class AssetService { createdAssets.push(await this.assetRepository.create(asset)) } + const providers = uniq( + createdAssets.flatMap(({ externalAssets }) => externalAssets).flatMap(({ provider }) => provider) + ) + + for (const provider of providers) { + const key = this.getListCacheKey(provider) + + this.logger.log('Delete asset list cache after bulk create', { key }) + + await this.cacheManager.del(key) + } + return createdAssets } @@ -52,46 +72,128 @@ export class AssetService { } async findAll(options?: FindAllOptions): Promise { - return this.assetRepository.findAll(options) + // IMPORTANT: If you add new filters to the findAll method, you MUST + // rethink the cache strategy. This will only work as long there's a single + // filter. + const key = this.getListCacheKey(options?.filters?.provider) + + this.logger.log('Read asset list from cache', { key }) + + const cached = await this.cacheManager.get(key) + + if (cached) { + return cached + } + + this.logger.log('Asset list cache not found. Fallback to database', { key }) + + const assets = await this.assetRepository.findAll(options) + + await this.cacheManager.set(key, assets) + + return assets + } + + private getListCacheKey(provider?: Provider) { + if (provider) { + return `asset:list:${provider}` + } + + return 'asset:list' + } + + async buildProviderExternalIdIndex(provider: Provider): Promise> { + const assets = await this.findAll({ filters: { provider } }) + const index = new Map() + + for (const asset of assets) { + for (const externalAsset of asset.externalAssets) { + if (externalAsset.provider === provider) { + index.set(externalAsset.externalId, asset) + } + } + } + + return index } async findById(assetId: string): Promise { - return this.assetRepository.findById(assetId) + const key = `asset:${assetId.toLowerCase()}` + + this.logger.log('Read asset by ID from cache', { key }) + + const cached = await this.cacheManager.get(key) + + if (cached) { + return cached + } + + this.logger.log('Asset cache not found by ID. Fallback to database', { key }) + + const asset = await this.assetRepository.findById(assetId) + + await this.cacheManager.set(key, asset) + + return asset } async findByExternalId(provider: Provider, externalId: string): Promise { - return this.assetRepository.findByExternalId(provider, externalId) + const key = `asset:${provider}:${externalId.toLowerCase()}` + + this.logger.log('Read asset by provider and external ID from cache', { key }) + + const cached = await this.cacheManager.get(key) + + if (cached) { + return cached + } + + this.logger.log('Asset cache not found by provider and external ID. Fallback to database', { key }) + + const asset = await this.assetRepository.findByExternalId(provider, externalId) + + await this.cacheManager.set(key, asset) + + return asset } async findByOnchainId(networkId: string, onchainId: string): Promise { - return this.assetRepository.findByOnchainId(networkId, onchainId.toLowerCase()) + const key = `asset:${networkId.toLowerCase()}:${onchainId.toLowerCase()}` + + this.logger.log('Read asset by network and onchain ID from cache', { key }) + + const cached = await this.cacheManager.get(key) + + if (cached) { + return cached + } + + this.logger.log('Asset cache not found by network and onchain ID. Fallback to database', { key }) + + const asset = await this.assetRepository.findByOnchainId(networkId, onchainId.toLowerCase()) + + await this.cacheManager.set(key, asset) + + return asset } async findNative(networkId: string): Promise { - return this.assetRepository.findNative(networkId) - } + const key = `asset:native:${networkId.toLowerCase()}` - async findTransferAsset(provider: Provider, transferAsset: TransferAsset): Promise { - if (transferAsset.externalAssetId) { - return this.findByExternalId(provider, transferAsset.externalAssetId) - } + this.logger.log('Read native asset from cache', { key }) - if (transferAsset.assetId) { - return this.findById(transferAsset.assetId) - } + const cached = await this.cacheManager.get(key) - if (!transferAsset.networkId) { - throw new AssetException({ - message: 'Cannot find transfer asset without network ID', - suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, - context: { asset: transferAsset } - }) + if (cached) { + return cached } - if (transferAsset.address) { - return this.findByOnchainId(transferAsset.networkId, transferAsset.address) - } + this.logger.log('Native asset cache not found. Fallback to database', { key }) + + const asset = await this.assetRepository.findNative(networkId) + + await this.cacheManager.set(key, asset) - return this.findNative(transferAsset.networkId) + return asset } } diff --git a/apps/vault/src/broker/core/service/connection.service.ts b/apps/vault/src/broker/core/service/connection.service.ts index b8df4d717..018ff56d9 100644 --- a/apps/vault/src/broker/core/service/connection.service.ts +++ b/apps/vault/src/broker/core/service/connection.service.ts @@ -14,6 +14,8 @@ import { ConnectionInvalidStatusException } from '../exception/connection-invali import { NotFoundException } from '../exception/not-found.exception' import { AnchorageCredentialService } from '../provider/anchorage/anchorage-credential.service' import { AnchorageCredentials, AnchorageInputCredentials } from '../provider/anchorage/anchorage.type' +import { BitgoCredentialService } from '../provider/bitgo/bitgo-credential.service' +import { BitgoCredentials, BitgoInputCredentials } from '../provider/bitgo/bitgo.type' import { FireblocksCredentialService } from '../provider/fireblocks/fireblocks-credential.service' import { FireblocksCredentials, FireblocksInputCredentials } from '../provider/fireblocks/fireblocks.type' import { @@ -33,11 +35,13 @@ import { Provider, ProviderCredentialService } from '../type/provider.type' type ProviderInputCredentialsMap = { anchorage: AnchorageInputCredentials fireblocks: FireblocksInputCredentials + bitgo: BitgoInputCredentials } type ProviderCredentialsMap = { anchorage: AnchorageCredentials fireblocks: FireblocksCredentials + bitgo: BitgoCredentials } @Injectable() @@ -54,11 +58,13 @@ export class ConnectionService { private readonly logger: LoggerService, // Provider Specific Credential Services fireblocksCredentialService: FireblocksCredentialService, - anchorageCredentialService: AnchorageCredentialService + anchorageCredentialService: AnchorageCredentialService, + bitgoCredentialService: BitgoCredentialService ) { this.providerCredentialServices = { [Provider.ANCHORAGE]: anchorageCredentialService, - [Provider.FIREBLOCKS]: fireblocksCredentialService + [Provider.FIREBLOCKS]: fireblocksCredentialService, + [Provider.BITGO]: bitgoCredentialService } } @@ -136,7 +142,7 @@ export class ConnectionService { // If a private key is provided in the input, it overrides the existing // private and public key. Otherwise, adds the API key to the // generated credentials. - if (inputCredentials.privateKey) { + if ('privateKey' in inputCredentials && inputCredentials.privateKey) { this.logger.log('Existing private key is being overridden with a new one', { clientId, connectionId: connection.connectionId @@ -293,7 +299,11 @@ export class ConnectionService { return Connection.parse(update) } - private async getInputCredentials(provider: Provider, clientId: string, input: CreateConnection | UpdateConnection) { + private async getInputCredentials

( + provider: P, + clientId: string, + input: CreateConnection | UpdateConnection + ): Promise { if (input.encryptedCredentials) { const raw = await this.encryptionKeyService.decrypt(clientId, input.encryptedCredentials) const json = JSON.parse(raw) diff --git a/apps/vault/src/broker/core/service/known-destination.service.ts b/apps/vault/src/broker/core/service/known-destination.service.ts index 1eb1a68e4..c1dbd8ca5 100644 --- a/apps/vault/src/broker/core/service/known-destination.service.ts +++ b/apps/vault/src/broker/core/service/known-destination.service.ts @@ -1,48 +1,68 @@ -import { PaginatedResult, PaginationOptions } from '@narval/nestjs-shared' -import { Injectable } from '@nestjs/common' +import { LoggerService, PaginatedResult, TraceService } from '@narval/nestjs-shared' +import { HttpStatus, Inject, Injectable, NotImplementedException } from '@nestjs/common' +import { SpanStatusCode } from '@opentelemetry/api' +import { OTEL_ATTR_CONNECTION_PROVIDER } from '../../shared/constant' +import { BrokerException } from '../exception/broker.exception' +import { AnchorageKnownDestinationService } from '../provider/anchorage/anchorage-known-destination.service' +import { FireblocksKnownDestinationService } from '../provider/fireblocks/fireblocks-known-destination.service' +import { isActiveConnection } from '../type/connection.type' +import { KnownDestination as KnownDestinationNext } from '../type/known-destination.type' import { - FindAllOptions, - KnownDestinationRepository, - UpdateKnownDestination -} from '../../persistence/repository/known-destination.repository' -import { KnownDestination } from '../type/indexed-resources.type' + Provider, + ProviderKnownDestinationPaginationOptions, + ProviderKnownDestinationService +} from '../type/provider.type' +import { ConnectionScope } from '../type/scope.type' +import { ConnectionService } from './connection.service' @Injectable() export class KnownDestinationService { - constructor(private readonly knownDestinationRepository: KnownDestinationRepository) {} + constructor( + private readonly connectionService: ConnectionService, + private readonly anchorageKnownDestinationService: AnchorageKnownDestinationService, + private readonly fireblocksKnownDestinationService: FireblocksKnownDestinationService, + private readonly logger: LoggerService, + @Inject(TraceService) private readonly traceService: TraceService + ) {} - async getKnownDestinations( - clientId: string, - options?: PaginationOptions - ): Promise> { - return this.knownDestinationRepository.findByClientId(clientId, options) - } + async findAll( + { clientId, connectionId }: ConnectionScope, + options?: ProviderKnownDestinationPaginationOptions + ): Promise> { + this.logger.log('Find provider known destinations', { clientId, connectionId, options }) - async getKnownDestination(clientId: string, KnownDestinationId: string): Promise { - return this.knownDestinationRepository.findById(clientId, KnownDestinationId) - } + return this.traceService.startActiveSpan(`${KnownDestinationService.name}.send`, async (span) => { + const connection = await this.connectionService.findWithCredentialsById(clientId, connectionId) - async bulkCreate(knownDestinations: KnownDestination[]): Promise { - return this.knownDestinationRepository.bulkCreate(knownDestinations) - } + span.setAttribute(OTEL_ATTR_CONNECTION_PROVIDER, connection.provider) - async bulkDelete(knownDestinationIds: string[]): Promise { - return this.knownDestinationRepository.bulkDelete(knownDestinationIds) - } + if (isActiveConnection(connection)) { + return this.getProviderKnownDestinationService(connection.provider).findAll(connection, options) + } - async bulkUpdate(knownDestinations: KnownDestination[]): Promise { - return Promise.all(knownDestinations.map((knownDestination) => this.update(knownDestination))) - } + span.setStatus({ + code: SpanStatusCode.ERROR, + message: 'Cannot find an active connection for the source' + }) - async update(knownDestination: UpdateKnownDestination): Promise { - return this.knownDestinationRepository.update(knownDestination) - } + span.end() - async findAll(clientId: string, opts?: FindAllOptions): Promise> { - return this.knownDestinationRepository.findAll(clientId, opts) + throw new BrokerException({ + message: 'Cannot find an active connection for the source', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, + context: { connectionId, clientId } + }) + }) } - async findById(clientId: string, knownDestinationId: string): Promise { - return this.knownDestinationRepository.findById(clientId, knownDestinationId) + getProviderKnownDestinationService(provider: Provider): ProviderKnownDestinationService { + switch (provider) { + case Provider.ANCHORAGE: + return this.anchorageKnownDestinationService + case Provider.FIREBLOCKS: + return this.fireblocksKnownDestinationService + default: + throw new NotImplementedException(`Unsupported known destination for provider ${provider}`) + } } } diff --git a/apps/vault/src/broker/core/service/network.service.ts b/apps/vault/src/broker/core/service/network.service.ts new file mode 100644 index 000000000..969a0480f --- /dev/null +++ b/apps/vault/src/broker/core/service/network.service.ts @@ -0,0 +1,131 @@ +import { LoggerService } from '@narval/nestjs-shared' +import { CACHE_MANAGER, Cache } from '@nestjs/cache-manager' +import { Inject, Injectable } from '@nestjs/common' +import { uniq } from 'lodash' +import { FindAllOptions, NetworkRepository } from '../../persistence/repository/network.repository' +import { ExternalNetwork, Network } from '../type/network.type' +import { Provider } from '../type/provider.type' + +@Injectable() +export class NetworkService { + constructor( + private readonly networkRepository: NetworkRepository, + private readonly logger: LoggerService, + @Inject(CACHE_MANAGER) private cacheManager: Cache + ) {} + + async bulkCreate(networks: Network[]): Promise { + await this.networkRepository.bulkCreate(networks) + + const providers = uniq( + networks.flatMap(({ externalNetworks }) => externalNetworks).flatMap(({ provider }) => provider) + ) + + for (const provider of providers) { + await this.cacheManager.del(this.getListCacheKey(provider)) + } + + return networks + } + + async addExternalNetwork(networkId: string, externalNetwork: ExternalNetwork): Promise { + await this.networkRepository.addExternalNetwork(networkId, externalNetwork) + + await this.cacheManager.del(this.getListCacheKey(externalNetwork.provider)) + + return externalNetwork + } + + async findAll(options?: FindAllOptions): Promise { + // IMPORTANT: If you add new filters to the findAll method, you MUST + // rethink the cache strategy. This will only work as long there's a single + // filter. + const key = this.getListCacheKey(options?.filters?.provider) + + this.logger.log('Read network list from cache', { key }) + + const cached = await this.cacheManager.get(key) + + if (cached) { + return cached + } + + this.logger.log('Network list cache not found. Fallback to database', { key }) + + const assets = this.networkRepository.findAll(options) + + await this.cacheManager.set(key, assets) + + return assets + } + + private getListCacheKey(provider?: Provider) { + if (provider) { + return `network:list:${provider}` + } + + return 'network:list' + } + + async findById(networkId: string): Promise { + const key = `network:${networkId.toLowerCase()}` + + this.logger.log('Read network by ID from cache', { key }) + + const cached = await this.cacheManager.get(key) + + if (cached) { + return cached + } + + this.logger.log('Network cache not found by ID. Fallback to database', { key }) + + const asset = await this.networkRepository.findById(networkId) + + await this.cacheManager.set(key, asset) + + return asset + } + + async findByExternalId(provider: Provider, externalId: string): Promise { + const key = `network:${provider}:${externalId.toLowerCase()}` + + this.logger.log('Read network by provider and external ID from cache', { key }) + + const cached = await this.cacheManager.get(key) + + if (cached) { + return cached + } + + this.logger.log('Network cache not found by provider and external ID. Fallback to database', { key }) + + const asset = await this.networkRepository.findByExternalId(provider, externalId) + + await this.cacheManager.set(key, asset) + + return asset + } + + /** + * Builds index structures for O(1) lookups of networks. + * + * This is a one-time O(n) operation at initialization to avoid O(n) array + * traversals on subsequent queries. All lookups become O(1) after indexing + * at the cost of O(n) additional memory. + */ + async buildProviderExternalIdIndex(provider: Provider): Promise> { + const networks = await this.findAll({ filters: { provider } }) + const index = new Map() + + for (const network of networks) { + for (const externalNetwork of network.externalNetworks) { + if (externalNetwork.provider === provider) { + index.set(externalNetwork.externalId, network) + } + } + } + + return index + } +} diff --git a/apps/vault/src/broker/core/service/proxy.service.ts b/apps/vault/src/broker/core/service/proxy.service.ts index 1a82e65c3..b8713db55 100644 --- a/apps/vault/src/broker/core/service/proxy.service.ts +++ b/apps/vault/src/broker/core/service/proxy.service.ts @@ -4,10 +4,11 @@ import { AnchorageProxyService } from '../provider/anchorage/anchorage-proxy.ser import { FireblocksProxyService } from '../provider/fireblocks/fireblocks-proxy.service' import { isActiveConnection } from '../type/connection.type' import { Provider, ProviderProxyService, ProxyResponse } from '../type/provider.type' +import { ConnectionScope } from '../type/scope.type' import { ConnectionService } from './connection.service' type ProxyRequestOptions = { - connectionId: string + // eslint-disable-next-line @typescript-eslint/no-explicit-any data?: any endpoint: string method: string @@ -21,8 +22,7 @@ export class ProxyService { private readonly fireblocksProxyService: FireblocksProxyService ) {} - async forward(clientId: string, options: ProxyRequestOptions): Promise { - const { connectionId } = options + async forward({ clientId, connectionId }: ConnectionScope, options: ProxyRequestOptions): Promise { const connection = await this.connectionRepository.findById(clientId, connectionId) if (!isActiveConnection(connection)) { diff --git a/apps/vault/src/broker/core/service/raw-account.service.ts b/apps/vault/src/broker/core/service/raw-account.service.ts new file mode 100644 index 000000000..2faa402ce --- /dev/null +++ b/apps/vault/src/broker/core/service/raw-account.service.ts @@ -0,0 +1,249 @@ +import { LoggerService, PaginatedResult, PaginationOptions } from '@narval/nestjs-shared' +import { HttpStatus, Injectable } from '@nestjs/common' +import { z } from 'zod' +import { AnchorageClient } from '../../http/client/anchorage.client' +import { FireblocksClient } from '../../http/client/fireblocks.client' +import { AccountRepository } from '../../persistence/repository/account.repository' +import { AssetRepository } from '../../persistence/repository/asset.repository' +import { NetworkRepository } from '../../persistence/repository/network.repository' +import { BrokerException } from '../exception/broker.exception' +import { validateConnection as validateAnchorageConnection } from '../provider/anchorage/anchorage.util' +import { validateConnection as validateFireblocksConnection } from '../provider/fireblocks/fireblocks.util' +import { Asset } from '../type/asset.type' +import { Network } from '../type/network.type' +import { Provider } from '../type/provider.type' +import { ConnectionService } from './connection.service' + +export const RawAccount = z.object({ + provider: z.nativeEnum(Provider), + externalId: z.string(), + label: z.string(), + subLabel: z.string().optional(), + defaultAddress: z.string().optional().describe('The deposit address for the account, if there are multiple'), + network: Network.nullish().describe('The network of the account'), + assets: z + .array( + z.object({ + asset: Asset, + balance: z.string().optional().describe('The balance of the this asset in this account') + }) + ) + .optional() + .describe('The assets of the account') +}) +export type RawAccount = z.infer + +type FindAllOptions = { + filters?: { + networkId?: string + assetId?: string + namePrefix?: string + nameSuffix?: string + includeAddress?: boolean + } + pagination?: PaginationOptions +} + +@Injectable() +export class RawAccountService { + constructor( + private readonly accountRepository: AccountRepository, + private readonly connectionService: ConnectionService, + private readonly networkRepository: NetworkRepository, + private readonly assetRepository: AssetRepository, + private readonly anchorageClient: AnchorageClient, + private readonly fireblocksClient: FireblocksClient, + private readonly loggerService: LoggerService + ) {} + + async findAllPaginated( + clientId: string, + connectionId: string, + options?: FindAllOptions + ): Promise> { + const connection = await this.connectionService.findWithCredentialsById(clientId, connectionId) + + const assetFilter = options?.filters?.assetId + ? await this.assetRepository.findById(options.filters.assetId) + : undefined + const networkFilter = options?.filters?.networkId + ? await this.networkRepository.findById(options.filters.networkId) + : undefined + + if (connection.provider === Provider.ANCHORAGE) { + validateAnchorageConnection(connection) + const wallets = await this.anchorageClient.getWallets({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey + }) + + // Anchorage doesn't have filtering, so we fetch everything & then filter in-memory. + // TODO: add caching to make this faster for repeat queries. + const rawAccounts = await Promise.all( + wallets.map(async (wallet) => ({ + provider: Provider.ANCHORAGE, + externalId: wallet.walletId, + label: wallet.walletName, + subLabel: wallet.vaultName, + defaultAddress: wallet.depositAddress.address, + network: await this.networkRepository.findByExternalId(Provider.ANCHORAGE, wallet.networkId), + assets: await Promise.all( + wallet.assets.map(async (a) => ({ + asset: await this.assetRepository.findByExternalId(Provider.ANCHORAGE, a.assetType), + balance: a.totalBalance?.quantity + })) + ).then((a) => a.filter((a) => !!a.asset)) + })) + ) + + // Filter the raw accounts based on the filters + const filteredRawAccounts = rawAccounts.filter((a) => { + let matches = true + if (networkFilter) { + matches = a.network?.networkId === networkFilter.networkId + if (!matches) return false + } + if (assetFilter) { + matches = a.assets?.some((a) => a.asset?.assetId === assetFilter.assetId) + if (!matches) return false + } + if (options?.filters?.namePrefix) { + matches = a.label.toLowerCase().startsWith(options.filters.namePrefix.toLowerCase()) + if (!matches) return false + } + if (options?.filters?.nameSuffix) { + matches = a.subLabel.toLowerCase().endsWith(options.filters.nameSuffix.toLowerCase()) + if (!matches) return false + } + return true + }) + + return { + data: filteredRawAccounts.map((a) => RawAccount.parse(a)) + } + } else if (connection.provider === Provider.FIREBLOCKS) { + validateFireblocksConnection(connection) + let fbNetworkFilter: string | undefined + if (networkFilter) { + // Fireblocks doesn't have network filtering, so we'll find the base asset for the network and filter by that. + const baseAsset = await this.assetRepository.findNative(networkFilter.networkId) + fbNetworkFilter = baseAsset?.externalAssets.find((a) => a.provider === Provider.FIREBLOCKS)?.externalId + if (!fbNetworkFilter) { + throw new BrokerException({ + message: 'Fireblocks does not support this network', + suggestedHttpStatusCode: HttpStatus.BAD_REQUEST, + context: { + networkId: networkFilter.networkId + } + }) + } + } + const fbAssetFilter = + assetFilter?.externalAssets.find((a) => a.provider === Provider.FIREBLOCKS)?.externalId || fbNetworkFilter + const response = await this.fireblocksClient.getVaultAccountsV2({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey, + options: { + namePrefix: options?.filters?.namePrefix, + nameSuffix: options?.filters?.nameSuffix, + limit: options?.pagination?.take, + after: options?.pagination?.cursor?.id, // TODO: Our cursor has too strict of typing, it can't pass-through + assetId: fbAssetFilter + } + }) + // In Fireblocks, a VaultAccount is not network-specific, so we'll map the AssetWallets to get what we call "Accounts" + const rawAccounts = await Promise.all( + response.accounts.map(async (account) => { + const assets = await Promise.all( + account.assets + .filter((a) => !a.hiddenOnUI) + .map(async (asset) => ({ + assetId: asset.id, + balance: asset.available, + asset: await this.assetRepository.findByExternalId(Provider.FIREBLOCKS, asset.id) + })) + ) + // Group assets by network + const assetsByNetwork = assets.reduce( + (acc, asset) => { + if (!asset.asset?.networkId) return acc // Skip assets without a networkId + if (!acc[asset.asset.networkId]) { + acc[asset.asset.networkId] = [] + } + acc[asset.asset.networkId].push(asset) + return acc + }, + {} as Record + ) + + // Create an account for each network that has assets + return await Promise.all( + Object.entries(assetsByNetwork).map(async ([networkId, networkAssets]) => { + const network = await this.networkRepository.findById(networkId) + return { + provider: Provider.FIREBLOCKS, + externalId: `${account.id}-${networkId}`, + label: account.name || account.id, + subLabel: networkId, + defaultAddress: '', // Fireblocks doesn't provide a default address at account level + network, + assets: networkAssets + .map((a) => + a.asset + ? { + asset: a.asset, + balance: a.balance + } + : undefined + ) + .filter((a) => !!a) + } + }) + ) + }) + ).then((a) => a.flat()) + + // Fetch the Address for the Base Asset + const rawAccountsWithAddresses = await Promise.all( + rawAccounts.map(async (account) => { + if (!account.network) return account + + // Get the fireblocks base asset for the network + const fireblocksBaseAsset = await this.assetRepository + .findNative(account.network?.networkId) + .then((a) => a?.externalAssets.find((a) => a.provider === Provider.FIREBLOCKS)?.externalId) + if (!fireblocksBaseAsset) return account + + // Fetch the base asset addresses. + const addresses = options?.filters?.includeAddress + ? await this.fireblocksClient.getAddresses({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey, + vaultAccountId: account.externalId.split('-')[0], + assetId: fireblocksBaseAsset + }) + : [] + return { + ...account, + defaultAddress: addresses[0]?.address || undefined + } + }) + ) + + return { + data: rawAccountsWithAddresses.map((account) => RawAccount.parse(account)) // TODO: don't re-do the parse. It's an asset typedef because the .filter isn't inferred that it's no longer nullable. + } + } + + throw new BrokerException({ + message: 'Unsupported provider', + suggestedHttpStatusCode: HttpStatus.NOT_IMPLEMENTED, + context: { + provider: connection.provider + } + }) + } +} diff --git a/apps/vault/src/broker/core/service/scoped-sync.service.ts b/apps/vault/src/broker/core/service/scoped-sync.service.ts new file mode 100644 index 000000000..f0c746afd --- /dev/null +++ b/apps/vault/src/broker/core/service/scoped-sync.service.ts @@ -0,0 +1,299 @@ +import { LoggerService, PaginatedResult, TraceService } from '@narval/nestjs-shared' +import { NotImplementedException } from '@nestjs/common' +import { Inject, Injectable } from '@nestjs/common/decorators' +import { EventEmitter2 } from '@nestjs/event-emitter' +import { SpanStatusCode } from '@opentelemetry/api' +import { zip } from 'lodash' +import { v4 as uuid } from 'uuid' +import { FindAllOptions, ScopedSyncRepository } from '../../persistence/repository/scoped-sync.repository' +import { OTEL_ATTR_CONNECTION_ID, OTEL_ATTR_CONNECTION_PROVIDER, OTEL_ATTR_SYNC_ID } from '../../shared/constant' +import { ScopedSyncStartedEvent } from '../../shared/event/scoped-sync-started.event' +import { AnchorageScopedSyncService } from '../provider/anchorage/anchorage-scoped-sync.service' +import { FireblocksScopedSyncService } from '../provider/fireblocks/fireblocks-scoped-sync.service' +import { ConnectionWithCredentials } from '../type/connection.type' +import { + Provider, + ProviderScopedSyncService, + ScopedSyncResult, + isCreateOperation, + isFailedOperation, + isUpdateOperation +} from '../type/provider.type' +import { ConnectionScope } from '../type/scope.type' +import { RawAccount, ScopedSync, ScopedSyncStarted, ScopedSyncStatus, StartScopedSync } from '../type/scoped-sync.type' +import { AccountService } from './account.service' +import { AddressService } from './address.service' +import { WalletService } from './wallet.service' + +@Injectable() +export class ScopedSyncService { + constructor( + private readonly scopedSyncRepository: ScopedSyncRepository, + private readonly anchorageScopedSyncService: AnchorageScopedSyncService, + private readonly fireblocksScopedSyncService: FireblocksScopedSyncService, + private readonly walletService: WalletService, + private readonly accountService: AccountService, + private readonly addressService: AddressService, + private readonly eventEmitter: EventEmitter2, + private readonly logger: LoggerService, + @Inject(TraceService) private readonly traceService: TraceService + ) {} + + async start(connections: ConnectionWithCredentials[], rawAccounts: RawAccount[]): Promise { + this.logger.log('Start connections scoped sync', { + connectionsCount: connections.length, + connectionIds: connections.map((connectionId) => connectionId), + rawAccounts: rawAccounts.map(({ provider, externalId }) => ({ provider, externalId })) + }) + + if (connections.length) { + const now = new Date() + + const scopedSyncs = await this.scopedSyncRepository.bulkCreate( + connections.map(({ connectionId, clientId }) => + this.toProcessingScopedSync({ + clientId, + connectionId, + createdAt: now, + scopedSyncId: uuid(), + rawAccounts + }) + ) + ) + + for (const [scopedSync, connection] of zip(scopedSyncs, connections)) { + if (scopedSync && connection) { + // NOTE: Emits an event that will delegate the scopedSync process to + // another worker, allowing to unblock the request. The event handler + // will then invoke the `ScopedSyncService.scopedSync` method. + this.eventEmitter.emit(ScopedSyncStartedEvent.EVENT_NAME, new ScopedSyncStartedEvent(scopedSync, connection)) + } + } + + return { started: true, scopedSyncs } + } + + this.logger.log('Skip scoped sync because active connections list is empty') + + return { started: false, scopedSyncs: [] } + } + + async scopedSync(scopedSync: ScopedSync, connection: ConnectionWithCredentials): Promise { + const { clientId, scopedSyncId } = scopedSync + const { provider, connectionId } = connection + const context = { + clientId, + scopedSyncId, + connectionId, + provider + } + + this.logger.log('Scoped sync connection', context) + + const span = this.traceService.startSpan(`${ScopedSyncService.name}.scopedSync`, { + attributes: { + [OTEL_ATTR_SYNC_ID]: scopedSyncId, + [OTEL_ATTR_CONNECTION_ID]: connectionId, + [OTEL_ATTR_CONNECTION_PROVIDER]: provider + } + }) + + let result: ScopedSyncResult | null = null + + // Ensure the scopedSync status is updated on failures. The `execute` method is + // not wrapped in the try/catch block because it already handles errors + // internally. + try { + result = await this.getProviderScopedSyncService(connection.provider).scopedSync( + connection, + scopedSync.rawAccounts + ) + } catch (error) { + this.logger.error('Scoped sync connection failed', { ...context, error }) + + span.recordException(error) + span.setStatus({ code: SpanStatusCode.ERROR }) + + return await this.fail(scopedSync, error) + } finally { + // The execute method has its own span. + span.end() + } + + if (result) { + return await this.execute(scopedSync, result) + } + + return scopedSync + } + + private toProcessingScopedSync( + input: StartScopedSync & { connectionId: string; createdAt?: Date; scopedSyncId?: string } + ): ScopedSync { + return { + ...input, + completedAt: undefined, + connectionId: input.connectionId, + createdAt: input.createdAt || new Date(), + status: ScopedSyncStatus.PROCESSING, + scopedSyncId: input.scopedSyncId || uuid(), + rawAccounts: input.rawAccounts + } + } + + async findAll(scope: ConnectionScope, options?: FindAllOptions): Promise> { + return this.scopedSyncRepository.findAll(scope, options) + } + + async findById(scope: ConnectionScope, scopedSyncId: string): Promise { + return this.scopedSyncRepository.findById(scope, scopedSyncId) + } + + // TODO: pessimist lock if there's already a scopedSync in process for the given + // connection. + async execute(scopedSync: ScopedSync, result: ScopedSyncResult): Promise { + // IMPORTANT: Thoroughly test the execution in the integration test + // `scopedSync.service.spec.ts`. + + const { clientId, scopedSyncId } = scopedSync + + const span = this.traceService.startSpan(`${ScopedSyncService.name}.execute`, { + attributes: { [OTEL_ATTR_SYNC_ID]: scopedSyncId } + }) + + const walletCreateOperations = result.wallets.filter(isCreateOperation).map(({ create }) => create) + const walletUpdateOperations = result.wallets.filter(isUpdateOperation).map(({ update }) => update) + const walletFailedOperations = result.wallets.filter(isFailedOperation) + + const accountCreateOperations = result.accounts.filter(isCreateOperation).map(({ create }) => create) + const accountUpdateOperations = result.accounts.filter(isUpdateOperation).map(({ update }) => update) + const accountFailedOperations = result.accounts.filter(isFailedOperation) + + const addressCreateOperations = result.addresses.filter(isCreateOperation).map(({ create }) => create) + const addressFailedOperations = result.addresses.filter(isFailedOperation) + + this.logger.log('Execute scoped sync operations', { + clientId, + scopedSyncId, + operations: { + wallet: { + create: walletCreateOperations.length, + update: walletUpdateOperations.length, + failed: walletFailedOperations.length + }, + account: { + create: accountCreateOperations.length, + update: accountUpdateOperations.length, + failed: accountFailedOperations.length + }, + address: { + create: addressCreateOperations.length, + failed: addressFailedOperations.length + } + } + }) + + if (walletFailedOperations.length) { + this.logger.error('Scoped sync operations contains failures for wallets', { + operations: walletFailedOperations + }) + } + + if (accountFailedOperations.length) { + this.logger.error('Scoped sync operations contains failures for accounts', { + operations: accountFailedOperations + }) + } + + if (addressFailedOperations.length) { + this.logger.error('Scoped sync operations contains failures for addresses', { + operations: addressFailedOperations + }) + } + + try { + this.logger.log('Execute wallet create operations', { scopedSyncId, clientId }) + await this.walletService.bulkCreate(walletCreateOperations) + this.logger.log('Execute wallet update operations', { scopedSyncId, clientId }) + await this.walletService.bulkUpdate(walletUpdateOperations) + + this.logger.log('Execute account create operations', { scopedSyncId, clientId }) + await this.accountService.bulkCreate(accountCreateOperations) + this.logger.log('Execute account update operations', { scopedSyncId, clientId }) + await this.accountService.bulkUpdate(accountUpdateOperations) + + // TODO: address update + this.logger.log('Execute address create operations', { scopedSyncId, clientId }) + await this.addressService.bulkCreate(addressCreateOperations) + + return await this.complete(scopedSync) + } catch (error) { + return await this.fail(scopedSync, error) + } finally { + span.end() + } + } + + async complete(scopedSync: ScopedSync): Promise { + const { clientId, scopedSyncId } = scopedSync + + this.logger.log('Scoped sync complete', { clientId, scopedSyncId }) + + const span = this.traceService.startSpan(`${ScopedSyncService.name}.complete`, { + attributes: { [OTEL_ATTR_SYNC_ID]: scopedSyncId } + }) + + const completedScopedSync = { + ...scopedSync, + status: ScopedSyncStatus.SUCCESS, + completedAt: scopedSync.completedAt || new Date() + } + + await this.scopedSyncRepository.update(completedScopedSync) + + span.end() + + return completedScopedSync + } + + async fail(scopedSync: ScopedSync, error: Error): Promise { + const { clientId, scopedSyncId } = scopedSync + + this.logger.log('Scoped sync fail', { clientId, scopedSyncId, error }) + + const span = this.traceService.startSpan(`${ScopedSyncService.name}.fail`, { + attributes: { [OTEL_ATTR_SYNC_ID]: scopedSyncId } + }) + + span.recordException(error) + span.setStatus({ code: SpanStatusCode.ERROR }) + + const failedScopedSync = { + ...scopedSync, + status: ScopedSyncStatus.FAILED, + error: { + name: error.name, + message: error.message, + traceId: this.traceService.getActiveSpan()?.spanContext().traceId + }, + completedAt: scopedSync.completedAt || new Date() + } + + await this.scopedSyncRepository.update(failedScopedSync) + + span.end() + + return failedScopedSync + } + + private getProviderScopedSyncService(provider: Provider): ProviderScopedSyncService { + switch (provider) { + case Provider.ANCHORAGE: + return this.anchorageScopedSyncService + case Provider.FIREBLOCKS: + return this.fireblocksScopedSyncService + default: + throw new NotImplementedException(`Unsupported scoped sync for provider ${provider}`) + } + } +} diff --git a/apps/vault/src/broker/core/service/sync.service.ts b/apps/vault/src/broker/core/service/sync.service.ts index c4406a1a4..13b305f79 100644 --- a/apps/vault/src/broker/core/service/sync.service.ts +++ b/apps/vault/src/broker/core/service/sync.service.ts @@ -1,367 +1,17 @@ -import { LoggerService, PaginatedResult, TraceService } from '@narval/nestjs-shared' -import { NotImplementedException } from '@nestjs/common' -import { Inject, Injectable } from '@nestjs/common/decorators' -import { EventEmitter2 } from '@nestjs/event-emitter' -import { SpanStatusCode } from '@opentelemetry/api' -import { zip } from 'lodash' -import { v4 as uuid } from 'uuid' +import { PaginatedResult } from '@narval/nestjs-shared' +import { Injectable } from '@nestjs/common/decorators' import { FindAllOptions, SyncRepository } from '../../persistence/repository/sync.repository' -import { OTEL_ATTR_CONNECTION_ID, OTEL_ATTR_CONNECTION_PROVIDER, OTEL_ATTR_SYNC_ID } from '../../shared/constant' -import { SyncStartedEvent } from '../../shared/event/sync-started.event' -import { AnchorageSyncService } from '../provider/anchorage/anchorage-sync.service' -import { FireblocksSyncService } from '../provider/fireblocks/fireblocks-sync.service' -import { ConnectionWithCredentials } from '../type/connection.type' -import { - Provider, - ProviderSyncService, - SyncResult, - isCreateOperation, - isDeleteOperation, - isFailedOperation, - isSkipOperation, - isUpdateOperation -} from '../type/provider.type' -import { StartSync, Sync, SyncStarted, SyncStatus } from '../type/sync.type' -import { AccountService } from './account.service' -import { AddressService } from './address.service' -import { KnownDestinationService } from './known-destination.service' -import { WalletService } from './wallet.service' +import { ConnectionScope } from '../type/scope.type' +import { Sync } from '../type/sync.type' @Injectable() export class SyncService { - constructor( - private readonly syncRepository: SyncRepository, - private readonly anchorageSyncService: AnchorageSyncService, - private readonly fireblocksSyncService: FireblocksSyncService, - private readonly walletService: WalletService, - private readonly accountService: AccountService, - private readonly addressService: AddressService, - private readonly knownDestinationService: KnownDestinationService, - private readonly eventEmitter: EventEmitter2, - private readonly logger: LoggerService, - @Inject(TraceService) private readonly traceService: TraceService - ) {} - - async start(connections: ConnectionWithCredentials[]): Promise { - this.logger.log('Start connections sync', { - connectionsCount: connections.length, - connectionIds: connections.map((connectionId) => connectionId) - }) - - if (connections.length) { - const now = new Date() - - const syncs = await this.syncRepository.bulkCreate( - connections.map(({ connectionId, clientId }) => - this.toProcessingSync({ - clientId, - connectionId, - createdAt: now, - syncId: uuid() - }) - ) - ) - - for (const [sync, connection] of zip(syncs, connections)) { - if (sync && connection) { - // NOTE: Emits an event that will delegate the sync process to - // another worker, allowing to unblock the request. The event handler - // will then invoke the `SyncService.sync` method. - this.eventEmitter.emit(SyncStartedEvent.EVENT_NAME, new SyncStartedEvent(sync, connection)) - } - } - - return { started: true, syncs } - } - - this.logger.log('Skip sync because active connections list is empty') - - return { started: false, syncs: [] } - } - - async sync(sync: Sync, connection: ConnectionWithCredentials): Promise { - const { clientId, syncId } = sync - const { provider, connectionId } = connection - const context = { - clientId, - syncId, - connectionId, - provider - } - - this.logger.log('Sync connection', context) - - const span = this.traceService.startSpan(`${SyncService.name}.sync`, { - attributes: { - [OTEL_ATTR_SYNC_ID]: syncId, - [OTEL_ATTR_CONNECTION_ID]: connectionId, - [OTEL_ATTR_CONNECTION_PROVIDER]: provider - } - }) - - let result: SyncResult | null = null - - // Ensure the sync status is updated on failures. The `execute` method is - // not wrapped in the try/catch block because it already handles errors - // internally. - try { - result = await this.getProviderSyncService(connection.provider).sync(connection) - } catch (error) { - this.logger.error('Sync connection failed', { ...context, error }) - - span.recordException(error) - span.setStatus({ code: SpanStatusCode.ERROR }) - - return await this.fail(sync, error) - } finally { - // The execute method has its own span. - span.end() - } - - if (result) { - return await this.execute(sync, result) - } - - return sync - } - - private toProcessingSync(input: StartSync & { connectionId: string; createdAt?: Date; syncId?: string }): Sync { - return { - ...input, - completedAt: undefined, - connectionId: input.connectionId, - createdAt: input.createdAt || new Date(), - status: SyncStatus.PROCESSING, - syncId: input.syncId || uuid() - } - } - - async findAll(clientId: string, options?: FindAllOptions): Promise> { - return this.syncRepository.findAll(clientId, options) - } - - async findById(clientId: string, syncId: string): Promise { - return this.syncRepository.findById(clientId, syncId) - } - - // TODO: pessimist lock if there's already a sync in process for the given - // connection. - async execute(sync: Sync, result: SyncResult): Promise { - // IMPORTANT: Thoroughly test the execution in the integration test - // `sync.service.spec.ts`. - - const { clientId, syncId } = sync - - const span = this.traceService.startSpan(`${SyncService.name}.execute`, { - attributes: { [OTEL_ATTR_SYNC_ID]: syncId } - }) - - const walletCreateOperations = result.wallets.filter(isCreateOperation).map(({ create }) => create) - const walletUpdateOperations = result.wallets.filter(isUpdateOperation).map(({ update }) => update) - const walletDeleteOperations = result.wallets.filter(isDeleteOperation).map(({ entityId }) => entityId) - const walletSkipOperations = result.wallets.filter(isSkipOperation) - const walletFailedOperations = result.wallets.filter(isFailedOperation) - - const accountCreateOperations = result.accounts.filter(isCreateOperation).map(({ create }) => create) - const accountUpdateOperations = result.accounts.filter(isUpdateOperation).map(({ update }) => update) - const accountDeleteOperations = result.accounts.filter(isDeleteOperation).map(({ entityId }) => entityId) - const accountSkipOperations = result.accounts.filter(isSkipOperation) - const accountFailedOperations = result.accounts.filter(isFailedOperation) - - const addressCreateOperations = result.addresses.filter(isCreateOperation).map(({ create }) => create) - const addressUpdateOperations = result.addresses.filter(isUpdateOperation).map(({ update }) => update) - const addressDeleteOperations = result.addresses.filter(isDeleteOperation).map(({ entityId }) => entityId) - const addressSkipOperations = result.addresses.filter(isSkipOperation) - const addressFailedOperations = result.addresses.filter(isFailedOperation) - - const knownDestinationCreateOperations = result.knownDestinations - .filter(isCreateOperation) - .map(({ create }) => create) - const knownDestinationUpdateOperations = result.knownDestinations - .filter(isUpdateOperation) - .map(({ update }) => update) - const knownDestinationDeleteOperations = result.knownDestinations - .filter(isDeleteOperation) - .map(({ entityId }) => entityId) - const knownDestinationSkipOperations = result.knownDestinations.filter(isSkipOperation) - const knownDestinationFailedOperations = result.knownDestinations.filter(isFailedOperation) - - this.logger.log('Execute sync operations', { - clientId, - syncId, - operations: { - wallet: { - create: walletCreateOperations.length, - update: walletUpdateOperations.length, - delete: walletDeleteOperations.length, - skip: walletSkipOperations.length, - failed: walletFailedOperations.length - }, - account: { - create: accountCreateOperations.length, - update: accountUpdateOperations.length, - delete: accountDeleteOperations.length, - skip: accountSkipOperations.length, - failed: accountFailedOperations.length - }, - address: { - create: addressCreateOperations.length, - update: addressUpdateOperations.length, - delete: addressDeleteOperations.length, - skip: addressSkipOperations.length, - failed: addressFailedOperations.length - }, - knownDestination: { - create: knownDestinationCreateOperations.length, - update: knownDestinationUpdateOperations.length, - delete: knownDestinationDeleteOperations.length, - skip: knownDestinationSkipOperations.length, - failed: knownDestinationFailedOperations.length - } - } - }) - - if (walletFailedOperations.length) { - this.logger.error('Sync operations contains failures for wallets', { - operations: walletFailedOperations - }) - } - - if (walletSkipOperations.length) { - this.logger.error('Sync operations contains skips for wallets', { - operations: walletSkipOperations - }) - } - - if (accountFailedOperations.length) { - this.logger.error('Sync operations contains failures for accounts', { - operations: accountFailedOperations - }) - } - - if (accountSkipOperations.length) { - this.logger.error('Sync operations contains skips for accounts', { - operations: accountSkipOperations - }) - } - - if (addressFailedOperations.length) { - this.logger.error('Sync operations contains failures for addresses', { - operations: addressFailedOperations - }) - } - - if (addressSkipOperations.length) { - this.logger.error('Sync operations contains skips for addresses', { - operations: addressSkipOperations - }) - } - - if (knownDestinationFailedOperations.length) { - this.logger.error('Sync operations contains failures for known destinations', { - operations: knownDestinationFailedOperations - }) - } - - if (knownDestinationSkipOperations.length) { - this.logger.error('Sync operations contains skips for known destinations', { - operations: knownDestinationSkipOperations - }) - } - - try { - this.logger.log('Execute wallet create operations', { syncId, clientId }) - await this.walletService.bulkCreate(walletCreateOperations) - - this.logger.log('Execute wallet update operations', { syncId, clientId }) - await this.walletService.bulkUpdate(walletUpdateOperations) - - this.logger.log('Execute account create operations', { syncId, clientId }) - await this.accountService.bulkCreate(accountCreateOperations) - this.logger.log('Execute account update operations', { syncId, clientId }) - await this.accountService.bulkUpdate(accountUpdateOperations) - - // TODO: address update - this.logger.log('Execute address create operations', { syncId, clientId }) - await this.addressService.bulkCreate(addressCreateOperations) - - this.logger.log('Execute known destination create operations', { syncId, clientId }) - await this.knownDestinationService.bulkCreate(knownDestinationCreateOperations) - - this.logger.log('Execute known destination update operations', { syncId, clientId }) - await this.knownDestinationService.bulkUpdate(knownDestinationUpdateOperations) - - this.logger.log('Execute known destination delete operations', { syncId, clientId }) - await this.knownDestinationService.bulkDelete(knownDestinationDeleteOperations) - - return await this.complete(sync) - } catch (error) { - return await this.fail(sync, error) - } finally { - span.end() - } - } - - async complete(sync: Sync): Promise { - const { clientId, syncId } = sync - - this.logger.log('Sync complete', { clientId, syncId }) - - const span = this.traceService.startSpan(`${SyncService.name}.complete`, { - attributes: { [OTEL_ATTR_SYNC_ID]: syncId } - }) - - const completedSync = { - ...sync, - status: SyncStatus.SUCCESS, - completedAt: sync.completedAt || new Date() - } - - await this.syncRepository.update(completedSync) - - span.end() - - return completedSync - } - - async fail(sync: Sync, error: Error): Promise { - const { clientId, syncId } = sync - - this.logger.log('Sync fail', { clientId, syncId, error }) - - const span = this.traceService.startSpan(`${SyncService.name}.fail`, { - attributes: { [OTEL_ATTR_SYNC_ID]: syncId } - }) - - span.recordException(error) - span.setStatus({ code: SpanStatusCode.ERROR }) - - const failedSync = { - ...sync, - status: SyncStatus.FAILED, - error: { - name: error.name, - message: error.message, - traceId: this.traceService.getActiveSpan()?.spanContext().traceId - }, - completedAt: sync.completedAt || new Date() - } - - await this.syncRepository.update(failedSync) - - span.end() - - return failedSync + constructor(private readonly syncRepository: SyncRepository) {} + async findAll(scope: ConnectionScope, options?: FindAllOptions): Promise> { + return this.syncRepository.findAll(scope, options) } - private getProviderSyncService(provider: Provider): ProviderSyncService { - switch (provider) { - case Provider.ANCHORAGE: - return this.anchorageSyncService - case Provider.FIREBLOCKS: - return this.fireblocksSyncService - default: - throw new NotImplementedException(`Unsupported sync for provider ${provider}`) - } + async findById(scope: ConnectionScope, syncId: string): Promise { + return this.syncRepository.findById(scope, syncId) } } diff --git a/apps/vault/src/broker/core/service/transfer-asset.service.ts b/apps/vault/src/broker/core/service/transfer-asset.service.ts new file mode 100644 index 000000000..64f6545e6 --- /dev/null +++ b/apps/vault/src/broker/core/service/transfer-asset.service.ts @@ -0,0 +1,264 @@ +import { LoggerService } from '@narval/nestjs-shared' +import { HttpStatus, Injectable } from '@nestjs/common' +import { AssetException } from '../exception/asset.exception' +import { Network } from '../type/network.type' +import { Provider } from '../type/provider.type' +import { TransferAsset } from '../type/transfer.type' +import { getExternalAsset } from '../util/asset.util' +import { getExternalNetwork } from '../util/network.util' +import { AssetService } from './asset.service' +import { NetworkService } from './network.service' + +export type ResolvedTransferAsset = { + network: Network + assetId: string | null + assetExternalId: string +} + +export type FindByExternalIdFallback = (externalAssetId: string) => Promise + +export type FindByOnchainIdFallback = (network: Network, onchainId: string) => Promise + +export type ResolveTransferAssetParams = { + transferAsset: TransferAsset + provider: Provider + findByExternalIdFallback?: FindByExternalIdFallback + findByOnchainIdFallback?: FindByOnchainIdFallback +} + +@Injectable() +export class TransferAssetService { + constructor( + private readonly assetService: AssetService, + private readonly networkService: NetworkService, + private readonly logger: LoggerService + ) {} + + /** + * Resolves a transfer asset using the following strategy: + * 1. By external asset ID if provided + * 2. By internal asset ID if provided + * 3. By network ID + onchain address if both provided + * 4. Falls back to native asset of the network if only network ID is provided + * + * For external ID and onchain address resolution, supports fallback + * functions that can handle assets not yet listed. Fallbacks are called only + * after an initial lookup fails to find the asset in our database. + * + * @throws {AssetException} When asset cannot be resolved or required network + * info is missing + */ + async resolve(params: ResolveTransferAssetParams): Promise { + const { transferAsset, provider, findByExternalIdFallback, findByOnchainIdFallback } = params + + this.logger.log(`Resolve ${provider} transfer asset`, { transferAsset, provider }) + + if (transferAsset.externalAssetId) { + return this.findByExternalId(provider, transferAsset.externalAssetId, findByExternalIdFallback) + } + + if (transferAsset.assetId) { + return this.findByAssetId(provider, transferAsset.assetId) + } + + if (!transferAsset.networkId) { + throw new AssetException({ + message: 'Cannot find transfer asset without network ID', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, + context: { transferAsset } + }) + } + + if (transferAsset.address) { + return this.findByOnchainId(provider, transferAsset.networkId, transferAsset.address, findByOnchainIdFallback) + } + + return this.findNative(provider, transferAsset.networkId) + } + + private async findByExternalId( + provider: Provider, + externalAssetId: string, + findByExternalIdFallback?: FindByExternalIdFallback + ): Promise { + this.logger.log('Find asset by external ID', { provider, externalAssetId }) + + const asset = await this.assetService.findByExternalId(provider, externalAssetId) + + if (asset) { + const network = await this.networkService.findById(asset.networkId) + if (!network) { + throw new AssetException({ + message: 'Asset network not found', + suggestedHttpStatusCode: HttpStatus.NOT_FOUND, + context: { asset } + }) + } + + const externalAsset = getExternalAsset(asset, provider) + if (!externalAsset) { + throw new AssetException({ + message: 'External asset not found', + suggestedHttpStatusCode: HttpStatus.NOT_FOUND, + context: { asset, provider } + }) + } + + return { + network, + assetId: asset.assetId, + assetExternalId: externalAsset.externalId + } + } + + if (findByExternalIdFallback) { + this.logger.log('Asset not listed. Calling given findByExternalIdFallback function', { + provider, + externalAssetId + }) + + return findByExternalIdFallback(externalAssetId) + } + + throw new AssetException({ + message: 'Transfer asset not found by external ID', + suggestedHttpStatusCode: HttpStatus.NOT_FOUND, + context: { externalAssetId, provider } + }) + } + + private async findByAssetId(provider: Provider, assetId: string): Promise { + this.logger.log('Find asset by ID', { provider, assetId }) + + const asset = await this.assetService.findById(assetId) + if (!asset) { + throw new AssetException({ + message: 'Asset not found by ID', + suggestedHttpStatusCode: HttpStatus.NOT_FOUND, + context: { assetId } + }) + } + + const externalAsset = getExternalAsset(asset, provider) + if (!externalAsset) { + throw new AssetException({ + message: 'External asset not found', + suggestedHttpStatusCode: HttpStatus.NOT_FOUND, + context: { assetId, asset, provider } + }) + } + + const network = await this.networkService.findById(asset.networkId) + if (!network) { + throw new AssetException({ + message: 'Asset network not found', + suggestedHttpStatusCode: HttpStatus.NOT_FOUND, + context: { assetId, asset } + }) + } + + return { + network, + assetId: asset.assetId, + assetExternalId: externalAsset.externalId + } + } + + private async findByOnchainId( + provider: Provider, + networkId: string, + onchainId: string, + findByOnchainIdFallback?: FindByOnchainIdFallback + ): Promise { + this.logger.log('Find asset by network and onchain ID', { provider, networkId, onchainId }) + + const network = await this.networkService.findById(networkId) + if (!network) { + throw new AssetException({ + message: 'Asset network not found', + suggestedHttpStatusCode: HttpStatus.NOT_FOUND, + context: { networkId } + }) + } + + const externalNetwork = getExternalNetwork(network, provider) + if (!externalNetwork) { + throw new AssetException({ + message: `Provider ${provider} unlisted network`, + suggestedHttpStatusCode: HttpStatus.NOT_IMPLEMENTED, + context: { provider, network } + }) + } + + const asset = await this.assetService.findByOnchainId(network.networkId, onchainId) + if (asset) { + const externalAsset = getExternalAsset(asset, provider) + if (!externalAsset) { + throw new AssetException({ + message: 'External asset not found', + suggestedHttpStatusCode: HttpStatus.NOT_FOUND, + context: { onchainId, asset, provider } + }) + } + + return { + network, + assetId: asset.assetId, + assetExternalId: externalAsset.externalId + } + } + + if (findByOnchainIdFallback) { + this.logger.log('Asset not listed. Calling given findByOnchainIdFallback function', { + network, + provider, + onchainId + }) + + return findByOnchainIdFallback(network, onchainId) + } + + throw new AssetException({ + message: 'Transfer asset not found by network and onchain ID', + suggestedHttpStatusCode: HttpStatus.NOT_FOUND, + context: { network, onchainId } + }) + } + + private async findNative(provider: Provider, networkId: string): Promise { + this.logger.log('Find native asset', { provider, networkId }) + + const asset = await this.assetService.findNative(networkId) + if (!asset) { + throw new AssetException({ + message: 'Native asset not found', + suggestedHttpStatusCode: HttpStatus.NOT_FOUND, + context: { networkId } + }) + } + + const externalAsset = getExternalAsset(asset, provider) + if (!externalAsset) { + throw new AssetException({ + message: 'External asset not found', + suggestedHttpStatusCode: HttpStatus.NOT_FOUND, + context: { provider, asset } + }) + } + + const network = await this.networkService.findById(networkId) + if (!network) { + throw new AssetException({ + message: 'Network of native asset not found', + suggestedHttpStatusCode: HttpStatus.NOT_FOUND, + context: { networkId, asset } + }) + } + + return { + network, + assetId: asset.assetId, + assetExternalId: externalAsset.externalId + } + } +} diff --git a/apps/vault/src/broker/core/service/transfer.service.ts b/apps/vault/src/broker/core/service/transfer.service.ts index c353cb8ba..180b23c67 100644 --- a/apps/vault/src/broker/core/service/transfer.service.ts +++ b/apps/vault/src/broker/core/service/transfer.service.ts @@ -8,6 +8,7 @@ import { AnchorageTransferService } from '../provider/anchorage/anchorage-transf import { FireblocksTransferService } from '../provider/fireblocks/fireblocks-transfer.service' import { isActiveConnection } from '../type/connection.type' import { Provider, ProviderTransferService } from '../type/provider.type' +import { ConnectionScope } from '../type/scope.type' import { InternalTransfer, SendTransfer } from '../type/transfer.type' import { ConnectionService } from './connection.service' @@ -22,7 +23,7 @@ export class TransferService { @Inject(TraceService) private readonly traceService: TraceService ) {} - async findById(clientId: string, connectionId: string, transferId: string): Promise { + async findById({ clientId, connectionId }: ConnectionScope, transferId: string): Promise { const span = this.traceService.startSpan(`${TransferService.name}.findById`) const connection = await this.connectionService.findWithCredentialsById(clientId, connectionId) @@ -37,7 +38,7 @@ export class TransferService { return this.transferRepository.bulkCreate(transfers) } - async send(clientId: string, connectionId: string, sendTransfer: SendTransfer): Promise { + async send({ clientId, connectionId }: ConnectionScope, sendTransfer: SendTransfer): Promise { this.logger.log('Send transfer', { clientId, sendTransfer }) const span = this.traceService.startSpan(`${TransferService.name}.send`) @@ -71,7 +72,7 @@ export class TransferService { throw new BrokerException({ message: 'Cannot find an active connection for the source', suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, - context: { connection, connectionId, clientId } + context: { connectionId, clientId } }) } diff --git a/apps/vault/src/broker/core/service/wallet.service.ts b/apps/vault/src/broker/core/service/wallet.service.ts index 7c3d5aa6e..75df878e5 100644 --- a/apps/vault/src/broker/core/service/wallet.service.ts +++ b/apps/vault/src/broker/core/service/wallet.service.ts @@ -2,6 +2,7 @@ import { PaginatedResult } from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' import { FindAllOptions, WalletRepository } from '../../persistence/repository/wallet.repository' import { UpdateWallet, Wallet } from '../type/indexed-resources.type' +import { ConnectionScope } from '../type/scope.type' @Injectable() export class WalletService { @@ -11,7 +12,7 @@ export class WalletService { return this.walletRepository.bulkCreate(wallets) } - async bulkUpdate(wallets: Wallet[]): Promise { + async bulkUpdate(wallets: UpdateWallet[]): Promise { return Promise.all(wallets.map((wallet) => this.update(wallet))) } @@ -19,11 +20,11 @@ export class WalletService { return this.walletRepository.update(wallet) } - async findAll(clientId: string, options?: FindAllOptions): Promise> { - return this.walletRepository.findAll(clientId, options) + async findAll(scope: ConnectionScope, options?: FindAllOptions): Promise> { + return this.walletRepository.findAll(scope, options) } - async findById(clientId: string, walletId: string): Promise { - return this.walletRepository.findById(clientId, walletId) + async findById(scope: ConnectionScope, walletId: string): Promise { + return this.walletRepository.findById(scope, walletId) } } diff --git a/apps/vault/src/broker/core/type/indexed-resources.type.ts b/apps/vault/src/broker/core/type/indexed-resources.type.ts index 58e7f9bf7..48632292c 100644 --- a/apps/vault/src/broker/core/type/indexed-resources.type.ts +++ b/apps/vault/src/broker/core/type/indexed-resources.type.ts @@ -1,28 +1,12 @@ import { z } from 'zod' -import { Connection } from './connection.type' import { Provider } from './provider.type' -export const KnownDestination = z.object({ - knownDestinationId: z.string(), - clientId: z.string(), - connections: z.array(Connection), - provider: z.nativeEnum(Provider), - label: z.string().nullable().optional(), - externalId: z.string(), - externalClassification: z.string().nullable().optional(), - address: z.string(), - assetId: z.string().nullable().optional(), - networkId: z.string(), - createdAt: z.date(), - updatedAt: z.date() -}) -export type KnownDestination = z.infer - export const Address = z.object({ accountId: z.string(), address: z.string(), addressId: z.string(), clientId: z.string(), + connectionId: z.string(), createdAt: z.date(), externalId: z.string(), provider: z.nativeEnum(Provider), @@ -34,6 +18,7 @@ export const Account = z.object({ accountId: z.string(), addresses: z.array(Address).optional(), clientId: z.string(), + connectionId: z.string(), createdAt: z.date(), externalId: z.string(), label: z.string().nullable().optional(), @@ -47,7 +32,7 @@ export type Account = z.infer export const Wallet = z.object({ accounts: z.array(Account).optional(), clientId: z.string(), - connections: z.array(Connection), + connectionId: z.string(), createdAt: z.date(), externalId: z.string(), label: z.string().nullable().optional(), @@ -61,7 +46,6 @@ export const UpdateWallet = Wallet.pick({ walletId: true, clientId: true, label: true, - connections: true, updatedAt: true }) export type UpdateWallet = z.infer diff --git a/apps/vault/src/broker/core/type/known-destination.type.ts b/apps/vault/src/broker/core/type/known-destination.type.ts new file mode 100644 index 000000000..4e703e770 --- /dev/null +++ b/apps/vault/src/broker/core/type/known-destination.type.ts @@ -0,0 +1,15 @@ +import { z } from 'zod' +import { Provider } from './provider.type' + +export const KnownDestination = z.object({ + clientId: z.string(), + connectionId: z.string(), + provider: z.nativeEnum(Provider), + label: z.string().nullable().optional(), + externalId: z.string(), + externalClassification: z.string().nullable().optional(), + address: z.string().toLowerCase(), + assetId: z.string().nullable().optional(), + networkId: z.string() +}) +export type KnownDestination = z.infer diff --git a/apps/vault/src/broker/core/type/provider.type.ts b/apps/vault/src/broker/core/type/provider.type.ts index 807c07afe..97fd837a4 100644 --- a/apps/vault/src/broker/core/type/provider.type.ts +++ b/apps/vault/src/broker/core/type/provider.type.ts @@ -1,14 +1,18 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ +import { PaginatedResult } from '@narval/nestjs-shared' import { HttpStatus } from '@nestjs/common' import { UpdateAccount } from '../../persistence/repository/account.repository' import { ConnectionWithCredentials } from './connection.type' -import { Account, Address, KnownDestination, UpdateWallet, Wallet } from './indexed-resources.type' +import { Account, Address, UpdateWallet, Wallet } from './indexed-resources.type' +import { KnownDestination as KnownDestinationNext } from './known-destination.type' +import { RawAccount } from './scoped-sync.type' import { InternalTransfer, SendTransfer, Transfer } from './transfer.type' export const Provider = { ANCHORAGE: 'anchorage', - FIREBLOCKS: 'fireblocks' + FIREBLOCKS: 'fireblocks', + BITGO: 'bitgo' } as const export type Provider = (typeof Provider)[keyof typeof Provider] @@ -25,6 +29,29 @@ export const SyncOperationType = { } as const export type SyncOperationType = (typeof SyncOperationType)[keyof typeof SyncOperationType] +export const ScopedSyncOperationType = { + CREATE: 'create', + UPDATE: 'update', + FAILED: 'failed' +} as const +export type ScopedSyncOperationType = (typeof ScopedSyncOperationType)[keyof typeof ScopedSyncOperationType] + +export type CreateScopedSyncOperation = { + type: typeof SyncOperationType.CREATE + create: CreateParams +} +export type UpdateScopedSyncOperation = { + type: typeof ScopedSyncOperationType.UPDATE + update: UpdateParams +} + +export type FailedScopedSyncOperation = { + type: typeof ScopedSyncOperationType.FAILED + externalId: string + message: string + context?: unknown +} + export type CreateSyncOperation = { type: typeof SyncOperationType.CREATE create: CreateParams @@ -69,6 +96,11 @@ export type SyncOperation = | FailedSyncOperation | SkipSyncOperation +export type ScopedSyncOperation = + | CreateScopedSyncOperation + | UpdateScopedSyncOperation + | FailedSyncOperation + export const isCreateOperation = ( operation: SyncOperation ): operation is CreateSyncOperation => { @@ -125,12 +157,6 @@ export type SyncContext = { */ addresses: SyncOperation[] - /** - * A map of known destination synchronization operations, keyed by - * destination external ID. - */ - knownDestinations: SyncOperation[] - /** * An optional timestamp used for setting the `createdAt` and `updatedAt` * fields during synchronization operations. @@ -142,7 +168,16 @@ export type SyncResult = { wallets: SyncOperation[] accounts: SyncOperation[] addresses: SyncOperation[] - knownDestinations: SyncOperation[] +} + +export type ScopedSyncResult = { + wallets: ScopedSyncOperation[] + accounts: ScopedSyncOperation[] + addresses: ScopedSyncOperation[] +} + +export interface ProviderScopedSyncService { + scopedSync(connection: ConnectionWithCredentials, rawAccounts: RawAccount[]): Promise } export interface ProviderSyncService { @@ -195,17 +230,6 @@ export interface ProviderSyncService { * @returns A promise that resolves to the updated synchronization context. */ syncAddresses(context: SyncContext): Promise - - /** - * Synchronizes known destination data within the provided context and - * returns an updated context. - * - * @param context - The current synchronization context containing existing - * data and operations. - * - * @returns A promise that resolves to the updated synchronization context. - */ - syncKnownDestinations(context: SyncContext): Promise } // @@ -247,7 +271,6 @@ export interface ProviderTransferService { * endpoint, and HTTP method. */ export type ProxyRequestOptions = { - connectionId: string data?: any nonce?: string endpoint: string @@ -327,3 +350,19 @@ export interface ProviderCredentialService { */ generate>(options?: Options): Promise } + +// +// Known Destination +// + +export type ProviderKnownDestinationPaginationOptions = { + cursor?: string + limit?: number +} + +export interface ProviderKnownDestinationService { + findAll( + connection: ConnectionWithCredentials, + options?: ProviderKnownDestinationPaginationOptions + ): Promise> +} diff --git a/apps/vault/src/broker/core/type/scope.type.ts b/apps/vault/src/broker/core/type/scope.type.ts new file mode 100644 index 000000000..f6cd215d4 --- /dev/null +++ b/apps/vault/src/broker/core/type/scope.type.ts @@ -0,0 +1,7 @@ +import { z } from 'zod' + +export const ConnectionScope = z.object({ + clientId: z.string(), + connectionId: z.string() +}) +export type ConnectionScope = z.infer diff --git a/apps/vault/src/broker/core/type/scoped-sync.type.ts b/apps/vault/src/broker/core/type/scoped-sync.type.ts new file mode 100644 index 000000000..5287a4438 --- /dev/null +++ b/apps/vault/src/broker/core/type/scoped-sync.type.ts @@ -0,0 +1,46 @@ +import { z } from 'zod' +import { Provider } from './provider.type' + +export const RawAccount = z.object({ + provider: z.nativeEnum(Provider), + externalId: z.string() +}) +export type RawAccount = z.infer + +export const ScopedSyncStatus = { + PROCESSING: 'processing', + SUCCESS: 'success', + FAILED: 'failed' +} as const +export type ScopedSyncStatus = (typeof ScopedSyncStatus)[keyof typeof ScopedSyncStatus] + +export const ScopedSync = z.object({ + clientId: z.string(), + completedAt: z.date().optional(), + connectionId: z.string(), + createdAt: z.date(), + error: z + .object({ + name: z.string().optional(), + message: z.string().optional(), + traceId: z.string().optional() + }) + .optional(), + status: z.nativeEnum(ScopedSyncStatus).default(ScopedSyncStatus.PROCESSING), + scopedSyncId: z.string(), + rawAccounts: z.array(RawAccount) +}) +export type ScopedSync = z.infer + +export const StartScopedSync = z.object({ + clientId: z.string(), + connectionId: z.string().describe('The connection to sync.'), + rawAccounts: z.array(RawAccount).describe('The accounts to sync.') +}) +export type StartScopedSync = z.infer + +export const ScopedSyncStarted = z.object({ + started: z.boolean(), + scopedSyncs: z.array(ScopedSync) +}) +export type ScopedSyncStarted = z.infer diff --git a/apps/vault/src/broker/core/type/sync.type.ts b/apps/vault/src/broker/core/type/sync.type.ts index d86ff5b60..e638565ac 100644 --- a/apps/vault/src/broker/core/type/sync.type.ts +++ b/apps/vault/src/broker/core/type/sync.type.ts @@ -26,10 +26,7 @@ export type Sync = z.infer export const StartSync = z.object({ clientId: z.string(), - connectionId: z - .string() - .describe('The connection to sync. If undefined, start the sync on all active connections') - .optional() + connectionId: z.string().describe('The connection to sync') }) export type StartSync = z.infer diff --git a/apps/vault/src/broker/core/type/transfer.type.ts b/apps/vault/src/broker/core/type/transfer.type.ts index 4bbe35dcc..e8be4aed8 100644 --- a/apps/vault/src/broker/core/type/transfer.type.ts +++ b/apps/vault/src/broker/core/type/transfer.type.ts @@ -95,8 +95,10 @@ export const TransferStatus = { export type TransferStatus = (typeof TransferStatus)[keyof typeof TransferStatus] export const InternalTransfer = z.object({ - assetId: z.string(), + assetExternalId: z.string().nullable(), + assetId: z.string().nullable(), clientId: z.string(), + connectionId: z.string(), createdAt: z.date(), customerRefId: z.string().nullable(), destination: Destination, diff --git a/apps/vault/src/broker/core/util/provider-sync.util.ts b/apps/vault/src/broker/core/util/provider-sync.util.ts index 71068b009..e98fd4f12 100644 --- a/apps/vault/src/broker/core/util/provider-sync.util.ts +++ b/apps/vault/src/broker/core/util/provider-sync.util.ts @@ -6,13 +6,11 @@ export const buildEmptyContext = ({ wallets, accounts, addresses, - knownDestinations, now }: SetRequired, 'connection'>): SyncContext => ({ connection, wallets: wallets || [], accounts: accounts || [], addresses: addresses || [], - knownDestinations: knownDestinations || [], now: now || new Date() }) diff --git a/apps/vault/src/broker/event/handler/connection-scoped-sync.event-handler.ts b/apps/vault/src/broker/event/handler/connection-scoped-sync.event-handler.ts new file mode 100644 index 000000000..7dafefb39 --- /dev/null +++ b/apps/vault/src/broker/event/handler/connection-scoped-sync.event-handler.ts @@ -0,0 +1,24 @@ +import { LoggerService } from '@narval/nestjs-shared' +import { Injectable } from '@nestjs/common' +import { OnEvent } from '@nestjs/event-emitter' +import { ScopedSyncService } from '../../core/service/scoped-sync.service' +import { ScopedSyncStartedEvent } from '../../shared/event/scoped-sync-started.event' + +@Injectable() +export class ConnectionScopedSyncEventHandler { + constructor( + private readonly scopedSyncService: ScopedSyncService, + private readonly logger: LoggerService + ) {} + + @OnEvent(ScopedSyncStartedEvent.EVENT_NAME) + async handleSyncStarted(event: ScopedSyncStartedEvent) { + this.logger.log(`Received ${ScopedSyncStartedEvent.EVENT_NAME} event`, { + clientId: event.connection.clientId, + connectionId: event.connection.connectionId, + rawAccounts: event.sync.rawAccounts + }) + + await this.scopedSyncService.scopedSync(event.sync, event.connection) + } +} diff --git a/apps/vault/src/broker/event/handler/connection-sync.event-handler.ts b/apps/vault/src/broker/event/handler/connection-sync.event-handler.ts deleted file mode 100644 index d44926e80..000000000 --- a/apps/vault/src/broker/event/handler/connection-sync.event-handler.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { LoggerService } from '@narval/nestjs-shared' -import { Injectable } from '@nestjs/common' -import { OnEvent } from '@nestjs/event-emitter' -import { SyncService } from '../../core/service/sync.service' -import { ConnectionActivatedEvent } from '../../shared/event/connection-activated.event' -import { SyncStartedEvent } from '../../shared/event/sync-started.event' - -@Injectable() -export class ConnectionSyncEventHandler { - constructor( - private readonly syncService: SyncService, - private readonly logger: LoggerService - ) {} - - @OnEvent(ConnectionActivatedEvent.EVENT_NAME) - async handleConnectionActivatedEvent(event: ConnectionActivatedEvent) { - this.logger.log(`Received ${ConnectionActivatedEvent.EVENT_NAME} event`, { - clientId: event.connection.clientId, - connectionId: event.connection.connectionId - }) - - await this.syncService.start([event.connection]) - } - - @OnEvent(SyncStartedEvent.EVENT_NAME) - async handleSyncStarted(event: SyncStartedEvent) { - this.logger.log(`Received ${SyncStartedEvent.EVENT_NAME} event`, { - clientId: event.connection.clientId, - connectionId: event.connection.connectionId - }) - - await this.syncService.sync(event.sync, event.connection) - } -} diff --git a/apps/vault/src/broker/http/client/anchorage.client.ts b/apps/vault/src/broker/http/client/anchorage.client.ts index 5a6c868ab..8ddc6b6b7 100644 --- a/apps/vault/src/broker/http/client/anchorage.client.ts +++ b/apps/vault/src/broker/http/client/anchorage.client.ts @@ -28,6 +28,16 @@ import { Provider } from '../../core/type/provider.type' // Response Schema // +const AssetType = z.object({ + assetType: z.string(), + decimals: z.number(), + featureSupport: z.array(z.string()), + name: z.string(), + networkId: z.string(), + onchainIdentifier: z.string().optional() +}) +type AssetType = z.infer + const Amount = z.object({ quantity: z.string(), assetType: z.string(), @@ -83,7 +93,12 @@ const Wallet = z.object({ networkId: z.string(), type: z.literal('WALLET') }) -type Wallet = z.infer +export type Wallet = z.infer + +const GetWalletResponse = z.object({ + data: Wallet +}) +type GetWalletResponse = z.infer const Address = z.object({ address: z.string(), @@ -204,6 +219,11 @@ const GetTrustedDestinationsResponse = z.object({ }) type GetTrustedDestinationsResponse = z.infer +const GetAssetTypeResponse = z.object({ + data: z.array(AssetType) +}) +type GetAssetTypeResponse = z.infer + // // Request Type // @@ -479,10 +499,35 @@ export class AnchorageClient { ) } - async getTrustedDestinations(opts: RequestOptions): Promise { - this.logger.log('Requesting Anchorage known addresses page', { + async getWallet(opts: RequestOptions & { walletId: string }): Promise { + const { apiKey, signKey, url, walletId } = opts + + this.logger.log('Requesting Anchorage wallet', { url }) + + return lastValueFrom( + this.sendSignedRequest({ + schema: GetWalletResponse, + request: { + url: `${url}/v2/wallets/${walletId}`, + method: 'GET' + }, + apiKey, + signKey + }).pipe( + map(({ data }) => data), + tap((wallet) => { + this.logger.log('Successfully fetched Anchorage wallet', { url, walletId: wallet.walletId }) + }), + this.handleError('Failed to get Anchorage wallet') + ) + ) + } + + async getTrustedDestinations(opts: RequestOptions & { afterId?: string }): Promise { + this.logger.log('Requesting Anchorage trusted destinations', { url: opts.url, - limit: opts.limit + limit: opts.limit, + afterId: opts.afterId }) const { apiKey, signKey, url } = opts @@ -491,44 +536,22 @@ export class AnchorageClient { schema: GetTrustedDestinationsResponse, request: { url: `${url}/v2/trusted_destinations`, - method: 'GET' + method: 'GET', + params: { + ...(opts.limit ? { limit: opts.limit } : {}), + ...(opts.afterId ? { afterId: opts.afterId } : {}) + } }, apiKey, signKey }).pipe( - expand((response) => { - if (response.page.next) { - return this.sendSignedRequest({ - schema: GetTrustedDestinationsResponse, - request: { - url: `${url}${response.page.next}`, - method: 'GET' - }, - apiKey, - signKey - }) - } - - return EMPTY - }), tap((response) => { - if (response.page.next) { - this.logger.log('Requesting Anchorage trusted-destinations next page', { - url: response.page.next, - limit: opts.limit - }) - } else { - this.logger.log('Reached Anchorage trusted-destinations last page') - } - }), - reduce((trustedDestinations: TrustedDestination[], response) => [...trustedDestinations, ...response.data], []), - tap((trustedDestinations) => { - this.logger.log('Completed fetching all Anchorage trusted-destinations', { - trustedDestinationsCount: trustedDestinations.length, - url: opts.url + this.logger.log('Requesting Anchorage trusted destinations', { + url: response.page.next, + limit: opts.limit }) }), - this.handleError('Failed to get Anchorage trusted-destinations') + this.handleError('Failed to get Anchorage trusted destinations') ) ) } @@ -654,6 +677,33 @@ export class AnchorageClient { ) } + async getAssetTypes(opts: RequestOptions): Promise { + const { apiKey, signKey, url } = opts + + this.logger.log('Request Anchorage asset types', { url }) + + return lastValueFrom( + this.sendSignedRequest({ + schema: GetAssetTypeResponse, + request: { + url: `${url}/v2/asset-types`, + method: 'GET' + }, + apiKey, + signKey + }).pipe( + map((response) => response.data), + tap((assetTypes) => { + this.logger.log('Successfully fetched Anchorage asset types', { + url, + assetTypesCount: assetTypes.length + }) + }), + this.handleError('Failed to fetch Anchorage asset types') + ) + ) + } + private handleError(logMessage: string): OperatorFunction { return catchError((error: unknown): Observable => { this.logger.error(logMessage, { error }) diff --git a/apps/vault/src/broker/http/client/fireblocks.client.ts b/apps/vault/src/broker/http/client/fireblocks.client.ts index 40e807f12..8d2f112d6 100644 --- a/apps/vault/src/broker/http/client/fireblocks.client.ts +++ b/apps/vault/src/broker/http/client/fireblocks.client.ts @@ -40,6 +40,17 @@ const RewardsInfo = z.object({ }) type RewardsInfo = z.infer +export const SupportedAsset = z.object({ + id: z.string(), + name: z.string(), + type: z.string(), + contractAddress: z.string(), + nativeAsset: z.string(), + decimals: z.number(), + issuerAddress: z.string().optional() +}) +export type SupportedAsset = z.infer + // Fireblocks API is not consistent in the response format for Asset and AssetWallet, but they seem to be the same underlying data const Asset = z.object({ // !![This is NOT discretionary.](https://developers.fireblocks.com/docs/list-supported-assets-1) @@ -66,7 +77,7 @@ const VaultAccount = z.object({ customerRefId: z.string().optional(), autoFuel: z.boolean() }) -type VaultAccount = z.infer +export type VaultAccount = z.infer const Paging = z.object({ before: z.string().optional(), @@ -121,7 +132,7 @@ const AssetAddress = z.object({ bip44AddressIndex: z.number(), userDefined: z.boolean() }) -type AssetAddress = z.infer +export type AssetAddress = z.infer const GetAddressListResponse = z.object({ addresses: z.array(AssetAddress), @@ -261,6 +272,12 @@ export interface CreateTransaction { idempotencyKey?: string requestId?: string } + +export const FIREBLOCKS_API_ERROR_CODES = { + INVALID_SPECIFIED_VAULT_ACCOUNT: 11001 +} as const +export type FIREBLOCKS_API_ERROR_CODES = (typeof FIREBLOCKS_API_ERROR_CODES)[keyof typeof FIREBLOCKS_API_ERROR_CODES] + @Injectable() export class FireblocksClient { constructor( @@ -421,8 +438,7 @@ export class FireblocksClient { this.logger.log('Received Fireblocks response', { url: opts.request.url, method: opts.request.method, - nextPage: response.data?.paging?.after, - body: response.data || null + nextPage: response.data?.paging?.after }) }), map((response) => opts.schema.parse(response.data)) @@ -488,6 +504,56 @@ export class FireblocksClient { ) } + async getVaultAccountsV2(opts: { + apiKey: string + signKey: RsaPrivateKey + url: string + options?: { + limit?: number + after?: string + namePrefix?: string + nameSuffix?: string + assetId?: string // Fireblocks externalId + } + }): Promise<{ accounts: VaultAccount[]; page?: { cursor?: string } }> { + this.logger.log('Requesting Fireblocks vault accounts page', { + url: opts.url, + options: opts.options + }) + + return lastValueFrom( + this.sendSignedRequest({ + schema: GetVaultAccountsResponse, + request: { + url: `${opts.url}/v1/vault/accounts_paged`, + params: { + limit: opts.options?.limit ?? 500, + after: opts.options?.after, + namePrefix: opts.options?.namePrefix, + nameSuffix: opts.options?.nameSuffix, + assetId: opts.options?.assetId + }, + method: 'GET' + }, + apiKey: opts.apiKey, + signKey: opts.signKey + }).pipe( + map((response) => ({ + accounts: response.accounts, + page: response.paging ? { cursor: response.paging.after } : undefined + })), + tap((response) => { + this.logger.log('Completed fetching vault accounts', { + accountsCount: response.accounts.length, + page: response.page, + url: opts.url + }) + }), + this.handleError('Failed to get Fireblocks vault accounts') + ) + ) + } + async getAssetWallets(opts: { apiKey: string; signKey: RsaPrivateKey; url: string }): Promise { this.logger.log('Requesting Fireblocks asset wallets page', { url: opts.url @@ -770,4 +836,60 @@ export class FireblocksClient { ) ) } + + async getVaultAccount(opts: { + apiKey: string + signKey: RsaPrivateKey + url: string + vaultAccountId: string + }): Promise { + this.logger.log('Requesting vault account per ID', { + url: opts.url + }) + + return lastValueFrom( + this.sendSignedRequest({ + schema: VaultAccount, + request: { + url: `${opts.url}/v1/vault/accounts/${opts.vaultAccountId}`, + method: 'GET' + }, + apiKey: opts.apiKey, + signKey: opts.signKey + }).pipe( + tap((vaultAccount) => { + this.logger.log('Completed fetching Vault Account', { + vaultAccountId: vaultAccount.id, + url: opts.url + }) + }), + this.handleError('Failed to get Fireblocks Vault Account') + ) + ) + } + + async getSupportedAssets(params: RequestParams): Promise { + const { apiKey, signKey, url } = params + + this.logger.log('Request Fireblocks supported assets', { url }) + + return lastValueFrom( + this.sendSignedRequest({ + schema: z.array(SupportedAsset), + request: { + url: `${params.url}/v1/supported_assets`, + method: 'GET' + }, + apiKey, + signKey + }).pipe( + tap((supportedAssets) => { + this.logger.log('Successfully got Fireblocks supported assets', { + supportedAssetsCount: supportedAssets.length + }) + }), + this.handleError('Failed to get Fireblocks supported assets') + ) + ) + } } diff --git a/apps/vault/src/broker/http/rest/controller/account.controller.ts b/apps/vault/src/broker/http/rest/controller/account.controller.ts index 3e2bc7919..df4042b6c 100644 --- a/apps/vault/src/broker/http/rest/controller/account.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/account.controller.ts @@ -1,12 +1,16 @@ import { ApiClientIdHeader, Paginated, PaginationOptions, PaginationParam } from '@narval/nestjs-shared' -import { Controller, Get, HttpStatus, Param } from '@nestjs/common' -import { ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger' +import { Controller, Get, HttpStatus, Param, Query } from '@nestjs/common' +import { ApiHeader, ApiOperation, ApiParam, ApiQuery, ApiResponse, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../shared/decorator/client-id.decorator' import { PermissionGuard } from '../../../../shared/decorator/permission-guard.decorator' import { VaultPermission } from '../../../../shared/type/domain.type' import { AccountService } from '../../../core/service/account.service' +import { RawAccountService } from '../../../core/service/raw-account.service' +import { REQUEST_HEADER_CONNECTION_ID } from '../../../shared/constant' +import { ConnectionId } from '../../../shared/decorator/connection-id.decorator' import { PaginatedAccountsDto } from '../dto/response/paginated-accounts.dto' import { PaginatedAddressesDto } from '../dto/response/paginated-addresses.dto' +import { PaginatedRawAccountsDto } from '../dto/response/paginated-raw-accounts.dto' import { ProviderAccountDto } from '../dto/response/provider-account.dto' @Controller({ @@ -16,22 +20,101 @@ import { ProviderAccountDto } from '../dto/response/provider-account.dto' @ApiClientIdHeader() @ApiTags('Provider Account') export class ProviderAccountController { - constructor(private readonly accountService: AccountService) {} + constructor( + private readonly accountService: AccountService, + private readonly rawAccountService: RawAccountService + ) {} @Get() @PermissionGuard(VaultPermission.CONNECTION_READ) @ApiOperation({ summary: 'List the client accounts' }) + @ApiHeader({ + name: REQUEST_HEADER_CONNECTION_ID, + description: 'The provider connection through which the resource is accessed' + }) @Paginated({ type: PaginatedAccountsDto, description: 'Returns a paginated list of accounts for the client' }) async list( @ClientId() clientId: string, + @ConnectionId() connectionId: string, @PaginationParam() pagination: PaginationOptions ): Promise { - return PaginatedAccountsDto.create(await this.accountService.findAll(clientId, { pagination })) + return PaginatedAccountsDto.create( + await this.accountService.findAll( + { + clientId, + connectionId + }, + { pagination } + ) + ) + } + + @Get('raw') + @PermissionGuard(VaultPermission.CONNECTION_READ) + @ApiOperation({ + summary: 'List the provider accounts in raw form, used to populate which accounts to connect' + }) + @ApiHeader({ + name: REQUEST_HEADER_CONNECTION_ID, + description: 'The provider connection through which the resource is accessed' + }) + @ApiQuery({ + name: 'namePrefix', + required: false, + description: 'Filter accounts by name prefix' + }) + @ApiQuery({ + name: 'nameSuffix', + required: false, + description: 'Filter accounts by name suffix' + }) + @ApiQuery({ + name: 'networkId', + required: false, + description: 'Filter accounts by network ID' + }) + @ApiQuery({ + name: 'assetId', + required: false, + description: 'Filter accounts by asset ID' + }) + @ApiQuery({ + name: 'includeAddress', + required: false, + type: 'boolean', + description: 'Include address information in the response' + }) + @Paginated({ + type: PaginatedRawAccountsDto, + description: 'Returns a paginated list of raw accounts, used to populate which accounts to connect.' + }) + async listRaw( + @ClientId() clientId: string, + @ConnectionId() connectionId: string, + @PaginationParam() pagination: PaginationOptions, + @Query('namePrefix') namePrefix?: string, + @Query('nameSuffix') nameSuffix?: string, + @Query('networkId') networkId?: string, + @Query('assetId') assetId?: string, + @Query('includeAddress') includeAddress?: boolean + ): Promise { + return PaginatedRawAccountsDto.create( + await this.rawAccountService.findAllPaginated(clientId, connectionId, { + pagination, + filters: { + namePrefix, + nameSuffix, + networkId, + assetId, + includeAddress + } + }) + ) } @Get(':accountId') @@ -39,6 +122,10 @@ export class ProviderAccountController { @ApiOperation({ summary: 'Get a specific account by ID' }) + @ApiHeader({ + name: REQUEST_HEADER_CONNECTION_ID, + description: 'The provider connection through which the resource is accessed' + }) @ApiParam({ name: 'accountId', description: 'The ID of the account to retrieve' @@ -51,8 +138,12 @@ export class ProviderAccountController { status: HttpStatus.NOT_FOUND, description: 'Account not found' }) - async getById(@ClientId() clientId: string, @Param('accountId') accountId: string): Promise { - const data = await this.accountService.findById(clientId, accountId) + async getById( + @ClientId() clientId: string, + @ConnectionId() connectionId: string, + @Param('accountId') accountId: string + ): Promise { + const data = await this.accountService.findById({ clientId, connectionId }, accountId) return ProviderAccountDto.create({ data }) } @@ -62,6 +153,10 @@ export class ProviderAccountController { @ApiOperation({ summary: 'List addresses for a specific account' }) + @ApiHeader({ + name: REQUEST_HEADER_CONNECTION_ID, + description: 'The provider connection through which the resource is accessed' + }) @ApiParam({ name: 'accountId', description: 'The ID of the account to retrieve addresses for' diff --git a/apps/vault/src/broker/http/rest/controller/address.controller.ts b/apps/vault/src/broker/http/rest/controller/address.controller.ts index 969cb3ea7..8c01cbf92 100644 --- a/apps/vault/src/broker/http/rest/controller/address.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/address.controller.ts @@ -1,10 +1,12 @@ import { ApiClientIdHeader, Paginated, PaginationOptions, PaginationParam } from '@narval/nestjs-shared' import { Controller, Get, HttpStatus, Param } from '@nestjs/common' -import { ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger' +import { ApiHeader, ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../shared/decorator/client-id.decorator' import { PermissionGuard } from '../../../../shared/decorator/permission-guard.decorator' import { VaultPermission } from '../../../../shared/type/domain.type' import { AddressService } from '../../../core/service/address.service' +import { REQUEST_HEADER_CONNECTION_ID } from '../../../shared/constant' +import { ConnectionId } from '../../../shared/decorator/connection-id.decorator' import { PaginatedAddressesDto } from '../dto/response/paginated-addresses.dto' import { ProviderAddressDto } from '../dto/response/provider-address.dto' @@ -19,6 +21,10 @@ export class ProviderAddressController { @Get() @PermissionGuard(VaultPermission.CONNECTION_READ) + @ApiHeader({ + name: REQUEST_HEADER_CONNECTION_ID, + description: 'The provider connection through which the resource is accessed' + }) @ApiOperation({ summary: 'List the client addresss' }) @@ -28,9 +34,20 @@ export class ProviderAddressController { }) async list( @ClientId() clientId: string, - @PaginationParam() options: PaginationOptions + @ConnectionId() connectionId: string, + @PaginationParam() pagination: PaginationOptions ): Promise { - return PaginatedAddressesDto.create(await this.addressService.getAddresses(clientId, options)) + return PaginatedAddressesDto.create( + await this.addressService.findAll( + { + clientId, + connectionId + }, + { + pagination + } + ) + ) } @Get(':addressId') @@ -38,6 +55,10 @@ export class ProviderAddressController { @ApiOperation({ summary: 'Get a specific address by ID' }) + @ApiHeader({ + name: REQUEST_HEADER_CONNECTION_ID, + description: 'The provider connection through which the resource is accessed' + }) @ApiParam({ name: 'addressId', description: 'The ID of the address to retrieve' @@ -50,8 +71,12 @@ export class ProviderAddressController { status: HttpStatus.NOT_FOUND, description: 'Address not found' }) - async getById(@ClientId() clientId: string, @Param('addressId') addressId: string): Promise { - const data = await this.addressService.getAddress(clientId, addressId) + async getById( + @ClientId() clientId: string, + @ConnectionId() connectionId: string, + @Param('addressId') addressId: string + ): Promise { + const data = await this.addressService.findById({ clientId, connectionId }, addressId) return ProviderAddressDto.create({ data }) } diff --git a/apps/vault/src/broker/http/rest/controller/asset.controller.ts b/apps/vault/src/broker/http/rest/controller/asset.controller.ts index 319a20e27..8ab3fc126 100644 --- a/apps/vault/src/broker/http/rest/controller/asset.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/asset.controller.ts @@ -1,11 +1,11 @@ -import { ApiClientIdHeader } from '@narval/nestjs-shared' -import { Controller, Get, HttpStatus, Query } from '@nestjs/common' -import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' +import { ApiClientIdHeader, Paginated } from '@narval/nestjs-shared' +import { Controller, Get, Query } from '@nestjs/common' +import { ApiOperation, ApiTags } from '@nestjs/swagger' import { PermissionGuard } from '../../../../shared/decorator/permission-guard.decorator' import { VaultPermission } from '../../../../shared/type/domain.type' import { AssetService } from '../../../core/service/asset.service' import { Provider } from '../../../core/type/provider.type' -import { AssetDto } from '../dto/response/asset.dto' +import { PaginatedAssetsDto } from '../dto/response/paginated-assets.dto' @Controller({ path: 'assets', @@ -22,16 +22,15 @@ export class AssetController { summary: 'Retrieve all assets', description: 'This endpoint retrieves a list of all available assets.' }) - @ApiResponse({ - status: HttpStatus.OK, - description: 'The assets were successfully retrieved.', - type: AssetDto + @Paginated({ + type: PaginatedAssetsDto, + description: 'The assets were successfully retrieved.' }) - async list(@Query('provider') provider?: Provider): Promise { + async list(@Query('provider') provider?: Provider): Promise { const data = await this.assetService.findAll({ filters: { provider } }) - return AssetDto.create({ data }) + return PaginatedAssetsDto.create({ data }) } } diff --git a/apps/vault/src/broker/http/rest/controller/connection.controller.ts b/apps/vault/src/broker/http/rest/controller/connection.controller.ts index 9223eec17..63100652e 100644 --- a/apps/vault/src/broker/http/rest/controller/connection.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/connection.controller.ts @@ -1,12 +1,16 @@ import { ApiClientIdHeader, Paginated, PaginationOptions, PaginationParam } from '@narval/nestjs-shared' +import { Alg, RsaPrivateKey } from '@narval/signature' import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Patch, Post } from '@nestjs/common' import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../shared/decorator/client-id.decorator' import { PermissionGuard } from '../../../../shared/decorator/permission-guard.decorator' import { VaultPermission } from '../../../../shared/type/domain.type' +import { FireblocksCredentialService } from '../../../core/provider/fireblocks/fireblocks-credential.service' import { AccountService } from '../../../core/service/account.service' import { ConnectionService } from '../../../core/service/connection.service' import { WalletService } from '../../../core/service/wallet.service' +import { PendingConnection } from '../../../core/type/connection.type' +import { Provider } from '../../../core/type/provider.type' import { formatPublicKey, formatRsaPublicKey } from '../../../core/util/user-friendly-key-format.util' import { CreateConnectionDto } from '../dto/request/create-connection.dto' import { InitiateConnectionDto } from '../dto/request/initiate-connection.dto' @@ -47,7 +51,7 @@ export class ConnectionController { @Body() body: InitiateConnectionDto ): Promise { const pendingConnection = await this.connectionService.initiate(clientId, body) - const credentials = await this.connectionService.findCredentials(pendingConnection) + const publicKey = await this.formatPublicKey(pendingConnection) const data = { ...pendingConnection, @@ -56,16 +60,35 @@ export class ConnectionController { encryptionPublicKey: await formatRsaPublicKey(pendingConnection.encryptionPublicKey) } : {}), - ...(credentials - ? { - publicKey: await formatPublicKey(credentials.publicKey) - } - : {}) + ...(publicKey ? { publicKey } : {}) } return ProviderPendingConnectionDto.create({ data }) } + private async formatPublicKey(connection: PendingConnection) { + const credentials = await this.connectionService.findCredentials(connection) + + if (credentials && 'publicKey' in credentials) { + const publicKey = await formatPublicKey(credentials.publicKey) + + if (connection.provider === Provider.FIREBLOCKS && credentials.publicKey.alg === Alg.RS256) { + const certificateOrgName = `Narval Fireblocks Connection - Client ${connection.clientId}` + + const csr = await FireblocksCredentialService.signCertificateRequest( + credentials.privateKey as RsaPrivateKey, + certificateOrgName + ) + + return { ...publicKey, csr } + } + + return publicKey + } + + return null + } + @Post() @PermissionGuard(VaultPermission.CONNECTION_WRITE) @ApiOperation({ @@ -100,25 +123,6 @@ export class ConnectionController { await this.connectionService.revoke(clientId, connectionId) } - @Get() - @PermissionGuard(VaultPermission.CONNECTION_READ) - @ApiOperation({ - summary: 'List all connections', - description: 'This endpoint retrieves a list of all connections associated with the client.' - }) - @Paginated({ - type: PaginatedConnectionsDto, - description: 'Returns a paginated list of connections associated with the client' - }) - async list( - @ClientId() clientId: string, - @PaginationParam() pagination: PaginationOptions - ): Promise { - const { data, page } = await this.connectionService.findAll(clientId, { pagination }) - - return PaginatedConnectionsDto.create({ data, page }) - } - @Get(':connectionId') @PermissionGuard(VaultPermission.CONNECTION_READ) @ApiOperation({ @@ -166,11 +170,31 @@ export class ConnectionController { return ProviderConnectionDto.create({ data }) } + @Get() + @PermissionGuard(VaultPermission.CONNECTION_READ) + @ApiOperation({ + summary: 'List all connections', + description: 'This endpoint retrieves a list of all connections associated with the client.' + }) + @Paginated({ + type: PaginatedConnectionsDto, + description: 'Returns a paginated list of connections associated with the client' + }) + async list( + @ClientId() clientId: string, + @PaginationParam() pagination: PaginationOptions + ): Promise { + const { data, page } = await this.connectionService.findAll(clientId, { pagination }) + + return PaginatedConnectionsDto.create({ data, page }) + } + @Get(':connectionId/wallets') @PermissionGuard(VaultPermission.CONNECTION_READ) @ApiOperation({ - summary: 'List wallets for a specific connection', - description: 'This endpoint retrieves a list of wallets associated with a specific connection.' + deprecated: true, + summary: '(DEPRECATED) List wallets for a specific connection', + description: 'Note: use GET /v1/provider/wallets endpoint instead' }) @Paginated({ type: PaginatedWalletsDto, @@ -181,19 +205,25 @@ export class ConnectionController { @Param('connectionId') connectionId: string, @PaginationParam() pagination: PaginationOptions ): Promise { - const { data, page } = await this.walletService.findAll(clientId, { - filters: { connectionId }, - pagination - }) - - return PaginatedWalletsDto.create({ data, page }) + const page = await this.walletService.findAll( + { + clientId, + connectionId + }, + { + pagination + } + ) + + return PaginatedWalletsDto.create(page) } @Get(':connectionId/accounts') @PermissionGuard(VaultPermission.CONNECTION_READ) @ApiOperation({ - summary: 'List accounts for a specific connection', - description: 'This endpoint retrieves a list of accounts associated with a specific connection.' + deprecated: true, + summary: '(DEPRECATED) List accounts for a specific connection', + description: 'Note: use GET /v1/provider/accounts endpoint instead' }) @Paginated({ type: PaginatedAccountsDto, @@ -204,11 +234,16 @@ export class ConnectionController { @Param('connectionId') connectionId: string, @PaginationParam() pagination: PaginationOptions ): Promise { - const { data, page } = await this.accountService.findAll(clientId, { - filters: { connectionId }, - pagination - }) - - return PaginatedAccountsDto.create({ data, page }) + const page = await this.accountService.findAll( + { + clientId, + connectionId + }, + { + pagination + } + ) + + return PaginatedAccountsDto.create(page) } } diff --git a/apps/vault/src/broker/http/rest/controller/known-destination.controller.ts b/apps/vault/src/broker/http/rest/controller/known-destination.controller.ts index 4b9f0e4da..5705e434b 100644 --- a/apps/vault/src/broker/http/rest/controller/known-destination.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/known-destination.controller.ts @@ -1,12 +1,13 @@ -import { ApiClientIdHeader, Paginated, PaginationOptions, PaginationParam } from '@narval/nestjs-shared' -import { Controller, Get, HttpStatus, Param, Query } from '@nestjs/common' -import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' +import { ApiClientIdHeader, Paginated } from '@narval/nestjs-shared' +import { Controller, Get, Query } from '@nestjs/common' +import { ApiHeader, ApiOperation, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../shared/decorator/client-id.decorator' import { PermissionGuard } from '../../../../shared/decorator/permission-guard.decorator' import { VaultPermission } from '../../../../shared/type/domain.type' import { KnownDestinationService } from '../../../core/service/known-destination.service' +import { REQUEST_HEADER_CONNECTION_ID } from '../../../shared/constant' +import { ConnectionId } from '../../../shared/decorator/connection-id.decorator' import { PaginatedKnownDestinationsDto } from '../dto/response/paginated-known-destinations.dto' -import { KnownDestinationDto } from '../dto/response/provider-known-destination.dto' @Controller({ path: 'known-destinations', @@ -20,42 +21,31 @@ export class KnownDestinationController { @Get() @PermissionGuard(VaultPermission.CONNECTION_READ) @ApiOperation({ summary: 'Get known destinations across providers' }) + @ApiHeader({ + name: REQUEST_HEADER_CONNECTION_ID, + description: 'The provider connection through which the resource is accessed' + }) @Paginated({ type: PaginatedKnownDestinationsDto, description: 'Returns a paginated list of known-destinations for the client' }) async list( @ClientId() clientId: string, - @PaginationParam() pagination: PaginationOptions, - @Query('connectionId') connectionId?: string + @ConnectionId() connectionId: string, + @Query('limit') limit?: number, + @Query('cursor') cursor?: string ): Promise { - const filters = connectionId ? { connections: [connectionId] } : {} - - const { data, page } = await this.knownDestinationService.findAll(clientId, { - filters, - pagination - }) + const { data, page } = await this.knownDestinationService.findAll( + { + clientId, + connectionId + }, + { + limit, + cursor + } + ) return PaginatedKnownDestinationsDto.create({ data, page }) } - - @Get(':knownDestinationId') - @PermissionGuard(VaultPermission.CONNECTION_READ) - @ApiOperation({ summary: 'Get known destination by ID' }) - @ApiResponse({ - status: HttpStatus.OK, - description: 'Returns known destination', - type: KnownDestinationDto - }) - @ApiResponse({ - status: HttpStatus.NOT_FOUND, - description: 'Known destination not found' - }) - async getById( - @ClientId() clientId: string, - @Param('knownDestinationId') knownDestinationId: string - ): Promise { - const data = await this.knownDestinationService.getKnownDestination(clientId, knownDestinationId) - return KnownDestinationDto.create({ data }) - } } diff --git a/apps/vault/src/broker/http/rest/controller/network.controller.ts b/apps/vault/src/broker/http/rest/controller/network.controller.ts index 8b05542c7..69f5c7b27 100644 --- a/apps/vault/src/broker/http/rest/controller/network.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/network.controller.ts @@ -1,11 +1,11 @@ -import { ApiClientIdHeader } from '@narval/nestjs-shared' -import { Controller, Get, HttpStatus, Query } from '@nestjs/common' -import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' +import { ApiClientIdHeader, Paginated } from '@narval/nestjs-shared' +import { Controller, Get, Query } from '@nestjs/common' +import { ApiOperation, ApiTags } from '@nestjs/swagger' import { PermissionGuard } from '../../../../shared/decorator/permission-guard.decorator' import { VaultPermission } from '../../../../shared/type/domain.type' +import { NetworkService } from '../../../core/service/network.service' import { Provider } from '../../../core/type/provider.type' -import { NetworkRepository } from '../../../persistence/repository/network.repository' -import { NetworkDto } from '../dto/response/network.dto' +import { PaginatedNetworksDto } from '../dto/response/paginated-networks.dto' @Controller({ path: 'networks', @@ -14,7 +14,7 @@ import { NetworkDto } from '../dto/response/network.dto' @ApiClientIdHeader() @ApiTags('Provider Network') export class NetworkController { - constructor(private readonly networkRepository: NetworkRepository) {} + constructor(private readonly networkService: NetworkService) {} @Get() @PermissionGuard(VaultPermission.CONNECTION_READ) @@ -22,14 +22,13 @@ export class NetworkController { summary: 'Retrieve all networks', description: 'This endpoint retrieves a list of all available networks.' }) - @ApiResponse({ - status: HttpStatus.OK, - description: 'The networks were successfully retrieved.', - type: NetworkDto + @Paginated({ + type: PaginatedNetworksDto, + description: 'The networks were successfully retrieved.' }) - async list(@Query('provider') provider: Provider): Promise { - const data = await this.networkRepository.findAll({ filters: { provider } }) + async list(@Query('provider') provider: Provider): Promise { + const data = await this.networkService.findAll({ filters: { provider } }) - return NetworkDto.create({ data }) + return PaginatedNetworksDto.create({ data }) } } diff --git a/apps/vault/src/broker/http/rest/controller/proxy.controller.ts b/apps/vault/src/broker/http/rest/controller/proxy.controller.ts index 6fb60407d..b9e018301 100644 --- a/apps/vault/src/broker/http/rest/controller/proxy.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/proxy.controller.ts @@ -68,12 +68,17 @@ export class ProxyController { const queryString = new URLSearchParams(request.query as Record).toString() const sanitizedEndpoint = queryString ? `/${endpoint}?${queryString}` : `/${endpoint}` - const response = await this.proxyService.forward(clientId, { - connectionId, - endpoint: sanitizedEndpoint, - method: request.method, - data: body - }) + const response = await this.proxyService.forward( + { + clientId, + connectionId + }, + { + endpoint: sanitizedEndpoint, + method: request.method, + data: body + } + ) res.status(response.code).set(response.headers) response.data.pipe(res) diff --git a/apps/vault/src/broker/http/rest/controller/scoped-sync.controller.ts b/apps/vault/src/broker/http/rest/controller/scoped-sync.controller.ts new file mode 100644 index 000000000..69cc2eaff --- /dev/null +++ b/apps/vault/src/broker/http/rest/controller/scoped-sync.controller.ts @@ -0,0 +1,105 @@ +import { ApiClientIdHeader, Paginated, PaginationOptions, PaginationParam } from '@narval/nestjs-shared' +import { Body, Controller, Get, HttpStatus, Param, Post } from '@nestjs/common' +import { ApiHeader, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' +import { ClientId } from '../../../../shared/decorator/client-id.decorator' +import { PermissionGuard } from '../../../../shared/decorator/permission-guard.decorator' +import { VaultPermission } from '../../../../shared/type/domain.type' +import { ConnectionService } from '../../../core/service/connection.service' +import { ScopedSyncService } from '../../../core/service/scoped-sync.service' +import { REQUEST_HEADER_CONNECTION_ID } from '../../../shared/constant' +import { ConnectionId } from '../../../shared/decorator/connection-id.decorator' +import { StartScopedSyncDto } from '../dto/request/start-scoped-sync.dto' +import { PaginatedScopedSyncsDto } from '../dto/response/paginated-scoped-syncs.dto' +import { ScopedSyncStartedDto } from '../dto/response/scoped-sync-started.dto' +import { ScopedSyncDto } from '../dto/response/scoped-sync.dto' + +@Controller({ + path: 'scoped-syncs', + version: '1' +}) +@ApiClientIdHeader() +@ApiTags('Provider Scoped Sync') +export class ScopedSyncController { + constructor( + private readonly scopedSyncService: ScopedSyncService, + private readonly connectionService: ConnectionService + ) {} + + @Post() + // ScopedSync is a read operation even though it's a POST. + @PermissionGuard(VaultPermission.CONNECTION_READ) + @ApiOperation({ + summary: 'Start a scoped synchronization process', + description: 'This endpoint starts scoped synchronization process for the client.' + }) + @ApiResponse({ + description: 'Returns the status of the scoped synchronization process.', + status: HttpStatus.CREATED, + type: ScopedSyncStartedDto + }) + async start(@ClientId() clientId: string, @Body() body: StartScopedSyncDto): Promise { + const connection = await this.connectionService.findWithCredentialsById(clientId, body.connectionId) + const data = await this.scopedSyncService.start([connection], body.rawAccounts) + + return ScopedSyncStartedDto.create({ data }) + } + + @Get(':scopedSyncId') + @PermissionGuard(VaultPermission.CONNECTION_READ) + @ApiOperation({ + summary: 'Retrieve a specific scoped synchronization process by ID', + description: + 'This endpoint retrieves the details of a specific scoped synchronization process associated with the client, identified by the scoped sync ID.' + }) + @ApiHeader({ + name: REQUEST_HEADER_CONNECTION_ID, + description: 'The provider connection through which the resource is accessed' + }) + @ApiResponse({ + description: 'Returns the details of the specified synchronization process.', + status: HttpStatus.OK, + type: ScopedSyncDto + }) + async getById( + @ClientId() clientId: string, + @ConnectionId() connectionId: string, + @Param('scopedSyncId') scopedSyncId: string + ): Promise { + const data = await this.scopedSyncService.findById({ clientId, connectionId }, scopedSyncId) + + return ScopedSyncDto.create({ data }) + } + + @Get() + @PermissionGuard(VaultPermission.CONNECTION_READ) + @ApiOperation({ + summary: 'Retrieve a list of synchronization processes', + description: + 'This endpoint retrieves a list of synchronization processes associated with the client. Optionally, it can filter the processes by a specific connection ID.' + }) + @ApiHeader({ + name: REQUEST_HEADER_CONNECTION_ID, + description: 'The provider connection through which the resource is accessed' + }) + @Paginated({ + type: PaginatedScopedSyncsDto, + description: 'Returns a paginated list of accounts associated with the connection' + }) + async list( + @ClientId() clientId: string, + @ConnectionId() connectionId: string, + @PaginationParam() pagination: PaginationOptions + ): Promise { + return PaginatedScopedSyncsDto.create( + await this.scopedSyncService.findAll( + { + clientId, + connectionId + }, + { + pagination + } + ) + ) + } +} diff --git a/apps/vault/src/broker/http/rest/controller/sync.controller.ts b/apps/vault/src/broker/http/rest/controller/sync.controller.ts index a8502fadb..998dcd496 100644 --- a/apps/vault/src/broker/http/rest/controller/sync.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/sync.controller.ts @@ -1,16 +1,13 @@ import { ApiClientIdHeader, Paginated, PaginationOptions, PaginationParam } from '@narval/nestjs-shared' -import { Body, Controller, Get, HttpStatus, Param, Post, Query } from '@nestjs/common' -import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' +import { Controller, Get } from '@nestjs/common' +import { ApiHeader, ApiOperation, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../shared/decorator/client-id.decorator' import { PermissionGuard } from '../../../../shared/decorator/permission-guard.decorator' import { VaultPermission } from '../../../../shared/type/domain.type' -import { ConnectionService } from '../../../core/service/connection.service' import { SyncService } from '../../../core/service/sync.service' -import { ConnectionStatus } from '../../../core/type/connection.type' -import { StartSyncDto } from '../dto/request/start-sync.dto' +import { REQUEST_HEADER_CONNECTION_ID } from '../../../shared/constant' +import { ConnectionId } from '../../../shared/decorator/connection-id.decorator' import { PaginatedSyncsDto } from '../dto/response/paginated-syncs.dto' -import { SyncStartedDto } from '../dto/response/sync-started.dto' -import { SyncDto } from '../dto/response/sync.dto' @Controller({ path: 'syncs', @@ -19,60 +16,7 @@ import { SyncDto } from '../dto/response/sync.dto' @ApiClientIdHeader() @ApiTags('Provider Sync') export class SyncController { - constructor( - private readonly syncService: SyncService, - private readonly connectionService: ConnectionService - ) {} - - @Post() - // Sync is a read operation even though it's a POST. - @PermissionGuard(VaultPermission.CONNECTION_READ) - @ApiOperation({ - summary: 'Start a synchronization process', - description: 'This endpoint starts synchronization process for the client.' - }) - @ApiResponse({ - description: 'Returns the status of the synchronization process.', - status: HttpStatus.CREATED, - type: SyncStartedDto - }) - async start(@ClientId() clientId: string, @Body() body: StartSyncDto): Promise { - if (body.connectionId) { - const connection = await this.connectionService.findWithCredentialsById(clientId, body.connectionId) - const data = await this.syncService.start([connection]) - - return SyncStartedDto.create({ data }) - } - - const { data: connections } = await this.connectionService.findAllWithCredentials(clientId, { - filters: { - status: ConnectionStatus.ACTIVE - } - }) - - const data = await this.syncService.start(connections) - - return SyncStartedDto.create({ data }) - } - - @Get(':syncId') - @PermissionGuard(VaultPermission.CONNECTION_READ) - @ApiOperation({ - summary: 'Retrieve a specific synchronization process by ID', - description: - 'This endpoint retrieves the details of a specific synchronization process associated with the client, identified by the sync ID.' - }) - @ApiResponse({ - description: 'Returns the details of the specified synchronization process.', - status: HttpStatus.OK, - type: SyncDto - }) - async getById(@ClientId() clientId: string, @Param('syncId') syncId: string): Promise { - const data = await this.syncService.findById(clientId, syncId) - - return SyncDto.create({ data }) - } - + constructor(private readonly syncService: SyncService) {} @Get() @PermissionGuard(VaultPermission.CONNECTION_READ) @ApiOperation({ @@ -80,20 +24,29 @@ export class SyncController { description: 'This endpoint retrieves a list of synchronization processes associated with the client. Optionally, it can filter the processes by a specific connection ID.' }) + @ApiHeader({ + name: REQUEST_HEADER_CONNECTION_ID, + description: 'The provider connection through which the resource is accessed' + }) @Paginated({ type: PaginatedSyncsDto, description: 'Returns a paginated list of accounts associated with the connection' }) async list( @ClientId() clientId: string, - @PaginationParam() pagination: PaginationOptions, - @Query('connectionId') connectionId?: string + @ConnectionId() connectionId: string, + @PaginationParam() pagination: PaginationOptions ): Promise { return PaginatedSyncsDto.create( - await this.syncService.findAll(clientId, { - filters: { connectionId }, - pagination - }) + await this.syncService.findAll( + { + clientId, + connectionId + }, + { + pagination + } + ) ) } } diff --git a/apps/vault/src/broker/http/rest/controller/transfer.controller.ts b/apps/vault/src/broker/http/rest/controller/transfer.controller.ts index 2cac5cdc1..eff9aeb66 100644 --- a/apps/vault/src/broker/http/rest/controller/transfer.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/transfer.controller.ts @@ -27,6 +27,7 @@ export class TransferController { }) @ApiHeader({ name: REQUEST_HEADER_CONNECTION_ID, + description: 'The provider connection through which the resource is accessed', required: true }) @ApiResponse({ @@ -39,7 +40,7 @@ export class TransferController { @ConnectionId() connectionId: string, @Body() body: SendTransferDto ): Promise { - const internalTransfer = await this.transferService.send(clientId, connectionId, body) + const internalTransfer = await this.transferService.send({ clientId, connectionId }, body) return TransferDto.create({ data: internalTransfer }) } @@ -50,21 +51,22 @@ export class TransferController { summary: 'Retrieve transfer details', description: 'This endpoint retrieves the details of a specific transfer using its ID.' }) + @ApiHeader({ + name: REQUEST_HEADER_CONNECTION_ID, + description: 'The provider connection through which the resource is accessed', + required: true + }) @ApiResponse({ status: HttpStatus.OK, description: 'The transfer details were successfully retrieved.', type: TransferDto }) - @ApiHeader({ - name: REQUEST_HEADER_CONNECTION_ID, - required: true - }) async getById( @ClientId() clientId: string, @ConnectionId() connectionId: string, @Param('transferId') transferId: string ) { - const internalTransfer = await this.transferService.findById(clientId, connectionId, transferId) + const internalTransfer = await this.transferService.findById({ clientId, connectionId }, transferId) return TransferDto.create({ data: internalTransfer }) } diff --git a/apps/vault/src/broker/http/rest/controller/wallet.controller.ts b/apps/vault/src/broker/http/rest/controller/wallet.controller.ts index f75810c23..8bf60868d 100644 --- a/apps/vault/src/broker/http/rest/controller/wallet.controller.ts +++ b/apps/vault/src/broker/http/rest/controller/wallet.controller.ts @@ -1,11 +1,13 @@ import { ApiClientIdHeader, Paginated, PaginationOptions, PaginationParam } from '@narval/nestjs-shared' import { Controller, Get, HttpStatus, Param } from '@nestjs/common' -import { ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger' +import { ApiHeader, ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger' import { ClientId } from '../../../../shared/decorator/client-id.decorator' import { PermissionGuard } from '../../../../shared/decorator/permission-guard.decorator' import { VaultPermission } from '../../../../shared/type/domain.type' import { AccountService } from '../../../core/service/account.service' import { WalletService } from '../../../core/service/wallet.service' +import { REQUEST_HEADER_CONNECTION_ID } from '../../../shared/constant' +import { ConnectionId } from '../../../shared/decorator/connection-id.decorator' import { PaginatedAccountsDto } from '../dto/response/paginated-accounts.dto' import { PaginatedWalletsDto } from '../dto/response/paginated-wallets.dto' import { ProviderWalletDto } from '../dto/response/provider-wallet.dto' @@ -24,6 +26,10 @@ export class ProviderWalletController { @Get() @PermissionGuard(VaultPermission.CONNECTION_READ) + @ApiHeader({ + name: REQUEST_HEADER_CONNECTION_ID, + description: 'The provider connection through which the resource is accessed' + }) @ApiOperation({ summary: 'List the client wallets' }) @@ -33,9 +39,18 @@ export class ProviderWalletController { }) async list( @ClientId() clientId: string, + @ConnectionId() connectionId: string, @PaginationParam() pagination: PaginationOptions ): Promise { - return PaginatedWalletsDto.create(await this.walletService.findAll(clientId, { pagination })) + return PaginatedWalletsDto.create( + await this.walletService.findAll( + { + clientId, + connectionId + }, + { pagination } + ) + ) } @Get(':walletId') @@ -43,6 +58,10 @@ export class ProviderWalletController { @ApiOperation({ summary: 'Get a specific wallet by ID' }) + @ApiHeader({ + name: REQUEST_HEADER_CONNECTION_ID, + description: 'The provider connection through which the resource is accessed' + }) @ApiParam({ name: 'walletId', description: 'The ID of the wallet to retrieve' @@ -55,8 +74,12 @@ export class ProviderWalletController { status: HttpStatus.NOT_FOUND, description: 'Wallet not found' }) - async getById(@ClientId() clientId: string, @Param('walletId') walletId: string): Promise { - const data = await this.walletService.findById(clientId, walletId) + async getById( + @ClientId() clientId: string, + @ConnectionId() connectionId: string, + @Param('walletId') walletId: string + ): Promise { + const data = await this.walletService.findById({ clientId, connectionId }, walletId) return ProviderWalletDto.create({ data }) } @@ -66,6 +89,10 @@ export class ProviderWalletController { @ApiOperation({ summary: 'List accounts for a specific wallet' }) + @ApiHeader({ + name: REQUEST_HEADER_CONNECTION_ID, + description: 'The provider connection through which the resource is accessed' + }) @ApiParam({ name: 'walletId', description: 'The ID of the wallet to retrieve accounts for' @@ -80,14 +107,21 @@ export class ProviderWalletController { }) async listAccounts( @ClientId() clientId: string, + @ConnectionId() connectionId: string, @Param('walletId') walletId: string, @PaginationParam() options: PaginationOptions ): Promise { return PaginatedAccountsDto.create( - await this.accountService.findAllPaginated(clientId, { - ...options, - filters: { walletId } - }) + await this.accountService.findAll( + { + clientId, + connectionId + }, + { + ...options, + filters: { walletId } + } + ) ) } } diff --git a/apps/vault/src/broker/http/rest/dto/request/start-scoped-sync.dto.ts b/apps/vault/src/broker/http/rest/dto/request/start-scoped-sync.dto.ts new file mode 100644 index 000000000..cde480668 --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/request/start-scoped-sync.dto.ts @@ -0,0 +1,4 @@ +import { createZodDto } from 'nestjs-zod' +import { StartScopedSync } from '../../../../core/type/scoped-sync.type' + +export class StartScopedSyncDto extends createZodDto(StartScopedSync.omit({ clientId: true })) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/paginated-accounts.dto.ts b/apps/vault/src/broker/http/rest/dto/response/paginated-accounts.dto.ts index 2d137af08..76b38fafd 100644 --- a/apps/vault/src/broker/http/rest/dto/response/paginated-accounts.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/paginated-accounts.dto.ts @@ -1,11 +1,22 @@ import { Page } from '@narval/nestjs-shared' import { createZodDto } from 'nestjs-zod' import { z } from 'zod' -import { Account } from '../../../../core/type/indexed-resources.type' +import { Account, Address } from '../../../../core/type/indexed-resources.type' export class PaginatedAccountsDto extends createZodDto( z.object({ - data: z.array(Account), + data: z.array( + Account.extend({ + createdAt: z.coerce.date(), + updatedAt: z.coerce.date(), + addresses: z.array( + Address.extend({ + createdAt: z.coerce.date(), + updatedAt: z.coerce.date() + }) + ) + }) + ), page: Page }) ) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/paginated-addresses.dto.ts b/apps/vault/src/broker/http/rest/dto/response/paginated-addresses.dto.ts index 1f6261d7f..72bc05092 100644 --- a/apps/vault/src/broker/http/rest/dto/response/paginated-addresses.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/paginated-addresses.dto.ts @@ -5,7 +5,12 @@ import { Address } from '../../../../core/type/indexed-resources.type' export class PaginatedAddressesDto extends createZodDto( z.object({ - data: z.array(Address), + data: z.array( + Address.extend({ + createdAt: z.coerce.date(), + updatedAt: z.coerce.date() + }) + ), page: Page }) ) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/asset.dto.ts b/apps/vault/src/broker/http/rest/dto/response/paginated-assets.dto.ts similarity index 85% rename from apps/vault/src/broker/http/rest/dto/response/asset.dto.ts rename to apps/vault/src/broker/http/rest/dto/response/paginated-assets.dto.ts index d54332ef0..89cee3040 100644 --- a/apps/vault/src/broker/http/rest/dto/response/asset.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/paginated-assets.dto.ts @@ -3,7 +3,7 @@ import { createZodDto } from 'nestjs-zod' import { z } from 'zod' import { Asset } from '../../../../core/type/asset.type' -export class AssetDto extends createZodDto( +export class PaginatedAssetsDto extends createZodDto( z.object({ data: z.array( Asset.extend({ diff --git a/apps/vault/src/broker/http/rest/dto/response/paginated-known-destinations.dto.ts b/apps/vault/src/broker/http/rest/dto/response/paginated-known-destinations.dto.ts index 1737982e4..ad7c848c0 100644 --- a/apps/vault/src/broker/http/rest/dto/response/paginated-known-destinations.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/paginated-known-destinations.dto.ts @@ -1,11 +1,11 @@ import { Page } from '@narval/nestjs-shared' import { createZodDto } from 'nestjs-zod' import { z } from 'zod' -import { KnownDestination } from '../../../../core/type/indexed-resources.type' +import { KnownDestination as KnownDestinationNext } from '../../../../core/type/known-destination.type' export class PaginatedKnownDestinationsDto extends createZodDto( z.object({ - data: z.array(KnownDestination), + data: z.array(KnownDestinationNext), page: Page }) ) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/network.dto.ts b/apps/vault/src/broker/http/rest/dto/response/paginated-networks.dto.ts similarity index 84% rename from apps/vault/src/broker/http/rest/dto/response/network.dto.ts rename to apps/vault/src/broker/http/rest/dto/response/paginated-networks.dto.ts index 82eace55c..370984061 100644 --- a/apps/vault/src/broker/http/rest/dto/response/network.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/paginated-networks.dto.ts @@ -3,7 +3,7 @@ import { createZodDto } from 'nestjs-zod' import { z } from 'zod' import { Network } from '../../../../core/type/network.type' -export class NetworkDto extends createZodDto( +export class PaginatedNetworksDto extends createZodDto( z.object({ data: z.array( Network.extend({ diff --git a/apps/vault/src/broker/http/rest/dto/response/paginated-raw-accounts.dto.ts b/apps/vault/src/broker/http/rest/dto/response/paginated-raw-accounts.dto.ts new file mode 100644 index 000000000..fe740aa29 --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/response/paginated-raw-accounts.dto.ts @@ -0,0 +1,11 @@ +import { Page } from '@narval/nestjs-shared' +import { createZodDto } from 'nestjs-zod' +import { z } from 'zod' +import { RawAccount } from '../../../../core/service/raw-account.service' + +export class PaginatedRawAccountsDto extends createZodDto( + z.object({ + data: z.array(RawAccount), + page: Page + }) +) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/paginated-scoped-syncs.dto.ts b/apps/vault/src/broker/http/rest/dto/response/paginated-scoped-syncs.dto.ts new file mode 100644 index 000000000..710530d47 --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/response/paginated-scoped-syncs.dto.ts @@ -0,0 +1,11 @@ +import { Page } from '@narval/nestjs-shared' +import { createZodDto } from 'nestjs-zod' +import { z } from 'zod' +import { ScopedSync } from '../../../../core/type/scoped-sync.type' + +export class PaginatedScopedSyncsDto extends createZodDto( + z.object({ + data: z.array(ScopedSync), + page: Page + }) +) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/paginated-wallets.dto.ts b/apps/vault/src/broker/http/rest/dto/response/paginated-wallets.dto.ts index 43cc2f268..13cff686f 100644 --- a/apps/vault/src/broker/http/rest/dto/response/paginated-wallets.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/paginated-wallets.dto.ts @@ -1,11 +1,28 @@ import { Page } from '@narval/nestjs-shared' import { createZodDto } from 'nestjs-zod' import { z } from 'zod' -import { Wallet } from '../../../../core/type/indexed-resources.type' +import { Account, Address, Wallet } from '../../../../core/type/indexed-resources.type' export class PaginatedWalletsDto extends createZodDto( z.object({ - data: z.array(Wallet), + data: z.array( + Wallet.extend({ + createdAt: z.coerce.date(), + updatedAt: z.coerce.date(), + accounts: z.array( + Account.extend({ + createdAt: z.coerce.date(), + updatedAt: z.coerce.date(), + addresses: z.array( + Address.extend({ + createdAt: z.coerce.date(), + updatedAt: z.coerce.date() + }) + ) + }) + ) + }) + ), page: Page }) ) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/provider-account.dto.ts b/apps/vault/src/broker/http/rest/dto/response/provider-account.dto.ts index 77e483ede..030073191 100644 --- a/apps/vault/src/broker/http/rest/dto/response/provider-account.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/provider-account.dto.ts @@ -1,9 +1,18 @@ import { createZodDto } from 'nestjs-zod' import { z } from 'zod' -import { Account } from '../../../../core/type/indexed-resources.type' +import { Account, Address } from '../../../../core/type/indexed-resources.type' export class ProviderAccountDto extends createZodDto( z.object({ - data: Account + data: Account.extend({ + createdAt: z.coerce.date(), + updatedAt: z.coerce.date(), + addresses: z.array( + Address.extend({ + createdAt: z.coerce.date(), + updatedAt: z.coerce.date() + }) + ) + }) }) ) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/provider-known-destination.dto.ts b/apps/vault/src/broker/http/rest/dto/response/provider-known-destination.dto.ts index a83af23a7..7c4289d0c 100644 --- a/apps/vault/src/broker/http/rest/dto/response/provider-known-destination.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/provider-known-destination.dto.ts @@ -1,6 +1,6 @@ import { createZodDto } from 'nestjs-zod' import { z } from 'zod' -import { KnownDestination } from '../../../../core/type/indexed-resources.type' +import { KnownDestination } from '../../../../core/type/known-destination.type' export class KnownDestinationDto extends createZodDto( z.object({ diff --git a/apps/vault/src/broker/http/rest/dto/response/provider-pending-connection.dto.ts b/apps/vault/src/broker/http/rest/dto/response/provider-pending-connection.dto.ts index 74eae3633..2211bf744 100644 --- a/apps/vault/src/broker/http/rest/dto/response/provider-pending-connection.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/provider-pending-connection.dto.ts @@ -17,7 +17,11 @@ export class ProviderPendingConnectionDto extends createZodDto( .object({ keyId: z.string().optional(), jwk: publicKeySchema.optional(), - hex: hexSchema.optional() + hex: hexSchema.optional(), + csr: z + .string() + .optional() + .describe('Certificate Signing Request PEM format of RSA public key encoded as base64') }) .optional(), encryptionPublicKey: z.object({ diff --git a/apps/vault/src/broker/http/rest/dto/response/provider-wallet.dto.ts b/apps/vault/src/broker/http/rest/dto/response/provider-wallet.dto.ts index fd4c6a767..ae410db47 100644 --- a/apps/vault/src/broker/http/rest/dto/response/provider-wallet.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/provider-wallet.dto.ts @@ -1,9 +1,24 @@ import { createZodDto } from 'nestjs-zod' import { z } from 'zod' -import { Wallet } from '../../../../core/type/indexed-resources.type' +import { Account, Address, Wallet } from '../../../../core/type/indexed-resources.type' export class ProviderWalletDto extends createZodDto( z.object({ - data: Wallet + data: Wallet.extend({ + createdAt: z.coerce.date(), + updatedAt: z.coerce.date(), + accounts: z.array( + Account.extend({ + createdAt: z.coerce.date(), + updatedAt: z.coerce.date(), + addresses: z.array( + Address.extend({ + createdAt: z.coerce.date(), + updatedAt: z.coerce.date() + }) + ) + }) + ) + }) }) ) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/scoped-sync-started.dto.ts b/apps/vault/src/broker/http/rest/dto/response/scoped-sync-started.dto.ts new file mode 100644 index 000000000..b170df6f4 --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/response/scoped-sync-started.dto.ts @@ -0,0 +1,9 @@ +import { createZodDto } from 'nestjs-zod' +import { z } from 'zod' +import { ScopedSyncStarted } from '../../../../core/type/scoped-sync.type' + +export class ScopedSyncStartedDto extends createZodDto( + z.object({ + data: ScopedSyncStarted + }) +) {} diff --git a/apps/vault/src/broker/http/rest/dto/response/scoped-sync.dto.ts b/apps/vault/src/broker/http/rest/dto/response/scoped-sync.dto.ts new file mode 100644 index 000000000..529818d1a --- /dev/null +++ b/apps/vault/src/broker/http/rest/dto/response/scoped-sync.dto.ts @@ -0,0 +1,9 @@ +import { createZodDto } from 'nestjs-zod' +import { z } from 'zod' +import { ScopedSync } from '../../../../core/type/scoped-sync.type' + +export class ScopedSyncDto extends createZodDto( + z.object({ + data: ScopedSync + }) +) {} diff --git a/apps/vault/src/broker/persistence/repository/account.repository.ts b/apps/vault/src/broker/persistence/repository/account.repository.ts index 0e6f49202..3075b8b11 100644 --- a/apps/vault/src/broker/persistence/repository/account.repository.ts +++ b/apps/vault/src/broker/persistence/repository/account.repository.ts @@ -4,6 +4,7 @@ import { ProviderAccount, ProviderAddress } from '@prisma/client/vault' import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' import { NotFoundException } from '../../core/exception/not-found.exception' import { Account, Address } from '../../core/type/indexed-resources.type' +import { ConnectionScope } from '../../core/type/scope.type' import { AddressRepository } from './address.repository' type ProviderAccountAndRelations = ProviderAccount & { @@ -12,7 +13,6 @@ type ProviderAccountAndRelations = ProviderAccount & { type FindAllFilters = { filters?: { - connectionId?: string walletId?: string externalIds?: string[] } @@ -47,6 +47,7 @@ export class AccountRepository { clientId: account.clientId, createdAt: account.createdAt, externalId: account.externalId, + connectionId: account.connectionId, id: account.accountId, label: account.label || null, networkId: account.networkId, @@ -74,9 +75,13 @@ export class AccountRepository { } } - async findById(clientId: string, accountId: string): Promise { + async findById({ clientId, connectionId }: ConnectionScope, accountId: string): Promise { const account = await this.prismaService.providerAccount.findUnique({ - where: { clientId, id: accountId }, + where: { + clientId, + connectionId, + id: accountId + }, include: { addresses: true } @@ -145,28 +150,21 @@ export class AccountRepository { return true } - async findAll(clientId: string, options?: FindAllOptions): Promise> { + async findAll( + { clientId, connectionId }: ConnectionScope, + options?: FindAllOptions + ): Promise> { const pagination = applyPagination(options?.pagination) const models = await this.prismaService.providerAccount.findMany({ where: { clientId, + connectionId, ...(options?.filters?.walletId ? { walletId: options.filters.walletId } : {}), - ...(options?.filters?.connectionId - ? { - wallet: { - connections: { - some: { - connectionId: options?.filters?.connectionId - } - } - } - } - : {}), ...(options?.filters?.externalIds ? { externalId: { diff --git a/apps/vault/src/broker/persistence/repository/address.repository.ts b/apps/vault/src/broker/persistence/repository/address.repository.ts index b14f9d497..ffbe4f998 100644 --- a/apps/vault/src/broker/persistence/repository/address.repository.ts +++ b/apps/vault/src/broker/persistence/repository/address.repository.ts @@ -6,12 +6,14 @@ import { PrismaService } from '../../../shared/module/persistence/service/prisma import { NotFoundException } from '../../core/exception/not-found.exception' import { Address } from '../../core/type/indexed-resources.type' import { Provider } from '../../core/type/provider.type' +import { ConnectionScope } from '../../core/type/scope.type' type FindAllFilters = { filters?: { externalIds?: string[] addresses?: string[] provider?: Provider + connectionId?: string } } @@ -36,6 +38,7 @@ export class AddressRepository { accountId: entity.accountId, address: entity.address, clientId: entity.clientId, + connectionId: entity.connectionId, createdAt: entity.createdAt, externalId: entity.externalId, id: entity.addressId, @@ -59,9 +62,13 @@ export class AddressRepository { } } - async findById(clientId: string, addressId: string): Promise

{ + async findById({ clientId, connectionId }: ConnectionScope, addressId: string): Promise
{ const address = await this.prismaService.providerAddress.findUnique({ - where: { clientId, id: addressId } + where: { + clientId, + connectionId, + id: addressId + } }) if (!address) { @@ -88,12 +95,13 @@ export class AddressRepository { return models.map(AddressRepository.parseModel) } - async findAll(clientId: string, opts?: FindAllOptions): Promise> { + async findAll({ clientId, connectionId }: ConnectionScope, opts?: FindAllOptions): Promise> { const pagination = applyPagination(opts?.pagination) const models = await this.prismaService.providerAddress.findMany({ where: { clientId, + connectionId, ...(opts?.filters?.provider ? { provider: opts.filters.provider @@ -112,6 +120,11 @@ export class AddressRepository { in: opts.filters.externalIds } } + : {}), + ...(opts?.filters?.connectionId + ? { + connectionId: opts.filters.connectionId + } : {}) }, ...pagination diff --git a/apps/vault/src/broker/persistence/repository/asset.repository.ts b/apps/vault/src/broker/persistence/repository/asset.repository.ts index b84f57281..486379706 100644 --- a/apps/vault/src/broker/persistence/repository/asset.repository.ts +++ b/apps/vault/src/broker/persistence/repository/asset.repository.ts @@ -37,6 +37,44 @@ export class AssetRepository { }) } + async bulkCreate(assets: Asset[]): Promise { + for (const asset of assets) { + const createdAt = asset.createdAt || new Date() + + const data = { + createdAt, + id: asset.assetId, + name: asset.name, + symbol: asset.symbol, + decimals: asset.decimals, + networkId: asset.networkId, + onchainId: asset.onchainId + } + + await this.prismaService.asset.upsert({ + where: { + id: asset.assetId + }, + create: data, + update: data + }) + + const externalAssets = asset.externalAssets.map(({ provider, externalId }) => ({ + provider, + externalId, + assetId: asset.assetId, + createdAt + })) + + await this.prismaService.providerAsset.createMany({ + data: externalAssets, + skipDuplicates: true + }) + } + + return assets + } + async create(asset: Asset): Promise { const parse = Asset.parse(asset) const createdAt = parse.createdAt || new Date() @@ -119,7 +157,7 @@ export class AssetRepository { async findById(assetId: string): Promise { const model = await this.prismaService.asset.findUnique({ where: { - id: assetId + id: assetId.toUpperCase() }, include: { externalAssets: true @@ -139,7 +177,7 @@ export class AssetRepository { externalAssets: { some: { provider, - externalId + externalId: externalId.toUpperCase() } } }, @@ -158,8 +196,8 @@ export class AssetRepository { async findByOnchainId(networkId: string, onchainId: string): Promise { const models = await this.prismaService.asset.findMany({ where: { - networkId, - onchainId + networkId: networkId.toUpperCase(), + onchainId: onchainId.toLowerCase() }, include: { externalAssets: true diff --git a/apps/vault/src/broker/persistence/repository/known-destination.repository.ts b/apps/vault/src/broker/persistence/repository/known-destination.repository.ts deleted file mode 100644 index f69259671..000000000 --- a/apps/vault/src/broker/persistence/repository/known-destination.repository.ts +++ /dev/null @@ -1,296 +0,0 @@ -import { PaginatedResult, PaginationOptions, applyPagination, getPaginatedResult } from '@narval/nestjs-shared' -import { Injectable } from '@nestjs/common' -import { ProviderConnection, ProviderKnownDestination, ProviderKnownDestinationConnection } from '@prisma/client/vault' -import { z } from 'zod' -import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' -import { NotFoundException } from '../../core/exception/not-found.exception' -import { KnownDestination } from '../../core/type/indexed-resources.type' -import { Provider } from '../../core/type/provider.type' -import { ConnectionRepository, SELECT_WITHOUT_CREDENTIALS } from './connection.repository' - -type FindAllFilters = { - filters?: { - externalIds?: string[] - addresses?: string[] - providers?: Provider[] - connections?: string[] - networksIds?: string[] - } -} - -type ProviderKnownDestinationAndRelations = ProviderKnownDestination & { - connections: { connection: Partial }[] -} - -export type FindAllOptions = FindAllFilters & { pagination?: PaginationOptions } - -export const UpdateKnownDestination = KnownDestination.pick({ - knownDestinationId: true, - label: true, - connections: true, - externalClassification: true, - updatedAt: true, - assetId: true, - clientId: true -}) -export type UpdateKnownDestination = z.infer - -@Injectable() -export class KnownDestinationRepository { - constructor(private prismaService: PrismaService) {} - - static parseModel(model: ProviderKnownDestinationAndRelations): KnownDestination { - const { connections, id, ...rest } = model - - const validConnections = connections.map((join) => { - return ConnectionRepository.parseModel(join.connection) - }) - - return KnownDestination.parse({ - ...rest, - connections: validConnections, - knownDestinationId: id, - provider: model.provider - }) - } - - static parseEntity(entity: KnownDestination): ProviderKnownDestination { - return { - id: entity.knownDestinationId, - clientId: entity.clientId, - label: entity.label || null, - provider: entity.provider, - externalId: entity.externalId, - externalClassification: entity.externalClassification || null, - address: entity.address, - assetId: entity.assetId || null, - networkId: entity.networkId, - createdAt: entity.createdAt, - updatedAt: entity.updatedAt - } - } - - async findByClientId(clientId: string, opts?: PaginationOptions): Promise> { - const pagination = applyPagination(opts) - - const result = await this.prismaService.providerKnownDestination.findMany({ - where: { clientId }, - include: { - connections: { - include: { - connection: { - select: SELECT_WITHOUT_CREDENTIALS - } - } - } - }, - ...pagination - }) - - const { data, page } = getPaginatedResult({ items: result, pagination }) - return { - data: data.map(KnownDestinationRepository.parseModel), - page - } - } - - async findById(clientId: string, knownDestinationId: string): Promise { - const knownDestination = await this.prismaService.providerKnownDestination.findUnique({ - where: { clientId, id: knownDestinationId }, - include: { - connections: { - include: { - connection: { - select: SELECT_WITHOUT_CREDENTIALS - } - } - } - } - }) - if (!knownDestination) { - throw new NotFoundException({ - message: 'Address not found', - context: { knownDestinationId } - }) - } - - return KnownDestinationRepository.parseModel(knownDestination) - } - - async findAll(clientId: string, opts?: FindAllOptions): Promise> { - const pagination = applyPagination(opts?.pagination) - - const models = await this.prismaService.providerKnownDestination.findMany({ - where: { - clientId, - ...(opts?.filters?.addresses - ? { - address: { - in: opts.filters.addresses - } - } - : {}), - ...(opts?.filters?.externalIds - ? { - externalId: { - in: opts.filters.externalIds - } - } - : {}), - ...(opts?.filters?.providers - ? { - provider: { - in: opts.filters.providers - } - } - : {}), - ...(opts?.filters?.connections - ? { - connections: { - some: { - connectionId: { - in: opts.filters.connections - } - } - } - } - : {}), - ...(opts?.filters?.networksIds - ? { - networkId: { - in: opts.filters.networksIds - } - } - : {}) - }, - include: { - connections: { - include: { - connection: { - select: SELECT_WITHOUT_CREDENTIALS - } - } - } - }, - ...pagination - }) - - const { data, page } = getPaginatedResult({ items: models, pagination }) - - return { - data: data.map(KnownDestinationRepository.parseModel), - page - } - } - - async bulkCreate(knownDestinations: KnownDestination[]): Promise { - const providerKnownDestinations: ProviderKnownDestination[] = knownDestinations.map( - KnownDestinationRepository.parseEntity - ) - const providerKnownDestinationConnections: ProviderKnownDestinationConnection[] = knownDestinations.flatMap( - this.getKnownDestinationConnectionModel - ) - - await this.prismaService.$transaction(async (tx) => { - await tx.providerKnownDestination.createMany({ - data: providerKnownDestinations, - skipDuplicates: true - }) - - await tx.providerKnownDestinationConnection.createMany({ - data: providerKnownDestinationConnections, - skipDuplicates: true - }) - }) - - const created = await this.prismaService.providerKnownDestination.findMany({ - where: { - id: { - in: knownDestinations.map((kd) => kd.knownDestinationId) - } - }, - include: { - connections: { - include: { - connection: { - select: SELECT_WITHOUT_CREDENTIALS - } - } - } - } - }) - - // Use the same parsing logic as findAll - return created.map(KnownDestinationRepository.parseModel) - } - - async bulkDelete(knownDestinationIds: string[]): Promise { - await this.prismaService.providerKnownDestinationConnection.deleteMany({ - where: { - knownDestinationId: { - in: knownDestinationIds - } - } - }) - - const { count } = await this.prismaService.providerKnownDestination.deleteMany({ - where: { - id: { - in: knownDestinationIds - } - } - }) - - return count - } - - async update(knownDestination: UpdateKnownDestination) { - const { clientId, connections, updatedAt, knownDestinationId, ...data } = knownDestination - - const connectionPayload = connections.map((connection) => { - return { - clientId: clientId, - knownDestinationId, - connectionId: connection.connectionId, - createdAt: updatedAt - } - }) - - await this.prismaService.providerKnownDestinationConnection.createMany({ - data: connectionPayload, - skipDuplicates: true - }) - - const updatedKnownDest = await this.prismaService.providerKnownDestination.update({ - where: { id: knownDestinationId }, - data: { - label: data.label, - externalClassification: data.externalClassification, - assetId: data.assetId, - updatedAt - }, - include: { - connections: { - include: { - connection: { - select: SELECT_WITHOUT_CREDENTIALS - } - } - } - } - }) - - return KnownDestinationRepository.parseModel(updatedKnownDest) - } - - private getKnownDestinationConnectionModel(knownDestination: KnownDestination): ProviderKnownDestinationConnection[] { - return knownDestination.connections.map((connection) => { - return { - clientId: knownDestination.clientId, - knownDestinationId: knownDestination.knownDestinationId, - connectionId: connection.connectionId, - createdAt: knownDestination.createdAt - } - }) - } -} diff --git a/apps/vault/src/broker/persistence/repository/network.repository.ts b/apps/vault/src/broker/persistence/repository/network.repository.ts index e0a25cea9..776eec896 100644 --- a/apps/vault/src/broker/persistence/repository/network.repository.ts +++ b/apps/vault/src/broker/persistence/repository/network.repository.ts @@ -1,26 +1,18 @@ -import { LoggerService } from '@narval/nestjs-shared' -import { Injectable, OnApplicationBootstrap } from '@nestjs/common' +import { Injectable } from '@nestjs/common' import { Prisma } from '@prisma/client/vault' import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' import { ExternalNetwork, Network } from '../../core/type/network.type' import { Provider } from '../../core/type/provider.type' -type FindAllOptions = { +export type FindAllOptions = { filters?: { provider?: Provider } } @Injectable() -export class NetworkRepository implements OnApplicationBootstrap { - private networkById: Map - private networkByProviderAndExternalId: Map - private networksByProvider: Map - - constructor( - private readonly prismaService: PrismaService, - private readonly logger: LoggerService - ) {} +export class NetworkRepository { + constructor(private readonly prismaService: PrismaService) {} static parseModel( model: Prisma.NetworkGetPayload<{ @@ -41,88 +33,40 @@ export class NetworkRepository implements OnApplicationBootstrap { }) } - async onApplicationBootstrap() { - await this.index() - } - - /** - * Builds index structures for O(1) lookups of networks. - * - * Creates three indexes: - * - networkById: Maps networkId -> Network for direct lookups - * - networkByProviderAndExternalId: Maps "provider:externalId" -> Network - * for external ID lookups - * - networksByProvider: Maps provider -> Network[] for provider-specific - * filtering - * - * This is a one-time O(n) operation at initialization to avoid O(n) array - * traversals on subsequent queries. All lookups become O(1) after indexing - * at the cost of O(n) additional memory. - */ - private async index(): Promise { - const networks = await this.findAll() - - this.networkById = new Map() - this.networkByProviderAndExternalId = new Map() - this.networksByProvider = new Map() - - for (const network of networks) { - this.networkById.set(network.networkId, network) - - for (const externalNetwork of network.externalNetworks) { - const key = `${externalNetwork.provider}:${externalNetwork.externalId}` - this.networkByProviderAndExternalId.set(key, network) - - const providerNetworks = this.networksByProvider.get(externalNetwork.provider) || [] - providerNetworks.push(network) - this.networksByProvider.set(externalNetwork.provider, providerNetworks) - } - } - } - - async buildProviderExternalIdIndex(provider: Provider): Promise> { - const networks = await this.findAll({ filters: { provider } }) - const index = new Map() - - for (const network of networks) { - for (const externalNetwork of network.externalNetworks) { - if (externalNetwork.provider === provider) { - index.set(externalNetwork.externalId, network) - } - } - } - - return index - } - - getNetworksByProvider(provider: Provider): Network[] { - return this.networksByProvider?.get(provider) || [] - } - async bulkCreate(networks: Network[]): Promise { for (const network of networks) { const createdAt = network.createdAt || new Date() - await this.prismaService.network.create({ - data: { + await this.prismaService.network.upsert({ + where: { + id: network.networkId + }, + create: { createdAt, id: network.networkId, coinType: network.coinType, - name: network.name, - externalNetworks: { - createMany: { - data: network.externalNetworks.map(({ provider, externalId }) => ({ - provider, - externalId, - createdAt - })) - } - } + name: network.name }, - include: { - externalNetworks: true + update: { + createdAt, + id: network.networkId, + coinType: network.coinType, + name: network.name } }) + + const externalNetworks = network.externalNetworks.map(({ provider, externalId }) => ({ + provider, + externalId, + networkId: network.networkId, + createdAt + })) + + // Ensure we have them all inserted + await this.prismaService.providerNetwork.createMany({ + data: externalNetworks, + skipDuplicates: true + }) } return networks @@ -139,39 +83,7 @@ export class NetworkRepository implements OnApplicationBootstrap { return externalNetwork } - async bulkAddExternalNetwork( - params: { - networkId: string - externalNetwork: ExternalNetwork - }[] - ): Promise { - await this.prismaService.providerNetwork.createMany({ - data: params.map(({ networkId, externalNetwork }) => ({ - ...externalNetwork, - networkId - })) - }) - - return true - } - async findAll(options?: FindAllOptions): Promise { - let networks: Network[] = [] - - if (this.networkById) { - if (options?.filters?.provider) { - networks = this.getNetworksByProvider(options.filters.provider) - } else { - networks = Array.from(this.networkById.values()) - } - } - - if (networks.length) { - return networks - } - - this.logger.log('Failed to findAll network in the index. Fallback to the database') - const models = await this.prismaService.network.findMany({ where: { ...(options?.filters?.provider @@ -193,21 +105,9 @@ export class NetworkRepository implements OnApplicationBootstrap { } async findById(networkId: string): Promise { - let network: Network | null = null - - if (this.networkById) { - network = this.networkById.get(networkId) || null - } - - if (network) { - return network - } - - this.logger.log('Failed to findById network in the index. Fallback to the database', { networkId }) - const model = await this.prismaService.network.findUnique({ where: { - id: networkId + id: networkId.toUpperCase() }, include: { externalNetworks: true @@ -222,28 +122,12 @@ export class NetworkRepository implements OnApplicationBootstrap { } async findByExternalId(provider: Provider, externalId: string): Promise { - let network: Network | null = null - - if (this.networkByProviderAndExternalId) { - const key = `${provider}:${externalId}` - network = this.networkByProviderAndExternalId.get(key) || null - } - - if (network) { - return network - } - - this.logger.log('Failed to findByExternalId network in the index. Fallback to the database', { - provider, - externalId - }) - const model = await this.prismaService.network.findFirst({ where: { externalNetworks: { some: { provider, - externalId + externalId: externalId.toUpperCase() } } }, diff --git a/apps/vault/src/broker/persistence/repository/scoped-sync.repository.ts b/apps/vault/src/broker/persistence/repository/scoped-sync.repository.ts new file mode 100644 index 000000000..792a853fd --- /dev/null +++ b/apps/vault/src/broker/persistence/repository/scoped-sync.repository.ts @@ -0,0 +1,147 @@ +import { PaginatedResult, PaginationOptions, applyPagination, getPaginatedResult } from '@narval/nestjs-shared' +import { Injectable } from '@nestjs/common/decorators' +import { ProviderScopedSync } from '@prisma/client/vault' +import { z } from 'zod' +import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' +import { ModelInvalidException } from '../../core/exception/model-invalid.exception' +import { NotFoundException } from '../../core/exception/not-found.exception' +import { ConnectionScope } from '../../core/type/scope.type' +import { RawAccount, ScopedSync, ScopedSyncStatus } from '../../core/type/scoped-sync.type' + +export type FindAllOptions = PaginationOptions & { + filters?: { + status?: ScopedSyncStatus + } + pagination?: PaginationOptions +} + +export type UpdateScopedSync = { + clientId: string + scopedSyncId: string + completedAt?: Date + status?: ScopedSyncStatus + error?: ScopedSync['error'] +} + +const parseErrorEntity = ( + error: ScopedSync['error'] +): Pick => ({ + errorName: error?.name || null, + errorMessage: error?.message || null, + errorTraceId: error?.traceId || null +}) + +@Injectable() +export class ScopedSyncRepository { + constructor(private readonly prismaService: PrismaService) {} + + static parseModel(model?: ProviderScopedSync | null): ScopedSync { + if (model) { + const { id, ...rest } = model + + return ScopedSync.parse({ + ...rest, + scopedSyncId: id, + // Prisma always returns null for optional fields that don't have a + // value, rather than undefined. This is actually by design and aligns + // with how NULL values work in databases. + rawAccounts: model.rawAccounts ? z.array(RawAccount).parse(PrismaService.toJson(model.rawAccounts)) : [], + completedAt: model.completedAt || undefined, + error: + model.errorName || model.errorMessage || model.errorTraceId + ? { + name: model.errorName || undefined, + message: model.errorMessage || undefined, + traceId: model.errorTraceId || undefined + } + : undefined + }) + } + + throw new ModelInvalidException() + } + + static parseEntity(entity: ScopedSync): ProviderScopedSync { + return { + id: entity.scopedSyncId, + clientId: entity.clientId, + completedAt: entity.completedAt || null, + connectionId: entity.connectionId, + rawAccounts: z.string().parse(PrismaService.toStringJson(entity.rawAccounts)), + createdAt: entity.createdAt, + status: entity.status, + ...parseErrorEntity(entity.error) + } + } + + async create(scopedSync: ScopedSync): Promise { + await this.prismaService.providerScopedSync.create({ + data: ScopedSyncRepository.parseEntity(scopedSync) + }) + + return scopedSync + } + + async bulkCreate(scopedSyncs: ScopedSync[]): Promise { + await this.prismaService.providerScopedSync.createMany({ + data: scopedSyncs.map(ScopedSyncRepository.parseEntity) + }) + + return scopedSyncs + } + + async update(updateScopedSync: UpdateScopedSync): Promise { + await this.prismaService.providerScopedSync.update({ + where: { + id: updateScopedSync.scopedSyncId, + clientId: updateScopedSync.clientId + }, + data: { + completedAt: updateScopedSync.completedAt, + status: updateScopedSync.status, + ...(updateScopedSync.error ? parseErrorEntity(updateScopedSync.error) : {}) + } + }) + + return true + } + + async findById({ clientId, connectionId }: ConnectionScope, scopedSyncId: string): Promise { + const model = await this.prismaService.providerScopedSync.findUnique({ + where: { + clientId, + id: scopedSyncId, + connectionId + } + }) + + if (model) { + return ScopedSyncRepository.parseModel(model) + } + + throw new NotFoundException({ context: { clientId, scopedSyncId } }) + } + + async findAll( + { clientId, connectionId }: ConnectionScope, + options?: FindAllOptions + ): Promise> { + const pagination = applyPagination(options?.pagination) + + const models = await this.prismaService.providerScopedSync.findMany({ + where: { + clientId, + status: options?.filters?.status, + connectionId + }, + ...pagination + }) + + const { data, page } = getPaginatedResult({ items: models, pagination }) + + return { + data: data.map(ScopedSyncRepository.parseModel), + page + } + } +} diff --git a/apps/vault/src/broker/persistence/repository/sync.repository.ts b/apps/vault/src/broker/persistence/repository/sync.repository.ts index a4bbb4d87..fbaaf3d11 100644 --- a/apps/vault/src/broker/persistence/repository/sync.repository.ts +++ b/apps/vault/src/broker/persistence/repository/sync.repository.ts @@ -4,11 +4,11 @@ import { ProviderSync } from '@prisma/client/vault' import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' import { ModelInvalidException } from '../../core/exception/model-invalid.exception' import { NotFoundException } from '../../core/exception/not-found.exception' +import { ConnectionScope } from '../../core/type/scope.type' import { Sync, SyncStatus } from '../../core/type/sync.type' export type FindAllOptions = PaginationOptions & { filters?: { - connectionId?: string status?: SyncStatus } pagination?: PaginationOptions @@ -101,10 +101,11 @@ export class SyncRepository { return true } - async findById(clientId: string, syncId: string): Promise { + async findById({ clientId, connectionId }: ConnectionScope, syncId: string): Promise { const model = await this.prismaService.providerSync.findUnique({ where: { clientId, + connectionId, id: syncId } }) @@ -116,14 +117,14 @@ export class SyncRepository { throw new NotFoundException({ context: { clientId, syncId } }) } - async findAll(clientId: string, options?: FindAllOptions): Promise> { + async findAll({ clientId, connectionId }: ConnectionScope, options?: FindAllOptions): Promise> { const pagination = applyPagination(options?.pagination) const models = await this.prismaService.providerSync.findMany({ where: { clientId, - status: options?.filters?.status, - connectionId: options?.filters?.connectionId + connectionId, + status: options?.filters?.status }, ...pagination }) diff --git a/apps/vault/src/broker/persistence/repository/transfer.repository.ts b/apps/vault/src/broker/persistence/repository/transfer.repository.ts index a71e14936..1dcd2f75e 100644 --- a/apps/vault/src/broker/persistence/repository/transfer.repository.ts +++ b/apps/vault/src/broker/persistence/repository/transfer.repository.ts @@ -14,16 +14,17 @@ export class TransferRepository { static parseEntity(entity: InternalTransfer): ProviderTransfer { return { + assetExternalId: entity.assetExternalId, assetId: entity.assetId, clientId: entity.clientId, + connectionId: entity.connectionId, createdAt: entity.createdAt, customerRefId: entity.customerRefId, - destinationAddressRaw: null, // TODO externalId: entity.externalId, + grossAmount: entity.grossAmount, id: entity.transferId, idempotenceId: entity.idempotenceId, memo: entity.memo, - grossAmount: entity.grossAmount, networkFeeAttribution: entity.networkFeeAttribution, provider: entity.provider, providerSpecific: PrismaService.toStringJson(entity.providerSpecific), @@ -73,12 +74,15 @@ export class TransferRepository { ? { destinationAddressRaw: entity.destination.address } - : {}) + : { + destinationAddressRaw: null + }) } } static parseModel(model: ProviderTransfer): InternalTransfer { return InternalTransfer.parse({ + assetExternalId: model.assetExternalId, assetId: model.assetId, clientId: model.clientId, createdAt: model.createdAt, @@ -89,6 +93,7 @@ export class TransferRepository { grossAmount: model.grossAmount, idempotenceId: model.idempotenceId, memo: model.memo, + connectionId: model.connectionId, networkFeeAttribution: model.networkFeeAttribution, provider: model.provider, providerSpecific: PrismaService.toJson(model.providerSpecific), diff --git a/apps/vault/src/broker/persistence/repository/wallet.repository.ts b/apps/vault/src/broker/persistence/repository/wallet.repository.ts index 9e7275709..05c4e9747 100644 --- a/apps/vault/src/broker/persistence/repository/wallet.repository.ts +++ b/apps/vault/src/broker/persistence/repository/wallet.repository.ts @@ -1,20 +1,13 @@ import { PaginatedResult, PaginationOptions, applyPagination, getPaginatedResult } from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' -import { - ProviderAccount, - ProviderAddress, - ProviderConnection, - ProviderWallet, - ProviderWalletConnection -} from '@prisma/client/vault' +import { ProviderAccount, ProviderAddress, ProviderWallet } from '@prisma/client/vault' import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' import { NotFoundException } from '../../core/exception/not-found.exception' import { Account, UpdateWallet, Wallet } from '../../core/type/indexed-resources.type' +import { ConnectionScope } from '../../core/type/scope.type' import { AccountRepository } from './account.repository' -import { ConnectionRepository, SELECT_WITHOUT_CREDENTIALS } from './connection.repository' type ProviderWalletsAndRelations = ProviderWallet & { - connections: { connection: Partial }[] accounts: Array< ProviderAccount & { addresses: ProviderAddress[] @@ -24,7 +17,6 @@ type ProviderWalletsAndRelations = ProviderWallet & { type FindAllFilters = { filters?: { - connectionId?: string walletIds?: string[] externalIds?: string[] } @@ -39,11 +31,7 @@ export class WalletRepository { constructor(private prismaService: PrismaService) {} static parseModel(wallet: ProviderWalletsAndRelations): Wallet { - const { connections, accounts, id, ...walletData } = wallet - - const validConnections = connections.map((join) => { - return ConnectionRepository.parseModel(join.connection) - }) + const { accounts, id, ...walletData } = wallet const mappedAccounts = accounts.map((account) => { return AccountRepository.parseModel(account) @@ -52,8 +40,7 @@ export class WalletRepository { const parsedWallet = Wallet.parse({ ...walletData, walletId: id, - accounts: mappedAccounts, - connections: validConnections + accounts: mappedAccounts }) return parsedWallet @@ -66,6 +53,7 @@ export class WalletRepository { externalId: entity.externalId, label: entity.label || null, createdAt: entity.createdAt, + connectionId: entity.connectionId, updatedAt: entity.updatedAt, provider: entity.provider } @@ -81,13 +69,6 @@ export class WalletRepository { include: { addresses: true } - }, - connections: { - include: { - connection: { - select: SELECT_WITHOUT_CREDENTIALS - } - } } }, ...pagination @@ -101,55 +82,47 @@ export class WalletRepository { } } - async findById(clientId: string, id: string): Promise { - const wallet = await this.prismaService.providerWallet.findUnique({ - where: { clientId, id }, + async findById({ clientId, connectionId }: ConnectionScope, id: string): Promise { + const model = await this.prismaService.providerWallet.findUnique({ + where: { + clientId, + connectionId, + id + }, include: { accounts: { include: { addresses: true } - }, - connections: { - include: { - connection: { - select: SELECT_WITHOUT_CREDENTIALS - } - } } } }) - if (!wallet) { + if (!model) { throw new NotFoundException({ message: 'Wallet not found', context: { walletId: id } }) } - return WalletRepository.parseModel(wallet) + return WalletRepository.parseModel(model) } - async findAll(clientId: string, options?: FindAllOptions): Promise> { + async findAll( + { clientId, connectionId }: ConnectionScope, + options?: FindAllOptions + ): Promise> { const pagination = applyPagination(options?.pagination) const result = await this.prismaService.providerWallet.findMany({ where: { clientId, + connectionId, ...(options?.filters?.walletIds ? { id: { in: options?.filters.walletIds } } - : {}), - ...(options?.filters?.connectionId - ? { - connections: { - some: { - connectionId: options?.filters.connectionId - } - } - } : {}) }, include: { @@ -157,13 +130,6 @@ export class WalletRepository { include: { addresses: true } - }, - connections: { - include: { - connection: { - select: SELECT_WITHOUT_CREDENTIALS - } - } } }, ...pagination @@ -189,13 +155,6 @@ export class WalletRepository { addresses: true }, ...pagination - }, - connections: { - include: { - connection: { - select: SELECT_WITHOUT_CREDENTIALS - } - } } } }) @@ -215,52 +174,25 @@ export class WalletRepository { async bulkCreate(wallets: Wallet[]): Promise { const providerWallets: ProviderWallet[] = wallets.map(WalletRepository.parseEntity) - const providerWalletConnections: ProviderWalletConnection[] = wallets.flatMap(this.getWalletConnectionModel) await this.prismaService.$transaction(async (tx) => { await tx.providerWallet.createMany({ data: providerWallets, skipDuplicates: true }) - - await tx.providerWalletConnection.createMany({ - data: providerWalletConnections, - skipDuplicates: true - }) }) return wallets } async update(wallet: UpdateWallet) { - const providerWalletConnections = wallet.connections.map((connection) => { - return { - clientId: wallet.clientId, - walletId: wallet.walletId, - connectionId: connection.connectionId, - createdAt: wallet.updatedAt - } - }) - - await this.prismaService.providerWalletConnection.createMany({ - data: providerWalletConnections, - skipDuplicates: true - }) - - const updatedWallet = await this.prismaService.providerWallet.update({ + const model = await this.prismaService.providerWallet.update({ where: { id: wallet.walletId }, data: { updatedAt: wallet.updatedAt, label: wallet.label }, include: { - connections: { - include: { - connection: { - select: SELECT_WITHOUT_CREDENTIALS - } - } - }, accounts: { include: { addresses: true @@ -269,17 +201,6 @@ export class WalletRepository { } }) - return WalletRepository.parseModel(updatedWallet) - } - - private getWalletConnectionModel(wallet: Wallet): ProviderWalletConnection[] { - return wallet.connections.map((connection) => { - return { - clientId: wallet.clientId, - walletId: wallet.walletId, - connectionId: connection.connectionId, - createdAt: wallet.createdAt - } - }) + return WalletRepository.parseModel(model) } } diff --git a/apps/vault/src/broker/persistence/seed/asset.seed.ts b/apps/vault/src/broker/persistence/seed/asset.seed.ts index f99c11936..26ea22c94 100644 --- a/apps/vault/src/broker/persistence/seed/asset.seed.ts +++ b/apps/vault/src/broker/persistence/seed/asset.seed.ts @@ -1,25 +1,18 @@ -import { ConfigService } from '@narval/config-module' import { LoggerService } from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' -import { Config, Env } from '../../../main.config' -import { AssetService } from '../../core/service/asset.service' import { Provider } from '../../core/type/provider.type' +import { AssetRepository } from '../repository/asset.repository' @Injectable() export class AssetSeed { constructor( - private readonly assetService: AssetService, - private readonly configService: ConfigService, + private readonly assetRepository: AssetRepository, private readonly logger: LoggerService ) {} // IMPORTANT: There's already a data migration for base assets. // See 20250116101514_add_asset_table_and_data/migration.sql async seed(): Promise { - if (this.configService.get('env') === Env.PRODUCTION) { - throw new Error('You CANNOT seed the production database') - } - const assets = this.getAssets().map((asset) => ({ networkId: asset.networkId, assetId: asset.assetId, @@ -43,346 +36,442 @@ export class AssetSeed { externalId: asset.fireblocksId } ] + : []), + ...(asset.bitgoId + ? [ + { + provider: Provider.BITGO, + externalId: asset.bitgoId + } + ] : []) ] })) - this.logger.log(`🪙 Seeding ${assets.length} assets`) + this.logger.log(`Seeding ${assets.length} assets`) - await this.assetService.bulkCreate(assets) + await this.assetRepository.bulkCreate(assets) } getAssets() { return [ - { - assetId: 'USDC', - name: 'USD Coin', - symbol: 'USDC', - decimals: 6, - networkId: 'ETHEREUM', - onchainId: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', - anchorageId: 'USDC', - fireblocksId: 'USDC' - }, - { - assetId: 'USDC_POLYGON', - name: 'USD Coin', - symbol: 'USDC', - decimals: 6, - networkId: 'POLYGON', - onchainId: '0x2791bca1f2de4661ed88a30c99a7a9449aa84174', - anchorageId: null, - fireblocksId: 'USDC_POLYGON' - }, - { - assetId: 'USDC_ARBITRUM', - name: 'USD Coin', - symbol: 'USDC', - decimals: 6, - networkId: 'ARBITRUM', - onchainId: '0xaf88d065e77c8cc2239327c5edb3a432268e5831', - anchorageId: null, - fireblocksId: 'USDC_ARB_3SBJ' - }, - { - assetId: 'UNI', - name: 'Uniswap', - symbol: 'UNI', - decimals: 18, - networkId: 'ETHEREUM', - onchainId: '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984', - anchorageId: 'UNI', - fireblocksId: 'UNI' - }, { assetId: '1INCH', - name: '1inch', symbol: '1INCH', decimals: 18, + name: '1inch', networkId: 'ETHEREUM', onchainId: '0x111111111117dc0aa78b770fa6a738034120c302', anchorageId: '1INCH', - fireblocksId: '1INCH' + fireblocksId: '1INCH', + bitgoId: null }, { assetId: 'AAVE', - name: 'Aave', symbol: 'AAVE', decimals: 18, + name: 'Aave', networkId: 'ETHEREUM', onchainId: '0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9', anchorageId: 'AAVE', - fireblocksId: 'AAVE' + fireblocksId: 'AAVE', + bitgoId: null + }, + { + assetId: 'ARB', + symbol: 'ARB', + decimals: 18, + name: 'Arbitrum', + networkId: 'ETHEREUM', + onchainId: '0xb50721bcf8d664c30412cfbc6cf7a15145234ad1', + anchorageId: 'ARB', + fireblocksId: null, + bitgoId: null + }, + { + assetId: 'ARB_ARB', + symbol: 'ARB', + decimals: 18, + name: 'Arbitrum', + networkId: 'ARBITRUM', + onchainId: '0x912ce59144191c1204e64559fe8253a0e49e6548', + anchorageId: null, + fireblocksId: 'ARB_ARB_FRK9', + bitgoId: 'ARBETH:ARB' }, { assetId: 'ATOM', - name: 'Cosmos', symbol: 'ATOM', decimals: 6, + name: 'Cosmos', networkId: 'ATOM', onchainId: null, anchorageId: 'ATOM', - fireblocksId: 'ATOM_COS' + fireblocksId: 'ATOM_COS', + bitgoId: 'ATOM' }, { - assetId: 'XRP', - name: 'Ripple', - symbol: 'XRP', - decimals: 6, - networkId: 'RIPPLE', + assetId: 'BTC', + symbol: 'BTC', + decimals: 8, + name: 'Bitcoin', + networkId: 'BITCOIN', onchainId: null, - anchorageId: 'XRP', - fireblocksId: 'XRP' + anchorageId: 'BTC', + fireblocksId: 'BTC', + bitgoId: 'BTC' }, { - assetId: 'WBTC', - name: 'Wrapped Bitcoin', - symbol: 'WBTC', + assetId: 'BTC_SIGNET', + symbol: 'BTC_S', decimals: 8, - networkId: 'ETHEREUM', - onchainId: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599', - anchorageId: 'WBTC', - fireblocksId: 'WBTC' - }, - { - assetId: 'USDT', - name: 'Tether', - symbol: 'USDT', - decimals: 6, - networkId: 'ETHEREUM', - onchainId: '0xdac17f958d2ee523a2206206994597c13d831ec7', - anchorageId: 'USDT', - fireblocksId: 'USDT_ERC20' + name: 'Bitcoin Signet', + networkId: 'BITCOIN_SIGNET', + onchainId: null, + anchorageId: 'BTC_S', + fireblocksId: null, + bitgoId: null }, { - assetId: 'USDT_POLYGON', - name: 'Tether', - symbol: 'USDT', - decimals: 6, - networkId: 'POLYGON', - onchainId: '0xc2132d05d31c914a87c6611c10748aeb04b58e8f', + assetId: 'DOT', + symbol: 'DOT', + decimals: 10, + name: 'Polkadot', + networkId: 'POLKADOT', + onchainId: null, anchorageId: null, - fireblocksId: 'USDT_POLYGON' + fireblocksId: 'DOT', + bitgoId: 'DOT' }, { - assetId: 'SUSHI', - name: 'SushiSwap', - symbol: 'SUSHI', + assetId: 'ETH', + symbol: 'ETH', decimals: 18, + name: 'Ethereum', networkId: 'ETHEREUM', - onchainId: '0x6b3595068778dd592e39a122f4f5a5cf09c90fe2', - anchorageId: 'SUSHI', - fireblocksId: 'SUSHI' + onchainId: null, + anchorageId: 'ETH', + fireblocksId: 'ETH', + bitgoId: 'ETH' }, { - assetId: 'SUI_TEST', - name: 'Sui Test', - symbol: 'SUI', - decimals: 9, - networkId: 'SUI_TESTNET', + assetId: 'ETH_HOLESKY', + symbol: 'ETH', + decimals: 18, + name: 'Holesky Ethereum', + networkId: 'ETHEREUM_HOLESKY', onchainId: null, - anchorageId: 'SUI_T', - fireblocksId: null + anchorageId: 'ETHHOL', + fireblocksId: 'ETH_TEST6', + bitgoId: 'HTETH' }, { - assetId: 'SOL_DEVNET', - name: 'Solana Devnet', - symbol: 'SOL', - decimals: 9, - networkId: 'SOLANA_DEVNET', + assetId: 'ETH_ARB', + symbol: 'ETH', + decimals: 18, + name: 'Arbitrum Ethereum', + networkId: 'ARBITRUM', onchainId: null, - anchorageId: 'SOL_TD', - fireblocksId: null + anchorageId: null, + fireblocksId: 'ETH-AETH', + bitgoId: 'ARBETH' }, { - assetId: 'SOL_TEST', - name: 'Solana Testnet', - symbol: 'SOL', - decimals: null, - networkId: 'SOLANA_TESTNET', + assetId: 'ETH_ARBITRUM_TEST', + symbol: 'ETH', + decimals: 18, + name: 'Arbitrum Sepolia Testnet', + networkId: 'ARBITRUM_SEPOLIA', + onchainId: null, + anchorageId: 'ETH_ARBITRUM_T', + fireblocksId: 'ETH-AETH_SEPOLIA', + bitgoId: null + }, + { + assetId: 'ETH_OPT', + symbol: 'ETH', + decimals: 18, + name: 'Optimistic Ethereum', + networkId: 'OPTIMISM', onchainId: null, anchorageId: null, - fireblocksId: 'SOL_TEST' + fireblocksId: 'ETH-OPT', + bitgoId: 'OPETH' }, { - assetId: 'SOL', - name: 'Solana', - symbol: 'SOL', - decimals: null, - networkId: 'SOLANA', + assetId: 'ETH_OPT_KOVAN', + symbol: 'ETH', + decimals: 18, + name: 'Optimistic Ethereum Kovan', + networkId: 'OPTIMISM_KOVAN', onchainId: null, anchorageId: null, - fireblocksId: 'SOL' + fireblocksId: 'ETH-OPT_KOV', + bitgoId: null }, { - assetId: 'PORTAL', - name: 'PORTAL', - symbol: 'PORTAL', + assetId: 'ETH_OPT_SEPOLIA', + symbol: 'ETH', decimals: 18, - networkId: 'ETHEREUM', - onchainId: '0x1bbe973bef3a977fc51cbed703e8ffdefe001fed', - anchorageId: 'PORTAL', - fireblocksId: null + name: 'Optimistic Ethereum Sepolia', + networkId: 'OPTIMISM_SEPOLIA', + onchainId: null, + anchorageId: null, + fireblocksId: 'ETH-OPT_SEPOLIA', + bitgoId: null }, { - assetId: 'POL_POLYGON', - name: 'Polygon', - symbol: 'POL', + assetId: 'ETH_ZKSYNC_TEST', + symbol: 'ETH', decimals: 18, - networkId: 'POLYGON', + name: 'ZKsync Sepolia Testnet', + networkId: 'ZKSYNC_SEPOLIA', onchainId: null, - anchorageId: 'POL_POLYGON', - fireblocksId: 'MATIC_POLYGON' + anchorageId: 'ETH_ZKSYNC_T', + fireblocksId: 'ETH_ZKSYNC_ERA_SEPOLIA', + bitgoId: null }, { - assetId: 'POL', - name: 'Polygon Token', - symbol: 'POL', + assetId: 'LTC', + symbol: 'LTC', + decimals: 8, + name: 'Litecoin', + networkId: 'LITECOIN', + onchainId: null, + anchorageId: 'LTC', + fireblocksId: 'LTC', + bitgoId: 'LTC' + }, + { + assetId: 'MATIC', + symbol: 'MATIC', decimals: 18, + name: 'Matic Token', networkId: 'ETHEREUM', - onchainId: '0x455e53cbb86018ac2b8092fdcd39d8444affc3f6', - anchorageId: 'POL', - fireblocksId: 'POL_ETH_9RYQ' + onchainId: '0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0', + anchorageId: 'MATIC', + fireblocksId: 'MATIC', + bitgoId: 'MATIC' }, { assetId: 'MORPHO', - name: 'Morpho Token', symbol: 'MORPHO', decimals: 18, + name: 'Morpho Token', networkId: 'ETHEREUM', onchainId: '0x9994e35db50125e0df82e4c2dde62496ce330999', anchorageId: 'MORPHO', - fireblocksId: null + fireblocksId: null, + bitgoId: null }, { - assetId: 'MATIC', - name: 'Matic Token', - symbol: 'MATIC', + assetId: 'POL', + symbol: 'POL', decimals: 18, + name: 'Polygon Token', networkId: 'ETHEREUM', - onchainId: '0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0', - anchorageId: 'MATIC', - fireblocksId: 'MATIC' + onchainId: '0x455e53cbb86018ac2b8092fdcd39d8444affc3f6', + anchorageId: 'POL', + fireblocksId: 'POL_ETH_9RYQ', + bitgoId: null }, { - assetId: 'LTC', - name: 'Litecoin', - symbol: 'LTC', - decimals: 8, - networkId: 'LITECOIN', + assetId: 'POL_POLYGON', + symbol: 'POL', + decimals: 18, + name: 'Polygon', + networkId: 'POLYGON', onchainId: null, - anchorageId: 'LTC', - fireblocksId: 'LTC' + anchorageId: 'POL_POLYGON', + fireblocksId: 'MATIC_POLYGON', + bitgoId: 'POLYGON' }, { - assetId: 'ETH_ZKSYNC_TEST', - name: 'ZKsync Sepolia Testnet', - symbol: 'ETH', + assetId: 'PORTAL', + symbol: 'PORTAL', decimals: 18, - networkId: 'ZKSYNC_SEPOLIA', + name: 'PORTAL', + networkId: 'ETHEREUM', + onchainId: '0x1bbe973bef3a977fc51cbed703e8ffdefe001fed', + anchorageId: 'PORTAL', + fireblocksId: null, + bitgoId: null + }, + { + assetId: 'SOL', + symbol: 'SOL', + decimals: 9, + name: 'Solana', + networkId: 'SOLANA', onchainId: null, - anchorageId: 'ETH_ZKSYNC_T', - fireblocksId: 'ETH_ZKSYNC_ERA_SEPOLIA' + anchorageId: null, + fireblocksId: 'SOL', + bitgoId: 'SOL' }, { - assetId: 'ETH_ARBITRUM_TEST', - name: 'Arbitrum Sepolia Testnet', - symbol: 'ETH', - decimals: 18, - networkId: 'ARBITRUM_SEPOLIA', + assetId: 'SOL_DEVNET', + symbol: 'SOL', + decimals: 9, + name: 'Solana Devnet', + networkId: 'SOLONA_DEVNET', onchainId: null, - anchorageId: 'ETH_ARBITRUM_T', - fireblocksId: 'ETH-AETH_SEPOLIA' + anchorageId: 'SOL_TD', + fireblocksId: null, + bitgoId: null }, { - assetId: 'ETH', - name: 'Ethereum', - symbol: 'ETH', - decimals: 18, - networkId: 'ETHEREUM', + assetId: 'SOL_TEST', + symbol: 'SOL', + decimals: 9, + name: 'Solana Testnet', + networkId: 'SOLANA_TESTNET', onchainId: null, - anchorageId: 'ETH', - fireblocksId: 'ETH' + anchorageId: null, + fireblocksId: 'SOL_TEST', + bitgoId: null }, { - assetId: 'BTC', - name: 'Bitcoin', - symbol: 'BTC', - decimals: 8, - networkId: 'BITCOIN', + assetId: 'SUI_TEST', + symbol: 'SUI', + decimals: 9, + name: 'Sui Test', + networkId: 'SUI_TESTNET', onchainId: null, - anchorageId: 'BTC', - fireblocksId: 'BTC' + anchorageId: 'SUI_T', + fireblocksId: null, + bitgoId: 'TSUI' }, { - assetId: 'ARB', - name: 'Arbitrum', - symbol: 'ARB', + assetId: 'SUI', + symbol: 'SUI', + decimals: 9, + name: 'Sui', + networkId: 'SUI', + onchainId: null, + anchorageId: 'SUI', + fireblocksId: null, + bitgoId: 'SUI' + }, + { + assetId: 'SUSHI', + symbol: 'SUSHI', decimals: 18, + name: 'SushiSwap', networkId: 'ETHEREUM', - onchainId: '0xb50721bcf8d664c30412cfbc6cf7a15145234ad1', - anchorageId: 'ARB', - fireblocksId: null + onchainId: '0x6b3595068778dd592e39a122f4f5a5cf09c90fe2', + anchorageId: 'SUSHI', + fireblocksId: 'SUSHI', + bitgoId: 'SUSHI' }, { - assetId: 'ETH_OPT', - name: 'Optimistic Ethereum', - symbol: 'ETH', + assetId: 'UNI', + symbol: 'UNI', decimals: 18, - networkId: 'OPTIMISM', - onchainId: null, - anchorageId: null, - fireblocksId: 'ETH-OPT' + name: 'Uniswap', + networkId: 'ETHEREUM', + onchainId: '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984', + anchorageId: 'UNI', + fireblocksId: 'UNI', + bitgoId: 'UNI' }, { - assetId: 'ETH_OPT_KOVAN', - name: 'Optimistic Ethereum Kovan', - symbol: 'ETH', - decimals: 18, - networkId: 'OPTIMISM_KOVAN', - onchainId: null, + assetId: 'USDC', + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + networkId: 'ETHEREUM', + onchainId: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + anchorageId: 'USDC', + fireblocksId: 'USDC', + bitgoId: 'USDC' + }, + { + assetId: 'USDC_ARBITRUM', + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + networkId: 'ARBITRUM', + onchainId: '0xaf88d065e77c8cc2239327c5edb3a432268e5831', anchorageId: null, - fireblocksId: 'ETH-OPT_KOV' + fireblocksId: 'USDC_ARB_3SBJ', + bitgoId: 'ARBETH:USDCV2' }, { - assetId: 'ETH_OPT_SEPOLIA', - name: 'Optimistic Ethereum Sepolia', - symbol: 'ETH', - decimals: 18, - networkId: 'OPTIMISM_SEPOLIA', - onchainId: null, + assetId: 'USDC_POLYGON', + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + networkId: 'POLYGON', + onchainId: '0x2791bca1f2de4661ed88a30c99a7a9449aa84174', anchorageId: null, - fireblocksId: 'ETH-OPT_SEPOLIA' + fireblocksId: 'USDC_POLYGON', + bitgoId: 'POLYGON:USDCV2' }, { - assetId: 'DOT', - name: 'Polkadot', - symbol: 'DOT', - decimals: 10, - networkId: 'POLKADOT', - onchainId: null, + assetId: 'USDT', + symbol: 'USDT', + decimals: 6, + name: 'Tether', + networkId: 'ETHEREUM', + onchainId: '0xdac17f958d2ee523a2206206994597c13d831ec7', + anchorageId: 'USDT', + fireblocksId: 'USDT_ERC20', + bitgoId: 'USDT' + }, + { + assetId: 'USDT_POLYGON', + symbol: 'USDT', + decimals: 6, + name: 'Tether', + networkId: 'POLYGON', + onchainId: '0xc2132d05d31c914a87c6611c10748aeb04b58e8f', anchorageId: null, - fireblocksId: 'DOT' + fireblocksId: 'USDT_POLYGON', + bitgoId: 'OPETH:USDCV2' }, { - assetId: 'ETH_ARB', - name: 'Arbitrum Ethereum', - symbol: 'ETH', + assetId: 'WBTC', + symbol: 'WBTC', + decimals: 8, + name: 'Wrapped Bitcoin', + networkId: 'ETHEREUM', + onchainId: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599', + anchorageId: 'WBTC', + fireblocksId: 'WBTC', + bitgoId: 'WBTC' + }, + { + assetId: 'WETH', + symbol: 'WETH', decimals: 18, - networkId: 'ARBITRUM', - onchainId: null, - anchorageId: null, - fireblocksId: 'ETH-AETH' + name: 'Wrapped Ether', + networkId: 'ETHEREUM', + onchainId: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', + anchorageId: 'WETH', + fireblocksId: 'WETH', + bitgoId: 'WETH' }, { - assetId: 'ARB_ARB', - name: 'Arbitrum', - symbol: 'ARB', + assetId: 'WETH_HOLESKY', + symbol: 'WETH', decimals: 18, - networkId: 'ARBITRUM', - onchainId: '0x912ce59144191c1204e64559fe8253a0e49e6548', + name: 'Wrapped Ether', + networkId: 'ETHEREUM_HOLESKY', + onchainId: '0x94373a4919b3240d86ea41593d5eba789fef3848', anchorageId: null, - fireblocksId: 'ARB_ARB_FRK9' + fireblocksId: null, + bitgoId: 'TWETH' + }, + { + assetId: 'XRP', + symbol: 'XRP', + decimals: 6, + name: 'Ripple', + networkId: 'RIPPLE', + onchainId: null, + anchorageId: 'XRP', + fireblocksId: 'XRP', + bitgoId: 'XRP' }, { assetId: 'LINK_ZKSYNC_SEPOLIA', diff --git a/apps/vault/src/broker/persistence/seed/network.seed.ts b/apps/vault/src/broker/persistence/seed/network.seed.ts index 13b2ef33b..1fb26ca99 100644 --- a/apps/vault/src/broker/persistence/seed/network.seed.ts +++ b/apps/vault/src/broker/persistence/seed/network.seed.ts @@ -1,25 +1,16 @@ -import { ConfigService } from '@narval/config-module' import { LoggerService } from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' -import { Config, Env } from '../../../main.config' +import { NetworkService } from '../../core/service/network.service' import { Provider } from '../../core/type/provider.type' -import { NetworkRepository } from '../repository/network.repository' @Injectable() export class NetworkSeed { constructor( - private readonly networkRepository: NetworkRepository, - private readonly configService: ConfigService, + private readonly networkService: NetworkService, private readonly logger: LoggerService ) {} - // IMPORTANT: There's already a data migration for base networks. - // See 20250115095035_add_network_table_and_data/migration.sql async seed(): Promise { - if (this.configService.get('env') === Env.PRODUCTION) { - throw new Error('You CANNOT seed the production database') - } - const networks = this.getNetworks().map((network) => ({ networkId: network.networkId, coinType: network.coinType, @@ -40,605 +31,800 @@ export class NetworkSeed { externalId: network.fireblocksId } ] + : []), + ...(network.bitgoId + ? [ + { + provider: Provider.BITGO, + externalId: network.bitgoId + } + ] : []) ] })) - this.logger.log(`🌐 Seeding ${networks.length} networks`) + this.logger.log(`Seeding ${networks.length} networks`) - await this.networkRepository.bulkCreate(networks) + await this.networkService.bulkCreate(networks) } getNetworks() { return [ - { - networkId: 'ARBITRUM', - coinType: 9001, - name: 'Arbitrum', - fireblocksId: 'ETH-AETH' - }, { networkId: 'AETH', + name: 'Aetherius', coinType: 514, - name: 'Aetherius' + anchorageId: null, + fireblocksId: null, + bitgoId: null }, { networkId: 'AEVO', - coinType: null, name: 'Aevo', - fireblocksId: 'AEVO' + coinType: null, + anchorageId: null, + fireblocksId: 'AEVO', + bitgoId: null }, { networkId: 'AGORIC', - coinType: 564, name: 'Agoric', - anchorageId: 'BLD' + coinType: 564, + anchorageId: 'BLD', + fireblocksId: null, + bitgoId: 'BLD' }, { networkId: 'ALEPH_ZERO', - coinType: 643, name: 'Aleph Zero', - fireblocksId: 'ALEPH_ZERO_EVM' + coinType: 643, + anchorageId: null, + fireblocksId: 'ALEPH_ZERO_EVM', + bitgoId: null }, { networkId: 'ALGORAND', - coinType: 283, name: 'Algorand', - fireblocksId: 'ALGO' + coinType: 283, + anchorageId: null, + fireblocksId: 'ALGO', + bitgoId: 'ALGO' }, { networkId: 'ALGORAND_TESTNET', - coinType: 1, name: 'Algorand Testnet', - fireblocksId: 'ALGO_TEST' + coinType: 1, + anchorageId: null, + fireblocksId: 'ALGO_TEST', + bitgoId: 'TALGO' }, { networkId: 'ALLORA', - coinType: null, name: 'Allora', - anchorageId: 'ALLO' + coinType: null, + anchorageId: 'ALLO', + fireblocksId: null, + bitgoId: null }, { networkId: 'ALLORA_TESTNET', - coinType: 1, name: 'Allora Testnet', - anchorageId: 'ALLO_T' + coinType: 1, + anchorageId: 'ALLO_T', + fireblocksId: null, + bitgoId: null }, { networkId: 'APTOS', - coinType: 637, name: 'Aptos', - anchorageId: 'APT' + coinType: 637, + anchorageId: 'APT', + fireblocksId: null, + bitgoId: null }, { networkId: 'APTOS_TESTNET', - coinType: 1, name: 'Aptos Testnet', - anchorageId: 'APT_T' + coinType: 1, + anchorageId: 'APT_T', + fireblocksId: null, + bitgoId: null + }, + { + networkId: 'ARBITRUM', + name: 'Arbitrum', + coinType: 9001, + anchorageId: null, + fireblocksId: 'ETH-AETH', + bitgoId: 'ARBETH' }, { networkId: 'ARBITRUM_SEPOLIA', - coinType: 1, name: 'Arbitrum Sepolia Testnet', - anchorageId: 'ARBITRUM_SEPOLIA' + coinType: 1, + anchorageId: 'ETH_ARBITRUM_T', + fireblocksId: null, + bitgoId: 'TARBETH' }, { networkId: 'ASTAR', - coinType: 810, name: 'Astar', - fireblocksId: 'ASTR_ASTR' + coinType: 810, + anchorageId: null, + fireblocksId: 'ASTR_ASTR', + bitgoId: null }, { networkId: 'ASTAR_TESTNET', - coinType: 1, name: 'Astar Testnet', - fireblocksId: 'ASTR_TEST' + coinType: 1, + anchorageId: null, + fireblocksId: 'ASTR_TEST', + bitgoId: null }, { networkId: 'ATOM', + name: 'Cosmos', coinType: 118, - name: 'Atom', - anchorageId: 'COSMOS', - fireblocksId: 'ATOM_COS' + anchorageId: 'ATOM', + fireblocksId: 'ATOM_COS', + bitgoId: 'ATOM' }, { networkId: 'ATOM_TESTNET', - coinType: 1, name: 'Atom Testnet', - fireblocksId: 'ATOM_COS_TEST' + coinType: 1, + anchorageId: null, + fireblocksId: 'ATOM_COS_TEST', + bitgoId: 'TATOM' }, { networkId: 'AURORA', - coinType: 2570, name: 'Aurora', - fireblocksId: 'AURORA_DEV' + coinType: 2570, + anchorageId: null, + fireblocksId: 'AURORA_DEV', + bitgoId: null }, { networkId: 'AVAX', - coinType: 9000, name: 'Avalanche', - fireblocksId: 'AVAX' + coinType: 9000, + anchorageId: null, + fireblocksId: 'AVAX', + bitgoId: 'AVAXC' }, { networkId: 'AVAX_TESTNET', - coinType: 1, name: 'Avalanche Testnet', - fireblocksId: 'AVAXTEST' + coinType: 1, + anchorageId: null, + fireblocksId: 'AVAXTEST', + bitgoId: 'TAVAXC' }, { networkId: 'AXELAR', - coinType: null, name: 'Axelar', - anchorageId: 'AXL' + coinType: null, + anchorageId: 'AXL', + fireblocksId: null, + bitgoId: null }, { networkId: 'AXELAR_TESTNET', - coinType: 1, name: 'Axelar Testnet', - anchorageId: 'AXL_T' + coinType: 1, + anchorageId: 'AXL_T', + fireblocksId: null, + bitgoId: null }, { networkId: 'BABYLON', - coinType: null, name: 'Babylon', - anchorageId: 'BBN' + coinType: null, + anchorageId: 'BBN', + fireblocksId: null, + bitgoId: null }, { networkId: 'BASE', - coinType: 8453, name: 'Base', - fireblocksId: 'BASECHAIN_ETH' + coinType: 8453, + anchorageId: null, + fireblocksId: 'BASECHAIN_ETH', + bitgoId: null }, { networkId: 'BASE_TESTNET', - coinType: 1, name: 'Base Testnet', - fireblocksId: 'BASECHAIN_ETH_TEST5' + coinType: 1, + anchorageId: null, + fireblocksId: 'BASECHAIN_ETH_TEST5', + bitgoId: null }, { networkId: 'BINANCE_SMART_CHAIN', - coinType: 9006, name: 'Binance Smart Chain', - fireblocksId: 'BNB_BSC' + coinType: 9006, + anchorageId: null, + fireblocksId: 'BNB_BSC', + bitgoId: 'BSC' }, { networkId: 'BINANCE_SMART_CHAIN_TESTNET', - coinType: 1, name: 'Binance Smart Chain Testnet', - fireblocksId: 'BNB_TEST' + coinType: 1, + anchorageId: null, + fireblocksId: 'BNB_TEST', + bitgoId: 'TBSC' }, { networkId: 'BITCOIN', - coinType: 0, name: 'Bitcoin', + coinType: 0, anchorageId: 'BTC', - fireblocksId: 'BTC' + fireblocksId: 'BTC', + bitgoId: 'BTC' }, { networkId: 'BITCOIN_CASH', - coinType: 145, name: 'Bitcoin Cash', + coinType: 145, anchorageId: 'BCH', - fireblocksId: 'BCH' + fireblocksId: 'BCH', + bitgoId: 'BCH' }, { networkId: 'BITCOIN_CASH_TESTNET', - coinType: 1, name: 'Bitcoin Cash Testnet', - fireblocksId: 'BCH_TEST' + coinType: 1, + anchorageId: null, + fireblocksId: 'BCH_TEST', + bitgoId: null }, { networkId: 'BITCOIN_SIGNET', - coinType: 1, name: 'Bitcoin Signet', - anchorageId: 'BTC_S' + coinType: 1, + anchorageId: 'BTC_S', + fireblocksId: null, + bitgoId: 'TBTCSIG' }, { networkId: 'BITCOIN_SV', - coinType: 236, name: 'BitcoinSV', - fireblocksId: 'BSV' + coinType: 236, + anchorageId: null, + fireblocksId: 'BSV', + bitgoId: null }, { networkId: 'BITCOIN_SV_TESTNET', - coinType: 1, name: 'BitcoinSV Testnet', - fireblocksId: 'BSV_TEST' + coinType: 1, + anchorageId: null, + fireblocksId: 'BSV_TEST', + bitgoId: null }, { networkId: 'BITCOIN_TESTNET', - coinType: 1, name: 'Bitcoin Testnet', - fireblocksId: 'BTC_TEST' + coinType: 1, + anchorageId: null, + fireblocksId: 'BTC_TEST', + bitgoId: null }, { networkId: 'CARDANO', - coinType: 1815, name: 'Cardano', - fireblocksId: 'ADA' + coinType: 1815, + anchorageId: null, + fireblocksId: 'ADA', + bitgoId: 'ADA' }, { networkId: 'CARDANO_TESTNET', - coinType: 1, name: 'Cardano Testnet', - fireblocksId: 'ADA_TEST' + coinType: 1, + anchorageId: null, + fireblocksId: 'ADA_TEST', + bitgoId: null }, { networkId: 'CELESTIA', - coinType: null, name: 'Celestia', - anchorageId: 'TIA' + coinType: null, + anchorageId: 'TIA', + fireblocksId: null, + bitgoId: 'TIA' }, { networkId: 'CELO', - coinType: 52752, name: 'Celo', - fireblocksId: 'CELO' + coinType: 52752, + anchorageId: null, + fireblocksId: 'CELO', + bitgoId: 'CELO' }, { networkId: 'CELO_ALFAJORES', - coinType: null, name: 'Celo Alfajores', - fireblocksId: 'CELO_ALF' + coinType: null, + anchorageId: null, + fireblocksId: 'CELO_ALF', + bitgoId: null }, { networkId: 'CELO_BAKLAVA', - coinType: 1, name: 'Celo Baklava', + coinType: 1, anchorageId: 'CGLD_TB', - fireblocksId: 'CELO_BAK' + fireblocksId: 'CELO_BAK', + bitgoId: null }, { networkId: 'CHILIZ', - coinType: null, name: 'Chiliz', - fireblocksId: 'CHZ_$CHZ' + coinType: null, + anchorageId: null, + fireblocksId: 'CHZ_$CHZ', + bitgoId: null }, { networkId: 'DABACUS', - coinType: 521, name: 'Dabacus', - fireblocksId: 'ABA' + coinType: 521, + anchorageId: null, + fireblocksId: 'ABA', + bitgoId: null + }, + { + networkId: 'DASH', + name: 'Dash', + coinType: 5, + anchorageId: null, + fireblocksId: 'DASH', + bitgoId: 'DASH' + }, + { + networkId: 'DASH_TESTNET', + name: 'Dash Testnet', + coinType: 1, + anchorageId: null, + fireblocksId: 'DASH_TEST', + bitgoId: null }, { networkId: 'DOGECOIN', - coinType: 3, name: 'Dogecoin', + coinType: 3, anchorageId: 'DOGE', - fireblocksId: 'DOGE' + fireblocksId: 'DOGE', + bitgoId: 'DOGE' }, { networkId: 'DOGECOIN_TESTNET', - coinType: 1, name: 'Dogecoin Testnet', - fireblocksId: 'DOGE_TEST' + coinType: 1, + anchorageId: null, + fireblocksId: 'DOGE_TEST', + bitgoId: null }, { networkId: 'DYDX_CHAIN', - coinType: null, name: 'Dydx Chain', - anchorageId: 'DYDX_CHAIN' + coinType: null, + anchorageId: 'DYDX_CHAIN', + fireblocksId: null, + bitgoId: null }, { networkId: 'DYDX_CHAIN_TESTNET', - coinType: 1, name: 'Dydx Testnet', - anchorageId: 'DYDX_CHAIN_T' + coinType: 1, + anchorageId: 'DYDX_CHAIN_T', + fireblocksId: null, + bitgoId: null + }, + { + networkId: 'EOS', + name: 'EOS', + coinType: 194, + anchorageId: null, + fireblocksId: 'EOS', + bitgoId: 'EOS' + }, + { + networkId: 'EOS_TESTNET', + name: 'EOS Testnet', + coinType: 1, + anchorageId: null, + fireblocksId: 'EOS_TEST', + bitgoId: null }, { networkId: 'ETHEREUM', - coinType: 60, name: 'Ethereum', + coinType: 60, anchorageId: 'ETH', - fireblocksId: 'ETH' + fireblocksId: 'ETH', + bitgoId: 'ETH' }, { networkId: 'ETHEREUM_HOLESKY', + name: 'Ethereum Holesky', coinType: 1, - name: 'Ethereum Holešky', - anchorageId: 'ETHHOL' + anchorageId: 'ETHHOL', + fireblocksId: null, + bitgoId: 'HTETH' }, { networkId: 'ETHEREUM_SEPOLIA', - coinType: 1, name: 'Ethereum Sepolia', - anchorageId: 'ETHSEP' + coinType: 1, + anchorageId: 'ETHSEP', + fireblocksId: null, + bitgoId: null }, { networkId: 'EVMOS', - coinType: null, name: 'Evmos', - anchorageId: 'EVMOS' + coinType: null, + anchorageId: 'EVMOS', + fireblocksId: null, + bitgoId: null }, { networkId: 'EVMOS_TESTNET', - coinType: 1, name: 'Evmos Testnet', - anchorageId: 'EVMOS_T' + coinType: 1, + anchorageId: 'EVMOS_T', + fireblocksId: null, + bitgoId: null }, { networkId: 'FILECOIN', - coinType: 461, name: 'Filecoin', - anchorageId: 'FIL' + coinType: 461, + anchorageId: 'FIL', + fireblocksId: null, + bitgoId: null }, { networkId: 'FLOW_TESTNET', - coinType: 1, name: 'Flow Testnet', - anchorageId: 'FLOW_T' + coinType: 1, + anchorageId: 'FLOW_T', + fireblocksId: null, + bitgoId: null }, { networkId: 'LITECOIN', - coinType: 2, name: 'Litecoin', + coinType: 2, anchorageId: 'LTC', - fireblocksId: 'LTC' + fireblocksId: 'LTC', + bitgoId: 'LTC' }, { networkId: 'LITECOIN_TESTNET', - coinType: 1, name: 'Litecoin Testnet', - fireblocksId: 'LTC_TEST' + coinType: 1, + anchorageId: null, + fireblocksId: 'LTC_TEST', + bitgoId: null }, { networkId: 'NEUTRON', - coinType: null, name: 'Neutron', - anchorageId: 'NTRN' + coinType: null, + anchorageId: 'NTRN', + fireblocksId: null, + bitgoId: null }, { networkId: 'OASIS', - coinType: 474, name: 'Oasis', - anchorageId: 'OAC' + coinType: 474, + anchorageId: 'ROSE', + fireblocksId: null, + bitgoId: null + }, + { + networkId: 'OASYS', + name: 'Oasys', + coinType: 685, + anchorageId: null, + fireblocksId: 'OAS', + bitgoId: 'OAS' + }, + { + networkId: 'OASYS_TESTNET', + name: 'Oasys Testnet', + coinType: 1, + anchorageId: null, + fireblocksId: 'OAS_TEST', + bitgoId: null }, { networkId: 'OM_MANTRA', - coinType: null, name: 'OM Mantra', - anchorageId: 'OM_MANTRA' + coinType: null, + anchorageId: 'OM_MANTRA', + fireblocksId: null, + bitgoId: null }, { networkId: 'OM_MANTRA_TESTNET', - coinType: 1, name: 'OM Mantra Testnet', - anchorageId: 'OM_MANTRA_T' + coinType: 1, + anchorageId: 'OM_MANTRA_T', + fireblocksId: null, + bitgoId: null + }, + { + networkId: 'OPTIMISM', + name: 'Optimism', + coinType: 614, + anchorageId: null, + fireblocksId: 'ETH-OPT', + bitgoId: 'OPETH' + }, + { + networkId: 'OPTIMISM_KOVAN', + name: 'Optimism Kovan', + coinType: 1, + anchorageId: null, + fireblocksId: 'ETH-OPT_KOV', + bitgoId: null + }, + { + networkId: 'OPTIMISM_SEPOLIA', + name: 'Optimism Sepolia', + coinType: 1, + anchorageId: null, + fireblocksId: 'ETH-OPT_SEPOLIA', + bitgoId: null }, { networkId: 'OSMOSIS', - coinType: 10000118, name: 'Osmosis', + coinType: 10000118, anchorageId: 'OSMO', - fireblocksId: 'OSMO' + fireblocksId: 'OSMO', + bitgoId: 'OSMO' }, { - networkId: 'PLUME_SEPOLIA', + networkId: 'OSMOSIS_TESTNET', + name: 'Osmosis Testnet', coinType: 1, + anchorageId: null, + fireblocksId: 'OSMO_TEST', + bitgoId: null + }, + { + networkId: 'PLUME_SEPOLIA', name: 'Plume Sepolia Testnet', - anchorageId: 'PLUME_SEPOLIA' + coinType: 1, + anchorageId: 'ETH_PLUME_T', + fireblocksId: null, + bitgoId: null + }, + { + networkId: 'POLKADOT', + name: 'Polkadot', + coinType: 354, + anchorageId: null, + fireblocksId: 'DOT', + bitgoId: 'DOT' }, { networkId: 'POLYGON', - coinType: 966, name: 'Polygon', - anchorageId: 'POLYGON', - fireblocksId: 'MATIC_POLYGON' + coinType: 966, + anchorageId: 'POL_POLYGON', + fireblocksId: 'MATIC_POLYGON', + bitgoId: 'POLYGON' }, { networkId: 'PROVENANCE', - coinType: 505, name: 'Provenance', - anchorageId: 'HASH' + coinType: 505, + anchorageId: 'HASH', + fireblocksId: null, + bitgoId: 'HASH' }, { networkId: 'RARIMO', - coinType: null, name: 'Rarimo', - anchorageId: 'RMO' + coinType: null, + anchorageId: 'RMO', + fireblocksId: null, + bitgoId: null }, { networkId: 'RIPPLE', - coinType: 144, name: 'Ripple', + coinType: 144, anchorageId: 'XRP', - fireblocksId: 'XRP' + fireblocksId: 'XRP', + bitgoId: 'XRP' }, { networkId: 'RIPPLE_TESTNET', - coinType: 1, name: 'Ripple Testnet', - fireblocksId: 'XRP_TEST' + coinType: 1, + anchorageId: null, + fireblocksId: 'XRP_TEST', + bitgoId: null }, { networkId: 'SEI', - coinType: 19000118, name: 'Sei', + coinType: 19000118, anchorageId: 'SEI', - fireblocksId: 'SEI' + fireblocksId: 'SEI', + bitgoId: 'SEI' }, { networkId: 'SEI_TESTNET', - coinType: 1, name: 'Sei Testnet', + coinType: 1, anchorageId: 'SEI_T', - fireblocksId: 'SEI_TEST' + fireblocksId: 'SEI_TEST', + bitgoId: null }, { networkId: 'SOLANA', - coinType: 501, name: 'Solana', - fireblocksId: 'SOL' + coinType: 501, + anchorageId: null, + fireblocksId: 'SOL', + bitgoId: 'SOL' }, { networkId: 'SOLANA_TESTNET', - coinType: 1, name: 'Solana Testnet', + coinType: 1, anchorageId: null, - fireblocksId: 'SOL_TEST' + fireblocksId: 'SOL_TEST', + bitgoId: null }, { - networkId: 'SOLANA_DEVNET', - coinType: 1, + networkId: 'SOLONA_DEVNET', name: 'Solana Devnet', - anchorageId: 'SOL_TD', - fireblocksId: null + coinType: 1, + anchorageId: null, + fireblocksId: 'SOL_TD', + bitgoId: 'TSOL' }, { networkId: 'STARKNET', - coinType: 9004, name: 'Starknet', - anchorageId: 'STARK_STARKNET' + coinType: 9004, + anchorageId: 'STRK_STARKNET', + fireblocksId: null, + bitgoId: null }, { networkId: 'STARKNET_TESTNET', - coinType: 1, name: 'Starknet Testnet', - anchorageId: 'STRK_STARKNET_T' + coinType: 1, + anchorageId: 'STRK_STARKNET_T', + fireblocksId: null, + bitgoId: null }, { networkId: 'STELLAR_LUMENS', - coinType: 148, name: 'Stellar Lumens', - fireblocksId: 'XLM' + coinType: 148, + anchorageId: null, + fireblocksId: 'XLM', + bitgoId: 'XLM' }, { networkId: 'STELLAR_LUMENS_TESTNET', - coinType: 1, name: 'Stellar Lumens Testnet', - fireblocksId: 'XLM_TEST' + coinType: 1, + anchorageId: null, + fireblocksId: 'XLM_TEST', + bitgoId: null }, { networkId: 'STRIDE', - coinType: null, name: 'Stride', - anchorageId: 'STRD' + coinType: null, + anchorageId: 'STRD', + fireblocksId: null, + bitgoId: null }, { networkId: 'SUI_TESTNET', - coinType: 1, name: 'Sui Testnet', - anchorageId: 'SUI_T' - }, - { - networkId: 'TRON', - coinType: 195, - name: 'Tron', - fireblocksId: 'TRX' - }, - { - networkId: 'TRON_TESTNET', - coinType: 1, - name: 'Tron Testnet', - fireblocksId: 'TRX_TEST' - }, - { - networkId: 'VANA', - coinType: null, - name: 'Vana', - anchorageId: 'VANA' - }, - { - networkId: 'VANA_MOKSHA_TESTNET', - coinType: 1, - name: 'Vana Moksha Testnet', - anchorageId: 'VANA_MOKSHA_TESTNET' - }, - { - networkId: 'ZKSYNC_SEPOLIA', - coinType: 1, - name: 'ZKsync Sepolia Testnet', - anchorageId: 'ZKSYNC_SEPOLIA' - }, - { - networkId: 'POLKADOT', - coinType: 354, - name: 'Polkadot', - fireblocksId: 'DOT' - }, - { - networkId: 'EOS', - coinType: 194, - name: 'EOS', - fireblocksId: 'EOS' - }, - { - networkId: 'EOS_TESTNET', coinType: 1, - name: 'EOS Testnet', - fireblocksId: 'EOS_TEST' + anchorageId: 'SUI_T', + fireblocksId: null, + bitgoId: 'TSUI' }, { - networkId: 'OASYS', - coinType: 685, - name: 'Oasys', - fireblocksId: 'OAS' - }, - { - networkId: 'OASYS_TESTNET', - coinType: 1, - name: 'Oasys Testnet', - fireblocksId: 'OAS_TEST' - }, - { - networkId: 'OSMOSIS_TESTNET', - coinType: 1, - name: 'Osmosis Testnet', - fireblocksId: 'OSMO_TEST' + networkId: 'SUI', + name: 'Sui', + coinType: 784, + anchorageId: 'SUI', + fireblocksId: null, + bitgoId: 'SUI' }, { networkId: 'TELOS', - coinType: 424, name: 'Telos', - fireblocksId: 'TELOS' + coinType: 424, + anchorageId: null, + fireblocksId: 'TELOS', + bitgoId: null }, { networkId: 'TELOS_TESTNET', - coinType: 1, name: 'Telos Testnet', - fireblocksId: 'TELOS_TEST' + coinType: 1, + anchorageId: null, + fireblocksId: 'TELOS_TEST', + bitgoId: null }, { networkId: 'TEZOS', - coinType: 1729, name: 'Tezos', - fireblocksId: 'XTZ' + coinType: 1729, + anchorageId: null, + fireblocksId: 'XTZ', + bitgoId: 'XTZ' }, { networkId: 'TEZOS_TESTNET', - coinType: 1, name: 'Tezos Testnet', - fireblocksId: 'XTZ_TEST' + coinType: 1, + anchorageId: null, + fireblocksId: 'XTZ_TEST', + bitgoId: null }, { - networkId: 'DASH', - coinType: 5, - name: 'Dash', - fireblocksId: 'DASH' + networkId: 'TRON', + name: 'Tron', + coinType: 195, + anchorageId: null, + fireblocksId: 'TRX', + bitgoId: 'TRX' }, { - networkId: 'DASH_TESTNET', + networkId: 'TRON_TESTNET', + name: 'Tron Testnet', coinType: 1, - name: 'Dash Testnet', - fireblocksId: 'DASH_TEST' + anchorageId: null, + fireblocksId: 'TRX_TEST', + bitgoId: null }, { - networkId: 'OPTIMISM', - coinType: 614, - name: 'Optimism', - fireblocksId: 'ETH-OPT' + networkId: 'VANA', + name: 'Vana', + coinType: null, + anchorageId: 'VANA_VANA', + fireblocksId: null, + bitgoId: null }, { - networkId: 'OPTIMISM_SEPOLIA', + networkId: 'VANA_MOKSHA_TESTNET', + name: 'Vana Moksha Testnet', coinType: 1, - name: 'Optimism Sepolia', - fireblocksId: 'ETH-OPT_SEPOLIA' + anchorageId: 'VANA_VANA_MOKSHA_T', + fireblocksId: null, + bitgoId: null }, { - networkId: 'OPTIMISM_KOVAN', + networkId: 'ZKSYNC_SEPOLIA', + name: 'ZKsync Sepolia Testnet', coinType: 1, - name: 'Optimism Kovan', - fireblocksId: 'ETH-OPT_KOV' + anchorageId: 'ETH_ZKSYNC_T', + fireblocksId: null, + bitgoId: null } ] } diff --git a/apps/vault/src/broker/shared/__test__/fixture.ts b/apps/vault/src/broker/shared/__test__/fixture.ts new file mode 100644 index 000000000..f2b435054 --- /dev/null +++ b/apps/vault/src/broker/shared/__test__/fixture.ts @@ -0,0 +1,209 @@ +import { privateKeyToHex, secp256k1PrivateKeyToJwk, secp256k1PrivateKeyToPublicJwk } from '@narval/signature' +import { TestingModule } from '@nestjs/testing' +import { randomUUID } from 'crypto' +import { ClientService } from '../../../client/core/service/client.service' +import { Client } from '../../../shared/type/domain.type' +import { ANCHORAGE_TEST_API_BASE_URL } from '../../core/provider/anchorage/__test__/server-mock/server' +import { AnchorageCredentials } from '../../core/provider/anchorage/anchorage.type' +import { ConnectionService } from '../../core/service/connection.service' +import { ConnectionStatus, ConnectionWithCredentials } from '../../core/type/connection.type' +import { Account, Address, Wallet } from '../../core/type/indexed-resources.type' +import { Provider } from '../../core/type/provider.type' +import { AccountRepository } from '../../persistence/repository/account.repository' +import { AddressRepository } from '../../persistence/repository/address.repository' +import { WalletRepository } from '../../persistence/repository/wallet.repository' + +export const clientId = randomUUID() + +const now = new Date() + +const USER_PRIVATE_KEY = '0x7cfef3303797cbc7515d9ce22ffe849c701b0f2812f999b0847229c47951fca5' + +export const userPrivateKey = secp256k1PrivateKeyToJwk(USER_PRIVATE_KEY) +export const userPublicKey = secp256k1PrivateKeyToPublicJwk(USER_PRIVATE_KEY) + +export const client: Client = { + clientId, + auth: { + disabled: false, + local: { + jwsd: { + maxAge: 600, + requiredComponents: ['htm', 'uri', 'created', 'ath'] + }, + allowedUsersJwksUrl: null, + allowedUsers: [ + { + userId: 'user-1', + publicKey: userPublicKey + } + ] + }, + tokenValidation: { + disabled: true, + url: null, + jwksUrl: null, + verification: { + audience: null, + issuer: 'https://armory.narval.xyz', + maxTokenAge: 300, + requireBoundTokens: false, // DO NOT REQUIRE BOUND TOKENS; we're testing both payload.cnf bound tokens and unbound here. + allowBearerTokens: false, + allowWildcard: [] + }, + pinnedPublicKey: null + } + }, + name: 'test-client', + configurationSource: 'dynamic', + backupPublicKey: null, + baseUrl: null, + createdAt: now, + updatedAt: now +} + +export const anchorageConnectionOneCredentials: AnchorageCredentials = { + apiKey: 'test-anchorage-api-key-one', + privateKey: { + kty: 'OKP', + crv: 'Ed25519', + alg: 'EDDSA', + kid: '0x50802454e9997ac331334bdfbc3a2f15826980d39e5ce5292353402dcd21d6f5', + x: 'BLEYbYCvYvA90guTeqCfIXMKdgcO2LiG9u-0h0lnqi4', + d: 'HXNx_HoOCxEbcTLjMY-dbL9psOuE3WFQ68zkd9oeeHw' + }, + publicKey: { + kty: 'OKP', + alg: 'EDDSA', + kid: '0x50802454e9997ac331334bdfbc3a2f15826980d39e5ce5292353402dcd21d6f5', + crv: 'Ed25519', + x: 'BLEYbYCvYvA90guTeqCfIXMKdgcO2LiG9u-0h0lnqi4' + } +} + +export const anchorageConnectionOne: ConnectionWithCredentials = { + clientId, + connectionId: randomUUID(), + provider: Provider.ANCHORAGE, + label: 'Anchorage test connection one', + url: ANCHORAGE_TEST_API_BASE_URL, + status: ConnectionStatus.ACTIVE, + revokedAt: undefined, + createdAt: now, + updatedAt: now, + credentials: anchorageConnectionOneCredentials +} + +export const anchorageWalletOne: Wallet = { + accounts: [], + clientId, + connectionId: anchorageConnectionOne.connectionId, + createdAt: new Date('2024-01-01T00:00:00Z'), + externalId: 'external-id-one', + label: 'wallet 1', + provider: anchorageConnectionOne.provider, + updatedAt: now, + walletId: randomUUID() +} + +export const anchorageWalletTwo: Wallet = { + clientId, + accounts: [], + connectionId: anchorageConnectionOne.connectionId, + createdAt: new Date('2024-01-02T00:00:00Z'), + externalId: 'external-id-two', + label: 'wallet 2', + provider: anchorageConnectionOne.provider, + updatedAt: now, + walletId: randomUUID() +} + +export const anchorageWalletThree: Wallet = { + clientId, + accounts: [], + connectionId: anchorageConnectionOne.connectionId, + createdAt: new Date('2024-01-03T00:00:00Z'), + externalId: 'external-id-three', + label: 'wallet 3', + provider: anchorageConnectionOne.provider, + updatedAt: now, + walletId: randomUUID() +} + +export const anchorageAccountOne: Account = { + clientId, + accountId: randomUUID(), + addresses: [], + createdAt: new Date('2024-01-01T00:00:00Z'), + externalId: 'account-external-id-one', + connectionId: anchorageConnectionOne.connectionId, + label: 'wallet 1 account 1', + networkId: 'BTC', + provider: anchorageConnectionOne.provider, + updatedAt: now, + walletId: anchorageWalletOne.walletId +} + +export const anchorageAccountTwo: Account = { + clientId, + accountId: randomUUID(), + addresses: [], + createdAt: new Date('2024-01-02T00:00:00Z'), + connectionId: anchorageConnectionOne.connectionId, + externalId: 'account-external-id-two', + label: 'wallet 1 account 2', + networkId: 'BTC', + provider: anchorageConnectionOne.provider, + updatedAt: now, + walletId: anchorageWalletOne.walletId +} + +export const anchorageAddressOne: Address = { + clientId, + accountId: anchorageAccountOne.accountId, + address: 'address-one', + addressId: randomUUID(), + connectionId: anchorageConnectionOne.connectionId, + createdAt: new Date('2024-01-01T00:00:00Z'), + externalId: 'address-external-id-one', + provider: anchorageConnectionOne.provider, + updatedAt: now +} + +export const anchorageAddressTwo: Address = { + clientId, + accountId: anchorageAccountOne.accountId, + address: 'address-two', + addressId: randomUUID(), + connectionId: anchorageConnectionOne.connectionId, + createdAt: new Date('2024-01-02T00:00:00Z'), + externalId: 'address-external-id-two', + provider: anchorageConnectionOne.provider, + updatedAt: now +} + +export const seed = async (module: TestingModule) => { + const clientService = module.get(ClientService) + const connectionService = module.get(ConnectionService) + const walletRepository = module.get(WalletRepository) + const accountRepository = module.get(AccountRepository) + const addressRepository = module.get(AddressRepository) + + await clientService.save(client) + + await connectionService.create(client.clientId, { + connectionId: anchorageConnectionOne.connectionId, + createdAt: anchorageConnectionOne.updatedAt, + label: anchorageConnectionOne.label, + provider: anchorageConnectionOne.provider, + url: anchorageConnectionOne.url as string, + credentials: { + apiKey: anchorageConnectionOneCredentials.apiKey, + privateKey: await privateKeyToHex(anchorageConnectionOneCredentials.privateKey) + } + }) + + await walletRepository.bulkCreate([anchorageWalletOne, anchorageWalletTwo, anchorageWalletThree]) + await accountRepository.bulkCreate([anchorageAccountOne, anchorageAccountTwo]) + await addressRepository.bulkCreate([anchorageAddressOne, anchorageAddressTwo]) +} diff --git a/apps/vault/src/broker/shared/__test__/request.ts b/apps/vault/src/broker/shared/__test__/request.ts new file mode 100644 index 000000000..b22799fb6 --- /dev/null +++ b/apps/vault/src/broker/shared/__test__/request.ts @@ -0,0 +1,118 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +import { JwsdHeader, PrivateKey, buildSignerForAlg, hash, hexToBase64Url, signJwsd } from '@narval/signature' +import { INestApplication } from '@nestjs/common' +import { isUndefined, omitBy } from 'lodash' +import request from 'supertest' + +export const getJwsd = async ({ + userPrivateJwk, + baseUrl, + requestUrl, + accessToken, + payload, + htm +}: { + userPrivateJwk: PrivateKey + baseUrl?: string + requestUrl: string + accessToken?: string + payload: object | string + htm?: string +}) => { + const now = Math.floor(Date.now() / 1000) + + const jwsdSigner = await buildSignerForAlg(userPrivateJwk) + const jwsdHeader: JwsdHeader = { + alg: userPrivateJwk.alg, + kid: userPrivateJwk.kid, + typ: 'gnap-binding-jwsd', + htm: htm || 'POST', + uri: `${baseUrl || 'https://vault-test.narval.xyz'}${requestUrl}`, // matches the client baseUrl + request url + created: now, + ath: accessToken ? hexToBase64Url(hash(accessToken)) : undefined + } + + const jwsd = await signJwsd(payload, jwsdHeader, jwsdSigner).then((jws) => { + // Strip out the middle part for size + const parts = jws.split('.') + parts[1] = '' + return parts.join('.') + }) + + return jwsd +} + +/** + * Creates a wrapper around supertest that automatically handles detached JWS + * signatures for API requests in tests. + * + * This helper ensures that all requests are properly signed with a detached + * JWS signature using the provided private key. It maintains the familiar + * supertest chainable API while handling the complexity of JWS signatures. + * + * @param app - The NestJS application instance to make requests against + * @param privateKey - The private key used to sign the requests + * + * @returns An object with HTTP method functions (get, post, put, delete, + * patch) that return chainable request objects + * + * @example + * const response = await signedRequest(app, userPrivateKey) + * .get('/api/resource') + * .set('header-name', 'value') + * .send() + */ +export const signedRequest = (app: INestApplication, privateKey: PrivateKey) => { + const wrapper = (method: 'get' | 'post' | 'put' | 'delete' | 'patch', url: string) => { + const req = request(app.getHttpServer())[method](url) + + let query: string | null = null + + return { + ...req, + set: function (key: string, value: string) { + if (key === 'detached-jws') { + throw new Error('You cannot override detached-jws with signedRequest') + } + + req.set(key, value) + + return this + }, + query: function (params: Record) { + if (url.includes('?')) { + throw new Error( + 'It seems the given URL already has a query string. Pass query params either in the URL or with the query method' + ) + } + + // Strip out undefined values but not null ones. + const parse = omitBy(params, isUndefined) + + req.query(parse) + query = new URLSearchParams(parse).toString() + + return this + }, + send: async function (body?: any) { + const jws = await getJwsd({ + userPrivateJwk: privateKey, + requestUrl: query ? `${url}?${query}` : url, + payload: body || {}, + htm: method.toUpperCase() + }) + + return req.set('detached-jws', jws).send(body) + } + } + } + + return { + get: (url: string) => wrapper('get', url), + post: (url: string) => wrapper('post', url), + put: (url: string) => wrapper('put', url), + delete: (url: string) => wrapper('delete', url), + patch: (url: string) => wrapper('patch', url) + } +} diff --git a/apps/vault/src/broker/shared/event/scoped-sync-started.event.ts b/apps/vault/src/broker/shared/event/scoped-sync-started.event.ts new file mode 100644 index 000000000..b7b4db4f5 --- /dev/null +++ b/apps/vault/src/broker/shared/event/scoped-sync-started.event.ts @@ -0,0 +1,11 @@ +import { ConnectionWithCredentials } from '../../core/type/connection.type' +import { ScopedSync } from '../../core/type/scoped-sync.type' + +export class ScopedSyncStartedEvent { + static EVENT_NAME = 'scoped.sync.started' + + constructor( + public readonly sync: ScopedSync, + public readonly connection: ConnectionWithCredentials + ) {} +} diff --git a/apps/vault/src/broker/shared/event/sync-started.event.ts b/apps/vault/src/broker/shared/event/sync-started.event.ts deleted file mode 100644 index 608b55c9b..000000000 --- a/apps/vault/src/broker/shared/event/sync-started.event.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { ConnectionWithCredentials } from '../../core/type/connection.type' -import { Sync } from '../../core/type/sync.type' - -export class SyncStartedEvent { - static EVENT_NAME = 'sync.started' - - constructor( - public readonly sync: Sync, - public readonly connection: ConnectionWithCredentials - ) {} -} diff --git a/apps/vault/src/shared/module/persistence/schema/migrations/20250116130521_add_provider_sync_table/migration.sql b/apps/vault/src/shared/module/persistence/schema/migrations/20250116130521_add_provider_sync_table/migration.sql new file mode 100644 index 000000000..572723484 --- /dev/null +++ b/apps/vault/src/shared/module/persistence/schema/migrations/20250116130521_add_provider_sync_table/migration.sql @@ -0,0 +1,17 @@ +-- CreateTable +CREATE TABLE "provider_scoped_sync" ( + "id" TEXT NOT NULL, + "client_id" TEXT NOT NULL, + "connection_id" TEXT NOT NULL, + "status" TEXT NOT NULL, + "error_name" TEXT, + "error_message" TEXT, + "error_trace_id" TEXT, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "completed_at" TIMESTAMP(3), + + CONSTRAINT "provider_scoped_sync_pkey" PRIMARY KEY ("id") +); + +-- AddForeignKey +ALTER TABLE "provider_scoped_sync" ADD CONSTRAINT "provider_scoped_sync_connection_id_fkey" FOREIGN KEY ("connection_id") REFERENCES "provider_connection"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/apps/vault/src/shared/module/persistence/schema/migrations/20250117120539_provider_data_per_connection/migration.sql b/apps/vault/src/shared/module/persistence/schema/migrations/20250117120539_provider_data_per_connection/migration.sql new file mode 100644 index 000000000..47165a77b --- /dev/null +++ b/apps/vault/src/shared/module/persistence/schema/migrations/20250117120539_provider_data_per_connection/migration.sql @@ -0,0 +1,453 @@ +BEGIN; + +-- 1. Add new columns (nullable first) +ALTER TABLE provider_wallet ADD COLUMN connection_id TEXT; +ALTER TABLE provider_account ADD COLUMN connection_id TEXT; +ALTER TABLE provider_address ADD COLUMN connection_id TEXT; +ALTER TABLE provider_known_destination ADD COLUMN connection_id TEXT; +ALTER TABLE provider_transfer ADD COLUMN connection_id TEXT; + + +-- 2. Drop indexes per client_id +DROP INDEX "provider_account_client_id_external_id_key"; +DROP INDEX "provider_address_client_id_external_id_key"; +DROP INDEX "provider_known_destination_client_id_external_id_key"; +DROP INDEX "provider_wallet_client_id_external_id_key"; + + +-- 3. Create temporary tables to store ID mappings +CREATE TEMP TABLE wallet_id_mapping ( + old_id TEXT, + new_id TEXT, + client_id TEXT, + external_id TEXT, + connection_id TEXT +); + +CREATE TEMP TABLE account_id_mapping ( + old_id TEXT, + new_id TEXT, + client_id TEXT, + external_id TEXT, + connection_id TEXT +); + +CREATE TEMP TABLE address_id_mapping ( + old_id TEXT, + new_id TEXT, + client_id TEXT, + external_id TEXT, + connection_id TEXT +); + +CREATE TEMP TABLE known_destination_id_mapping ( + old_id TEXT, + new_id TEXT, + client_id TEXT, + external_id TEXT, + connection_id TEXT +); + +-- 4. For wallets with mapping +WITH inserted_wallets AS ( + INSERT INTO provider_wallet ( + id, + label, + client_id, + external_id, + provider, + created_at, + updated_at, + connection_id + ) + SELECT + gen_random_uuid(), + w.label, + w.client_id, + w.external_id, + w.provider, + w.created_at, + w.updated_at, + pwc.connection_id + FROM provider_wallet w + JOIN provider_wallet_connection pwc ON w.id = pwc.wallet_id + WHERE NOT EXISTS ( + SELECT 1 + FROM provider_wallet w2 + WHERE w2.client_id = w.client_id + AND w2.external_id = w.external_id + AND w2.connection_id = pwc.connection_id + ) + RETURNING id as new_id, client_id, external_id, connection_id +) +INSERT INTO wallet_id_mapping (old_id, new_id, client_id, external_id, connection_id) +SELECT w.id as old_id, i.new_id, i.client_id, i.external_id, i.connection_id +FROM provider_wallet w +JOIN provider_wallet_connection pwc ON w.id = pwc.wallet_id +JOIN inserted_wallets i ON w.client_id = i.client_id + AND w.external_id = i.external_id + AND pwc.connection_id = i.connection_id; + +-- For known destinations with mapping +WITH inserted_known_destinations AS ( + INSERT INTO provider_known_destination ( + id, + client_id, + external_id, + external_classification, + address, + label, + asset_id, + network_id, + created_at, + updated_at, + provider, + connection_id + ) + SELECT + gen_random_uuid(), + kd.client_id, + kd.external_id, + kd.external_classification, + kd.address, + kd.label, + kd.asset_id, + kd.network_id, + kd.created_at, + kd.updated_at, + kd.provider, + kdc.connection_id + FROM provider_known_destination kd + JOIN provider_known_destination_connection kdc ON kd.id = kdc.known_destination_id + WHERE NOT EXISTS ( + SELECT 1 + FROM provider_known_destination kd2 + WHERE kd2.client_id = kd.client_id + AND kd2.external_id = kd.external_id + AND kd2.connection_id = kdc.connection_id + ) + RETURNING id as new_id, client_id, external_id, connection_id +) +INSERT INTO known_destination_id_mapping (old_id, new_id, client_id, external_id, connection_id) +SELECT kd.id as old_id, i.new_id, i.client_id, i.external_id, i.connection_id +FROM provider_known_destination kd +JOIN provider_known_destination_connection kdc ON kd.id = kdc.known_destination_id +JOIN inserted_known_destinations i ON kd.client_id = i.client_id + AND kd.external_id = i.external_id + AND kdc.connection_id = i.connection_id; + +-- For accounts with mapping +WITH inserted_accounts AS ( + INSERT INTO provider_account ( + id, + label, + client_id, + provider, + external_id, + wallet_id, + network_id, + created_at, + updated_at, + connection_id + ) + SELECT + gen_random_uuid(), + a.label, + a.client_id, + a.provider, + a.external_id, + w.id, + a.network_id, + a.created_at, + a.updated_at, + w.connection_id + FROM provider_account a + JOIN provider_wallet w_old ON a.wallet_id = w_old.id + JOIN provider_wallet w ON w.client_id = w_old.client_id + AND w.external_id = w_old.external_id + WHERE NOT EXISTS ( + SELECT 1 + FROM provider_account a2 + WHERE a2.client_id = a.client_id + AND a2.external_id = a.external_id + AND a2.connection_id = w.connection_id + ) + RETURNING id as new_id, client_id, external_id, connection_id +) +INSERT INTO account_id_mapping (old_id, new_id, client_id, external_id, connection_id) +SELECT a.id as old_id, i.new_id, i.client_id, i.external_id, i.connection_id +FROM provider_account a +JOIN provider_wallet w_old ON a.wallet_id = w_old.id +JOIN provider_wallet w ON w.client_id = w_old.client_id + AND w.external_id = w_old.external_id +JOIN inserted_accounts i ON a.client_id = i.client_id + AND a.external_id = i.external_id + AND w.connection_id = i.connection_id; + +-- For addresses with mapping +WITH inserted_addresses AS ( + INSERT INTO provider_address ( + id, + client_id, + provider, + external_id, + account_id, + address, + created_at, + updated_at, + connection_id + ) + SELECT + gen_random_uuid(), + addr.client_id, + addr.provider, + addr.external_id, + a.id, + addr.address, + addr.created_at, + addr.updated_at, + a.connection_id + FROM provider_address addr + JOIN provider_account a_old ON addr.account_id = a_old.id + JOIN provider_account a ON a.client_id = a_old.client_id + AND a.external_id = a_old.external_id + WHERE NOT EXISTS ( + SELECT 1 + FROM provider_address addr2 + WHERE addr2.client_id = addr.client_id + AND addr2.external_id = addr.external_id + AND addr2.connection_id = a.connection_id + ) + RETURNING id as new_id, client_id, external_id, connection_id +) +INSERT INTO address_id_mapping (old_id, new_id, client_id, external_id, connection_id) +SELECT addr.id as old_id, i.new_id, i.client_id, i.external_id, i.connection_id +FROM provider_address addr +JOIN provider_account a_old ON addr.account_id = a_old.id +JOIN provider_account a ON a.client_id = a_old.client_id + AND a.external_id = a_old.external_id +JOIN inserted_addresses i ON addr.client_id = i.client_id + AND addr.external_id = i.external_id + AND a.connection_id = i.connection_id; + + +DO $$ +DECLARE + wallet_count INTEGER; + account_count INTEGER; + address_count INTEGER; + transfer_count INTEGER; + sample_mapping RECORD; +BEGIN + -- Check mapping tables + SELECT COUNT(*) INTO wallet_count FROM wallet_id_mapping; + SELECT COUNT(*) INTO account_count FROM account_id_mapping; + SELECT COUNT(*) INTO address_count FROM address_id_mapping; + SELECT COUNT(*) INTO transfer_count FROM provider_transfer; + + RAISE NOTICE 'Mapping table counts: wallets=%, accounts=%, addresses=%, transfers=%', + wallet_count, account_count, address_count, transfer_count; + + -- Check a sample mapping + SELECT * INTO sample_mapping + FROM ( + SELECT + t.id as old_transfer_id, + t.source_wallet_id as old_source_wallet, + sw_map.new_id as mapped_source_wallet, + t.destination_wallet_id as old_dest_wallet, + dw_map.new_id as mapped_dest_wallet + FROM provider_transfer t + LEFT JOIN wallet_id_mapping sw_map ON t.source_wallet_id = sw_map.old_id + LEFT JOIN wallet_id_mapping dw_map ON t.destination_wallet_id = dw_map.old_id + LIMIT 1 + ) subquery; + + IF sample_mapping IS NOT NULL THEN + RAISE NOTICE 'Sample mapping: %', sample_mapping; + ELSE + RAISE NOTICE 'No sample mapping found'; + END IF; + + -- Check for NULL required fields + PERFORM t.id + FROM provider_transfer t + WHERE client_id IS NULL + OR external_id IS NULL + OR asset_id IS NULL + OR network_fee_attribution IS NULL + OR provider IS NULL; + + IF FOUND THEN + RAISE NOTICE 'Found transfers with NULL required fields'; + ELSE + RAISE NOTICE 'No NULL required fields found'; + END IF; +END $$; + + +-- For transfers (using mappings) +WITH transfer_conn AS ( + SELECT + t.id AS transfer_id, + + -- Get whichever connection_id is available + COALESCE( + sw_map.connection_id, + sa_map.connection_id, + saddr_map.connection_id + ) AS new_connection_id, + + -- “New” source fields from the mapping tables + sw_map.new_id AS new_source_wallet_id, + sa_map.new_id AS new_source_account_id, + saddr_map.new_id AS new_source_address_id + + FROM provider_transfer t + LEFT JOIN wallet_id_mapping sw_map ON t.source_wallet_id = sw_map.old_id + LEFT JOIN account_id_mapping sa_map ON t.source_account_id = sa_map.old_id + LEFT JOIN address_id_mapping saddr_map ON t.source_address_id = saddr_map.old_id +) +UPDATE provider_transfer t +SET + -- If we found a mapping for wallet/account/address, use that new ID; + -- otherwise, keep the existing source_* field. + source_wallet_id = COALESCE(transfer_conn.new_source_wallet_id, t.source_wallet_id), + source_account_id = COALESCE(transfer_conn.new_source_account_id, t.source_account_id), + source_address_id = COALESCE(transfer_conn.new_source_address_id, t.source_address_id), + + -- Overwrite connection_id with whichever was found + connection_id = COALESCE(transfer_conn.new_connection_id, t.connection_id) +FROM transfer_conn +WHERE t.id = transfer_conn.transfer_id; + +DO $$ +DECLARE + old_wallet_count INTEGER; + new_wallet_count INTEGER; + expected_wallet_count INTEGER; +BEGIN + -- Count old wallets + SELECT COUNT(*) INTO old_wallet_count + FROM provider_wallet w + WHERE w.connection_id IS NULL; + + -- Count new wallets + SELECT COUNT(*) INTO new_wallet_count + FROM provider_wallet w + WHERE w.connection_id IS NOT NULL; + + -- Count expected wallets (from wallet connections) + SELECT COUNT(*) INTO expected_wallet_count + FROM provider_wallet_connection; + + -- Verify we have the expected number of new records + IF new_wallet_count != expected_wallet_count THEN + RAISE EXCEPTION 'Migration verification failed: got % new wallets, expected %', + new_wallet_count, expected_wallet_count; + END IF; + + RAISE NOTICE 'Verification passed: % old wallets, % new wallets created', + old_wallet_count, new_wallet_count; +END $$; + +-- 5. Delete old records after successful migration +DELETE FROM provider_transfer WHERE connection_id IS NULL; +DELETE FROM provider_address WHERE connection_id IS NULL; +DELETE FROM provider_account WHERE connection_id IS NULL; +DELETE FROM provider_known_destination WHERE connection_id IS NULL; +DELETE FROM provider_wallet WHERE connection_id IS NULL; + +-- 6. Verify migrations completed +DO $$ +BEGIN + IF EXISTS (SELECT 1 FROM provider_wallet WHERE connection_id IS NULL) THEN + RAISE EXCEPTION 'Data migration incomplete: found wallet(s) without connection_id'; + END IF; + IF EXISTS (SELECT 1 FROM provider_known_destination WHERE connection_id IS NULL) THEN + RAISE EXCEPTION 'Data migration incomplete: found known destination(s) without connection_id'; + END IF; + IF EXISTS (SELECT 1 FROM provider_account WHERE connection_id IS NULL) THEN + RAISE EXCEPTION 'Data migration incomplete: found account(s) without connection_id'; + END IF; + IF EXISTS (SELECT 1 FROM provider_address WHERE connection_id IS NULL) THEN + RAISE EXCEPTION 'Data migration incomplete: found address(es) without connection_id'; + END IF; + IF EXISTS (SELECT 1 FROM provider_transfer WHERE connection_id IS NULL) THEN + RAISE EXCEPTION 'Data migration incomplete: found transfer(s) without connection_id'; + END IF; +END $$; + +-- -- 7. Make columns NOT NULL +ALTER TABLE provider_wallet ALTER COLUMN connection_id SET NOT NULL; +ALTER TABLE provider_account ALTER COLUMN connection_id SET NOT NULL; +ALTER TABLE provider_address ALTER COLUMN connection_id SET NOT NULL; +ALTER TABLE provider_known_destination ALTER COLUMN connection_id SET NOT NULL; +ALTER TABLE provider_transfer ALTER COLUMN connection_id SET NOT NULL; + +-- 8. Check for potential violations of new unique constraints +DO $$ +BEGIN + -- Check wallets + IF EXISTS ( + SELECT client_id, external_id, connection_id, COUNT(*) + FROM provider_wallet + GROUP BY client_id, external_id, connection_id + HAVING COUNT(*) > 1 + ) THEN + RAISE EXCEPTION 'Found duplicate wallet entries that would violate new unique constraint'; + END IF; + + -- Check accounts + IF EXISTS ( + SELECT client_id, external_id, connection_id, COUNT(*) + FROM provider_account + GROUP BY client_id, external_id, connection_id + HAVING COUNT(*) > 1 + ) THEN + RAISE EXCEPTION 'Found duplicate account entries that would violate new unique constraint'; + END IF; + + -- Check addresses + IF EXISTS ( + SELECT client_id, external_id, connection_id, COUNT(*) + FROM provider_address + GROUP BY client_id, external_id, connection_id + HAVING COUNT(*) > 1 + ) THEN + RAISE EXCEPTION 'Found duplicate address entries that would violate new unique constraint'; + END IF; + + -- Check known destinations + IF EXISTS ( + SELECT client_id, external_id, connection_id, COUNT(*) + FROM provider_known_destination + GROUP BY client_id, external_id, connection_id + HAVING COUNT(*) > 1 + ) THEN + RAISE EXCEPTION 'Found duplicate known destination entries that would violate new unique constraint'; + END IF; +END $$; + +-- 9. Create new unique indexes +CREATE UNIQUE INDEX "provider_account_client_id_connection_id_external_id_key" + ON "provider_account"("client_id", "connection_id", "external_id"); +CREATE UNIQUE INDEX "provider_address_client_id_connection_id_external_id_key" + ON "provider_address"("client_id", "connection_id", "external_id"); +CREATE UNIQUE INDEX "provider_known_destination_client_id_connection_id_external_key" + ON "provider_known_destination"("client_id", "connection_id", "external_id"); +CREATE UNIQUE INDEX "provider_wallet_client_id_connection_id_external_id_key" + ON "provider_wallet"("client_id", "connection_id", "external_id"); + +-- 10. Drop old tables +DROP TABLE provider_wallet_connection; +DROP TABLE provider_known_destination_connection; + +-- 10. Add foreign key constraints +ALTER TABLE "provider_wallet" ADD CONSTRAINT "provider_wallet_connection_id_fkey" FOREIGN KEY ("connection_id") REFERENCES "provider_connection"("id") ON DELETE RESTRICT ON UPDATE CASCADE; +ALTER TABLE "provider_account" ADD CONSTRAINT "provider_account_connection_id_fkey" FOREIGN KEY ("connection_id") REFERENCES "provider_connection"("id") ON DELETE RESTRICT ON UPDATE CASCADE; +ALTER TABLE "provider_address" ADD CONSTRAINT "provider_address_connection_id_fkey" FOREIGN KEY ("connection_id") REFERENCES "provider_connection"("id") ON DELETE RESTRICT ON UPDATE CASCADE; +ALTER TABLE "provider_known_destination" ADD CONSTRAINT "provider_known_destination_connection_id_fkey" FOREIGN KEY ("connection_id") REFERENCES "provider_connection"("id") ON DELETE RESTRICT ON UPDATE CASCADE; +ALTER TABLE "provider_transfer" ADD CONSTRAINT "provider_transfer_connection_id_fkey" FOREIGN KEY ("connection_id") REFERENCES "provider_connection"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +COMMIT; \ No newline at end of file diff --git a/apps/vault/src/shared/module/persistence/schema/migrations/20250120144703_add_btc_signet_to_assets/migration.sql b/apps/vault/src/shared/module/persistence/schema/migrations/20250120144703_add_btc_signet_to_assets/migration.sql new file mode 100644 index 000000000..8daec65fa --- /dev/null +++ b/apps/vault/src/shared/module/persistence/schema/migrations/20250120144703_add_btc_signet_to_assets/migration.sql @@ -0,0 +1,6 @@ +INSERT INTO public.asset (id,"name",symbol,decimals,network_id) VALUES + ('BTC_SIGNET','Bitcoin Signet','BTC',18,'BITCOIN_SIGNET'); + + INSERT INTO public.provider_asset (asset_id,provider,external_id) VALUES + ('BTC_SIGNET','anchorage','BTC_S'); + \ No newline at end of file diff --git a/apps/vault/src/shared/module/persistence/schema/migrations/20250121131658_delete_provider_known_destination_table/migration.sql b/apps/vault/src/shared/module/persistence/schema/migrations/20250121131658_delete_provider_known_destination_table/migration.sql new file mode 100644 index 000000000..a157d218a --- /dev/null +++ b/apps/vault/src/shared/module/persistence/schema/migrations/20250121131658_delete_provider_known_destination_table/migration.sql @@ -0,0 +1,11 @@ +/* + Warnings: + + - You are about to drop the `provider_known_destination` table. If the table is not empty, all the data it contains will be lost. + +*/ +-- DropForeignKey +ALTER TABLE "provider_known_destination" DROP CONSTRAINT "provider_known_destination_connection_id_fkey"; + +-- DropTable +DROP TABLE "provider_known_destination"; diff --git a/apps/vault/src/shared/module/persistence/schema/migrations/20250123092543_add_raw_accounts_to_scoped_sync/migration.sql b/apps/vault/src/shared/module/persistence/schema/migrations/20250123092543_add_raw_accounts_to_scoped_sync/migration.sql new file mode 100644 index 000000000..4d0928e10 --- /dev/null +++ b/apps/vault/src/shared/module/persistence/schema/migrations/20250123092543_add_raw_accounts_to_scoped_sync/migration.sql @@ -0,0 +1,8 @@ +/* + Warnings: + + - Added the required column `raw_accounts` to the `provider_scoped_sync` table without a default value. This is not possible if the table is not empty. + +*/ +-- AlterTable +ALTER TABLE "provider_scoped_sync" ADD COLUMN "raw_accounts" TEXT NOT NULL; diff --git a/apps/vault/src/shared/module/persistence/schema/migrations/20250124102305_add_transfer_external_asset_id/migration.sql b/apps/vault/src/shared/module/persistence/schema/migrations/20250124102305_add_transfer_external_asset_id/migration.sql new file mode 100644 index 000000000..a64da4748 --- /dev/null +++ b/apps/vault/src/shared/module/persistence/schema/migrations/20250124102305_add_transfer_external_asset_id/migration.sql @@ -0,0 +1,3 @@ +-- AlterTable +ALTER TABLE "provider_transfer" ADD COLUMN "asset_external_id" TEXT, +ALTER COLUMN "asset_id" DROP NOT NULL; diff --git a/apps/vault/src/shared/module/persistence/schema/schema.prisma b/apps/vault/src/shared/module/persistence/schema/schema.prisma index a4653ea2b..525453ad1 100644 --- a/apps/vault/src/shared/module/persistence/schema/schema.prisma +++ b/apps/vault/src/shared/module/persistence/schema/schema.prisma @@ -98,87 +98,71 @@ model ClientLocalAuthAllowedUser { } model ProviderWallet { - id String @id - label String? - clientId String @map("client_id") - provider String - externalId String @map("external_id") - createdAt DateTime @default(now()) @map("created_at") - updatedAt DateTime @updatedAt @map("updated_at") - - accounts ProviderAccount[] - connections ProviderWalletConnection[] + id String @id + label String? + clientId String @map("client_id") + provider String + externalId String @map("external_id") + connectionId String @map("connection_id") + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") - sourceTransfers ProviderTransfer[] @relation("SourceWallet") - destinationTransfers ProviderTransfer[] @relation("DestinationWallet") + connection ProviderConnection? @relation(fields: [connectionId], references: [id]) + accounts ProviderAccount[] + sourceTransfers ProviderTransfer[] @relation("SourceWallet") + destinationTransfers ProviderTransfer[] @relation("DestinationWallet") - @@unique([clientId, externalId]) + @@unique([clientId, connectionId, externalId]) @@index([createdAt, clientId]) @@map("provider_wallet") } model ProviderAccount { - id String @id - label String? - clientId String @map("client_id") - provider String - externalId String @map("external_id") - walletId String @map("wallet_id") - networkId String @map("network_id") - createdAt DateTime @default(now()) @map("created_at") - updatedAt DateTime @updatedAt @map("updated_at") + id String @id + label String? + clientId String @map("client_id") + connectionId String @map("connection_id") + externalId String @map("external_id") + provider String + walletId String @map("wallet_id") + networkId String @map("network_id") + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") - wallet ProviderWallet @relation(fields: [walletId], references: [id]) - addresses ProviderAddress[] + connection ProviderConnection @relation(fields: [connectionId], references: [id]) + wallet ProviderWallet @relation(fields: [walletId], references: [id]) + addresses ProviderAddress[] sourceTransfers ProviderTransfer[] @relation("SourceAccount") destinationTransfers ProviderTransfer[] @relation("DestinationAccount") - @@unique([clientId, externalId]) + @@unique([clientId, connectionId, externalId]) @@index([createdAt, clientId]) @@map("provider_account") } model ProviderAddress { - id String @id - clientId String @map("client_id") - provider String - externalId String @map("external_id") - accountId String @map("account_id") - address String - createdAt DateTime @default(now()) @map("created_at") - updatedAt DateTime @updatedAt @map("updated_at") + id String @id + clientId String @map("client_id") + connectionId String @map("connection_id") + provider String + externalId String @map("external_id") + accountId String @map("account_id") + address String + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") - account ProviderAccount @relation(fields: [accountId], references: [id]) + connection ProviderConnection @relation(fields: [connectionId], references: [id]) + account ProviderAccount @relation(fields: [accountId], references: [id]) sourceTransfers ProviderTransfer[] @relation("SourceAddress") destinationTransfers ProviderTransfer[] @relation("DestinationAddress") - @@unique([clientId, externalId]) + @@unique([clientId, connectionId, externalId]) @@index([createdAt, clientId]) @@map("provider_address") } -model ProviderKnownDestination { - id String @id - clientId String @map("client_id") - provider String - externalId String @map("external_id") - externalClassification String? @map("external_classification") - address String - label String? - assetId String? @map("asset_id") - networkId String @map("network_id") - createdAt DateTime @default(now()) @map("created_at") - updatedAt DateTime @updatedAt @map("updated_at") - - connections ProviderKnownDestinationConnection[] - - @@unique([clientId, externalId]) - @@index([createdAt, clientId]) - @@map("provider_known_destination") -} - model ProviderConnection { id String @id clientId String @map("client_id") @@ -194,41 +178,34 @@ model ProviderConnection { updatedAt DateTime @map("updated_at") revokedAt DateTime? @map("revoked_at") - knownDestinationConnections ProviderKnownDestinationConnection[] - connections ProviderWalletConnection[] - syncs ProviderSync[] + wallets ProviderWallet[] + scopedSyncs ProviderScopedSync[] + accounts ProviderAccount[] + addresses ProviderAddress[] + transfers ProviderTransfer[] + syncs ProviderSync[] @@index([createdAt, clientId]) @@map("provider_connection") } -model ProviderKnownDestinationConnection { - clientId String @map("client_id") - connectionId String @map("connection_id") - knownDestinationId String @map("known_destination_id") - createdAt DateTime @default(now()) @map("created_at") - - connection ProviderConnection @relation(fields: [connectionId], references: [id], onDelete: Cascade) - knownDestination ProviderKnownDestination @relation(fields: [knownDestinationId], references: [id], onDelete: Cascade) - - @@id([clientId, connectionId, knownDestinationId]) - @@map("provider_known_destination_connection") -} - -model ProviderWalletConnection { - clientId String @map("client_id") - connectionId String @map("connection_id") - walletId String @map("wallet_id") - createdAt DateTime @default(now()) @map("created_at") +model ProviderSync { + id String @id + clientId String @map("client_id") + connectionId String @map("connection_id") + status String + errorName String? @map("error_name") + errorMessage String? @map("error_message") + errorTraceId String? @map("error_trace_id") + createdAt DateTime @default(now()) @map("created_at") + completedAt DateTime? @map("completed_at") - connection ProviderConnection @relation(fields: [connectionId], references: [id], onDelete: Cascade) - wallet ProviderWallet @relation(fields: [walletId], references: [id], onDelete: Cascade) + connection ProviderConnection @relation(fields: [connectionId], references: [id]) - @@id([clientId, connectionId, walletId]) - @@map("provider_wallet_connection") + @@map("provider_sync") } -model ProviderSync { +model ProviderScopedSync { id String @id clientId String @map("client_id") connectionId String @map("connection_id") @@ -236,17 +213,19 @@ model ProviderSync { errorName String? @map("error_name") errorMessage String? @map("error_message") errorTraceId String? @map("error_trace_id") + rawAccounts String @map("raw_accounts") createdAt DateTime @default(now()) @map("created_at") completedAt DateTime? @map("completed_at") connection ProviderConnection @relation(fields: [connectionId], references: [id]) - @@map("provider_sync") + @@map("provider_scoped_sync") } model ProviderTransfer { id String @id - assetId String @map("asset_id") + assetId String? @map("asset_id") + assetExternalId String? @map("asset_external_id") clientId String @map("client_id") createdAt DateTime @default(now()) @map("created_at") customerRefId String? @map("customer_ref_id") @@ -264,14 +243,15 @@ model ProviderTransfer { sourceAccountId String? @map("source_account_id") sourceAddressId String? @map("source_address_id") sourceWalletId String? @map("source_wallet_id") - - sourceWallet ProviderWallet? @relation("SourceWallet", fields: [sourceWalletId], references: [id]) - sourceAccount ProviderAccount? @relation("SourceAccount", fields: [sourceAccountId], references: [id]) - sourceAddress ProviderAddress? @relation("SourceAddress", fields: [sourceAddressId], references: [id]) - - destinationWallet ProviderWallet? @relation("DestinationWallet", fields: [destinationWalletId], references: [id]) - destinationAccount ProviderAccount? @relation("DestinationAccount", fields: [destinationAccountId], references: [id]) - destinationAddress ProviderAddress? @relation("DestinationAddress", fields: [destinationAddressId], references: [id]) + connectionId String @map("connection_id") + + connection ProviderConnection @relation(fields: [connectionId], references: [id]) + sourceWallet ProviderWallet? @relation("SourceWallet", fields: [sourceWalletId], references: [id]) + sourceAccount ProviderAccount? @relation("SourceAccount", fields: [sourceAccountId], references: [id]) + sourceAddress ProviderAddress? @relation("SourceAddress", fields: [sourceAddressId], references: [id]) + destinationWallet ProviderWallet? @relation("DestinationWallet", fields: [destinationWalletId], references: [id]) + destinationAccount ProviderAccount? @relation("DestinationAccount", fields: [destinationAccountId], references: [id]) + destinationAddress ProviderAddress? @relation("DestinationAddress", fields: [destinationAddressId], references: [id]) @@unique([clientId, externalId]) @@unique([clientId, idempotenceId]) diff --git a/apps/vault/src/shared/module/persistence/service/test-prisma.service.ts b/apps/vault/src/shared/module/persistence/service/test-prisma.service.ts index ab644d4ec..564a1e7b6 100644 --- a/apps/vault/src/shared/module/persistence/service/test-prisma.service.ts +++ b/apps/vault/src/shared/module/persistence/service/test-prisma.service.ts @@ -4,7 +4,6 @@ import { TEST_ACCOUNTS, TEST_ADDRESSES, TEST_CONNECTIONS, - TEST_WALLET_CONNECTIONS, TEST_WALLETS, TEST_WALLETS_WITH_SAME_TIMESTAMP } from '../../../../broker/__test__/util/mock-data' @@ -56,10 +55,6 @@ export class TestPrismaService { data: TEST_WALLETS_WITH_SAME_TIMESTAMP }) - await client.providerWalletConnection.createMany({ - data: TEST_WALLET_CONNECTIONS - }) - await client.providerAccount.createMany({ data: TEST_ACCOUNTS }) diff --git a/examples/unified-api/tsconfig.json b/examples/unified-api/tsconfig.json index cd04af0b0..37d9845f0 100644 --- a/examples/unified-api/tsconfig.json +++ b/examples/unified-api/tsconfig.json @@ -1,4 +1,5 @@ { + "extends": "../../tsconfig.base.json", "compilerOptions": { /* Visit https://aka.ms/tsconfig to read more about this file */ /* Projects */ diff --git a/examples/unified-api/vault.client.ts b/examples/unified-api/vault.client.ts index 1c1f4d4ed..b1e817dd2 100644 --- a/examples/unified-api/vault.client.ts +++ b/examples/unified-api/vault.client.ts @@ -1,9 +1,10 @@ -import { Hex, privateKeyToJwk, VaultClient } from '@narval-xyz/armory-sdk' +import { Hex, privateKeyToJwk } from '@narval-xyz/armory-sdk' import { buildSignerEdDSA } from '@narval-xyz/armory-sdk/signature' import dotenv from 'dotenv' import fs from 'fs' import path from 'path' import { z } from 'zod' +import { VaultClient } from '../../packages/armory-sdk/src/lib/vault/client' dotenv.config() const configSchema = z.object({ diff --git a/package-lock.json b/package-lock.json index 482e6df7f..f761c6795 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,7 @@ "@monaco-editor/react": "4.6.0", "@nestjs/axios": "3.0.2", "@nestjs/bull": "10.2.0", + "@nestjs/cache-manager": "3.0.0", "@nestjs/common": "10.3.10", "@nestjs/config": "3.1.1", "@nestjs/core": "10.4.7", @@ -57,6 +58,7 @@ "axios": "1.7.7", "axios-retry": "4.5.0", "bull": "4.16.4", + "cache-manager": "6.3.2", "class-transformer": "0.5.1", "class-validator": "0.14.1", "clsx": "2.1.1", @@ -69,6 +71,7 @@ "lowdb": "7.0.1", "nestjs-zod": "3.0.0", "next": "14.2.4", + "node-forge": "1.3.1", "permissionless": "0.1.44", "prism-react-renderer": "2.3.1", "react": "18.2.0", @@ -1332,13 +1335,13 @@ } }, "node_modules/@babel/generator": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.3.tgz", - "integrity": "sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.5.tgz", + "integrity": "sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.26.3", - "@babel/types": "^7.26.3", + "@babel/parser": "^7.26.5", + "@babel/types": "^7.26.5", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -1523,9 +1526,10 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz", - "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", + "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -1636,12 +1640,12 @@ } }, "node_modules/@babel/parser": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.3.tgz", - "integrity": "sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.5.tgz", + "integrity": "sha512-SRJ4jYmXRqV1/Xc+TIVG84WjHBXKlxO9sHQnA2Pf12QQEAp1LOh6kDzNHXcUnbH1QI0FDoPPVOt+vyUDucxpaw==", "license": "MIT", "dependencies": { - "@babel/types": "^7.26.3" + "@babel/types": "^7.26.5" }, "bin": { "parser": "bin/babel-parser.js" @@ -1710,24 +1714,6 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-proposal-class-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", - "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-proposal-decorators": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.24.7.tgz", @@ -1761,43 +1747,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", - "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead.", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-optional-chaining": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", - "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead.", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-proposal-private-property-in-object": { "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", @@ -2340,14 +2289,14 @@ } }, "node_modules/@babel/plugin-transform-flow-strip-types": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.25.9.tgz", - "integrity": "sha512-/VVukELzPDdci7UUsWQaSkhgnjIWXnIyRpM02ldxaVoFK96c41So8JcKT3m0gYjyv7j5FNPGS5vfELrWalkbDA==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.26.5.tgz", + "integrity": "sha512-eGK26RsbIkYUns3Y8qKl362juDDYK+wEdPGHGrhzUl6CewZFo55VZ7hg+CyMFU4dd5QQakBN86nBMpRsFpRvbQ==", "license": "MIT", "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/plugin-syntax-flow": "^7.25.9" + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/plugin-syntax-flow": "^7.26.0" }, "engines": { "node": ">=6.9.0" @@ -3391,17 +3340,17 @@ }, "node_modules/@babel/traverse--for-generate-function-map": { "name": "@babel/traverse", - "version": "7.26.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.4.tgz", - "integrity": "sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.5.tgz", + "integrity": "sha512-rkOSPOw+AXbgtwUga3U4u8RpoK9FEFWBNAlTpcnkLFjL5CT+oyHNuUUC/xx6XefEJ16r38r8Bc/lfp6rYuHeJQ==", "license": "MIT", "peer": true, "dependencies": { "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.3", - "@babel/parser": "^7.26.3", + "@babel/generator": "^7.26.5", + "@babel/parser": "^7.26.5", "@babel/template": "^7.25.9", - "@babel/types": "^7.26.3", + "@babel/types": "^7.26.5", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -3410,9 +3359,9 @@ } }, "node_modules/@babel/types": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz", - "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.5.tgz", + "integrity": "sha512-L6mZmwFDK6Cjh1nRCLXpa6no13ZIioJDz7mdkzHv399pThrTa/k0nUlNaenOeh2kWu/iaOQYElEpKPUswUa9Vg==", "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.25.9", @@ -5583,6 +5532,39 @@ "tslib": "2" } }, + "node_modules/@keyv/serialize": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.0.2.tgz", + "integrity": "sha512-+E/LyaAeuABniD/RvUezWVXKpeuvwLEA9//nE9952zBaOdBd2mQ3pPoM8cUe2X6IcMByfuSLzmYqnYshG60+HQ==", + "license": "MIT", + "dependencies": { + "buffer": "^6.0.3" + } + }, + "node_modules/@keyv/serialize/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, "node_modules/@leichtgewicht/ip-codec": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", @@ -6939,6 +6921,18 @@ "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0" } }, + "node_modules/@nestjs/cache-manager": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@nestjs/cache-manager/-/cache-manager-3.0.0.tgz", + "integrity": "sha512-csKvxHSQWfC0OiDo0bNEhLqrmYDopHEvRyC81MxV9xFj1AO+rOKocpHa4M1ZGH//6uKFIPGN9oiR0mvZY77APA==", + "license": "MIT", + "peerDependencies": { + "@nestjs/common": "^9.0.0 || ^10.0.0 || ^11.0.0", + "@nestjs/core": "^9.0.0 || ^10.0.0 || ^11.0.0", + "cache-manager": ">=6", + "rxjs": "^7.8.1" + } + }, "node_modules/@nestjs/common": { "version": "10.3.10", "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.3.10.tgz", @@ -17692,9 +17686,9 @@ "integrity": "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==" }, "node_modules/@react-native/assets-registry": { - "version": "0.76.5", - "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.76.5.tgz", - "integrity": "sha512-MN5dasWo37MirVcKWuysRkRr4BjNc81SXwUtJYstwbn8oEkfnwR9DaqdDTo/hHOnTdhafffLIa2xOOHcjDIGEw==", + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.77.0.tgz", + "integrity": "sha512-Ms4tYYAMScgINAXIhE4riCFJPPL/yltughHS950l0VP5sm5glbimn9n7RFn9Tc8cipX74/ddbk19+ydK2iDMmA==", "license": "MIT", "peer": true, "engines": { @@ -17702,22 +17696,23 @@ } }, "node_modules/@react-native/babel-plugin-codegen": { - "version": "0.76.5", - "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.76.5.tgz", - "integrity": "sha512-xe7HSQGop4bnOLMaXt0aU+rIatMNEQbz242SDl8V9vx5oOTI0VbZV9yLy6yBc6poUlYbcboF20YVjoRsxX4yww==", + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.77.0.tgz", + "integrity": "sha512-5TYPn1k+jdDOZJU4EVb1kZ0p9TCVICXK3uplRev5Gul57oWesAaiWGZOzfRS3lonWeuR4ij8v8PFfIHOaq0vmA==", "license": "MIT", "peer": true, "dependencies": { - "@react-native/codegen": "0.76.5" + "@babel/traverse": "^7.25.3", + "@react-native/codegen": "0.77.0" }, "engines": { "node": ">=18" } }, "node_modules/@react-native/babel-preset": { - "version": "0.76.5", - "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.76.5.tgz", - "integrity": "sha512-1Nu5Um4EogOdppBLI4pfupkteTjWfmI0hqW8ezWTg7Bezw0FtBj8yS8UYVd3wTnDFT9A5mA2VNoNUqomJnvj2A==", + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.77.0.tgz", + "integrity": "sha512-Z4yxE66OvPyQ/iAlaETI1ptRLcDm7Tk6ZLqtCPuUX3AMg+JNgIA86979T4RSk486/JrBUBH5WZe2xjj7eEHXsA==", "license": "MIT", "peer": true, "dependencies": { @@ -17762,8 +17757,8 @@ "@babel/plugin-transform-typescript": "^7.25.2", "@babel/plugin-transform-unicode-regex": "^7.24.7", "@babel/template": "^7.25.0", - "@react-native/babel-plugin-codegen": "0.76.5", - "babel-plugin-syntax-hermes-parser": "^0.25.1", + "@react-native/babel-plugin-codegen": "0.77.0", + "babel-plugin-syntax-hermes-parser": "0.25.1", "babel-plugin-transform-flow-enums": "^0.0.2", "react-refresh": "^0.14.0" }, @@ -17774,46 +17769,28 @@ "@babel/core": "*" } }, - "node_modules/@react-native/babel-preset/node_modules/babel-plugin-syntax-hermes-parser": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.25.1.tgz", - "integrity": "sha512-IVNpGzboFLfXZUAwkLFcI/bnqVbwky0jP3eBno4HKtqvQJAHBLdgxiG6lQ4to0+Q/YCN3PO0od5NZwIKyY4REQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "hermes-parser": "0.25.1" - } - }, - "node_modules/@react-native/babel-preset/node_modules/hermes-estree": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", - "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", - "license": "MIT", - "peer": true - }, - "node_modules/@react-native/babel-preset/node_modules/hermes-parser": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", - "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "node_modules/@react-native/babel-preset/node_modules/react-refresh": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", "license": "MIT", "peer": true, - "dependencies": { - "hermes-estree": "0.25.1" + "engines": { + "node": ">=0.10.0" } }, "node_modules/@react-native/codegen": { - "version": "0.76.5", - "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.76.5.tgz", - "integrity": "sha512-FoZ9VRQ5MpgtDAnVo1rT9nNRfjnWpE40o1GeJSDlpUMttd36bVXvsDm8W/NhX8BKTWXSX+CPQJsRcvN1UPYGKg==", + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.77.0.tgz", + "integrity": "sha512-rE9lXx41ZjvE8cG7e62y/yGqzUpxnSvJ6me6axiX+aDewmI4ZrddvRGYyxCnawxy5dIBHSnrpZse3P87/4Lm7w==", "license": "MIT", "peer": true, "dependencies": { "@babel/parser": "^7.25.3", "glob": "^7.1.1", - "hermes-parser": "0.23.1", + "hermes-parser": "0.25.1", "invariant": "^2.2.4", - "jscodeshift": "^0.14.0", - "mkdirp": "^0.5.1", + "jscodeshift": "^17.0.0", "nullthrows": "^1.1.1", "yargs": "^17.6.2" }, @@ -17876,21 +17853,20 @@ } }, "node_modules/@react-native/community-cli-plugin": { - "version": "0.76.5", - "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.76.5.tgz", - "integrity": "sha512-3MKMnlU0cZOWlMhz5UG6WqACJiWUrE3XwBEumzbMmZw3Iw3h+fIsn+7kLLE5EhzqLt0hg5Y4cgYFi4kOaNgq+g==", + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.77.0.tgz", + "integrity": "sha512-GRshwhCHhtupa3yyCbel14SlQligV8ffNYN5L1f8HCo2SeGPsBDNjhj2U+JTrMPnoqpwowPGvkCwyqwqYff4MQ==", "license": "MIT", "peer": true, "dependencies": { - "@react-native/dev-middleware": "0.76.5", - "@react-native/metro-babel-transformer": "0.76.5", + "@react-native/dev-middleware": "0.77.0", + "@react-native/metro-babel-transformer": "0.77.0", "chalk": "^4.0.0", - "execa": "^5.1.1", + "debug": "^2.2.0", "invariant": "^2.2.4", "metro": "^0.81.0", "metro-config": "^0.81.0", "metro-core": "^0.81.0", - "node-fetch": "^2.2.0", "readline": "^1.3.0", "semver": "^7.1.3" }, @@ -17906,6 +17882,23 @@ } } }, + "node_modules/@react-native/community-cli-plugin/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/@react-native/community-cli-plugin/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT", + "peer": true + }, "node_modules/@react-native/community-cli-plugin/node_modules/semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", @@ -17920,9 +17913,9 @@ } }, "node_modules/@react-native/debugger-frontend": { - "version": "0.76.5", - "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.76.5.tgz", - "integrity": "sha512-5gtsLfBaSoa9WP8ToDb/8NnDBLZjv4sybQQj7rDKytKOdsXm3Pr2y4D7x7GQQtP1ZQRqzU0X0OZrhRz9xNnOqA==", + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.77.0.tgz", + "integrity": "sha512-glOvSEjCbVXw+KtfiOAmrq21FuLE1VsmBsyT7qud4KWbXP43aUEhzn70mWyFuiIdxnzVPKe2u8iWTQTdJksR1w==", "license": "BSD-3-Clause", "peer": true, "engines": { @@ -17930,14 +17923,14 @@ } }, "node_modules/@react-native/dev-middleware": { - "version": "0.76.5", - "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.76.5.tgz", - "integrity": "sha512-f8eimsxpkvMgJia7POKoUu9uqjGF6KgkxX4zqr/a6eoR1qdEAWUd6PonSAqtag3PAqvEaJpB99gLH2ZJI1nDGg==", + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.77.0.tgz", + "integrity": "sha512-DAlEYujm43O+Dq98KP2XfLSX5c/TEGtt+JBDEIOQewk374uYY52HzRb1+Gj6tNaEj/b33no4GibtdxbO5zmPhg==", "license": "MIT", "peer": true, "dependencies": { "@isaacs/ttlcache": "^1.4.1", - "@react-native/debugger-frontend": "0.76.5", + "@react-native/debugger-frontend": "0.77.0", "chrome-launcher": "^0.15.2", "chromium-edge-launcher": "^0.2.0", "connect": "^3.6.5", @@ -17945,7 +17938,7 @@ "nullthrows": "^1.1.1", "open": "^7.0.3", "selfsigned": "^2.4.1", - "serve-static": "^1.13.1", + "serve-static": "^1.16.2", "ws": "^6.2.3" }, "engines": { @@ -17962,6 +17955,16 @@ "ms": "2.0.0" } }, + "node_modules/@react-native/dev-middleware/node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/@react-native/dev-middleware/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -17986,6 +17989,64 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@react-native/dev-middleware/node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", + "peer": true, + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/@react-native/dev-middleware/node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/@react-native/dev-middleware/node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT", + "peer": true + }, + "node_modules/@react-native/dev-middleware/node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", + "peer": true, + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/@react-native/dev-middleware/node_modules/ws": { "version": "6.2.3", "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", @@ -17997,9 +18058,9 @@ } }, "node_modules/@react-native/gradle-plugin": { - "version": "0.76.5", - "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.76.5.tgz", - "integrity": "sha512-7KSyD0g0KhbngITduC8OABn0MAlJfwjIdze7nA4Oe1q3R7qmAv+wQzW+UEXvPah8m1WqFjYTkQwz/4mK3XrQGw==", + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.77.0.tgz", + "integrity": "sha512-rmfh93jzbndSq7kihYHUQ/EGHTP8CCd3GDCmg5SbxSOHAaAYx2HZ28ZG7AVcGUsWeXp+e/90zGIyfOzDRx0Zaw==", "license": "MIT", "peer": true, "engines": { @@ -18007,9 +18068,9 @@ } }, "node_modules/@react-native/js-polyfills": { - "version": "0.76.5", - "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.76.5.tgz", - "integrity": "sha512-ggM8tcKTcaqyKQcXMIvcB0vVfqr9ZRhWVxWIdiFO1mPvJyS6n+a+lLGkgQAyO8pfH0R1qw6K9D0nqbbDo865WQ==", + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.77.0.tgz", + "integrity": "sha512-kHFcMJVkGb3ptj3yg1soUsMHATqal4dh0QTGAbYihngJ6zy+TnP65J3GJq4UlwqFE9K1RZkeCmTwlmyPFHOGvA==", "license": "MIT", "peer": true, "engines": { @@ -18017,15 +18078,15 @@ } }, "node_modules/@react-native/metro-babel-transformer": { - "version": "0.76.5", - "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.76.5.tgz", - "integrity": "sha512-Cm9G5Sg5BDty3/MKa3vbCAJtT3YHhlEaPlQALLykju7qBS+pHZV9bE9hocfyyvc5N/osTIGWxG5YOfqTeMu1oQ==", + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.77.0.tgz", + "integrity": "sha512-19GfvhBRKCU3UDWwCnDR4QjIzz3B2ZuwhnxMRwfAgPxz7QY9uKour9RGmBAVUk1Wxi/SP7dLEvWnmnuBO39e2A==", "license": "MIT", "peer": true, "dependencies": { "@babel/core": "^7.25.2", - "@react-native/babel-preset": "0.76.5", - "hermes-parser": "0.23.1", + "@react-native/babel-preset": "0.77.0", + "hermes-parser": "0.25.1", "nullthrows": "^1.1.1" }, "engines": { @@ -18036,16 +18097,16 @@ } }, "node_modules/@react-native/normalize-colors": { - "version": "0.76.5", - "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.76.5.tgz", - "integrity": "sha512-6QRLEok1r55gLqj+94mEWUENuU5A6wsr2OoXpyq/CgQ7THWowbHtru/kRGRr6o3AQXrVnZheR60JNgFcpNYIug==", + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.77.0.tgz", + "integrity": "sha512-qjmxW3xRZe4T0ZBEaXZNHtuUbRgyfybWijf1yUuQwjBt24tSapmIslwhCjpKidA0p93ssPcepquhY0ykH25mew==", "license": "MIT", "peer": true }, "node_modules/@react-native/virtualized-lists": { - "version": "0.76.5", - "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.76.5.tgz", - "integrity": "sha512-M/fW1fTwxrHbcx0OiVOIxzG6rKC0j9cR9Csf80o77y1Xry0yrNPpAlf8D1ev3LvHsiAUiRNFlauoPtodrs2J1A==", + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.77.0.tgz", + "integrity": "sha512-ppPtEu9ISO9iuzpA2HBqrfmDpDAnGGduNDVaegadOzbMCPAB3tC9Blxdu9W68LyYlNQILIsP6/FYtLwf7kfNew==", "license": "MIT", "peer": true, "dependencies": { @@ -21856,9 +21917,9 @@ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" }, "node_modules/ast-types": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.15.2.tgz", - "integrity": "sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg==", + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", + "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", "license": "MIT", "peer": true, "dependencies": { @@ -22012,16 +22073,6 @@ "deep-equal": "^2.0.5" } }, - "node_modules/babel-core": { - "version": "7.0.0-bridge.0", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", - "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==", - "license": "MIT", - "peer": true, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -22198,13 +22249,13 @@ } }, "node_modules/babel-plugin-syntax-hermes-parser": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.23.1.tgz", - "integrity": "sha512-uNLD0tk2tLUjGFdmCk+u/3FEw2o+BAwW4g+z2QVlxJrzZYOOPADroEcNtTPt5lNiScctaUmnsTkVEnOwZUOLhA==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.25.1.tgz", + "integrity": "sha512-IVNpGzboFLfXZUAwkLFcI/bnqVbwky0jP3eBno4HKtqvQJAHBLdgxiG6lQ4to0+Q/YCN3PO0od5NZwIKyY4REQ==", "license": "MIT", "peer": true, "dependencies": { - "hermes-parser": "0.23.1" + "hermes-parser": "0.25.1" } }, "node_modules/babel-plugin-transform-flow-enums": { @@ -22678,6 +22729,24 @@ "node": ">= 6.0.0" } }, + "node_modules/cache-manager": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/cache-manager/-/cache-manager-6.3.2.tgz", + "integrity": "sha512-VmLouPUrvpm9dfwYB6OE7YVXDZ7BCfbt7hq10EHiBYaW9K9ZthK1bbjDQAtXGDK7d9u8t4G/7dMWSJOwN33msg==", + "license": "MIT", + "dependencies": { + "keyv": "^5.2.3" + } + }, + "node_modules/cache-manager/node_modules/keyv": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.2.3.tgz", + "integrity": "sha512-AGKecUfzrowabUv0bH1RIR5Vf7w+l4S3xtQAypKaUpTdIR1EbrAcTxHCrpo9Q+IWeUlFE2palRtgIQcgm+PQJw==", + "license": "MIT", + "dependencies": { + "@keyv/serialize": "^1.0.2" + } + }, "node_modules/cacheable-lookup": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", @@ -25605,6 +25674,31 @@ "node": ">= 0.8" } }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -27717,9 +27811,9 @@ "peer": true }, "node_modules/flow-parser": { - "version": "0.258.0", - "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.258.0.tgz", - "integrity": "sha512-/f3ui3WaPTRUtqnWaGzf/f352hn4VhqGOiuSVkgaW6SbHNp5EwdDoh6BF3zB9A6kcWhCpg/0x0A3aXU+KXugAA==", + "version": "0.259.1", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.259.1.tgz", + "integrity": "sha512-xiXLmMH2Z7OmdE9Q+MjljUMr/rbemFqZIRxaeZieVScG4HzQrKKhNcCYZbWTGpoN7ZPi7z8ClQbeVPq6t5AszQ==", "license": "MIT", "peer": true, "engines": { @@ -28966,20 +29060,20 @@ "license": "MIT" }, "node_modules/hermes-estree": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.23.1.tgz", - "integrity": "sha512-eT5MU3f5aVhTqsfIReZ6n41X5sYn4IdQL0nvz6yO+MMlPxw49aSARHLg/MSehQftyjnrE8X6bYregzSumqc6cg==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", "license": "MIT", "peer": true }, "node_modules/hermes-parser": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.23.1.tgz", - "integrity": "sha512-oxl5h2DkFW83hT4DAUJorpah8ou4yvmweUzLJmmr6YV2cezduCdlil1AvU/a/xSsAFo4WUcNA4GoV5Bvq6JffA==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", "license": "MIT", "peer": true, "dependencies": { - "hermes-estree": "0.23.1" + "hermes-estree": "0.25.1" } }, "node_modules/hexoid": { @@ -31897,49 +31991,71 @@ "peer": true }, "node_modules/jscodeshift": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.14.0.tgz", - "integrity": "sha512-7eCC1knD7bLUPuSCwXsMZUH51O8jIcoVyKtI6P0XM0IVzlGjckPy3FIwQlorzbN0Sg79oK+RlohN32Mqf/lrYA==", + "version": "17.1.2", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-17.1.2.tgz", + "integrity": "sha512-uime4vFOiZ1o3ICT4Sm/AbItHEVw2oCxQ3a0egYVy3JMMOctxe07H3SKL1v175YqjMt27jn1N+3+Bj9SKDNgdQ==", "license": "MIT", "peer": true, "dependencies": { - "@babel/core": "^7.13.16", - "@babel/parser": "^7.13.16", - "@babel/plugin-proposal-class-properties": "^7.13.0", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.13.8", - "@babel/plugin-proposal-optional-chaining": "^7.13.12", - "@babel/plugin-transform-modules-commonjs": "^7.13.8", - "@babel/preset-flow": "^7.13.13", - "@babel/preset-typescript": "^7.13.0", - "@babel/register": "^7.13.16", - "babel-core": "^7.0.0-bridge.0", - "chalk": "^4.1.2", + "@babel/core": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/plugin-transform-class-properties": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.24.7", + "@babel/preset-flow": "^7.24.7", + "@babel/preset-typescript": "^7.24.7", + "@babel/register": "^7.24.6", "flow-parser": "0.*", "graceful-fs": "^4.2.4", - "micromatch": "^4.0.4", + "micromatch": "^4.0.7", "neo-async": "^2.5.0", - "node-dir": "^0.1.17", - "recast": "^0.21.0", - "temp": "^0.8.4", - "write-file-atomic": "^2.3.0" + "picocolors": "^1.0.1", + "recast": "^0.23.9", + "tmp": "^0.2.3", + "write-file-atomic": "^5.0.1" }, "bin": { "jscodeshift": "bin/jscodeshift.js" }, + "engines": { + "node": ">=16" + }, "peerDependencies": { "@babel/preset-env": "^7.1.6" + }, + "peerDependenciesMeta": { + "@babel/preset-env": { + "optional": true + } + } + }, + "node_modules/jscodeshift/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "peer": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/jscodeshift/node_modules/write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", "license": "ISC", "peer": true, "dependencies": { - "graceful-fs": "^4.1.11", "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/jsdom": { @@ -36832,43 +36948,6 @@ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" }, - "node_modules/node-dir": { - "version": "0.1.17", - "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", - "integrity": "sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==", - "license": "MIT", - "peer": true, - "dependencies": { - "minimatch": "^3.0.2" - }, - "engines": { - "node": ">= 0.10.5" - } - }, - "node_modules/node-dir/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "license": "MIT", - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/node-dir/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "license": "ISC", - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/node-emoji": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.1.3.tgz", @@ -36930,6 +37009,7 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "license": "(BSD-3-Clause OR GPL-2.0)", "engines": { "node": ">= 6.13.0" } @@ -39206,16 +39286,6 @@ "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-1.0.0.tgz", "integrity": "sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==" }, - "node_modules/promise": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", - "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", - "license": "MIT", - "peer": true, - "dependencies": { - "asap": "~2.0.6" - } - }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -39967,9 +40037,9 @@ } }, "node_modules/react-devtools-core": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-5.3.2.tgz", - "integrity": "sha512-crr9HkVrDiJ0A4zot89oS0Cgv0Oa4OG1Em4jit3P3ZxZSKPMYyMjfwMqgcJna9o625g8oN87rBm8SWWrSTBZxg==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-6.0.1.tgz", + "integrity": "sha512-II3iSJhnR5nAscYDa9FCgPLq8mO5aEx/EKKtdXYTDnvdFEa3K7gs3jn1SKRXwQf9maOmIilmjnnx7Qy+3annPA==", "license": "MIT", "peer": true, "dependencies": { @@ -40082,25 +40152,25 @@ } }, "node_modules/react-native": { - "version": "0.76.5", - "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.76.5.tgz", - "integrity": "sha512-op2p2kB+lqMF1D7AdX4+wvaR0OPFbvWYs+VBE7bwsb99Cn9xISrLRLAgFflZedQsa5HvnOGrULhtnmItbIKVVw==", + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.77.0.tgz", + "integrity": "sha512-oCgHLGHFIp6F5UbyHSedyUXrZg6/GPe727freGFvlT7BjPJ3K6yvvdlsp7OEXSAHz6Fe7BI2n5cpUyqmP9Zn+Q==", "license": "MIT", "peer": true, "dependencies": { "@jest/create-cache-key-function": "^29.6.3", - "@react-native/assets-registry": "0.76.5", - "@react-native/codegen": "0.76.5", - "@react-native/community-cli-plugin": "0.76.5", - "@react-native/gradle-plugin": "0.76.5", - "@react-native/js-polyfills": "0.76.5", - "@react-native/normalize-colors": "0.76.5", - "@react-native/virtualized-lists": "0.76.5", + "@react-native/assets-registry": "0.77.0", + "@react-native/codegen": "0.77.0", + "@react-native/community-cli-plugin": "0.77.0", + "@react-native/gradle-plugin": "0.77.0", + "@react-native/js-polyfills": "0.77.0", + "@react-native/normalize-colors": "0.77.0", + "@react-native/virtualized-lists": "0.77.0", "abort-controller": "^3.0.0", "anser": "^1.4.9", "ansi-regex": "^5.0.0", "babel-jest": "^29.7.0", - "babel-plugin-syntax-hermes-parser": "^0.23.1", + "babel-plugin-syntax-hermes-parser": "0.25.1", "base64-js": "^1.5.1", "chalk": "^4.0.0", "commander": "^12.0.0", @@ -40113,11 +40183,10 @@ "memoize-one": "^5.0.0", "metro-runtime": "^0.81.0", "metro-source-map": "^0.81.0", - "mkdirp": "^0.5.1", "nullthrows": "^1.1.1", "pretty-format": "^29.7.0", "promise": "^8.3.0", - "react-devtools-core": "^5.3.1", + "react-devtools-core": "^6.0.1", "react-refresh": "^0.14.0", "regenerator-runtime": "^0.13.2", "scheduler": "0.24.0-canary-efb381bbf-20230505", @@ -40219,6 +40288,16 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/react-native/node_modules/promise": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", + "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", + "license": "MIT", + "peer": true, + "dependencies": { + "asap": "~2.0.6" + } + }, "node_modules/react-native/node_modules/react-is": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", @@ -40226,6 +40305,16 @@ "license": "MIT", "peer": true }, + "node_modules/react-native/node_modules/react-refresh": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/react-native/node_modules/regenerator-runtime": { "version": "0.13.11", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", @@ -40300,16 +40389,6 @@ "node": ">=12" } }, - "node_modules/react-refresh": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", - "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/react-remove-scroll": { "version": "2.5.5", "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz", @@ -40497,15 +40576,16 @@ } }, "node_modules/recast": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/recast/-/recast-0.21.5.tgz", - "integrity": "sha512-hjMmLaUXAm1hIuTqOdeYObMslq/q+Xff6QE3Y2P+uoHAg2nmVlLBps2hzh1UJDdMtDTMXOFewK6ky51JQIeECg==", + "version": "0.23.9", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.9.tgz", + "integrity": "sha512-Hx/BGIbwj+Des3+xy5uAtAbdCyqK9y9wbBcDFDYanLS9JnMqf7OeF87HQwUimE87OEc72mr6tkKUKMBBL+hF9Q==", "license": "MIT", "peer": true, "dependencies": { - "ast-types": "0.15.2", + "ast-types": "^0.16.1", "esprima": "~4.0.0", "source-map": "~0.6.1", + "tiny-invariant": "^1.3.3", "tslib": "^2.0.1" }, "engines": { @@ -43235,33 +43315,6 @@ "node": ">=6" } }, - "node_modules/temp": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.4.tgz", - "integrity": "sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==", - "license": "MIT", - "peer": true, - "dependencies": { - "rimraf": "~2.6.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/temp/node_modules/rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "license": "ISC", - "peer": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, "node_modules/terser": { "version": "5.31.2", "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.2.tgz", @@ -43573,7 +43626,6 @@ "version": "0.2.3", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", - "dev": true, "engines": { "node": ">=14.14" } @@ -46204,7 +46256,7 @@ }, "packages/armory-sdk": { "name": "@narval-xyz/armory-sdk", - "version": "0.17.0", + "version": "0.18.0", "license": "MPL-2.0", "dependencies": { "@noble/curves": "1.6.0", diff --git a/package.json b/package.json index 8aeeb8fbf..7bba43f77 100644 --- a/package.json +++ b/package.json @@ -84,6 +84,7 @@ "@monaco-editor/react": "4.6.0", "@nestjs/axios": "3.0.2", "@nestjs/bull": "10.2.0", + "@nestjs/cache-manager": "3.0.0", "@nestjs/common": "10.3.10", "@nestjs/config": "3.1.1", "@nestjs/core": "10.4.7", @@ -117,6 +118,7 @@ "axios": "1.7.7", "axios-retry": "4.5.0", "bull": "4.16.4", + "cache-manager": "6.3.2", "class-transformer": "0.5.1", "class-validator": "0.14.1", "clsx": "2.1.1", @@ -129,6 +131,7 @@ "lowdb": "7.0.1", "nestjs-zod": "3.0.0", "next": "14.2.4", + "node-forge": "1.3.1", "permissionless": "0.1.44", "prism-react-renderer": "2.3.1", "react": "18.2.0", diff --git a/packages/armory-sdk/package.json b/packages/armory-sdk/package.json index 0d4c2b55e..67f5b8c35 100644 --- a/packages/armory-sdk/package.json +++ b/packages/armory-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@narval-xyz/armory-sdk", - "version": "0.17.0", + "version": "0.18.0", "license": "MPL-2.0", "publishConfig": { "access": "public" diff --git a/packages/armory-sdk/src/lib/http/client/vault/api.ts b/packages/armory-sdk/src/lib/http/client/vault/api.ts index 5640bea20..9f731f27f 100644 --- a/packages/armory-sdk/src/lib/http/client/vault/api.ts +++ b/packages/armory-sdk/src/lib/http/client/vault/api.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * Vault - * Secure storage for private keys and sensitive data, designed to protect your most critical assets in web3.0 + * Secure Enclave-backed authorization proxy for web3 secrets. Holds encrypted credentials and proxies API requests to custodians and wallet tech providers. Can also generate evm wallet private keys & sign transactions. * * The version of the OpenAPI document: 1.0 * @@ -1004,7 +1004,8 @@ export interface CreateConnectionDto { export const CreateConnectionDtoProviderEnum = { Anchorage: 'anchorage', - Fireblocks: 'fireblocks' + Fireblocks: 'fireblocks', + Bitgo: 'bitgo' } as const; export type CreateConnectionDtoProviderEnum = typeof CreateConnectionDtoProviderEnum[keyof typeof CreateConnectionDtoProviderEnum]; @@ -1262,24 +1263,12 @@ export interface InitiateConnectionDto { export const InitiateConnectionDtoProviderEnum = { Anchorage: 'anchorage', - Fireblocks: 'fireblocks' + Fireblocks: 'fireblocks', + Bitgo: 'bitgo' } as const; export type InitiateConnectionDtoProviderEnum = typeof InitiateConnectionDtoProviderEnum[keyof typeof InitiateConnectionDtoProviderEnum]; -/** - * - * @export - * @interface KnownDestinationDto - */ -export interface KnownDestinationDto { - /** - * - * @type {PaginatedKnownDestinationsDtoDataInner} - * @memberof KnownDestinationDto - */ - 'data': PaginatedKnownDestinationsDtoDataInner; -} /** * * @export @@ -1294,10 +1283,10 @@ export interface PaginatedAccountsDto { 'data': Array; /** * - * @type {PaginatedConnectionsDtoPage} + * @type {PaginatedAssetsDtoPage} * @memberof PaginatedAccountsDto */ - 'page'?: PaginatedConnectionsDtoPage; + 'page'?: PaginatedAssetsDtoPage; } /** * @@ -1313,43 +1302,145 @@ export interface PaginatedAddressesDto { 'data': Array; /** * - * @type {PaginatedConnectionsDtoPage} + * @type {PaginatedAssetsDtoPage} * @memberof PaginatedAddressesDto */ - 'page'?: PaginatedConnectionsDtoPage; + 'page'?: PaginatedAssetsDtoPage; } /** * * @export - * @interface PaginatedConnectionsDto + * @interface PaginatedAssetsDto */ -export interface PaginatedConnectionsDto { +export interface PaginatedAssetsDto { /** * - * @type {Array} - * @memberof PaginatedConnectionsDto + * @type {Array} + * @memberof PaginatedAssetsDto */ - 'data': Array; + 'data': Array; /** * - * @type {PaginatedConnectionsDtoPage} - * @memberof PaginatedConnectionsDto + * @type {PaginatedAssetsDtoPage} + * @memberof PaginatedAssetsDto + */ + 'page'?: PaginatedAssetsDtoPage; +} +/** + * + * @export + * @interface PaginatedAssetsDtoDataInner + */ +export interface PaginatedAssetsDtoDataInner { + /** + * + * @type {string} + * @memberof PaginatedAssetsDtoDataInner + */ + 'assetId': string; + /** + * + * @type {any} + * @memberof PaginatedAssetsDtoDataInner + */ + 'createdAt'?: any; + /** + * + * @type {number} + * @memberof PaginatedAssetsDtoDataInner + */ + 'decimals': number | null; + /** + * + * @type {Array} + * @memberof PaginatedAssetsDtoDataInner + */ + 'externalAssets'?: Array; + /** + * + * @type {string} + * @memberof PaginatedAssetsDtoDataInner + */ + 'name': string; + /** + * + * @type {string} + * @memberof PaginatedAssetsDtoDataInner + */ + 'networkId': string; + /** + * + * @type {string} + * @memberof PaginatedAssetsDtoDataInner + */ + 'onchainId': string | null; + /** + * + * @type {string} + * @memberof PaginatedAssetsDtoDataInner + */ + 'symbol': string | null; +} +/** + * + * @export + * @interface PaginatedAssetsDtoDataInnerExternalAssetsInner + */ +export interface PaginatedAssetsDtoDataInnerExternalAssetsInner { + /** + * + * @type {string} + * @memberof PaginatedAssetsDtoDataInnerExternalAssetsInner + */ + 'externalId': string; + /** + * + * @type {string} + * @memberof PaginatedAssetsDtoDataInnerExternalAssetsInner */ - 'page'?: PaginatedConnectionsDtoPage; + 'provider': PaginatedAssetsDtoDataInnerExternalAssetsInnerProviderEnum; } + +export const PaginatedAssetsDtoDataInnerExternalAssetsInnerProviderEnum = { + Anchorage: 'anchorage', + Fireblocks: 'fireblocks', + Bitgo: 'bitgo' +} as const; + +export type PaginatedAssetsDtoDataInnerExternalAssetsInnerProviderEnum = typeof PaginatedAssetsDtoDataInnerExternalAssetsInnerProviderEnum[keyof typeof PaginatedAssetsDtoDataInnerExternalAssetsInnerProviderEnum]; + /** * * @export - * @interface PaginatedConnectionsDtoPage + * @interface PaginatedAssetsDtoPage */ -export interface PaginatedConnectionsDtoPage { +export interface PaginatedAssetsDtoPage { /** * * @type {string} - * @memberof PaginatedConnectionsDtoPage + * @memberof PaginatedAssetsDtoPage */ 'next': string | null; } +/** + * + * @export + * @interface PaginatedConnectionsDto + */ +export interface PaginatedConnectionsDto { + /** + * + * @type {Array} + * @memberof PaginatedConnectionsDto + */ + 'data': Array; + /** + * + * @type {PaginatedAssetsDtoPage} + * @memberof PaginatedConnectionsDto + */ + 'page'?: PaginatedAssetsDtoPage; +} /** * * @export @@ -1364,10 +1455,10 @@ export interface PaginatedKnownDestinationsDto { 'data': Array; /** * - * @type {PaginatedConnectionsDtoPage} + * @type {PaginatedAssetsDtoPage} * @memberof PaginatedKnownDestinationsDto */ - 'page'?: PaginatedConnectionsDtoPage; + 'page'?: PaginatedAssetsDtoPage; } /** * @@ -1375,12 +1466,6 @@ export interface PaginatedKnownDestinationsDto { * @interface PaginatedKnownDestinationsDtoDataInner */ export interface PaginatedKnownDestinationsDtoDataInner { - /** - * - * @type {string} - * @memberof PaginatedKnownDestinationsDtoDataInner - */ - 'knownDestinationId': string; /** * * @type {string} @@ -1389,10 +1474,10 @@ export interface PaginatedKnownDestinationsDtoDataInner { 'clientId': string; /** * - * @type {Array} + * @type {string} * @memberof PaginatedKnownDestinationsDtoDataInner */ - 'connections': Array; + 'connectionId': string; /** * * @type {string} @@ -1435,23 +1520,12 @@ export interface PaginatedKnownDestinationsDtoDataInner { * @memberof PaginatedKnownDestinationsDtoDataInner */ 'networkId': string; - /** - * - * @type {any} - * @memberof PaginatedKnownDestinationsDtoDataInner - */ - 'createdAt': any; - /** - * - * @type {any} - * @memberof PaginatedKnownDestinationsDtoDataInner - */ - 'updatedAt': any; } export const PaginatedKnownDestinationsDtoDataInnerProviderEnum = { Anchorage: 'anchorage', - Fireblocks: 'fireblocks' + Fireblocks: 'fireblocks', + Bitgo: 'bitgo' } as const; export type PaginatedKnownDestinationsDtoDataInnerProviderEnum = typeof PaginatedKnownDestinationsDtoDataInnerProviderEnum[keyof typeof PaginatedKnownDestinationsDtoDataInnerProviderEnum]; @@ -1459,219 +1533,524 @@ export type PaginatedKnownDestinationsDtoDataInnerProviderEnum = typeof Paginate /** * * @export - * @interface PaginatedSyncsDto + * @interface PaginatedNetworksDto */ -export interface PaginatedSyncsDto { +export interface PaginatedNetworksDto { /** * - * @type {Array} - * @memberof PaginatedSyncsDto + * @type {Array} + * @memberof PaginatedNetworksDto */ - 'data': Array; + 'data': Array; /** * - * @type {PaginatedConnectionsDtoPage} - * @memberof PaginatedSyncsDto + * @type {PaginatedAssetsDtoPage} + * @memberof PaginatedNetworksDto */ - 'page'?: PaginatedConnectionsDtoPage; + 'page'?: PaginatedAssetsDtoPage; } /** * * @export - * @interface PaginatedWalletsDto + * @interface PaginatedNetworksDtoDataInner */ -export interface PaginatedWalletsDto { +export interface PaginatedNetworksDtoDataInner { /** * - * @type {Array} - * @memberof PaginatedWalletsDto + * @type {string} + * @memberof PaginatedNetworksDtoDataInner */ - 'data': Array; + 'networkId': string; /** * - * @type {PaginatedConnectionsDtoPage} - * @memberof PaginatedWalletsDto + * @type {number} + * @memberof PaginatedNetworksDtoDataInner + */ + 'coinType': number | null; + /** + * + * @type {string} + * @memberof PaginatedNetworksDtoDataInner + */ + 'name': string; + /** + * + * @type {Array} + * @memberof PaginatedNetworksDtoDataInner + */ + 'externalNetworks'?: Array; + /** + * + * @type {any} + * @memberof PaginatedNetworksDtoDataInner */ - 'page'?: PaginatedConnectionsDtoPage; + 'createdAt'?: any; } /** * * @export - * @interface PaginatedWalletsDtoDataInner + * @interface PaginatedRawAccountsDto */ -export interface PaginatedWalletsDtoDataInner { +export interface PaginatedRawAccountsDto { /** * - * @type {Array} - * @memberof PaginatedWalletsDtoDataInner + * @type {Array} + * @memberof PaginatedRawAccountsDto */ - 'accounts'?: Array; + 'data': Array; /** * - * @type {string} - * @memberof PaginatedWalletsDtoDataInner + * @type {PaginatedAssetsDtoPage} + * @memberof PaginatedRawAccountsDto */ - 'clientId': string; + 'page'?: PaginatedAssetsDtoPage; +} +/** + * + * @export + * @interface PaginatedRawAccountsDtoDataInner + */ +export interface PaginatedRawAccountsDtoDataInner { /** * - * @type {Array} - * @memberof PaginatedWalletsDtoDataInner + * @type {string} + * @memberof PaginatedRawAccountsDtoDataInner */ - 'connections': Array; + 'provider': PaginatedRawAccountsDtoDataInnerProviderEnum; /** * - * @type {any} - * @memberof PaginatedWalletsDtoDataInner + * @type {string} + * @memberof PaginatedRawAccountsDtoDataInner */ - 'createdAt': any; + 'externalId': string; /** * * @type {string} - * @memberof PaginatedWalletsDtoDataInner + * @memberof PaginatedRawAccountsDtoDataInner */ - 'externalId': string; + 'label': string; /** * * @type {string} - * @memberof PaginatedWalletsDtoDataInner + * @memberof PaginatedRawAccountsDtoDataInner */ - 'label'?: string | null; + 'subLabel'?: string; /** - * + * The deposit address for the account, if there are multiple * @type {string} - * @memberof PaginatedWalletsDtoDataInner + * @memberof PaginatedRawAccountsDtoDataInner */ - 'provider': PaginatedWalletsDtoDataInnerProviderEnum; + 'defaultAddress'?: string; /** * - * @type {any} - * @memberof PaginatedWalletsDtoDataInner + * @type {PaginatedRawAccountsDtoDataInnerNetwork} + * @memberof PaginatedRawAccountsDtoDataInner */ - 'updatedAt': any; + 'network'?: PaginatedRawAccountsDtoDataInnerNetwork | null; /** - * - * @type {string} - * @memberof PaginatedWalletsDtoDataInner + * The assets of the account + * @type {Array} + * @memberof PaginatedRawAccountsDtoDataInner */ - 'walletId': string; + 'assets'?: Array; } -export const PaginatedWalletsDtoDataInnerProviderEnum = { +export const PaginatedRawAccountsDtoDataInnerProviderEnum = { Anchorage: 'anchorage', - Fireblocks: 'fireblocks' + Fireblocks: 'fireblocks', + Bitgo: 'bitgo' } as const; -export type PaginatedWalletsDtoDataInnerProviderEnum = typeof PaginatedWalletsDtoDataInnerProviderEnum[keyof typeof PaginatedWalletsDtoDataInnerProviderEnum]; +export type PaginatedRawAccountsDtoDataInnerProviderEnum = typeof PaginatedRawAccountsDtoDataInnerProviderEnum[keyof typeof PaginatedRawAccountsDtoDataInnerProviderEnum]; /** * * @export - * @interface PaginatedWalletsDtoDataInnerAccountsInner + * @interface PaginatedRawAccountsDtoDataInnerAssetsInner */ -export interface PaginatedWalletsDtoDataInnerAccountsInner { - /** - * - * @type {string} - * @memberof PaginatedWalletsDtoDataInnerAccountsInner - */ - 'accountId': string; +export interface PaginatedRawAccountsDtoDataInnerAssetsInner { /** * - * @type {Array} - * @memberof PaginatedWalletsDtoDataInnerAccountsInner + * @type {PaginatedAssetsDtoDataInner} + * @memberof PaginatedRawAccountsDtoDataInnerAssetsInner */ - 'addresses'?: Array; + 'asset': PaginatedAssetsDtoDataInner; /** - * + * The balance of the this asset in this account * @type {string} - * @memberof PaginatedWalletsDtoDataInnerAccountsInner + * @memberof PaginatedRawAccountsDtoDataInnerAssetsInner */ - 'clientId': string; + 'balance'?: string; +} +/** + * The network of the account + * @export + * @interface PaginatedRawAccountsDtoDataInnerNetwork + */ +export interface PaginatedRawAccountsDtoDataInnerNetwork { /** * - * @type {any} - * @memberof PaginatedWalletsDtoDataInnerAccountsInner + * @type {string} + * @memberof PaginatedRawAccountsDtoDataInnerNetwork */ - 'createdAt': any; + 'networkId': string; /** * - * @type {string} - * @memberof PaginatedWalletsDtoDataInnerAccountsInner + * @type {number} + * @memberof PaginatedRawAccountsDtoDataInnerNetwork */ - 'externalId': string; + 'coinType': number | null; /** * * @type {string} - * @memberof PaginatedWalletsDtoDataInnerAccountsInner + * @memberof PaginatedRawAccountsDtoDataInnerNetwork */ - 'label'?: string | null; + 'name': string; /** * - * @type {string} - * @memberof PaginatedWalletsDtoDataInnerAccountsInner + * @type {Array} + * @memberof PaginatedRawAccountsDtoDataInnerNetwork */ - 'networkId': string; + 'externalNetworks'?: Array; /** * - * @type {string} - * @memberof PaginatedWalletsDtoDataInnerAccountsInner + * @type {any} + * @memberof PaginatedRawAccountsDtoDataInnerNetwork */ - 'provider': PaginatedWalletsDtoDataInnerAccountsInnerProviderEnum; + 'createdAt'?: any; +} +/** + * + * @export + * @interface PaginatedScopedSyncsDto + */ +export interface PaginatedScopedSyncsDto { /** * - * @type {any} - * @memberof PaginatedWalletsDtoDataInnerAccountsInner + * @type {Array} + * @memberof PaginatedScopedSyncsDto */ - 'updatedAt': any; + 'data': Array; /** * - * @type {string} - * @memberof PaginatedWalletsDtoDataInnerAccountsInner + * @type {PaginatedAssetsDtoPage} + * @memberof PaginatedScopedSyncsDto */ - 'walletId': string; + 'page'?: PaginatedAssetsDtoPage; } - -export const PaginatedWalletsDtoDataInnerAccountsInnerProviderEnum = { - Anchorage: 'anchorage', - Fireblocks: 'fireblocks' -} as const; - -export type PaginatedWalletsDtoDataInnerAccountsInnerProviderEnum = typeof PaginatedWalletsDtoDataInnerAccountsInnerProviderEnum[keyof typeof PaginatedWalletsDtoDataInnerAccountsInnerProviderEnum]; - /** * * @export - * @interface PaginatedWalletsDtoDataInnerAccountsInnerAddressesInner + * @interface PaginatedSyncsDto */ -export interface PaginatedWalletsDtoDataInnerAccountsInnerAddressesInner { +export interface PaginatedSyncsDto { /** * - * @type {string} - * @memberof PaginatedWalletsDtoDataInnerAccountsInnerAddressesInner + * @type {Array} + * @memberof PaginatedSyncsDto */ - 'accountId': string; + 'data': Array; /** * - * @type {string} - * @memberof PaginatedWalletsDtoDataInnerAccountsInnerAddressesInner + * @type {PaginatedAssetsDtoPage} + * @memberof PaginatedSyncsDto */ - 'address': string; + 'page'?: PaginatedAssetsDtoPage; +} +/** + * + * @export + * @interface PaginatedSyncsDtoDataInner + */ +export interface PaginatedSyncsDtoDataInner { /** * * @type {string} - * @memberof PaginatedWalletsDtoDataInnerAccountsInnerAddressesInner + * @memberof PaginatedSyncsDtoDataInner */ - 'addressId': string; + 'clientId': string; + /** + * + * @type {any} + * @memberof PaginatedSyncsDtoDataInner + */ + 'completedAt'?: any; /** * * @type {string} - * @memberof PaginatedWalletsDtoDataInnerAccountsInnerAddressesInner + * @memberof PaginatedSyncsDtoDataInner */ - 'clientId': string; + 'connectionId': string; /** * * @type {any} - * @memberof PaginatedWalletsDtoDataInnerAccountsInnerAddressesInner + * @memberof PaginatedSyncsDtoDataInner + */ + 'createdAt': any; + /** + * + * @type {PaginatedSyncsDtoDataInnerError} + * @memberof PaginatedSyncsDtoDataInner + */ + 'error'?: PaginatedSyncsDtoDataInnerError; + /** + * + * @type {string} + * @memberof PaginatedSyncsDtoDataInner + */ + 'status'?: PaginatedSyncsDtoDataInnerStatusEnum; + /** + * + * @type {string} + * @memberof PaginatedSyncsDtoDataInner + */ + 'syncId': string; +} + +export const PaginatedSyncsDtoDataInnerStatusEnum = { + Processing: 'processing', + Success: 'success', + Failed: 'failed' +} as const; + +export type PaginatedSyncsDtoDataInnerStatusEnum = typeof PaginatedSyncsDtoDataInnerStatusEnum[keyof typeof PaginatedSyncsDtoDataInnerStatusEnum]; + +/** + * + * @export + * @interface PaginatedSyncsDtoDataInnerError + */ +export interface PaginatedSyncsDtoDataInnerError { + /** + * + * @type {string} + * @memberof PaginatedSyncsDtoDataInnerError + */ + 'name'?: string; + /** + * + * @type {string} + * @memberof PaginatedSyncsDtoDataInnerError + */ + 'message'?: string; + /** + * + * @type {string} + * @memberof PaginatedSyncsDtoDataInnerError + */ + 'traceId'?: string; +} +/** + * + * @export + * @interface PaginatedWalletsDto + */ +export interface PaginatedWalletsDto { + /** + * + * @type {Array} + * @memberof PaginatedWalletsDto + */ + 'data': Array; + /** + * + * @type {PaginatedAssetsDtoPage} + * @memberof PaginatedWalletsDto + */ + 'page'?: PaginatedAssetsDtoPage; +} +/** + * + * @export + * @interface PaginatedWalletsDtoDataInner + */ +export interface PaginatedWalletsDtoDataInner { + /** + * + * @type {Array} + * @memberof PaginatedWalletsDtoDataInner + */ + 'accounts': Array; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoDataInner + */ + 'clientId': string; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoDataInner + */ + 'connectionId': string; + /** + * + * @type {any} + * @memberof PaginatedWalletsDtoDataInner + */ + 'createdAt': any; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoDataInner + */ + 'externalId': string; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoDataInner + */ + 'label'?: string | null; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoDataInner + */ + 'provider': PaginatedWalletsDtoDataInnerProviderEnum; + /** + * + * @type {any} + * @memberof PaginatedWalletsDtoDataInner + */ + 'updatedAt': any; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoDataInner + */ + 'walletId': string; +} + +export const PaginatedWalletsDtoDataInnerProviderEnum = { + Anchorage: 'anchorage', + Fireblocks: 'fireblocks', + Bitgo: 'bitgo' +} as const; + +export type PaginatedWalletsDtoDataInnerProviderEnum = typeof PaginatedWalletsDtoDataInnerProviderEnum[keyof typeof PaginatedWalletsDtoDataInnerProviderEnum]; + +/** + * + * @export + * @interface PaginatedWalletsDtoDataInnerAccountsInner + */ +export interface PaginatedWalletsDtoDataInnerAccountsInner { + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoDataInnerAccountsInner + */ + 'accountId': string; + /** + * + * @type {Array} + * @memberof PaginatedWalletsDtoDataInnerAccountsInner + */ + 'addresses': Array; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoDataInnerAccountsInner + */ + 'clientId': string; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoDataInnerAccountsInner + */ + 'connectionId': string; + /** + * + * @type {any} + * @memberof PaginatedWalletsDtoDataInnerAccountsInner + */ + 'createdAt': any; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoDataInnerAccountsInner + */ + 'externalId': string; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoDataInnerAccountsInner + */ + 'label'?: string | null; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoDataInnerAccountsInner + */ + 'networkId': string; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoDataInnerAccountsInner + */ + 'provider': PaginatedWalletsDtoDataInnerAccountsInnerProviderEnum; + /** + * + * @type {any} + * @memberof PaginatedWalletsDtoDataInnerAccountsInner + */ + 'updatedAt': any; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoDataInnerAccountsInner + */ + 'walletId': string; +} + +export const PaginatedWalletsDtoDataInnerAccountsInnerProviderEnum = { + Anchorage: 'anchorage', + Fireblocks: 'fireblocks', + Bitgo: 'bitgo' +} as const; + +export type PaginatedWalletsDtoDataInnerAccountsInnerProviderEnum = typeof PaginatedWalletsDtoDataInnerAccountsInnerProviderEnum[keyof typeof PaginatedWalletsDtoDataInnerAccountsInnerProviderEnum]; + +/** + * + * @export + * @interface PaginatedWalletsDtoDataInnerAccountsInnerAddressesInner + */ +export interface PaginatedWalletsDtoDataInnerAccountsInnerAddressesInner { + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoDataInnerAccountsInnerAddressesInner + */ + 'accountId': string; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoDataInnerAccountsInnerAddressesInner + */ + 'address': string; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoDataInnerAccountsInnerAddressesInner + */ + 'addressId': string; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoDataInnerAccountsInnerAddressesInner + */ + 'clientId': string; + /** + * + * @type {string} + * @memberof PaginatedWalletsDtoDataInnerAccountsInnerAddressesInner + */ + 'connectionId': string; + /** + * + * @type {any} + * @memberof PaginatedWalletsDtoDataInnerAccountsInnerAddressesInner */ 'createdAt': any; /** @@ -1696,7 +2075,8 @@ export interface PaginatedWalletsDtoDataInnerAccountsInnerAddressesInner { export const PaginatedWalletsDtoDataInnerAccountsInnerAddressesInnerProviderEnum = { Anchorage: 'anchorage', - Fireblocks: 'fireblocks' + Fireblocks: 'fireblocks', + Bitgo: 'bitgo' } as const; export type PaginatedWalletsDtoDataInnerAccountsInnerAddressesInnerProviderEnum = typeof PaginatedWalletsDtoDataInnerAccountsInnerAddressesInnerProviderEnum[keyof typeof PaginatedWalletsDtoDataInnerAccountsInnerAddressesInnerProviderEnum]; @@ -1810,7 +2190,8 @@ export interface ProviderConnectionDtoDataOneOf { export const ProviderConnectionDtoDataOneOfProviderEnum = { Anchorage: 'anchorage', - Fireblocks: 'fireblocks' + Fireblocks: 'fireblocks', + Bitgo: 'bitgo' } as const; export type ProviderConnectionDtoDataOneOfProviderEnum = typeof ProviderConnectionDtoDataOneOfProviderEnum[keyof typeof ProviderConnectionDtoDataOneOfProviderEnum]; @@ -1884,7 +2265,8 @@ export interface ProviderConnectionDtoDataOneOf1 { export const ProviderConnectionDtoDataOneOf1ProviderEnum = { Anchorage: 'anchorage', - Fireblocks: 'fireblocks' + Fireblocks: 'fireblocks', + Bitgo: 'bitgo' } as const; export type ProviderConnectionDtoDataOneOf1ProviderEnum = typeof ProviderConnectionDtoDataOneOf1ProviderEnum[keyof typeof ProviderConnectionDtoDataOneOf1ProviderEnum]; @@ -1964,7 +2346,8 @@ export interface ProviderConnectionDtoDataOneOf2 { export const ProviderConnectionDtoDataOneOf2ProviderEnum = { Anchorage: 'anchorage', - Fireblocks: 'fireblocks' + Fireblocks: 'fireblocks', + Bitgo: 'bitgo' } as const; export type ProviderConnectionDtoDataOneOf2ProviderEnum = typeof ProviderConnectionDtoDataOneOf2ProviderEnum[keyof typeof ProviderConnectionDtoDataOneOf2ProviderEnum]; @@ -2039,7 +2422,8 @@ export interface ProviderPendingConnectionDtoData { export const ProviderPendingConnectionDtoDataProviderEnum = { Anchorage: 'anchorage', - Fireblocks: 'fireblocks' + Fireblocks: 'fireblocks', + Bitgo: 'bitgo' } as const; export type ProviderPendingConnectionDtoDataProviderEnum = typeof ProviderPendingConnectionDtoDataProviderEnum[keyof typeof ProviderPendingConnectionDtoDataProviderEnum]; @@ -2073,6 +2457,12 @@ export interface ProviderPendingConnectionDtoDataPublicKey { * @memberof ProviderPendingConnectionDtoDataPublicKey */ 'hex'?: any; + /** + * Certificate Signing Request PEM format of RSA public key encoded as base64 + * @type {string} + * @memberof ProviderPendingConnectionDtoDataPublicKey + */ + 'csr'?: string; } /** * @@ -2090,17 +2480,126 @@ export interface ProviderWalletDto { /** * * @export - * @interface SendTransferDto + * @interface ScopedSyncDto */ -export interface SendTransferDto { +export interface ScopedSyncDto { /** * - * @type {SendTransferDtoSource} - * @memberof SendTransferDto + * @type {ScopedSyncStartedDtoDataScopedSyncsInner} + * @memberof ScopedSyncDto */ - 'source': SendTransferDtoSource; - /** - * + 'data': ScopedSyncStartedDtoDataScopedSyncsInner; +} +/** + * + * @export + * @interface ScopedSyncStartedDto + */ +export interface ScopedSyncStartedDto { + /** + * + * @type {ScopedSyncStartedDtoData} + * @memberof ScopedSyncStartedDto + */ + 'data': ScopedSyncStartedDtoData; +} +/** + * + * @export + * @interface ScopedSyncStartedDtoData + */ +export interface ScopedSyncStartedDtoData { + /** + * + * @type {boolean} + * @memberof ScopedSyncStartedDtoData + */ + 'started': boolean; + /** + * + * @type {Array} + * @memberof ScopedSyncStartedDtoData + */ + 'scopedSyncs': Array; +} +/** + * + * @export + * @interface ScopedSyncStartedDtoDataScopedSyncsInner + */ +export interface ScopedSyncStartedDtoDataScopedSyncsInner { + /** + * + * @type {string} + * @memberof ScopedSyncStartedDtoDataScopedSyncsInner + */ + 'clientId': string; + /** + * + * @type {any} + * @memberof ScopedSyncStartedDtoDataScopedSyncsInner + */ + 'completedAt'?: any; + /** + * + * @type {string} + * @memberof ScopedSyncStartedDtoDataScopedSyncsInner + */ + 'connectionId': string; + /** + * + * @type {any} + * @memberof ScopedSyncStartedDtoDataScopedSyncsInner + */ + 'createdAt': any; + /** + * + * @type {PaginatedSyncsDtoDataInnerError} + * @memberof ScopedSyncStartedDtoDataScopedSyncsInner + */ + 'error'?: PaginatedSyncsDtoDataInnerError; + /** + * + * @type {string} + * @memberof ScopedSyncStartedDtoDataScopedSyncsInner + */ + 'status'?: ScopedSyncStartedDtoDataScopedSyncsInnerStatusEnum; + /** + * + * @type {string} + * @memberof ScopedSyncStartedDtoDataScopedSyncsInner + */ + 'scopedSyncId': string; + /** + * + * @type {Array} + * @memberof ScopedSyncStartedDtoDataScopedSyncsInner + */ + 'rawAccounts': Array; +} + +export const ScopedSyncStartedDtoDataScopedSyncsInnerStatusEnum = { + Processing: 'processing', + Success: 'success', + Failed: 'failed' +} as const; + +export type ScopedSyncStartedDtoDataScopedSyncsInnerStatusEnum = typeof ScopedSyncStartedDtoDataScopedSyncsInnerStatusEnum[keyof typeof ScopedSyncStartedDtoDataScopedSyncsInnerStatusEnum]; + +/** + * + * @export + * @interface SendTransferDto + */ +export interface SendTransferDto { + /** + * + * @type {SendTransferDtoSource} + * @memberof SendTransferDto + */ + 'source': SendTransferDtoSource; + /** + * * @type {SendTransferDtoDestination} * @memberof SendTransferDto */ @@ -2124,7 +2623,7 @@ export interface SendTransferDto { */ 'asset': SendTransferDtoAsset; /** - * + * Controls how network fees are charged. Example: a request to transfer 1 ETH with networkFeeAttribution=ON_TOP would result in exactly 1 ETH received to the destination and just over 1 ETH spent by the source. Note: This property is optional and its default always depend on the underlying provider. * @type {string} * @memberof SendTransferDto */ @@ -2169,7 +2668,8 @@ export const SendTransferDtoNetworkFeeAttributionEnum = { export type SendTransferDtoNetworkFeeAttributionEnum = typeof SendTransferDtoNetworkFeeAttributionEnum[keyof typeof SendTransferDtoNetworkFeeAttributionEnum]; export const SendTransferDtoProviderEnum = { Anchorage: 'anchorage', - Fireblocks: 'fireblocks' + Fireblocks: 'fireblocks', + Bitgo: 'bitgo' } as const; export type SendTransferDtoProviderEnum = typeof SendTransferDtoProviderEnum[keyof typeof SendTransferDtoProviderEnum]; @@ -2847,144 +3347,50 @@ export interface SignatureDto { /** * * @export - * @interface StartSyncDto + * @interface StartScopedSyncDto */ -export interface StartSyncDto { +export interface StartScopedSyncDto { /** - * The connection to sync. If undefined, start the sync on all active connections + * The connection to sync. * @type {string} - * @memberof StartSyncDto - */ - 'connectionId'?: string; -} -/** - * - * @export - * @interface SyncDto - */ -export interface SyncDto { - /** - * - * @type {SyncStartedDtoDataSyncsInner} - * @memberof SyncDto - */ - 'data': SyncStartedDtoDataSyncsInner; -} -/** - * - * @export - * @interface SyncStartedDto - */ -export interface SyncStartedDto { - /** - * - * @type {SyncStartedDtoData} - * @memberof SyncStartedDto - */ - 'data': SyncStartedDtoData; -} -/** - * - * @export - * @interface SyncStartedDtoData - */ -export interface SyncStartedDtoData { - /** - * - * @type {boolean} - * @memberof SyncStartedDtoData + * @memberof StartScopedSyncDto */ - 'started': boolean; + 'connectionId': string; /** - * - * @type {Array} - * @memberof SyncStartedDtoData + * The accounts to sync. + * @type {Array} + * @memberof StartScopedSyncDto */ - 'syncs': Array; + 'rawAccounts': Array; } /** * * @export - * @interface SyncStartedDtoDataSyncsInner + * @interface StartScopedSyncDtoRawAccountsInner */ -export interface SyncStartedDtoDataSyncsInner { - /** - * - * @type {string} - * @memberof SyncStartedDtoDataSyncsInner - */ - 'clientId': string; - /** - * - * @type {any} - * @memberof SyncStartedDtoDataSyncsInner - */ - 'completedAt'?: any; - /** - * - * @type {string} - * @memberof SyncStartedDtoDataSyncsInner - */ - 'connectionId': string; - /** - * - * @type {any} - * @memberof SyncStartedDtoDataSyncsInner - */ - 'createdAt': any; - /** - * - * @type {SyncStartedDtoDataSyncsInnerError} - * @memberof SyncStartedDtoDataSyncsInner - */ - 'error'?: SyncStartedDtoDataSyncsInnerError; +export interface StartScopedSyncDtoRawAccountsInner { /** * * @type {string} - * @memberof SyncStartedDtoDataSyncsInner + * @memberof StartScopedSyncDtoRawAccountsInner */ - 'status'?: SyncStartedDtoDataSyncsInnerStatusEnum; + 'provider': StartScopedSyncDtoRawAccountsInnerProviderEnum; /** * * @type {string} - * @memberof SyncStartedDtoDataSyncsInner + * @memberof StartScopedSyncDtoRawAccountsInner */ - 'syncId': string; + 'externalId': string; } -export const SyncStartedDtoDataSyncsInnerStatusEnum = { - Processing: 'processing', - Success: 'success', - Failed: 'failed' +export const StartScopedSyncDtoRawAccountsInnerProviderEnum = { + Anchorage: 'anchorage', + Fireblocks: 'fireblocks', + Bitgo: 'bitgo' } as const; -export type SyncStartedDtoDataSyncsInnerStatusEnum = typeof SyncStartedDtoDataSyncsInnerStatusEnum[keyof typeof SyncStartedDtoDataSyncsInnerStatusEnum]; +export type StartScopedSyncDtoRawAccountsInnerProviderEnum = typeof StartScopedSyncDtoRawAccountsInnerProviderEnum[keyof typeof StartScopedSyncDtoRawAccountsInnerProviderEnum]; -/** - * - * @export - * @interface SyncStartedDtoDataSyncsInnerError - */ -export interface SyncStartedDtoDataSyncsInnerError { - /** - * - * @type {string} - * @memberof SyncStartedDtoDataSyncsInnerError - */ - 'name'?: string; - /** - * - * @type {string} - * @memberof SyncStartedDtoDataSyncsInnerError - */ - 'message'?: string; - /** - * - * @type {string} - * @memberof SyncStartedDtoDataSyncsInnerError - */ - 'traceId'?: string; -} /** * * @export @@ -3040,6 +3446,12 @@ export interface TransferDtoData { * @memberof TransferDtoData */ 'externalId': string; + /** + * + * @type {string} + * @memberof TransferDtoData + */ + 'externalStatus': string | null; /** * * @type {string} @@ -3052,6 +3464,12 @@ export interface TransferDtoData { * @memberof TransferDtoData */ 'idempotenceId': string | null; + /** + * + * @type {string} + * @memberof TransferDtoData + */ + 'connectionId': string; /** * * @type {string} @@ -3104,7 +3522,8 @@ export const TransferDtoDataNetworkFeeAttributionEnum = { export type TransferDtoDataNetworkFeeAttributionEnum = typeof TransferDtoDataNetworkFeeAttributionEnum[keyof typeof TransferDtoDataNetworkFeeAttributionEnum]; export const TransferDtoDataProviderEnum = { Anchorage: 'anchorage', - Fireblocks: 'fireblocks' + Fireblocks: 'fireblocks', + Bitgo: 'bitgo' } as const; export type TransferDtoDataProviderEnum = typeof TransferDtoDataProviderEnum[keyof typeof TransferDtoDataProviderEnum]; @@ -4065,11 +4484,12 @@ export const ProviderAccountApiAxiosParamCreator = function (configuration?: Con * @summary Get a specific account by ID * @param {string} xClientId * @param {string} accountId The ID of the account to retrieve + * @param {string} [xConnectionId] The provider connection through which the resource is accessed * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getById: async (xClientId: string, accountId: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + getById: async (xClientId: string, accountId: string, xConnectionId?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'xClientId' is not null or undefined assertParamExists('getById', 'xClientId', xClientId) // verify required parameter 'accountId' is not null or undefined @@ -4096,6 +4516,10 @@ export const ProviderAccountApiAxiosParamCreator = function (configuration?: Con localVarHeaderParameter['x-client-id'] = String(xClientId); } + if (xConnectionId != null) { + localVarHeaderParameter['x-connection-id'] = String(xConnectionId); + } + if (authorization != null) { localVarHeaderParameter['Authorization'] = String(authorization); } @@ -4119,11 +4543,12 @@ export const ProviderAccountApiAxiosParamCreator = function (configuration?: Con * @param {number} [limit] Number of records to return per page * @param {string} [orderBy] Field to order results by * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [xConnectionId] The provider connection through which the resource is accessed * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - list: async (xClientId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + list: async (xClientId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, xConnectionId?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'xClientId' is not null or undefined assertParamExists('list', 'xClientId', xClientId) const localVarPath = `/v1/provider/accounts`; @@ -4163,6 +4588,10 @@ export const ProviderAccountApiAxiosParamCreator = function (configuration?: Con localVarHeaderParameter['x-client-id'] = String(xClientId); } + if (xConnectionId != null) { + localVarHeaderParameter['x-connection-id'] = String(xConnectionId); + } + if (authorization != null) { localVarHeaderParameter['Authorization'] = String(authorization); } @@ -4187,11 +4616,12 @@ export const ProviderAccountApiAxiosParamCreator = function (configuration?: Con * @param {number} [limit] Number of records to return per page * @param {string} [orderBy] Field to order results by * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [xConnectionId] The provider connection through which the resource is accessed * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - listAddresses: async (xClientId: string, accountId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + listAddresses: async (xClientId: string, accountId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, xConnectionId?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'xClientId' is not null or undefined assertParamExists('listAddresses', 'xClientId', xClientId) // verify required parameter 'accountId' is not null or undefined @@ -4234,6 +4664,10 @@ export const ProviderAccountApiAxiosParamCreator = function (configuration?: Con localVarHeaderParameter['x-client-id'] = String(xClientId); } + if (xConnectionId != null) { + localVarHeaderParameter['x-connection-id'] = String(xConnectionId); + } + if (authorization != null) { localVarHeaderParameter['Authorization'] = String(authorization); } @@ -4249,88 +4683,212 @@ export const ProviderAccountApiAxiosParamCreator = function (configuration?: Con options: localVarRequestOptions, }; }, - } -}; - -/** - * ProviderAccountApi - functional programming interface - * @export - */ -export const ProviderAccountApiFp = function(configuration?: Configuration) { - const localVarAxiosParamCreator = ProviderAccountApiAxiosParamCreator(configuration) - return { - /** - * - * @summary Get a specific account by ID - * @param {string} xClientId - * @param {string} accountId The ID of the account to retrieve - * @param {string} [authorization] - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async getById(xClientId: string, accountId: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.getById(xClientId, accountId, authorization, options); - const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = operationServerMap['ProviderAccountApi.getById']?.[localVarOperationServerIndex]?.url; - return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); - }, - /** - * - * @summary List the client accounts - * @param {string} xClientId - * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page - * @param {number} [limit] Number of records to return per page - * @param {string} [orderBy] Field to order results by - * @param {string} [desc] Set to \"true\" or \"1\" for descending order - * @param {string} [authorization] - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async list(xClientId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.list(xClientId, cursor, limit, orderBy, desc, authorization, options); - const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = operationServerMap['ProviderAccountApi.list']?.[localVarOperationServerIndex]?.url; - return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); - }, /** * - * @summary List addresses for a specific account + * @summary List the provider accounts in raw form, used to populate which accounts to connect * @param {string} xClientId - * @param {string} accountId The ID of the account to retrieve addresses for + * @param {string} [namePrefix] Filter accounts by name prefix + * @param {string} [nameSuffix] Filter accounts by name suffix + * @param {string} [networkId] Filter accounts by network ID + * @param {string} [assetId] Filter accounts by asset ID + * @param {boolean} [includeAddress] Include address information in the response * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page * @param {number} [limit] Number of records to return per page * @param {string} [orderBy] Field to order results by * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [xConnectionId] The provider connection through which the resource is accessed * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async listAddresses(xClientId: string, accountId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.listAddresses(xClientId, accountId, cursor, limit, orderBy, desc, authorization, options); - const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = operationServerMap['ProviderAccountApi.listAddresses']?.[localVarOperationServerIndex]?.url; - return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); - }, - } -}; + listRaw: async (xClientId: string, namePrefix?: string, nameSuffix?: string, networkId?: string, assetId?: string, includeAddress?: boolean, cursor?: string, limit?: number, orderBy?: string, desc?: string, xConnectionId?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('listRaw', 'xClientId', xClientId) + const localVarPath = `/v1/provider/accounts/raw`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } -/** - * ProviderAccountApi - factory interface - * @export - */ -export const ProviderAccountApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { - const localVarFp = ProviderAccountApiFp(configuration) - return { - /** - * - * @summary Get a specific account by ID - * @param {ProviderAccountApiGetByIdRequest} requestParameters Request parameters. - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - getById(requestParameters: ProviderAccountApiGetByIdRequest, options?: RawAxiosRequestConfig): AxiosPromise { - return localVarFp.getById(requestParameters.xClientId, requestParameters.accountId, requestParameters.authorization, options).then((request) => request(axios, basePath)); - }, + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + + if (namePrefix !== undefined) { + localVarQueryParameter['namePrefix'] = namePrefix; + } + + if (nameSuffix !== undefined) { + localVarQueryParameter['nameSuffix'] = nameSuffix; + } + + if (networkId !== undefined) { + localVarQueryParameter['networkId'] = networkId; + } + + if (assetId !== undefined) { + localVarQueryParameter['assetId'] = assetId; + } + + if (includeAddress !== undefined) { + localVarQueryParameter['includeAddress'] = includeAddress; + } + + if (cursor !== undefined) { + localVarQueryParameter['cursor'] = cursor; + } + + if (limit !== undefined) { + localVarQueryParameter['limit'] = limit; + } + + if (orderBy !== undefined) { + localVarQueryParameter['orderBy'] = orderBy; + } + + if (desc !== undefined) { + localVarQueryParameter['desc'] = desc; + } + + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + + if (xConnectionId != null) { + localVarHeaderParameter['x-connection-id'] = String(xConnectionId); + } + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + } +}; + +/** + * ProviderAccountApi - functional programming interface + * @export + */ +export const ProviderAccountApiFp = function(configuration?: Configuration) { + const localVarAxiosParamCreator = ProviderAccountApiAxiosParamCreator(configuration) + return { + /** + * + * @summary Get a specific account by ID + * @param {string} xClientId + * @param {string} accountId The ID of the account to retrieve + * @param {string} [xConnectionId] The provider connection through which the resource is accessed + * @param {string} [authorization] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getById(xClientId: string, accountId: string, xConnectionId?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getById(xClientId, accountId, xConnectionId, authorization, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderAccountApi.getById']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + /** + * + * @summary List the client accounts + * @param {string} xClientId + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [xConnectionId] The provider connection through which the resource is accessed + * @param {string} [authorization] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async list(xClientId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, xConnectionId?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.list(xClientId, cursor, limit, orderBy, desc, xConnectionId, authorization, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderAccountApi.list']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + /** + * + * @summary List addresses for a specific account + * @param {string} xClientId + * @param {string} accountId The ID of the account to retrieve addresses for + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [xConnectionId] The provider connection through which the resource is accessed + * @param {string} [authorization] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async listAddresses(xClientId: string, accountId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, xConnectionId?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.listAddresses(xClientId, accountId, cursor, limit, orderBy, desc, xConnectionId, authorization, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderAccountApi.listAddresses']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + /** + * + * @summary List the provider accounts in raw form, used to populate which accounts to connect + * @param {string} xClientId + * @param {string} [namePrefix] Filter accounts by name prefix + * @param {string} [nameSuffix] Filter accounts by name suffix + * @param {string} [networkId] Filter accounts by network ID + * @param {string} [assetId] Filter accounts by asset ID + * @param {boolean} [includeAddress] Include address information in the response + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [xConnectionId] The provider connection through which the resource is accessed + * @param {string} [authorization] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async listRaw(xClientId: string, namePrefix?: string, nameSuffix?: string, networkId?: string, assetId?: string, includeAddress?: boolean, cursor?: string, limit?: number, orderBy?: string, desc?: string, xConnectionId?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.listRaw(xClientId, namePrefix, nameSuffix, networkId, assetId, includeAddress, cursor, limit, orderBy, desc, xConnectionId, authorization, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderAccountApi.listRaw']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + } +}; + +/** + * ProviderAccountApi - factory interface + * @export + */ +export const ProviderAccountApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { + const localVarFp = ProviderAccountApiFp(configuration) + return { + /** + * + * @summary Get a specific account by ID + * @param {ProviderAccountApiGetByIdRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getById(requestParameters: ProviderAccountApiGetByIdRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.getById(requestParameters.xClientId, requestParameters.accountId, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(axios, basePath)); + }, /** * * @summary List the client accounts @@ -4339,7 +4897,7 @@ export const ProviderAccountApiFactory = function (configuration?: Configuration * @throws {RequiredError} */ list(requestParameters: ProviderAccountApiListRequest, options?: RawAxiosRequestConfig): AxiosPromise { - return localVarFp.list(requestParameters.xClientId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(axios, basePath)); + return localVarFp.list(requestParameters.xClientId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, /** * @@ -4349,7 +4907,17 @@ export const ProviderAccountApiFactory = function (configuration?: Configuration * @throws {RequiredError} */ listAddresses(requestParameters: ProviderAccountApiListAddressesRequest, options?: RawAxiosRequestConfig): AxiosPromise { - return localVarFp.listAddresses(requestParameters.xClientId, requestParameters.accountId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(axios, basePath)); + return localVarFp.listAddresses(requestParameters.xClientId, requestParameters.accountId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary List the provider accounts in raw form, used to populate which accounts to connect + * @param {ProviderAccountApiListRawRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + listRaw(requestParameters: ProviderAccountApiListRawRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.listRaw(requestParameters.xClientId, requestParameters.namePrefix, requestParameters.nameSuffix, requestParameters.networkId, requestParameters.assetId, requestParameters.includeAddress, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, }; }; @@ -4374,6 +4942,13 @@ export interface ProviderAccountApiGetByIdRequest { */ readonly accountId: string + /** + * The provider connection through which the resource is accessed + * @type {string} + * @memberof ProviderAccountApiGetById + */ + readonly xConnectionId?: string + /** * * @type {string} @@ -4423,6 +4998,13 @@ export interface ProviderAccountApiListRequest { */ readonly desc?: string + /** + * The provider connection through which the resource is accessed + * @type {string} + * @memberof ProviderAccountApiList + */ + readonly xConnectionId?: string + /** * * @type {string} @@ -4479,6 +5061,13 @@ export interface ProviderAccountApiListAddressesRequest { */ readonly desc?: string + /** + * The provider connection through which the resource is accessed + * @type {string} + * @memberof ProviderAccountApiListAddresses + */ + readonly xConnectionId?: string + /** * * @type {string} @@ -4487,6 +5076,97 @@ export interface ProviderAccountApiListAddressesRequest { readonly authorization?: string } +/** + * Request parameters for listRaw operation in ProviderAccountApi. + * @export + * @interface ProviderAccountApiListRawRequest + */ +export interface ProviderAccountApiListRawRequest { + /** + * + * @type {string} + * @memberof ProviderAccountApiListRaw + */ + readonly xClientId: string + + /** + * Filter accounts by name prefix + * @type {string} + * @memberof ProviderAccountApiListRaw + */ + readonly namePrefix?: string + + /** + * Filter accounts by name suffix + * @type {string} + * @memberof ProviderAccountApiListRaw + */ + readonly nameSuffix?: string + + /** + * Filter accounts by network ID + * @type {string} + * @memberof ProviderAccountApiListRaw + */ + readonly networkId?: string + + /** + * Filter accounts by asset ID + * @type {string} + * @memberof ProviderAccountApiListRaw + */ + readonly assetId?: string + + /** + * Include address information in the response + * @type {boolean} + * @memberof ProviderAccountApiListRaw + */ + readonly includeAddress?: boolean + + /** + * Cursor for pagination. Use the next cursor from previous response to get next page + * @type {string} + * @memberof ProviderAccountApiListRaw + */ + readonly cursor?: string + + /** + * Number of records to return per page + * @type {number} + * @memberof ProviderAccountApiListRaw + */ + readonly limit?: number + + /** + * Field to order results by + * @type {string} + * @memberof ProviderAccountApiListRaw + */ + readonly orderBy?: string + + /** + * Set to \"true\" or \"1\" for descending order + * @type {string} + * @memberof ProviderAccountApiListRaw + */ + readonly desc?: string + + /** + * The provider connection through which the resource is accessed + * @type {string} + * @memberof ProviderAccountApiListRaw + */ + readonly xConnectionId?: string + + /** + * + * @type {string} + * @memberof ProviderAccountApiListRaw + */ + readonly authorization?: string +} + /** * ProviderAccountApi - object-oriented interface * @export @@ -4503,7 +5183,7 @@ export class ProviderAccountApi extends BaseAPI { * @memberof ProviderAccountApi */ public getById(requestParameters: ProviderAccountApiGetByIdRequest, options?: RawAxiosRequestConfig) { - return ProviderAccountApiFp(this.configuration).getById(requestParameters.xClientId, requestParameters.accountId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + return ProviderAccountApiFp(this.configuration).getById(requestParameters.xClientId, requestParameters.accountId, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } /** @@ -4515,7 +5195,7 @@ export class ProviderAccountApi extends BaseAPI { * @memberof ProviderAccountApi */ public list(requestParameters: ProviderAccountApiListRequest, options?: RawAxiosRequestConfig) { - return ProviderAccountApiFp(this.configuration).list(requestParameters.xClientId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + return ProviderAccountApiFp(this.configuration).list(requestParameters.xClientId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } /** @@ -4527,7 +5207,19 @@ export class ProviderAccountApi extends BaseAPI { * @memberof ProviderAccountApi */ public listAddresses(requestParameters: ProviderAccountApiListAddressesRequest, options?: RawAxiosRequestConfig) { - return ProviderAccountApiFp(this.configuration).listAddresses(requestParameters.xClientId, requestParameters.accountId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + return ProviderAccountApiFp(this.configuration).listAddresses(requestParameters.xClientId, requestParameters.accountId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * + * @summary List the provider accounts in raw form, used to populate which accounts to connect + * @param {ProviderAccountApiListRawRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderAccountApi + */ + public listRaw(requestParameters: ProviderAccountApiListRawRequest, options?: RawAxiosRequestConfig) { + return ProviderAccountApiFp(this.configuration).listRaw(requestParameters.xClientId, requestParameters.namePrefix, requestParameters.nameSuffix, requestParameters.networkId, requestParameters.assetId, requestParameters.includeAddress, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } } @@ -4544,11 +5236,12 @@ export const ProviderAddressApiAxiosParamCreator = function (configuration?: Con * @summary Get a specific address by ID * @param {string} xClientId * @param {string} addressId The ID of the address to retrieve + * @param {string} [xConnectionId] The provider connection through which the resource is accessed * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getById: async (xClientId: string, addressId: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + getById: async (xClientId: string, addressId: string, xConnectionId?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'xClientId' is not null or undefined assertParamExists('getById', 'xClientId', xClientId) // verify required parameter 'addressId' is not null or undefined @@ -4575,6 +5268,10 @@ export const ProviderAddressApiAxiosParamCreator = function (configuration?: Con localVarHeaderParameter['x-client-id'] = String(xClientId); } + if (xConnectionId != null) { + localVarHeaderParameter['x-connection-id'] = String(xConnectionId); + } + if (authorization != null) { localVarHeaderParameter['Authorization'] = String(authorization); } @@ -4598,11 +5295,12 @@ export const ProviderAddressApiAxiosParamCreator = function (configuration?: Con * @param {number} [limit] Number of records to return per page * @param {string} [orderBy] Field to order results by * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [xConnectionId] The provider connection through which the resource is accessed * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - list: async (xClientId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + list: async (xClientId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, xConnectionId?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'xClientId' is not null or undefined assertParamExists('list', 'xClientId', xClientId) const localVarPath = `/v1/provider/addresses`; @@ -4642,6 +5340,10 @@ export const ProviderAddressApiAxiosParamCreator = function (configuration?: Con localVarHeaderParameter['x-client-id'] = String(xClientId); } + if (xConnectionId != null) { + localVarHeaderParameter['x-connection-id'] = String(xConnectionId); + } + if (authorization != null) { localVarHeaderParameter['Authorization'] = String(authorization); } @@ -4672,12 +5374,13 @@ export const ProviderAddressApiFp = function(configuration?: Configuration) { * @summary Get a specific address by ID * @param {string} xClientId * @param {string} addressId The ID of the address to retrieve + * @param {string} [xConnectionId] The provider connection through which the resource is accessed * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async getById(xClientId: string, addressId: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.getById(xClientId, addressId, authorization, options); + async getById(xClientId: string, addressId: string, xConnectionId?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getById(xClientId, addressId, xConnectionId, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['ProviderAddressApi.getById']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); @@ -4690,12 +5393,13 @@ export const ProviderAddressApiFp = function(configuration?: Configuration) { * @param {number} [limit] Number of records to return per page * @param {string} [orderBy] Field to order results by * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [xConnectionId] The provider connection through which the resource is accessed * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async list(xClientId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.list(xClientId, cursor, limit, orderBy, desc, authorization, options); + async list(xClientId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, xConnectionId?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.list(xClientId, cursor, limit, orderBy, desc, xConnectionId, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['ProviderAddressApi.list']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); @@ -4718,7 +5422,7 @@ export const ProviderAddressApiFactory = function (configuration?: Configuration * @throws {RequiredError} */ getById(requestParameters: ProviderAddressApiGetByIdRequest, options?: RawAxiosRequestConfig): AxiosPromise { - return localVarFp.getById(requestParameters.xClientId, requestParameters.addressId, requestParameters.authorization, options).then((request) => request(axios, basePath)); + return localVarFp.getById(requestParameters.xClientId, requestParameters.addressId, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, /** * @@ -4728,7 +5432,7 @@ export const ProviderAddressApiFactory = function (configuration?: Configuration * @throws {RequiredError} */ list(requestParameters: ProviderAddressApiListRequest, options?: RawAxiosRequestConfig): AxiosPromise { - return localVarFp.list(requestParameters.xClientId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(axios, basePath)); + return localVarFp.list(requestParameters.xClientId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, }; }; @@ -4754,14 +5458,21 @@ export interface ProviderAddressApiGetByIdRequest { readonly addressId: string /** - * + * The provider connection through which the resource is accessed * @type {string} * @memberof ProviderAddressApiGetById */ - readonly authorization?: string -} + readonly xConnectionId?: string -/** + /** + * + * @type {string} + * @memberof ProviderAddressApiGetById + */ + readonly authorization?: string +} + +/** * Request parameters for list operation in ProviderAddressApi. * @export * @interface ProviderAddressApiListRequest @@ -4802,6 +5513,13 @@ export interface ProviderAddressApiListRequest { */ readonly desc?: string + /** + * The provider connection through which the resource is accessed + * @type {string} + * @memberof ProviderAddressApiList + */ + readonly xConnectionId?: string + /** * * @type {string} @@ -4826,7 +5544,7 @@ export class ProviderAddressApi extends BaseAPI { * @memberof ProviderAddressApi */ public getById(requestParameters: ProviderAddressApiGetByIdRequest, options?: RawAxiosRequestConfig) { - return ProviderAddressApiFp(this.configuration).getById(requestParameters.xClientId, requestParameters.addressId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + return ProviderAddressApiFp(this.configuration).getById(requestParameters.xClientId, requestParameters.addressId, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } /** @@ -4838,7 +5556,202 @@ export class ProviderAddressApi extends BaseAPI { * @memberof ProviderAddressApi */ public list(requestParameters: ProviderAddressApiListRequest, options?: RawAxiosRequestConfig) { - return ProviderAddressApiFp(this.configuration).list(requestParameters.xClientId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + return ProviderAddressApiFp(this.configuration).list(requestParameters.xClientId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + } +} + + + +/** + * ProviderAssetApi - axios parameter creator + * @export + */ +export const ProviderAssetApiAxiosParamCreator = function (configuration?: Configuration) { + return { + /** + * This endpoint retrieves a list of all available assets. + * @summary Retrieve all assets + * @param {string} xClientId + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [authorization] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + list: async (xClientId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('list', 'xClientId', xClientId) + const localVarPath = `/v1/provider/assets`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + + if (cursor !== undefined) { + localVarQueryParameter['cursor'] = cursor; + } + + if (limit !== undefined) { + localVarQueryParameter['limit'] = limit; + } + + if (orderBy !== undefined) { + localVarQueryParameter['orderBy'] = orderBy; + } + + if (desc !== undefined) { + localVarQueryParameter['desc'] = desc; + } + + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + } +}; + +/** + * ProviderAssetApi - functional programming interface + * @export + */ +export const ProviderAssetApiFp = function(configuration?: Configuration) { + const localVarAxiosParamCreator = ProviderAssetApiAxiosParamCreator(configuration) + return { + /** + * This endpoint retrieves a list of all available assets. + * @summary Retrieve all assets + * @param {string} xClientId + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [authorization] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async list(xClientId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.list(xClientId, cursor, limit, orderBy, desc, authorization, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderAssetApi.list']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + } +}; + +/** + * ProviderAssetApi - factory interface + * @export + */ +export const ProviderAssetApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { + const localVarFp = ProviderAssetApiFp(configuration) + return { + /** + * This endpoint retrieves a list of all available assets. + * @summary Retrieve all assets + * @param {ProviderAssetApiListRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + list(requestParameters: ProviderAssetApiListRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.list(requestParameters.xClientId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(axios, basePath)); + }, + }; +}; + +/** + * Request parameters for list operation in ProviderAssetApi. + * @export + * @interface ProviderAssetApiListRequest + */ +export interface ProviderAssetApiListRequest { + /** + * + * @type {string} + * @memberof ProviderAssetApiList + */ + readonly xClientId: string + + /** + * Cursor for pagination. Use the next cursor from previous response to get next page + * @type {string} + * @memberof ProviderAssetApiList + */ + readonly cursor?: string + + /** + * Number of records to return per page + * @type {number} + * @memberof ProviderAssetApiList + */ + readonly limit?: number + + /** + * Field to order results by + * @type {string} + * @memberof ProviderAssetApiList + */ + readonly orderBy?: string + + /** + * Set to \"true\" or \"1\" for descending order + * @type {string} + * @memberof ProviderAssetApiList + */ + readonly desc?: string + + /** + * + * @type {string} + * @memberof ProviderAssetApiList + */ + readonly authorization?: string +} + +/** + * ProviderAssetApi - object-oriented interface + * @export + * @class ProviderAssetApi + * @extends {BaseAPI} + */ +export class ProviderAssetApi extends BaseAPI { + /** + * This endpoint retrieves a list of all available assets. + * @summary Retrieve all assets + * @param {ProviderAssetApiListRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderAssetApi + */ + public list(requestParameters: ProviderAssetApiListRequest, options?: RawAxiosRequestConfig) { + return ProviderAssetApiFp(this.configuration).list(requestParameters.xClientId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } } @@ -5075,8 +5988,8 @@ export const ProviderConnectionApiAxiosParamCreator = function (configuration?: }; }, /** - * This endpoint retrieves a list of accounts associated with a specific connection. - * @summary List accounts for a specific connection + * Note: use GET /v1/provider/accounts endpoint instead + * @summary (DEPRECATED) List accounts for a specific connection * @param {string} xClientId * @param {string} connectionId * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page @@ -5085,6 +5998,7 @@ export const ProviderConnectionApiAxiosParamCreator = function (configuration?: * @param {string} [desc] Set to \"true\" or \"1\" for descending order * @param {string} [authorization] * @param {*} [options] Override http request option. + * @deprecated * @throws {RequiredError} */ listAccounts: async (xClientId: string, connectionId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { @@ -5146,8 +6060,8 @@ export const ProviderConnectionApiAxiosParamCreator = function (configuration?: }; }, /** - * This endpoint retrieves a list of wallets associated with a specific connection. - * @summary List wallets for a specific connection + * Note: use GET /v1/provider/wallets endpoint instead + * @summary (DEPRECATED) List wallets for a specific connection * @param {string} xClientId * @param {string} connectionId * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page @@ -5156,6 +6070,7 @@ export const ProviderConnectionApiAxiosParamCreator = function (configuration?: * @param {string} [desc] Set to \"true\" or \"1\" for descending order * @param {string} [authorization] * @param {*} [options] Override http request option. + * @deprecated * @throws {RequiredError} */ listWallets: async (xClientId: string, connectionId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { @@ -5398,8 +6313,8 @@ export const ProviderConnectionApiFp = function(configuration?: Configuration) { return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** - * This endpoint retrieves a list of accounts associated with a specific connection. - * @summary List accounts for a specific connection + * Note: use GET /v1/provider/accounts endpoint instead + * @summary (DEPRECATED) List accounts for a specific connection * @param {string} xClientId * @param {string} connectionId * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page @@ -5408,6 +6323,7 @@ export const ProviderConnectionApiFp = function(configuration?: Configuration) { * @param {string} [desc] Set to \"true\" or \"1\" for descending order * @param {string} [authorization] * @param {*} [options] Override http request option. + * @deprecated * @throws {RequiredError} */ async listAccounts(xClientId: string, connectionId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { @@ -5417,8 +6333,8 @@ export const ProviderConnectionApiFp = function(configuration?: Configuration) { return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** - * This endpoint retrieves a list of wallets associated with a specific connection. - * @summary List wallets for a specific connection + * Note: use GET /v1/provider/wallets endpoint instead + * @summary (DEPRECATED) List wallets for a specific connection * @param {string} xClientId * @param {string} connectionId * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page @@ -5427,6 +6343,7 @@ export const ProviderConnectionApiFp = function(configuration?: Configuration) { * @param {string} [desc] Set to \"true\" or \"1\" for descending order * @param {string} [authorization] * @param {*} [options] Override http request option. + * @deprecated * @throws {RequiredError} */ async listWallets(xClientId: string, connectionId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { @@ -5517,20 +6434,22 @@ export const ProviderConnectionApiFactory = function (configuration?: Configurat return localVarFp.list(requestParameters.xClientId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, /** - * This endpoint retrieves a list of accounts associated with a specific connection. - * @summary List accounts for a specific connection + * Note: use GET /v1/provider/accounts endpoint instead + * @summary (DEPRECATED) List accounts for a specific connection * @param {ProviderConnectionApiListAccountsRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. + * @deprecated * @throws {RequiredError} */ listAccounts(requestParameters: ProviderConnectionApiListAccountsRequest, options?: RawAxiosRequestConfig): AxiosPromise { return localVarFp.listAccounts(requestParameters.xClientId, requestParameters.connectionId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, /** - * This endpoint retrieves a list of wallets associated with a specific connection. - * @summary List wallets for a specific connection + * Note: use GET /v1/provider/wallets endpoint instead + * @summary (DEPRECATED) List wallets for a specific connection * @param {ProviderConnectionApiListWalletsRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. + * @deprecated * @throws {RequiredError} */ listWallets(requestParameters: ProviderConnectionApiListWalletsRequest, options?: RawAxiosRequestConfig): AxiosPromise { @@ -5923,10 +6842,11 @@ export class ProviderConnectionApi extends BaseAPI { } /** - * This endpoint retrieves a list of accounts associated with a specific connection. - * @summary List accounts for a specific connection + * Note: use GET /v1/provider/accounts endpoint instead + * @summary (DEPRECATED) List accounts for a specific connection * @param {ProviderConnectionApiListAccountsRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. + * @deprecated * @throws {RequiredError} * @memberof ProviderConnectionApi */ @@ -5935,10 +6855,11 @@ export class ProviderConnectionApi extends BaseAPI { } /** - * This endpoint retrieves a list of wallets associated with a specific connection. - * @summary List wallets for a specific connection + * Note: use GET /v1/provider/wallets endpoint instead + * @summary (DEPRECATED) List wallets for a specific connection * @param {ProviderConnectionApiListWalletsRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. + * @deprecated * @throws {RequiredError} * @memberof ProviderConnectionApi */ @@ -5979,75 +6900,22 @@ export class ProviderConnectionApi extends BaseAPI { */ export const ProviderKnownDestinationApiAxiosParamCreator = function (configuration?: Configuration) { return { - /** - * - * @summary Get known destination by ID - * @param {string} xClientId - * @param {string} knownDestinationId - * @param {string} [authorization] - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - getById: async (xClientId: string, knownDestinationId: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { - // verify required parameter 'xClientId' is not null or undefined - assertParamExists('getById', 'xClientId', xClientId) - // verify required parameter 'knownDestinationId' is not null or undefined - assertParamExists('getById', 'knownDestinationId', knownDestinationId) - const localVarPath = `/v1/provider/known-destinations/{knownDestinationId}` - .replace(`{${"knownDestinationId"}}`, encodeURIComponent(String(knownDestinationId))); - // use dummy base URL string because the URL constructor only accepts absolute URLs. - const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); - let baseOptions; - if (configuration) { - baseOptions = configuration.baseOptions; - } - - const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; - const localVarHeaderParameter = {} as any; - const localVarQueryParameter = {} as any; - - // authentication GNAP required - - // authentication Detached-JWS-Signature required - await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) - - if (xClientId != null) { - localVarHeaderParameter['x-client-id'] = String(xClientId); - } - - if (authorization != null) { - localVarHeaderParameter['Authorization'] = String(authorization); - } - - - - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, /** * * @summary Get known destinations across providers * @param {string} xClientId - * @param {string} connectionId - * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page * @param {number} [limit] Number of records to return per page + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page * @param {string} [orderBy] Field to order results by * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [xConnectionId] The provider connection through which the resource is accessed * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - list: async (xClientId: string, connectionId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + list: async (xClientId: string, limit?: number, cursor?: string, orderBy?: string, desc?: string, xConnectionId?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'xClientId' is not null or undefined assertParamExists('list', 'xClientId', xClientId) - // verify required parameter 'connectionId' is not null or undefined - assertParamExists('list', 'connectionId', connectionId) const localVarPath = `/v1/provider/known-destinations`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -6065,18 +6933,14 @@ export const ProviderKnownDestinationApiAxiosParamCreator = function (configurat // authentication Detached-JWS-Signature required await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) - if (connectionId !== undefined) { - localVarQueryParameter['connectionId'] = connectionId; + if (limit !== undefined) { + localVarQueryParameter['limit'] = limit; } if (cursor !== undefined) { localVarQueryParameter['cursor'] = cursor; } - if (limit !== undefined) { - localVarQueryParameter['limit'] = limit; - } - if (orderBy !== undefined) { localVarQueryParameter['orderBy'] = orderBy; } @@ -6089,6 +6953,10 @@ export const ProviderKnownDestinationApiAxiosParamCreator = function (configurat localVarHeaderParameter['x-client-id'] = String(xClientId); } + if (xConnectionId != null) { + localVarHeaderParameter['x-connection-id'] = String(xConnectionId); + } + if (authorization != null) { localVarHeaderParameter['Authorization'] = String(authorization); } @@ -6114,36 +6982,21 @@ export const ProviderKnownDestinationApiAxiosParamCreator = function (configurat export const ProviderKnownDestinationApiFp = function(configuration?: Configuration) { const localVarAxiosParamCreator = ProviderKnownDestinationApiAxiosParamCreator(configuration) return { - /** - * - * @summary Get known destination by ID - * @param {string} xClientId - * @param {string} knownDestinationId - * @param {string} [authorization] - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async getById(xClientId: string, knownDestinationId: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.getById(xClientId, knownDestinationId, authorization, options); - const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = operationServerMap['ProviderKnownDestinationApi.getById']?.[localVarOperationServerIndex]?.url; - return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); - }, /** * * @summary Get known destinations across providers * @param {string} xClientId - * @param {string} connectionId - * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page * @param {number} [limit] Number of records to return per page + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page * @param {string} [orderBy] Field to order results by * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [xConnectionId] The provider connection through which the resource is accessed * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async list(xClientId: string, connectionId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.list(xClientId, connectionId, cursor, limit, orderBy, desc, authorization, options); + async list(xClientId: string, limit?: number, cursor?: string, orderBy?: string, desc?: string, xConnectionId?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.list(xClientId, limit, cursor, orderBy, desc, xConnectionId, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['ProviderKnownDestinationApi.list']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); @@ -6158,16 +7011,6 @@ export const ProviderKnownDestinationApiFp = function(configuration?: Configurat export const ProviderKnownDestinationApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { const localVarFp = ProviderKnownDestinationApiFp(configuration) return { - /** - * - * @summary Get known destination by ID - * @param {ProviderKnownDestinationApiGetByIdRequest} requestParameters Request parameters. - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - getById(requestParameters: ProviderKnownDestinationApiGetByIdRequest, options?: RawAxiosRequestConfig): AxiosPromise { - return localVarFp.getById(requestParameters.xClientId, requestParameters.knownDestinationId, requestParameters.authorization, options).then((request) => request(axios, basePath)); - }, /** * * @summary Get known destinations across providers @@ -6176,124 +7019,279 @@ export const ProviderKnownDestinationApiFactory = function (configuration?: Conf * @throws {RequiredError} */ list(requestParameters: ProviderKnownDestinationApiListRequest, options?: RawAxiosRequestConfig): AxiosPromise { - return localVarFp.list(requestParameters.xClientId, requestParameters.connectionId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(axios, basePath)); + return localVarFp.list(requestParameters.xClientId, requestParameters.limit, requestParameters.cursor, requestParameters.orderBy, requestParameters.desc, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, }; }; /** - * Request parameters for getById operation in ProviderKnownDestinationApi. + * Request parameters for list operation in ProviderKnownDestinationApi. * @export - * @interface ProviderKnownDestinationApiGetByIdRequest + * @interface ProviderKnownDestinationApiListRequest */ -export interface ProviderKnownDestinationApiGetByIdRequest { +export interface ProviderKnownDestinationApiListRequest { /** * * @type {string} - * @memberof ProviderKnownDestinationApiGetById + * @memberof ProviderKnownDestinationApiList */ readonly xClientId: string /** - * - * @type {string} - * @memberof ProviderKnownDestinationApiGetById - */ - readonly knownDestinationId: string + * Number of records to return per page + * @type {number} + * @memberof ProviderKnownDestinationApiList + */ + readonly limit?: number + + /** + * Cursor for pagination. Use the next cursor from previous response to get next page + * @type {string} + * @memberof ProviderKnownDestinationApiList + */ + readonly cursor?: string + + /** + * Field to order results by + * @type {string} + * @memberof ProviderKnownDestinationApiList + */ + readonly orderBy?: string + + /** + * Set to \"true\" or \"1\" for descending order + * @type {string} + * @memberof ProviderKnownDestinationApiList + */ + readonly desc?: string + + /** + * The provider connection through which the resource is accessed + * @type {string} + * @memberof ProviderKnownDestinationApiList + */ + readonly xConnectionId?: string /** * * @type {string} - * @memberof ProviderKnownDestinationApiGetById + * @memberof ProviderKnownDestinationApiList */ readonly authorization?: string } /** - * Request parameters for list operation in ProviderKnownDestinationApi. + * ProviderKnownDestinationApi - object-oriented interface * @export - * @interface ProviderKnownDestinationApiListRequest + * @class ProviderKnownDestinationApi + * @extends {BaseAPI} */ -export interface ProviderKnownDestinationApiListRequest { +export class ProviderKnownDestinationApi extends BaseAPI { /** * - * @type {string} - * @memberof ProviderKnownDestinationApiList + * @summary Get known destinations across providers + * @param {ProviderKnownDestinationApiListRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderKnownDestinationApi */ - readonly xClientId: string + public list(requestParameters: ProviderKnownDestinationApiListRequest, options?: RawAxiosRequestConfig) { + return ProviderKnownDestinationApiFp(this.configuration).list(requestParameters.xClientId, requestParameters.limit, requestParameters.cursor, requestParameters.orderBy, requestParameters.desc, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + } +} + + + +/** + * ProviderNetworkApi - axios parameter creator + * @export + */ +export const ProviderNetworkApiAxiosParamCreator = function (configuration?: Configuration) { + return { + /** + * This endpoint retrieves a list of all available networks. + * @summary Retrieve all networks + * @param {string} xClientId + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [authorization] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + list: async (xClientId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('list', 'xClientId', xClientId) + const localVarPath = `/v1/provider/networks`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + + if (cursor !== undefined) { + localVarQueryParameter['cursor'] = cursor; + } + + if (limit !== undefined) { + localVarQueryParameter['limit'] = limit; + } + + if (orderBy !== undefined) { + localVarQueryParameter['orderBy'] = orderBy; + } + + if (desc !== undefined) { + localVarQueryParameter['desc'] = desc; + } + + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + } +}; + +/** + * ProviderNetworkApi - functional programming interface + * @export + */ +export const ProviderNetworkApiFp = function(configuration?: Configuration) { + const localVarAxiosParamCreator = ProviderNetworkApiAxiosParamCreator(configuration) + return { + /** + * This endpoint retrieves a list of all available networks. + * @summary Retrieve all networks + * @param {string} xClientId + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [authorization] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async list(xClientId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.list(xClientId, cursor, limit, orderBy, desc, authorization, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderNetworkApi.list']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + } +}; +/** + * ProviderNetworkApi - factory interface + * @export + */ +export const ProviderNetworkApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { + const localVarFp = ProviderNetworkApiFp(configuration) + return { + /** + * This endpoint retrieves a list of all available networks. + * @summary Retrieve all networks + * @param {ProviderNetworkApiListRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + list(requestParameters: ProviderNetworkApiListRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.list(requestParameters.xClientId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(axios, basePath)); + }, + }; +}; + +/** + * Request parameters for list operation in ProviderNetworkApi. + * @export + * @interface ProviderNetworkApiListRequest + */ +export interface ProviderNetworkApiListRequest { /** * * @type {string} - * @memberof ProviderKnownDestinationApiList + * @memberof ProviderNetworkApiList */ - readonly connectionId: string + readonly xClientId: string /** * Cursor for pagination. Use the next cursor from previous response to get next page * @type {string} - * @memberof ProviderKnownDestinationApiList + * @memberof ProviderNetworkApiList */ readonly cursor?: string /** * Number of records to return per page * @type {number} - * @memberof ProviderKnownDestinationApiList + * @memberof ProviderNetworkApiList */ readonly limit?: number /** * Field to order results by * @type {string} - * @memberof ProviderKnownDestinationApiList + * @memberof ProviderNetworkApiList */ readonly orderBy?: string /** * Set to \"true\" or \"1\" for descending order * @type {string} - * @memberof ProviderKnownDestinationApiList + * @memberof ProviderNetworkApiList */ readonly desc?: string /** * * @type {string} - * @memberof ProviderKnownDestinationApiList + * @memberof ProviderNetworkApiList */ readonly authorization?: string } /** - * ProviderKnownDestinationApi - object-oriented interface + * ProviderNetworkApi - object-oriented interface * @export - * @class ProviderKnownDestinationApi + * @class ProviderNetworkApi * @extends {BaseAPI} */ -export class ProviderKnownDestinationApi extends BaseAPI { - /** - * - * @summary Get known destination by ID - * @param {ProviderKnownDestinationApiGetByIdRequest} requestParameters Request parameters. - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof ProviderKnownDestinationApi - */ - public getById(requestParameters: ProviderKnownDestinationApiGetByIdRequest, options?: RawAxiosRequestConfig) { - return ProviderKnownDestinationApiFp(this.configuration).getById(requestParameters.xClientId, requestParameters.knownDestinationId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); - } - +export class ProviderNetworkApi extends BaseAPI { /** - * - * @summary Get known destinations across providers - * @param {ProviderKnownDestinationApiListRequest} requestParameters Request parameters. + * This endpoint retrieves a list of all available networks. + * @summary Retrieve all networks + * @param {ProviderNetworkApiListRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} - * @memberof ProviderKnownDestinationApi + * @memberof ProviderNetworkApi */ - public list(requestParameters: ProviderKnownDestinationApiListRequest, options?: RawAxiosRequestConfig) { - return ProviderKnownDestinationApiFp(this.configuration).list(requestParameters.xClientId, requestParameters.connectionId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + public list(requestParameters: ProviderNetworkApiListRequest, options?: RawAxiosRequestConfig) { + return ProviderNetworkApiFp(this.configuration).list(requestParameters.xClientId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } } @@ -7200,56 +8198,511 @@ export class ProviderProxyApi extends BaseAPI { * @throws {RequiredError} * @memberof ProviderProxyApi */ - public get(requestParameters: ProviderProxyApiGetRequest, options?: RawAxiosRequestConfig) { - return ProviderProxyApiFp(this.configuration).get(requestParameters.xClientId, requestParameters.endpoint, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); - } + public get(requestParameters: ProviderProxyApiGetRequest, options?: RawAxiosRequestConfig) { + return ProviderProxyApiFp(this.configuration).get(requestParameters.xClientId, requestParameters.endpoint, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. + * @summary Authorizes and forwards the request to the provider + * @param {ProviderProxyApiHeadRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderProxyApi + */ + public head(requestParameters: ProviderProxyApiHeadRequest, options?: RawAxiosRequestConfig) { + return ProviderProxyApiFp(this.configuration).head(requestParameters.xClientId, requestParameters.endpoint, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. + * @summary Authorizes and forwards the request to the provider + * @param {ProviderProxyApiPatchRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderProxyApi + */ + public patch(requestParameters: ProviderProxyApiPatchRequest, options?: RawAxiosRequestConfig) { + return ProviderProxyApiFp(this.configuration).patch(requestParameters.xClientId, requestParameters.endpoint, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. + * @summary Authorizes and forwards the request to the provider + * @param {ProviderProxyApiPostRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderProxyApi + */ + public post(requestParameters: ProviderProxyApiPostRequest, options?: RawAxiosRequestConfig) { + return ProviderProxyApiFp(this.configuration).post(requestParameters.xClientId, requestParameters.endpoint, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. + * @summary Authorizes and forwards the request to the provider + * @param {ProviderProxyApiPutRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ProviderProxyApi + */ + public put(requestParameters: ProviderProxyApiPutRequest, options?: RawAxiosRequestConfig) { + return ProviderProxyApiFp(this.configuration).put(requestParameters.xClientId, requestParameters.endpoint, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + } +} + + + +/** + * ProviderScopedSyncApi - axios parameter creator + * @export + */ +export const ProviderScopedSyncApiAxiosParamCreator = function (configuration?: Configuration) { + return { + /** + * This endpoint retrieves the details of a specific scoped synchronization process associated with the client, identified by the scoped sync ID. + * @summary Retrieve a specific scoped synchronization process by ID + * @param {string} xClientId + * @param {string} scopedSyncId + * @param {string} [xConnectionId] The provider connection through which the resource is accessed + * @param {string} [authorization] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getById: async (xClientId: string, scopedSyncId: string, xConnectionId?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('getById', 'xClientId', xClientId) + // verify required parameter 'scopedSyncId' is not null or undefined + assertParamExists('getById', 'scopedSyncId', scopedSyncId) + const localVarPath = `/v1/provider/scoped-syncs/{scopedSyncId}` + .replace(`{${"scopedSyncId"}}`, encodeURIComponent(String(scopedSyncId))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + + if (xConnectionId != null) { + localVarHeaderParameter['x-connection-id'] = String(xConnectionId); + } + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * This endpoint retrieves a list of synchronization processes associated with the client. Optionally, it can filter the processes by a specific connection ID. + * @summary Retrieve a list of synchronization processes + * @param {string} xClientId + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [xConnectionId] The provider connection through which the resource is accessed + * @param {string} [authorization] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + list: async (xClientId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, xConnectionId?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('list', 'xClientId', xClientId) + const localVarPath = `/v1/provider/scoped-syncs`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + + if (cursor !== undefined) { + localVarQueryParameter['cursor'] = cursor; + } + + if (limit !== undefined) { + localVarQueryParameter['limit'] = limit; + } + + if (orderBy !== undefined) { + localVarQueryParameter['orderBy'] = orderBy; + } + + if (desc !== undefined) { + localVarQueryParameter['desc'] = desc; + } + + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + + if (xConnectionId != null) { + localVarHeaderParameter['x-connection-id'] = String(xConnectionId); + } + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * This endpoint starts scoped synchronization process for the client. + * @summary Start a scoped synchronization process + * @param {string} xClientId + * @param {StartScopedSyncDto} startScopedSyncDto + * @param {string} [authorization] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + start: async (xClientId: string, startScopedSyncDto: StartScopedSyncDto, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'xClientId' is not null or undefined + assertParamExists('start', 'xClientId', xClientId) + // verify required parameter 'startScopedSyncDto' is not null or undefined + assertParamExists('start', 'startScopedSyncDto', startScopedSyncDto) + const localVarPath = `/v1/provider/scoped-syncs`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication GNAP required + + // authentication Detached-JWS-Signature required + await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) + + if (xClientId != null) { + localVarHeaderParameter['x-client-id'] = String(xClientId); + } + + if (authorization != null) { + localVarHeaderParameter['Authorization'] = String(authorization); + } + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(startScopedSyncDto, localVarRequestOptions, configuration) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + } +}; + +/** + * ProviderScopedSyncApi - functional programming interface + * @export + */ +export const ProviderScopedSyncApiFp = function(configuration?: Configuration) { + const localVarAxiosParamCreator = ProviderScopedSyncApiAxiosParamCreator(configuration) + return { + /** + * This endpoint retrieves the details of a specific scoped synchronization process associated with the client, identified by the scoped sync ID. + * @summary Retrieve a specific scoped synchronization process by ID + * @param {string} xClientId + * @param {string} scopedSyncId + * @param {string} [xConnectionId] The provider connection through which the resource is accessed + * @param {string} [authorization] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getById(xClientId: string, scopedSyncId: string, xConnectionId?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getById(xClientId, scopedSyncId, xConnectionId, authorization, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderScopedSyncApi.getById']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + /** + * This endpoint retrieves a list of synchronization processes associated with the client. Optionally, it can filter the processes by a specific connection ID. + * @summary Retrieve a list of synchronization processes + * @param {string} xClientId + * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page + * @param {number} [limit] Number of records to return per page + * @param {string} [orderBy] Field to order results by + * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [xConnectionId] The provider connection through which the resource is accessed + * @param {string} [authorization] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async list(xClientId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, xConnectionId?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.list(xClientId, cursor, limit, orderBy, desc, xConnectionId, authorization, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderScopedSyncApi.list']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + /** + * This endpoint starts scoped synchronization process for the client. + * @summary Start a scoped synchronization process + * @param {string} xClientId + * @param {StartScopedSyncDto} startScopedSyncDto + * @param {string} [authorization] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async start(xClientId: string, startScopedSyncDto: StartScopedSyncDto, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.start(xClientId, startScopedSyncDto, authorization, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['ProviderScopedSyncApi.start']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + } +}; + +/** + * ProviderScopedSyncApi - factory interface + * @export + */ +export const ProviderScopedSyncApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { + const localVarFp = ProviderScopedSyncApiFp(configuration) + return { + /** + * This endpoint retrieves the details of a specific scoped synchronization process associated with the client, identified by the scoped sync ID. + * @summary Retrieve a specific scoped synchronization process by ID + * @param {ProviderScopedSyncApiGetByIdRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getById(requestParameters: ProviderScopedSyncApiGetByIdRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.getById(requestParameters.xClientId, requestParameters.scopedSyncId, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(axios, basePath)); + }, + /** + * This endpoint retrieves a list of synchronization processes associated with the client. Optionally, it can filter the processes by a specific connection ID. + * @summary Retrieve a list of synchronization processes + * @param {ProviderScopedSyncApiListRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + list(requestParameters: ProviderScopedSyncApiListRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.list(requestParameters.xClientId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(axios, basePath)); + }, + /** + * This endpoint starts scoped synchronization process for the client. + * @summary Start a scoped synchronization process + * @param {ProviderScopedSyncApiStartRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + start(requestParameters: ProviderScopedSyncApiStartRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.start(requestParameters.xClientId, requestParameters.startScopedSyncDto, requestParameters.authorization, options).then((request) => request(axios, basePath)); + }, + }; +}; + +/** + * Request parameters for getById operation in ProviderScopedSyncApi. + * @export + * @interface ProviderScopedSyncApiGetByIdRequest + */ +export interface ProviderScopedSyncApiGetByIdRequest { + /** + * + * @type {string} + * @memberof ProviderScopedSyncApiGetById + */ + readonly xClientId: string + + /** + * + * @type {string} + * @memberof ProviderScopedSyncApiGetById + */ + readonly scopedSyncId: string + + /** + * The provider connection through which the resource is accessed + * @type {string} + * @memberof ProviderScopedSyncApiGetById + */ + readonly xConnectionId?: string + + /** + * + * @type {string} + * @memberof ProviderScopedSyncApiGetById + */ + readonly authorization?: string +} + +/** + * Request parameters for list operation in ProviderScopedSyncApi. + * @export + * @interface ProviderScopedSyncApiListRequest + */ +export interface ProviderScopedSyncApiListRequest { + /** + * + * @type {string} + * @memberof ProviderScopedSyncApiList + */ + readonly xClientId: string + + /** + * Cursor for pagination. Use the next cursor from previous response to get next page + * @type {string} + * @memberof ProviderScopedSyncApiList + */ + readonly cursor?: string + + /** + * Number of records to return per page + * @type {number} + * @memberof ProviderScopedSyncApiList + */ + readonly limit?: number + + /** + * Field to order results by + * @type {string} + * @memberof ProviderScopedSyncApiList + */ + readonly orderBy?: string + + /** + * Set to \"true\" or \"1\" for descending order + * @type {string} + * @memberof ProviderScopedSyncApiList + */ + readonly desc?: string + + /** + * The provider connection through which the resource is accessed + * @type {string} + * @memberof ProviderScopedSyncApiList + */ + readonly xConnectionId?: string + + /** + * + * @type {string} + * @memberof ProviderScopedSyncApiList + */ + readonly authorization?: string +} + +/** + * Request parameters for start operation in ProviderScopedSyncApi. + * @export + * @interface ProviderScopedSyncApiStartRequest + */ +export interface ProviderScopedSyncApiStartRequest { + /** + * + * @type {string} + * @memberof ProviderScopedSyncApiStart + */ + readonly xClientId: string + + /** + * + * @type {StartScopedSyncDto} + * @memberof ProviderScopedSyncApiStart + */ + readonly startScopedSyncDto: StartScopedSyncDto /** - * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. - * @summary Authorizes and forwards the request to the provider - * @param {ProviderProxyApiHeadRequest} requestParameters Request parameters. - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof ProviderProxyApi + * + * @type {string} + * @memberof ProviderScopedSyncApiStart */ - public head(requestParameters: ProviderProxyApiHeadRequest, options?: RawAxiosRequestConfig) { - return ProviderProxyApiFp(this.configuration).head(requestParameters.xClientId, requestParameters.endpoint, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); - } + readonly authorization?: string +} +/** + * ProviderScopedSyncApi - object-oriented interface + * @export + * @class ProviderScopedSyncApi + * @extends {BaseAPI} + */ +export class ProviderScopedSyncApi extends BaseAPI { /** - * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. - * @summary Authorizes and forwards the request to the provider - * @param {ProviderProxyApiPatchRequest} requestParameters Request parameters. + * This endpoint retrieves the details of a specific scoped synchronization process associated with the client, identified by the scoped sync ID. + * @summary Retrieve a specific scoped synchronization process by ID + * @param {ProviderScopedSyncApiGetByIdRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} - * @memberof ProviderProxyApi + * @memberof ProviderScopedSyncApi */ - public patch(requestParameters: ProviderProxyApiPatchRequest, options?: RawAxiosRequestConfig) { - return ProviderProxyApiFp(this.configuration).patch(requestParameters.xClientId, requestParameters.endpoint, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + public getById(requestParameters: ProviderScopedSyncApiGetByIdRequest, options?: RawAxiosRequestConfig) { + return ProviderScopedSyncApiFp(this.configuration).getById(requestParameters.xClientId, requestParameters.scopedSyncId, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } /** - * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. - * @summary Authorizes and forwards the request to the provider - * @param {ProviderProxyApiPostRequest} requestParameters Request parameters. + * This endpoint retrieves a list of synchronization processes associated with the client. Optionally, it can filter the processes by a specific connection ID. + * @summary Retrieve a list of synchronization processes + * @param {ProviderScopedSyncApiListRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} - * @memberof ProviderProxyApi + * @memberof ProviderScopedSyncApi */ - public post(requestParameters: ProviderProxyApiPostRequest, options?: RawAxiosRequestConfig) { - return ProviderProxyApiFp(this.configuration).post(requestParameters.xClientId, requestParameters.endpoint, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + public list(requestParameters: ProviderScopedSyncApiListRequest, options?: RawAxiosRequestConfig) { + return ProviderScopedSyncApiFp(this.configuration).list(requestParameters.xClientId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } /** - * This endpoint uses the connection specified in the header to authorize and forward the request in the path to the provider. - * @summary Authorizes and forwards the request to the provider - * @param {ProviderProxyApiPutRequest} requestParameters Request parameters. + * This endpoint starts scoped synchronization process for the client. + * @summary Start a scoped synchronization process + * @param {ProviderScopedSyncApiStartRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} - * @memberof ProviderProxyApi + * @memberof ProviderScopedSyncApi */ - public put(requestParameters: ProviderProxyApiPutRequest, options?: RawAxiosRequestConfig) { - return ProviderProxyApiFp(this.configuration).put(requestParameters.xClientId, requestParameters.endpoint, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + public start(requestParameters: ProviderScopedSyncApiStartRequest, options?: RawAxiosRequestConfig) { + return ProviderScopedSyncApiFp(this.configuration).start(requestParameters.xClientId, requestParameters.startScopedSyncDto, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } } @@ -7261,75 +8714,22 @@ export class ProviderProxyApi extends BaseAPI { */ export const ProviderSyncApiAxiosParamCreator = function (configuration?: Configuration) { return { - /** - * This endpoint retrieves the details of a specific synchronization process associated with the client, identified by the sync ID. - * @summary Retrieve a specific synchronization process by ID - * @param {string} xClientId - * @param {string} syncId - * @param {string} [authorization] - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - getById: async (xClientId: string, syncId: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { - // verify required parameter 'xClientId' is not null or undefined - assertParamExists('getById', 'xClientId', xClientId) - // verify required parameter 'syncId' is not null or undefined - assertParamExists('getById', 'syncId', syncId) - const localVarPath = `/v1/provider/syncs/{syncId}` - .replace(`{${"syncId"}}`, encodeURIComponent(String(syncId))); - // use dummy base URL string because the URL constructor only accepts absolute URLs. - const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); - let baseOptions; - if (configuration) { - baseOptions = configuration.baseOptions; - } - - const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; - const localVarHeaderParameter = {} as any; - const localVarQueryParameter = {} as any; - - // authentication GNAP required - - // authentication Detached-JWS-Signature required - await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) - - if (xClientId != null) { - localVarHeaderParameter['x-client-id'] = String(xClientId); - } - - if (authorization != null) { - localVarHeaderParameter['Authorization'] = String(authorization); - } - - - - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, /** * This endpoint retrieves a list of synchronization processes associated with the client. Optionally, it can filter the processes by a specific connection ID. * @summary Retrieve a list of synchronization processes * @param {string} xClientId - * @param {string} connectionId * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page * @param {number} [limit] Number of records to return per page * @param {string} [orderBy] Field to order results by * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [xConnectionId] The provider connection through which the resource is accessed * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - list: async (xClientId: string, connectionId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + list: async (xClientId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, xConnectionId?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'xClientId' is not null or undefined assertParamExists('list', 'xClientId', xClientId) - // verify required parameter 'connectionId' is not null or undefined - assertParamExists('list', 'connectionId', connectionId) const localVarPath = `/v1/provider/syncs`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -7347,10 +8747,6 @@ export const ProviderSyncApiAxiosParamCreator = function (configuration?: Config // authentication Detached-JWS-Signature required await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) - if (connectionId !== undefined) { - localVarQueryParameter['connectionId'] = connectionId; - } - if (cursor !== undefined) { localVarQueryParameter['cursor'] = cursor; } @@ -7371,54 +8767,8 @@ export const ProviderSyncApiAxiosParamCreator = function (configuration?: Config localVarHeaderParameter['x-client-id'] = String(xClientId); } - if (authorization != null) { - localVarHeaderParameter['Authorization'] = String(authorization); - } - - - - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * This endpoint starts synchronization process for the client. - * @summary Start a synchronization process - * @param {string} xClientId - * @param {StartSyncDto} startSyncDto - * @param {string} [authorization] - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - start: async (xClientId: string, startSyncDto: StartSyncDto, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { - // verify required parameter 'xClientId' is not null or undefined - assertParamExists('start', 'xClientId', xClientId) - // verify required parameter 'startSyncDto' is not null or undefined - assertParamExists('start', 'startSyncDto', startSyncDto) - const localVarPath = `/v1/provider/syncs`; - // use dummy base URL string because the URL constructor only accepts absolute URLs. - const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); - let baseOptions; - if (configuration) { - baseOptions = configuration.baseOptions; - } - - const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; - const localVarHeaderParameter = {} as any; - const localVarQueryParameter = {} as any; - - // authentication GNAP required - - // authentication Detached-JWS-Signature required - await setApiKeyToObject(localVarHeaderParameter, "detached-jws", configuration) - - if (xClientId != null) { - localVarHeaderParameter['x-client-id'] = String(xClientId); + if (xConnectionId != null) { + localVarHeaderParameter['x-connection-id'] = String(xConnectionId); } if (authorization != null) { @@ -7427,12 +8777,9 @@ export const ProviderSyncApiAxiosParamCreator = function (configuration?: Config - localVarHeaderParameter['Content-Type'] = 'application/json'; - setSearchParams(localVarUrlObj, localVarQueryParameter); let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - localVarRequestOptions.data = serializeDataIfNeeded(startSyncDto, localVarRequestOptions, configuration) return { url: toPathString(localVarUrlObj), @@ -7449,55 +8796,25 @@ export const ProviderSyncApiAxiosParamCreator = function (configuration?: Config export const ProviderSyncApiFp = function(configuration?: Configuration) { const localVarAxiosParamCreator = ProviderSyncApiAxiosParamCreator(configuration) return { - /** - * This endpoint retrieves the details of a specific synchronization process associated with the client, identified by the sync ID. - * @summary Retrieve a specific synchronization process by ID - * @param {string} xClientId - * @param {string} syncId - * @param {string} [authorization] - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async getById(xClientId: string, syncId: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.getById(xClientId, syncId, authorization, options); - const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = operationServerMap['ProviderSyncApi.getById']?.[localVarOperationServerIndex]?.url; - return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); - }, /** * This endpoint retrieves a list of synchronization processes associated with the client. Optionally, it can filter the processes by a specific connection ID. * @summary Retrieve a list of synchronization processes * @param {string} xClientId - * @param {string} connectionId * @param {string} [cursor] Cursor for pagination. Use the next cursor from previous response to get next page * @param {number} [limit] Number of records to return per page * @param {string} [orderBy] Field to order results by * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [xConnectionId] The provider connection through which the resource is accessed * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async list(xClientId: string, connectionId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.list(xClientId, connectionId, cursor, limit, orderBy, desc, authorization, options); + async list(xClientId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, xConnectionId?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.list(xClientId, cursor, limit, orderBy, desc, xConnectionId, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['ProviderSyncApi.list']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, - /** - * This endpoint starts synchronization process for the client. - * @summary Start a synchronization process - * @param {string} xClientId - * @param {StartSyncDto} startSyncDto - * @param {string} [authorization] - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async start(xClientId: string, startSyncDto: StartSyncDto, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.start(xClientId, startSyncDto, authorization, options); - const localVarOperationServerIndex = configuration?.serverIndex ?? 0; - const localVarOperationServerBasePath = operationServerMap['ProviderSyncApi.start']?.[localVarOperationServerIndex]?.url; - return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); - }, } }; @@ -7508,16 +8825,6 @@ export const ProviderSyncApiFp = function(configuration?: Configuration) { export const ProviderSyncApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { const localVarFp = ProviderSyncApiFp(configuration) return { - /** - * This endpoint retrieves the details of a specific synchronization process associated with the client, identified by the sync ID. - * @summary Retrieve a specific synchronization process by ID - * @param {ProviderSyncApiGetByIdRequest} requestParameters Request parameters. - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - getById(requestParameters: ProviderSyncApiGetByIdRequest, options?: RawAxiosRequestConfig): AxiosPromise { - return localVarFp.getById(requestParameters.xClientId, requestParameters.syncId, requestParameters.authorization, options).then((request) => request(axios, basePath)); - }, /** * This endpoint retrieves a list of synchronization processes associated with the client. Optionally, it can filter the processes by a specific connection ID. * @summary Retrieve a list of synchronization processes @@ -7526,49 +8833,11 @@ export const ProviderSyncApiFactory = function (configuration?: Configuration, b * @throws {RequiredError} */ list(requestParameters: ProviderSyncApiListRequest, options?: RawAxiosRequestConfig): AxiosPromise { - return localVarFp.list(requestParameters.xClientId, requestParameters.connectionId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(axios, basePath)); - }, - /** - * This endpoint starts synchronization process for the client. - * @summary Start a synchronization process - * @param {ProviderSyncApiStartRequest} requestParameters Request parameters. - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - start(requestParameters: ProviderSyncApiStartRequest, options?: RawAxiosRequestConfig): AxiosPromise { - return localVarFp.start(requestParameters.xClientId, requestParameters.startSyncDto, requestParameters.authorization, options).then((request) => request(axios, basePath)); + return localVarFp.list(requestParameters.xClientId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, }; }; -/** - * Request parameters for getById operation in ProviderSyncApi. - * @export - * @interface ProviderSyncApiGetByIdRequest - */ -export interface ProviderSyncApiGetByIdRequest { - /** - * - * @type {string} - * @memberof ProviderSyncApiGetById - */ - readonly xClientId: string - - /** - * - * @type {string} - * @memberof ProviderSyncApiGetById - */ - readonly syncId: string - - /** - * - * @type {string} - * @memberof ProviderSyncApiGetById - */ - readonly authorization?: string -} - /** * Request parameters for list operation in ProviderSyncApi. * @export @@ -7582,13 +8851,6 @@ export interface ProviderSyncApiListRequest { */ readonly xClientId: string - /** - * - * @type {string} - * @memberof ProviderSyncApiList - */ - readonly connectionId: string - /** * Cursor for pagination. Use the next cursor from previous response to get next page * @type {string} @@ -7618,37 +8880,16 @@ export interface ProviderSyncApiListRequest { readonly desc?: string /** - * + * The provider connection through which the resource is accessed * @type {string} * @memberof ProviderSyncApiList */ - readonly authorization?: string -} - -/** - * Request parameters for start operation in ProviderSyncApi. - * @export - * @interface ProviderSyncApiStartRequest - */ -export interface ProviderSyncApiStartRequest { - /** - * - * @type {string} - * @memberof ProviderSyncApiStart - */ - readonly xClientId: string - - /** - * - * @type {StartSyncDto} - * @memberof ProviderSyncApiStart - */ - readonly startSyncDto: StartSyncDto + readonly xConnectionId?: string /** * * @type {string} - * @memberof ProviderSyncApiStart + * @memberof ProviderSyncApiList */ readonly authorization?: string } @@ -7660,18 +8901,6 @@ export interface ProviderSyncApiStartRequest { * @extends {BaseAPI} */ export class ProviderSyncApi extends BaseAPI { - /** - * This endpoint retrieves the details of a specific synchronization process associated with the client, identified by the sync ID. - * @summary Retrieve a specific synchronization process by ID - * @param {ProviderSyncApiGetByIdRequest} requestParameters Request parameters. - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof ProviderSyncApi - */ - public getById(requestParameters: ProviderSyncApiGetByIdRequest, options?: RawAxiosRequestConfig) { - return ProviderSyncApiFp(this.configuration).getById(requestParameters.xClientId, requestParameters.syncId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); - } - /** * This endpoint retrieves a list of synchronization processes associated with the client. Optionally, it can filter the processes by a specific connection ID. * @summary Retrieve a list of synchronization processes @@ -7681,19 +8910,7 @@ export class ProviderSyncApi extends BaseAPI { * @memberof ProviderSyncApi */ public list(requestParameters: ProviderSyncApiListRequest, options?: RawAxiosRequestConfig) { - return ProviderSyncApiFp(this.configuration).list(requestParameters.xClientId, requestParameters.connectionId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); - } - - /** - * This endpoint starts synchronization process for the client. - * @summary Start a synchronization process - * @param {ProviderSyncApiStartRequest} requestParameters Request parameters. - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof ProviderSyncApi - */ - public start(requestParameters: ProviderSyncApiStartRequest, options?: RawAxiosRequestConfig) { - return ProviderSyncApiFp(this.configuration).start(requestParameters.xClientId, requestParameters.startSyncDto, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + return ProviderSyncApiFp(this.configuration).list(requestParameters.xClientId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } } @@ -7710,7 +8927,7 @@ export const ProviderTransferApiAxiosParamCreator = function (configuration?: Co * @summary Retrieve transfer details * @param {string} xClientId * @param {string} transferId - * @param {string} xConnectionId + * @param {string} xConnectionId The provider connection through which the resource is accessed * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} @@ -7767,7 +8984,7 @@ export const ProviderTransferApiAxiosParamCreator = function (configuration?: Co * This endpoint sends a transfer to the source\'s provider. * @summary Send a transfer * @param {string} xClientId - * @param {string} xConnectionId + * @param {string} xConnectionId The provider connection through which the resource is accessed * @param {SendTransferDto} sendTransferDto * @param {string} [authorization] * @param {*} [options] Override http request option. @@ -7838,7 +9055,7 @@ export const ProviderTransferApiFp = function(configuration?: Configuration) { * @summary Retrieve transfer details * @param {string} xClientId * @param {string} transferId - * @param {string} xConnectionId + * @param {string} xConnectionId The provider connection through which the resource is accessed * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} @@ -7853,7 +9070,7 @@ export const ProviderTransferApiFp = function(configuration?: Configuration) { * This endpoint sends a transfer to the source\'s provider. * @summary Send a transfer * @param {string} xClientId - * @param {string} xConnectionId + * @param {string} xConnectionId The provider connection through which the resource is accessed * @param {SendTransferDto} sendTransferDto * @param {string} [authorization] * @param {*} [options] Override http request option. @@ -7919,7 +9136,7 @@ export interface ProviderTransferApiGetByIdRequest { readonly transferId: string /** - * + * The provider connection through which the resource is accessed * @type {string} * @memberof ProviderTransferApiGetById */ @@ -7947,7 +9164,7 @@ export interface ProviderTransferApiSendRequest { readonly xClientId: string /** - * + * The provider connection through which the resource is accessed * @type {string} * @memberof ProviderTransferApiSend */ @@ -8013,11 +9230,12 @@ export const ProviderWalletApiAxiosParamCreator = function (configuration?: Conf * @summary Get a specific wallet by ID * @param {string} xClientId * @param {string} walletId The ID of the wallet to retrieve + * @param {string} [xConnectionId] The provider connection through which the resource is accessed * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getById: async (xClientId: string, walletId: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + getById: async (xClientId: string, walletId: string, xConnectionId?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'xClientId' is not null or undefined assertParamExists('getById', 'xClientId', xClientId) // verify required parameter 'walletId' is not null or undefined @@ -8044,6 +9262,10 @@ export const ProviderWalletApiAxiosParamCreator = function (configuration?: Conf localVarHeaderParameter['x-client-id'] = String(xClientId); } + if (xConnectionId != null) { + localVarHeaderParameter['x-connection-id'] = String(xConnectionId); + } + if (authorization != null) { localVarHeaderParameter['Authorization'] = String(authorization); } @@ -8067,11 +9289,12 @@ export const ProviderWalletApiAxiosParamCreator = function (configuration?: Conf * @param {number} [limit] Number of records to return per page * @param {string} [orderBy] Field to order results by * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [xConnectionId] The provider connection through which the resource is accessed * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - list: async (xClientId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + list: async (xClientId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, xConnectionId?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'xClientId' is not null or undefined assertParamExists('list', 'xClientId', xClientId) const localVarPath = `/v1/provider/wallets`; @@ -8111,6 +9334,10 @@ export const ProviderWalletApiAxiosParamCreator = function (configuration?: Conf localVarHeaderParameter['x-client-id'] = String(xClientId); } + if (xConnectionId != null) { + localVarHeaderParameter['x-connection-id'] = String(xConnectionId); + } + if (authorization != null) { localVarHeaderParameter['Authorization'] = String(authorization); } @@ -8135,11 +9362,12 @@ export const ProviderWalletApiAxiosParamCreator = function (configuration?: Conf * @param {number} [limit] Number of records to return per page * @param {string} [orderBy] Field to order results by * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [xConnectionId] The provider connection through which the resource is accessed * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - listAccounts: async (xClientId: string, walletId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { + listAccounts: async (xClientId: string, walletId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, xConnectionId?: string, authorization?: string, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'xClientId' is not null or undefined assertParamExists('listAccounts', 'xClientId', xClientId) // verify required parameter 'walletId' is not null or undefined @@ -8182,6 +9410,10 @@ export const ProviderWalletApiAxiosParamCreator = function (configuration?: Conf localVarHeaderParameter['x-client-id'] = String(xClientId); } + if (xConnectionId != null) { + localVarHeaderParameter['x-connection-id'] = String(xConnectionId); + } + if (authorization != null) { localVarHeaderParameter['Authorization'] = String(authorization); } @@ -8212,12 +9444,13 @@ export const ProviderWalletApiFp = function(configuration?: Configuration) { * @summary Get a specific wallet by ID * @param {string} xClientId * @param {string} walletId The ID of the wallet to retrieve + * @param {string} [xConnectionId] The provider connection through which the resource is accessed * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async getById(xClientId: string, walletId: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.getById(xClientId, walletId, authorization, options); + async getById(xClientId: string, walletId: string, xConnectionId?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getById(xClientId, walletId, xConnectionId, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['ProviderWalletApi.getById']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); @@ -8230,12 +9463,13 @@ export const ProviderWalletApiFp = function(configuration?: Configuration) { * @param {number} [limit] Number of records to return per page * @param {string} [orderBy] Field to order results by * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [xConnectionId] The provider connection through which the resource is accessed * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async list(xClientId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.list(xClientId, cursor, limit, orderBy, desc, authorization, options); + async list(xClientId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, xConnectionId?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.list(xClientId, cursor, limit, orderBy, desc, xConnectionId, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['ProviderWalletApi.list']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); @@ -8249,12 +9483,13 @@ export const ProviderWalletApiFp = function(configuration?: Configuration) { * @param {number} [limit] Number of records to return per page * @param {string} [orderBy] Field to order results by * @param {string} [desc] Set to \"true\" or \"1\" for descending order + * @param {string} [xConnectionId] The provider connection through which the resource is accessed * @param {string} [authorization] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async listAccounts(xClientId: string, walletId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.listAccounts(xClientId, walletId, cursor, limit, orderBy, desc, authorization, options); + async listAccounts(xClientId: string, walletId: string, cursor?: string, limit?: number, orderBy?: string, desc?: string, xConnectionId?: string, authorization?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.listAccounts(xClientId, walletId, cursor, limit, orderBy, desc, xConnectionId, authorization, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['ProviderWalletApi.listAccounts']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); @@ -8277,7 +9512,7 @@ export const ProviderWalletApiFactory = function (configuration?: Configuration, * @throws {RequiredError} */ getById(requestParameters: ProviderWalletApiGetByIdRequest, options?: RawAxiosRequestConfig): AxiosPromise { - return localVarFp.getById(requestParameters.xClientId, requestParameters.walletId, requestParameters.authorization, options).then((request) => request(axios, basePath)); + return localVarFp.getById(requestParameters.xClientId, requestParameters.walletId, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, /** * @@ -8287,7 +9522,7 @@ export const ProviderWalletApiFactory = function (configuration?: Configuration, * @throws {RequiredError} */ list(requestParameters: ProviderWalletApiListRequest, options?: RawAxiosRequestConfig): AxiosPromise { - return localVarFp.list(requestParameters.xClientId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(axios, basePath)); + return localVarFp.list(requestParameters.xClientId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, /** * @@ -8297,7 +9532,7 @@ export const ProviderWalletApiFactory = function (configuration?: Configuration, * @throws {RequiredError} */ listAccounts(requestParameters: ProviderWalletApiListAccountsRequest, options?: RawAxiosRequestConfig): AxiosPromise { - return localVarFp.listAccounts(requestParameters.xClientId, requestParameters.walletId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(axios, basePath)); + return localVarFp.listAccounts(requestParameters.xClientId, requestParameters.walletId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(axios, basePath)); }, }; }; @@ -8322,6 +9557,13 @@ export interface ProviderWalletApiGetByIdRequest { */ readonly walletId: string + /** + * The provider connection through which the resource is accessed + * @type {string} + * @memberof ProviderWalletApiGetById + */ + readonly xConnectionId?: string + /** * * @type {string} @@ -8371,6 +9613,13 @@ export interface ProviderWalletApiListRequest { */ readonly desc?: string + /** + * The provider connection through which the resource is accessed + * @type {string} + * @memberof ProviderWalletApiList + */ + readonly xConnectionId?: string + /** * * @type {string} @@ -8427,6 +9676,13 @@ export interface ProviderWalletApiListAccountsRequest { */ readonly desc?: string + /** + * The provider connection through which the resource is accessed + * @type {string} + * @memberof ProviderWalletApiListAccounts + */ + readonly xConnectionId?: string + /** * * @type {string} @@ -8451,7 +9707,7 @@ export class ProviderWalletApi extends BaseAPI { * @memberof ProviderWalletApi */ public getById(requestParameters: ProviderWalletApiGetByIdRequest, options?: RawAxiosRequestConfig) { - return ProviderWalletApiFp(this.configuration).getById(requestParameters.xClientId, requestParameters.walletId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + return ProviderWalletApiFp(this.configuration).getById(requestParameters.xClientId, requestParameters.walletId, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } /** @@ -8463,7 +9719,7 @@ export class ProviderWalletApi extends BaseAPI { * @memberof ProviderWalletApi */ public list(requestParameters: ProviderWalletApiListRequest, options?: RawAxiosRequestConfig) { - return ProviderWalletApiFp(this.configuration).list(requestParameters.xClientId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + return ProviderWalletApiFp(this.configuration).list(requestParameters.xClientId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } /** @@ -8475,7 +9731,7 @@ export class ProviderWalletApi extends BaseAPI { * @memberof ProviderWalletApi */ public listAccounts(requestParameters: ProviderWalletApiListAccountsRequest, options?: RawAxiosRequestConfig) { - return ProviderWalletApiFp(this.configuration).listAccounts(requestParameters.xClientId, requestParameters.walletId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); + return ProviderWalletApiFp(this.configuration).listAccounts(requestParameters.xClientId, requestParameters.walletId, requestParameters.cursor, requestParameters.limit, requestParameters.orderBy, requestParameters.desc, requestParameters.xConnectionId, requestParameters.authorization, options).then((request) => request(this.axios, this.basePath)); } } diff --git a/packages/armory-sdk/src/lib/http/client/vault/base.ts b/packages/armory-sdk/src/lib/http/client/vault/base.ts index b617443dc..af115d924 100644 --- a/packages/armory-sdk/src/lib/http/client/vault/base.ts +++ b/packages/armory-sdk/src/lib/http/client/vault/base.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * Vault - * Secure storage for private keys and sensitive data, designed to protect your most critical assets in web3.0 + * Secure Enclave-backed authorization proxy for web3 secrets. Holds encrypted credentials and proxies API requests to custodians and wallet tech providers. Can also generate evm wallet private keys & sign transactions. * * The version of the OpenAPI document: 1.0 * diff --git a/packages/armory-sdk/src/lib/http/client/vault/common.ts b/packages/armory-sdk/src/lib/http/client/vault/common.ts index 210c71527..d095f5a22 100644 --- a/packages/armory-sdk/src/lib/http/client/vault/common.ts +++ b/packages/armory-sdk/src/lib/http/client/vault/common.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * Vault - * Secure storage for private keys and sensitive data, designed to protect your most critical assets in web3.0 + * Secure Enclave-backed authorization proxy for web3 secrets. Holds encrypted credentials and proxies API requests to custodians and wallet tech providers. Can also generate evm wallet private keys & sign transactions. * * The version of the OpenAPI document: 1.0 * diff --git a/packages/armory-sdk/src/lib/http/client/vault/configuration.ts b/packages/armory-sdk/src/lib/http/client/vault/configuration.ts index af17d53c5..edb19b2a8 100644 --- a/packages/armory-sdk/src/lib/http/client/vault/configuration.ts +++ b/packages/armory-sdk/src/lib/http/client/vault/configuration.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * Vault - * Secure storage for private keys and sensitive data, designed to protect your most critical assets in web3.0 + * Secure Enclave-backed authorization proxy for web3 secrets. Holds encrypted credentials and proxies API requests to custodians and wallet tech providers. Can also generate evm wallet private keys & sign transactions. * * The version of the OpenAPI document: 1.0 * diff --git a/packages/armory-sdk/src/lib/http/client/vault/index.ts b/packages/armory-sdk/src/lib/http/client/vault/index.ts index a317f1912..a5ee35e24 100644 --- a/packages/armory-sdk/src/lib/http/client/vault/index.ts +++ b/packages/armory-sdk/src/lib/http/client/vault/index.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * Vault - * Secure storage for private keys and sensitive data, designed to protect your most critical assets in web3.0 + * Secure Enclave-backed authorization proxy for web3 secrets. Holds encrypted credentials and proxies API requests to custodians and wallet tech providers. Can also generate evm wallet private keys & sign transactions. * * The version of the OpenAPI document: 1.0 * diff --git a/packages/armory-sdk/src/lib/vault/client.ts b/packages/armory-sdk/src/lib/vault/client.ts index f40694ffd..d390e6a90 100644 --- a/packages/armory-sdk/src/lib/vault/client.ts +++ b/packages/armory-sdk/src/lib/vault/client.ts @@ -18,20 +18,25 @@ import { ImportPrivateKeyDto, ImportWalletDto, InitiateConnectionDto, - KnownDestinationDto, PaginatedAccountsDto, PaginatedAddressesDto, + PaginatedAssetsDto, PaginatedConnectionsDto, PaginatedKnownDestinationsDto, + PaginatedNetworksDto, + PaginatedRawAccountsDto, + PaginatedScopedSyncsDto, PaginatedSyncsDto, PaginatedWalletsDto, PongDto, ProviderAccountApiFactory, ProviderAccountDto, ProviderAddressApiFactory, + ProviderAssetApiFactory, ProviderConnectionApiFactory, ProviderConnectionDto, ProviderKnownDestinationApiFactory, + ProviderNetworkApiFactory, ProviderPendingConnectionDto, ProviderProxyApiDeleteRequest, ProviderProxyApiFactory, @@ -41,16 +46,16 @@ import { ProviderProxyApiPatchRequest, ProviderProxyApiPostRequest, ProviderProxyApiPutRequest, + ProviderScopedSyncApiFactory, ProviderSyncApiFactory, ProviderTransferApiFactory, ProviderWalletApiFactory, ProviderWalletDto, + ScopedSyncDto, SendTransferDto, SignApiFactory, SignatureDto, - StartSyncDto, - SyncDto, - SyncStartedDto, + StartScopedSyncDto, TransferDto, UpdateConnectionDto, WalletApiFactory, @@ -103,10 +108,16 @@ export class VaultClient { private signHttp + private providerNetworkHttp + + private providerAssetHttp + private providerConnectionHttp private providerSyncHttp + private providerScopedSyncHttp + private providerWalletHttp private providerAccountHttp @@ -141,12 +152,15 @@ export class VaultClient { // Provider API clients this.providerConnectionHttp = ProviderConnectionApiFactory(httpConfig, config.host, axiosInstance) this.providerSyncHttp = ProviderSyncApiFactory(httpConfig, config.host, axiosInstance) + this.providerScopedSyncHttp = ProviderScopedSyncApiFactory(httpConfig, config.host, axiosInstance) this.providerWalletHttp = ProviderWalletApiFactory(httpConfig, config.host, axiosInstance) this.providerAccountHttp = ProviderAccountApiFactory(httpConfig, config.host, axiosInstance) this.providerAddressHttp = ProviderAddressApiFactory(httpConfig, config.host, axiosInstance) this.providerKnownDestinationHttp = ProviderKnownDestinationApiFactory(httpConfig, config.host, axiosInstance) this.providerTransferHttp = ProviderTransferApiFactory(httpConfig, config.host, axiosInstance) this.providerProxyHttp = ProviderProxyApiFactory(httpConfig, config.host, axiosInstance) + this.providerNetworkHttp = ProviderNetworkApiFactory(httpConfig, config.host, axiosInstance) + this.providerAssetHttp = ProviderAssetApiFactory(httpConfig, config.host, axiosInstance) this.applicationApi = new ApplicationApi(httpConfig, config.host, axiosInstance) } @@ -287,6 +301,46 @@ export class VaultClient { return signature } + async listNetworks({ + accessToken, + pagination + }: { + accessToken?: AccessToken + pagination?: RequestPagination + } = {}): Promise { + const token = accessToken ? prefixGnapToken(accessToken) : undefined + + const { data } = await this.providerNetworkHttp.list({ + xClientId: this.config.clientId, + authorization: token, + cursor: pagination?.cursor, + limit: pagination?.limit, + desc: pagination?.desc + }) + + return data + } + + async listAssets({ + accessToken, + pagination + }: { + accessToken?: AccessToken + pagination?: RequestPagination + } = {}): Promise { + const token = accessToken ? prefixGnapToken(accessToken) : undefined + + const { data } = await this.providerAssetHttp.list({ + xClientId: this.config.clientId, + authorization: token, + cursor: pagination?.cursor, + limit: pagination?.limit, + desc: pagination?.desc + }) + + return data + } + /** * Provider Connection */ @@ -404,7 +458,7 @@ export class VaultClient { accessToken, pagination }: { - connectionId?: string + connectionId: string walletId?: string accessToken?: AccessToken pagination?: RequestPagination @@ -420,58 +474,63 @@ export class VaultClient { desc: pagination?.desc }) - return accounts - } else if (connectionId) { - const { data: accounts } = await this.providerConnectionHttp.listAccounts({ - xClientId: this.config.clientId, - connectionId, - authorization: token, - cursor: pagination?.cursor, - limit: pagination?.limit, - desc: pagination?.desc - }) - return accounts } const { data: accounts } = await this.providerAccountHttp.list({ xClientId: this.config.clientId, + xConnectionId: connectionId, authorization: token, cursor: pagination?.cursor, limit: pagination?.limit, desc: pagination?.desc }) + return accounts } - /** - * Provider Sync - */ - - async startSync({ data, accessToken }: { data: StartSyncDto; accessToken?: AccessToken }): Promise { + async listProviderRawAccounts({ + accessToken, + assetId, + connectionId, + includeAddress, + namePrefix, + nameSuffix, + networkId, + pagination + }: { + accessToken?: AccessToken + assetId?: string + connectionId: string + includeAddress?: boolean + namePrefix?: string + nameSuffix?: string + networkId?: string + pagination?: RequestPagination + walletId?: string + }): Promise { const token = accessToken ? prefixGnapToken(accessToken) : undefined - const { data: sync } = await this.providerSyncHttp.start({ - xClientId: this.config.clientId, + const { data } = await this.providerAccountHttp.listRaw({ + assetId, + includeAddress, + namePrefix, + nameSuffix, + networkId, authorization: token, - startSyncDto: data - }) - - return sync - } - - async getSync({ syncId, accessToken }: { syncId: string; accessToken?: AccessToken }): Promise { - const token = accessToken ? prefixGnapToken(accessToken) : undefined - - const { data: sync } = await this.providerSyncHttp.getById({ + cursor: pagination?.cursor, + desc: pagination?.desc, + limit: pagination?.limit, xClientId: this.config.clientId, - syncId, - authorization: token + xConnectionId: connectionId }) - return sync + return data } + /** + * @deprecated Use listScopedSyncs() instead. + */ async listSyncs({ connectionId, accessToken, @@ -485,7 +544,7 @@ export class VaultClient { const { data: syncs } = await this.providerSyncHttp.list({ xClientId: this.config.clientId, - connectionId, + xConnectionId: connectionId, authorization: token, cursor: pagination?.cursor, limit: pagination?.limit, @@ -522,26 +581,15 @@ export class VaultClient { accessToken, pagination }: { - connectionId?: string + connectionId: string accessToken?: AccessToken pagination?: RequestPagination - } = {}): Promise { + }): Promise { const token = accessToken ? prefixGnapToken(accessToken) : undefined - if (connectionId) { - const { data: wallets } = await this.providerConnectionHttp.listWallets({ - xClientId: this.config.clientId, - connectionId, - authorization: token, - cursor: pagination?.cursor, - limit: pagination?.limit, - desc: pagination?.desc - }) - return wallets - } - const { data: wallets } = await this.providerWalletHttp.list({ xClientId: this.config.clientId, + xConnectionId: connectionId, authorization: token, cursor: pagination?.cursor, limit: pagination?.limit, @@ -646,7 +694,7 @@ export class VaultClient { const { data: knownDestinations } = await this.providerKnownDestinationHttp.list({ xClientId: this.config.clientId, - connectionId, + xConnectionId: connectionId, authorization: token, cursor: pagination?.cursor, limit: pagination?.limit, @@ -656,24 +704,6 @@ export class VaultClient { return knownDestinations } - async getProviderKnownDestination({ - knownDestinationId, - accessToken - }: { - knownDestinationId: string - accessToken?: AccessToken - }): Promise { - const token = accessToken ? prefixGnapToken(accessToken) : undefined - - const { data: knownDestination } = await this.providerKnownDestinationHttp.getById({ - xClientId: this.config.clientId, - knownDestinationId, - authorization: token - }) - - return knownDestination - } - /** * Provider Transfer */ @@ -849,4 +879,60 @@ export class VaultClient { }) return ret } + + async scopedSync({ data, accessToken }: { data: StartScopedSyncDto; accessToken?: AccessToken }) { + const token = accessToken ? prefixGnapToken(accessToken) : undefined + + const { data: sync } = await this.providerScopedSyncHttp.start({ + xClientId: this.config.clientId, + authorization: token, + startScopedSyncDto: data + }) + + return sync + } + + async getScopedSync({ + scopedSyncId, + accessToken, + connectionId + }: { + scopedSyncId: string + connectionId: string + accessToken?: AccessToken + }): Promise { + const token = accessToken ? prefixGnapToken(accessToken) : undefined + + const { data: sync } = await this.providerScopedSyncHttp.getById({ + xClientId: this.config.clientId, + xConnectionId: connectionId, + scopedSyncId, + authorization: token + }) + + return sync + } + + async listScopedSyncs({ + connectionId, + accessToken, + pagination + }: { + connectionId: string + accessToken?: AccessToken + pagination?: RequestPagination + }): Promise { + const token = accessToken ? prefixGnapToken(accessToken) : undefined + + const { data: scopedSyncs } = await this.providerScopedSyncHttp.list({ + xClientId: this.config.clientId, + xConnectionId: connectionId, + authorization: token, + cursor: pagination?.cursor, + limit: pagination?.limit, + desc: pagination?.desc + }) + + return scopedSyncs + } } From d1f17e5553cf7045f70a93aefcc344cf0b336738 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Mon, 27 Jan 2025 14:23:48 +0100 Subject: [PATCH 101/120] Update Unified API Anchorage examples (#106) * Migration, data is persisted per-connection (#88) * schema migration to scope all data per connection * data migration script * fix provider type per connection * unique keys order * fixed failing tests * added connectionId to mock data in transfer and sync tests * handle known destination connections to connectionId * abstract away single tie to connection change from known destinations * filter on correct row in wallet repository * updated migration script to duplicate provider resources * updates existing transfers * Pass through known destination (#90) * Add CSR public key format for FB connection (#92) * Add CSR public key format for FB connection * Add optional CSR format in the public key DTO * Add describe block * Pin node-forge version * Remove wallet connections list (#95) * Scope operations by connection (#96) * Scope operations by connection * Scope sync operations by connection * Fix supertest wrapper to work with query method * Use signed request util in the wallet E2E tests * Fix flaky tests * Add back connection list endpoint * Fix address E2E tests * Bump SDK version * Add network and asset endpoints in the SDK * Adding BitGo connection * ScopedSync by RawAccounts (#84) * duplicated sync, poc working * fixed rebase conflicts and format * cleanup rebase merge, correctly insert connectionId on scope sync * fireblocks scoped-sync updates * use vault label * added updates to anchorage's scoped sync service * add tests on anchorage scoped sync * cleaned up anchorage scope sync tests * map fireblocks assetWallets to network specific accounts * fixed not found test expectation * test fireblocks scoped sync * fixed rebase conflicts * changed externalId standard * Adding Raw Accounts endpoint & Assed/Network bootstrap * Adding includeAddress query param so fireblocks does not always fetch addresses * Cache assets & refactor network cache (#98) * Cache asset Refactor network to use cache manager * Remove draft config * Pin cache-manager version * Lower case cache keys * Fix findAll method * Endpoints to fetch scoped-syncs (#101) * scoped sync persists stringified raw accounts * add status fetching endpoints for scoped syncs * use prismaservice methods to json stringify and parse * Minor fixes before release connection-specific (#102) * Add back the nested wallet and account endpoints in the connection * Minor fix on scope sync logs Connection ID is mandatory in the Vault Client * connect a new connection triggers full sync on anchorage (#103) * connect a new connection triggers full sync on anchorage * fix test excpetation for empty raw accounts on anchorage * Add listProviderRawAccounts method in the Vault SDK * removed references to 'sync' and dropped table * removed syncService from connection test * deleted sync e2e test * re-generated sdk without scoped sync methods * Revert "re-generated sdk without scoped sync methods" This reverts commit 66dccdfa2bd909d2f6c015b153e87c3728004dd2. * Revert "removed references to 'sync' and dropped table" This reverts commit 9c2cd022b95439ce9bc4a45a44d7c67da0cdc535. * Revert "deleted sync e2e test" This reverts commit 2f4a252650fb871662cbe92ba149aa9e2dc5d0c6. * Revert "removed syncService from connection test" This reverts commit 450ece6a34ec5ef04bf170c176f56de4e71b97c9. * removed sync functionality except list * removed deprecated imports --------- Co-authored-by: Ptroger <44851272+Ptroger@users.noreply.github.com> Co-authored-by: Pierre Troger * Feature/nar 2059 make scoped sync quicker (#104) * fireblocks query uniquely scoped accounts, handle duplicated rawAccounts * optimized queries per wallet * anchorage scoped syncs swallow not found errors * batch requests to control rate limiting * removed connection-sync event handler * manage error handling in promiseAllSettled * use httpstatus * expect precisely one account * Asset fallback (#105) * Asset fallback for Anchorage and Fireblocks * Add TransferAssetService * Remove findTransferAsset from AssetService * Remove fallback type * Refactor TransferAssetService * Fix integration test types * Fix E2E tests * Fix provider * Update Unified API examples * Remove pagination * Update README * Update quickstart README * Quickstart, Select Accounts section * Adding `.` before quickstart readme so it orders first in gist * Update SDK version * Ignore config.*.yaml files in git --------- Co-authored-by: Ptroger <44851272+Ptroger@users.noreply.github.com> Co-authored-by: Matt Schoch Co-authored-by: Pierre Troger --- examples/unified-api/.gitignore | 3 +- examples/unified-api/1-connect.ts | 38 ++- examples/unified-api/2-read-wallets.ts | 34 ++- examples/unified-api/3-read-accounts.ts | 36 +-- examples/unified-api/4-create-transfer.ts | 21 +- examples/unified-api/5-sync.ts | 26 --- examples/unified-api/6-known-destinations.ts | 18 -- examples/unified-api/README-quickstart.md | 233 ------------------- examples/unified-api/README.md | 44 ++-- examples/unified-api/config.default.json | 15 -- examples/unified-api/config.default.yaml | 14 ++ examples/unified-api/package-lock.json | 27 ++- examples/unified-api/package.json | 4 +- examples/unified-api/vault.client.ts | 83 ++++--- 14 files changed, 208 insertions(+), 388 deletions(-) delete mode 100644 examples/unified-api/5-sync.ts delete mode 100644 examples/unified-api/6-known-destinations.ts delete mode 100644 examples/unified-api/README-quickstart.md delete mode 100644 examples/unified-api/config.default.json create mode 100644 examples/unified-api/config.default.yaml diff --git a/examples/unified-api/.gitignore b/examples/unified-api/.gitignore index 3df2574c7..49ba8cf09 100644 --- a/examples/unified-api/.gitignore +++ b/examples/unified-api/.gitignore @@ -1,3 +1,4 @@ .env node_modules -config.json \ No newline at end of file +config.yaml +config.*.yaml diff --git a/examples/unified-api/1-connect.ts b/examples/unified-api/1-connect.ts index 2d028fb9f..976a87745 100644 --- a/examples/unified-api/1-connect.ts +++ b/examples/unified-api/1-connect.ts @@ -5,9 +5,9 @@ import { config, setConfig, vaultClient } from './vault.client' dotenv.config() const main = async () => { - const apiKey = config.connectionApiKey - const privateKey = config.connectionPrivateKey - const url = config.connectionUrl + const apiKey = config.connection.credentials.apiKey + const privateKey = config.connection.credentials.privateKey + const url = config.connection.url const credentials = { apiKey, privateKey @@ -22,12 +22,40 @@ const main = async () => { data: { url, encryptedCredentials, provider: 'anchorage' } }) + const rawAccounts = await vaultClient.listProviderRawAccounts({ + connectionId: connection.data.connectionId + }) + + console.log( + 'Syncing raw accounts', + rawAccounts.data.map((rawAccount) => `${rawAccount.label} - ${rawAccount.externalId}`) + ) + + await vaultClient.scopedSync({ + data: { + connectionId: connection.data.connectionId, + rawAccounts: rawAccounts.data + } + }) + // Save the connectionId to the config file - setConfig('connectionId', connection.data.connectionId) + setConfig('connection.id', connection.data.connectionId) console.dir(connection.data) } main() .then(() => console.log('done')) - .catch(console.error) + .catch((error) => { + if ('response' in error) { + console.dir( + { + status: error.response?.status, + body: error.response?.data + }, + { depth: null } + ) + } else { + console.error('Error', error) + } + }) diff --git a/examples/unified-api/2-read-wallets.ts b/examples/unified-api/2-read-wallets.ts index 00fa42b3b..b4922a8d0 100644 --- a/examples/unified-api/2-read-wallets.ts +++ b/examples/unified-api/2-read-wallets.ts @@ -1,13 +1,15 @@ +import { AxiosError } from 'axios' import { config, vaultClient } from './vault.client' const main = async () => { - if (!config.connectionId) { - console.error('No connectionId found in config.json. Please connect first.') + if (!config.connection.id) { + console.error('No connection.id found in config.yaml. Please connect first.') process.exit(1) } - const { data, page } = await vaultClient.listProviderWallets({ - connectionId: config.connectionId + const { data } = await vaultClient.listProviderWallets({ + connectionId: config.connection.id, + pagination: { limit: 100 } }) console.dir( @@ -15,11 +17,29 @@ const main = async () => { label: wallet.label, walletId: wallet.walletId, provider: wallet.provider, - externalId: wallet.externalId - })) + externalId: wallet.externalId, + accounts: (wallet.accounts || []).map((account) => ({ + accountId: account.accountId, + networkId: account.networkId, + label: account.label + })) + })), + { depth: null } ) } main() .then(() => console.log('done')) - .catch(console.error) + .catch((error) => { + if (error instanceof AxiosError) { + console.dir( + { + status: error.response?.status, + body: error.response?.data + }, + { depth: null } + ) + } else { + console.error(error) + } + }) diff --git a/examples/unified-api/3-read-accounts.ts b/examples/unified-api/3-read-accounts.ts index da4bb4c24..d89d5a368 100644 --- a/examples/unified-api/3-read-accounts.ts +++ b/examples/unified-api/3-read-accounts.ts @@ -1,28 +1,32 @@ +import { AxiosError } from 'axios' import { config, vaultClient } from './vault.client' const main = async () => { - if (!config.connectionId) { - console.error('No connectionId found in config.json. Please connect first.') + if (!config.connection.id) { + console.error('No connection.id found in config.yaml. Please connect first.') process.exit(1) } - const { data, page } = await vaultClient.listProviderAccounts({ - connectionId: config.connectionId + const { data } = await vaultClient.listProviderAccounts({ + connectionId: config.connection.id, + pagination: { limit: 100 } }) - console.dir( - data.map((account) => ({ - label: account.label, - accountId: account.accountId, - provider: account.provider, - externalId: account.externalId, - networkId: account.networkId, - walletId: account.walletId, - addresses: account?.addresses?.map((address) => address.address) - })) - ) + console.dir(data, { depth: null }) } main() .then(() => console.log('done')) - .catch(console.error) + .catch((error) => { + if (error instanceof AxiosError) { + console.dir( + { + status: error.response?.status, + body: error.response?.data + }, + { depth: null } + ) + } else { + console.error(error) + } + }) diff --git a/examples/unified-api/4-create-transfer.ts b/examples/unified-api/4-create-transfer.ts index ee65305a5..7608b2b01 100644 --- a/examples/unified-api/4-create-transfer.ts +++ b/examples/unified-api/4-create-transfer.ts @@ -12,13 +12,13 @@ const main = async () => { ? { address: config.destinationAddress } : null - if (!config.connectionId || !config.sourceId || !destination || !config.assetId || !config.amount) { + if (!config.connection.id || !config.sourceId || !destination || !config.assetId || !config.amount) { console.error('Please provide transfer parameters in config.json') process.exit(1) } const initiatedTransfer = await vaultClient.sendTransfer({ - connectionId: config.connectionId, + connectionId: config.connection.id, data: { idempotenceId: uuid(), source: { @@ -56,9 +56,10 @@ const main = async () => { // Poll transfer status until it's no longer processing let transfer + do { transfer = await vaultClient.getTransfer({ - connectionId: config.connectionId, + connectionId: config.connection.id, transferId: initiatedTransfer.data.transferId }) @@ -74,4 +75,16 @@ const main = async () => { main() .then(() => console.log('done')) - .catch(console.error) + .catch((error) => { + if ('response' in error) { + console.dir( + { + status: error.response?.status, + body: error.response?.data + }, + { depth: null } + ) + } else { + console.error('Error', error) + } + }) diff --git a/examples/unified-api/5-sync.ts b/examples/unified-api/5-sync.ts deleted file mode 100644 index efc9bc2b7..000000000 --- a/examples/unified-api/5-sync.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { config, vaultClient } from './vault.client' - -const main = async () => { - if (!config.connectionId) { - console.error('No connectionId found in config.json. Please connect first.') - process.exit(1) - } - - const { data } = await vaultClient.startSync({ data: { connectionId: config.connectionId } }) - console.log('Sync Started') - let sync - do { - sync = await vaultClient.getSync({ syncId: data.syncs[0].syncId }) - console.log(`Sync Status: ${sync.data.status}`) - if (sync.data.status === 'processing') { - // Wait for 1 second before next poll - await new Promise((resolve) => setTimeout(resolve, 1000)) - } - } while (sync.data.status === 'processing') - - console.log(sync) -} - -main() - .then(() => console.log('done')) - .catch(console.error) diff --git a/examples/unified-api/6-known-destinations.ts b/examples/unified-api/6-known-destinations.ts deleted file mode 100644 index 5cb246231..000000000 --- a/examples/unified-api/6-known-destinations.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { config, vaultClient } from './vault.client' - -const main = async () => { - if (!config.connectionId) { - console.error('No connectionId found in config.json. Please connect first.') - process.exit(1) - } - - const addresses = await vaultClient.listProviderKnownDestinations({ - connectionId: config.connectionId - }) - - console.log(addresses) -} - -main() - .then(() => console.log('done')) - .catch(console.error) diff --git a/examples/unified-api/README-quickstart.md b/examples/unified-api/README-quickstart.md deleted file mode 100644 index 25652718f..000000000 --- a/examples/unified-api/README-quickstart.md +++ /dev/null @@ -1,233 +0,0 @@ -# Narval Quickstart - Unified API - -## Prerequisites - -- Node.js 18+ -- tsx (`npm i -g tsx`) -- Narval SDK (`npm i @narval-xyz/armory-sdk`) - -Note: This has only been tested on Mac - -### Narval Setup - -All API requests are signed by a private key. Begin by generating a credential. - -```shell - tsx generate-key.ts - - ## Outputs - # { - # "publicHexKey": "0x432...", // Provide this to Narval - # "privateHex": "0xa288..." // Store this securely - # } -``` - -Provide the PUBLIC key when activating your Narval account. - -> Use the provided invite link to activate your Narval account, then return here with your Client ID. - -Set up the following environment variables: - -### Example Script Config - -```properties -# Set these in .env -CLIENT_ID=your_narval_client_id -NARVAL_AUTH_PRIVATE_KEY=Private key you generated above -BASE_URL=https://vault.armory.playnarval.com -``` - -## 0. Initialize SDK - -SDK should be installed already, or install with `npm i @narval-xyz/armory-sdk` - -```typescript -// Initialize an SDK Client with your clientId and your private key credential -import { Hex, privateKeyToJwk, VaultClient } from '@narval-xyz/armory-sdk' -import { buildSignerEdDSA } from '@narval-xyz/armory-sdk/signature' - -const vaultClient = new VaultClient({ - clientId: CLIENT_ID, - signer: { - sign: buildSignerEdDSA(NARVAL_AUTH_PRIVATE_KEY_HEX), - jwk: privateKeyToJwk(NARVAL_AUTH_PRIVATE_KEY_HEX as Hex, 'EDDSA'), - alg: 'EDDSA' - }, - host: BASE_URL -}) -``` - -## 1. Create a new Connection - -A Connection is a set of authenticate credentials to a custody provider. - -There are two flows possible: - -1. Generate the API Signing Key Pair in the Vault so the private key never leaves the TEE. -2. Generate the API Signing Key Pair outside the TEE and provide it to the Vault. - -Method 1 is recommended for production environments. - -Method 2 is easier for development so you can re-use the same provider API keys. - -### Method 1 - Generate the API Signing Key Pair in the Vault - -First, initiate a connection. This returns the API Signing Public Key, and an encryption key for the next step. - -```typescript -const { - data: { connectionId, publicKey, encryptionPublicKey } -} = await vaultClient.initiateConnection({ data: { provider: 'anchorage' } }) -``` - -Go to Anchorage and create a new API key, using the publicKey hex value. (note: remove the 0x prefix when pasting into Anchorage). - -After creating the API Key in Anchorage, return here to activate the connection by providing the Anchorage API Key. - -```typescript -import { rsaPublicKeySchema } from '@narval-xyz/armory-sdk' -import { rsaEncrypt } from '@narval-xyz/armory-sdk/signature' - -// Encrypt the Anchorage API Key with the encryption key -const encryptionKey = rsaPublicKeySchema.parse(encryptionPublicKey.jwk) -const encryptedCredentials = await rsaEncrypt( - JSON.stringify({ - apiKey: 'your_api_key' - }), - encryptionKey -) - -// Activate the connection in the Vault -const connection = await vaultClient.createConnection({ - data: { - connectionId, - url: 'https://api.anchorage-staging.com', - encryptedCredentials, - provider: 'anchorage', - label: 'My Anchorage Connection' - } -}) -``` - -### Method 2 - Generate the API Signing Key Pair outside the Vault - -Generate your EDDSA key pair and create an API key in Anchorage. -If you need to generate a new key pair, you can use the util method mentioned above: `tsx generate-key.ts` - -```typescript -import { rsaPublicKeySchema } from '@narval-xyz/armory-sdk' -import { rsaEncrypt } from '@narval-xyz/armory-sdk/signature' - -// Generate the transit encryption key -const jwk = await vaultClient.generateEncryptionKey() -const encryptionKey = rsaPublicKeySchema.parse(jwk) - -// Encrypt the Anchorage API Key with the encryption key -const encryptedCredentials = await rsaEncrypt( - JSON.stringify({ - apiKey: 'your_api_key', - privateKey: 'your_private_key' // hex string of the eddsa private key registered with Anchorage - }), - encryptionKey -) - -const connection = await vaultClient.createConnection({ - data: { - url: 'https://api.anchorage-staging.com', - encryptedCredentials, - provider: 'anchorage', - label: 'My Anchorage Connection' - } -}) -``` - -## 2. Read Methods - -Narval normalizes the provider data model into a standard structure of Wallets > Accounts > Addresses, where a Wallet has 1 or more Accounts, and an Account has 1 or more Addresses. Accounts are network-specific, while Wallets can have multiple accounts of the same or different networks. - -### List available Wallets - -```typescript -const { data, page } = await vaultClient.listProviderWallets({ - connectionId -}) -``` - -### List available Accounts - -```typescript -const { data, page } = await vaultClient.listProviderAccounts({ - connectionId -}) -``` - -## 3. Write Methods - -### Create a Transfer - -```typescript -const initiatedTransfer = await vaultClient.sendTransfer({ - connectionId, - data: { - idempotenceId: new Date().toISOString(), // use a real unique id in production - source: { - type: 'account', - id: sourceId // The AccountId to send from, from the listProviderAccounts call - }, - destination: { - type: 'account', - id: destinationId // The AccountId to send to, from the listProviderAccounts call - }, // can also pass in `address` instead of `type`+`id` to send to an external address - asset: { - externalAssetId: assetType // The asset type to send. `externalAssetId` expects the providers asset type, while `assetId` will use Narval's mapping of the asset types. - }, - amount: '0.00001', - // Optional provider specific fields. Anchorage external transfers require transferAmlQuestionnaire. - providerSpecific: null - } -}) -``` - -The transfer could take a bit, particularly if it requires quorum approval. - -```typescript -// Poll transfer status until it's no longer processing -let transfer -do { - transfer = await vaultClient.getTransfer({ - connectionId, - transferId: initiatedTransfer.data.transferId - }) - - console.log(`Transfer status: ${transfer.data.status}`) - - if (transfer.data.status === 'processing') { - await new Promise((resolve) => setTimeout(resolve, 2000)) // Wait 2 seconds between polls - } -} while (transfer.data.status === 'processing') -``` - -### Re-sync data - -Narval syncs the account data from the Provider when the connection is established. If Accounts are created after the connection, you may need to re-sync. - -```typescript -// Start the sync -const { data } = await vaultClient.startSync({ data: { connectionId } }) - -// Poll the sync until it's complete. Could take a bit if lots of data. -let sync -do { - sync = await vaultClient.getSync({ syncId: data.syncs[0].syncId }) - if (sync.data.status === 'processing') { - // Wait for 1 second before next poll - await new Promise((resolve) => setTimeout(resolve, 1000)) - } -} while (sync.data.status === 'processing') -``` - -## API Reference - -Underlying API is documented here: -All endpoints are available through the Typescript SDK. -https://narval.apidocumentation.com/ diff --git a/examples/unified-api/README.md b/examples/unified-api/README.md index 5adf94b8e..1fb7c9d72 100644 --- a/examples/unified-api/README.md +++ b/examples/unified-api/README.md @@ -13,7 +13,7 @@ Note: This has only been tested on Mac Set up the example project -- `cp config.default.json config.json` +- `cp config.default.yaml config.yaml` - `npm install` ### Narval Credential Setup @@ -34,15 +34,11 @@ Provide the PUBLIC key when activating your Narval account. > Use the provided invite link to activate your Narval account, then return here with your Client ID. -Set up the following into your `config.json` file: +Set up the following into your `config.yaml` file: -```json -// config.json -{ - "clientId": "YOUR NARVAL CLIENT ID", - "narvalAuthPrivateKey": "YOUR NARVAL AUTH PRIVATE KEY, HEX ENCODED (0x...)" - // ... -} +```yaml +clientId: "YOUR NARVAL CLIENT ID" +narvalAuthPrivateKey: "YOUR NARVAL AUTH PRIVATE KEY, HEX ENCODED (0x...)" ``` ### Anchorage API Setup @@ -65,14 +61,14 @@ tsx generate-key.ts > Go create your Anchorage API Key if you don't have one already. When finished, return here to set your config.json -```json -// config.json -{ - // ... - "connectionPrivateKey": "YOUR ANCHORAGE API SIGNING PRIVATE KEY, HEX ENCODED (0x...)", - "connectionApiKey": "YOUR ANCHORAGE API KEY" - // ... -} +```yaml +connection: + provider: "anchorage" + url: "https://api.anchorage-staging.com" + id: null + credentials: + apiKey: "YOUR ANCHORAGE API KEY" + privateKey: "YOUR ANCHORAGE API SIGNING PRIVATE KEY, HEX ENCODED (0x...)" ``` ## Script Usage Guide @@ -106,18 +102,14 @@ Basic scripts are available for the following operations: 4. Create Transfer Creates a transfer between two accounts. - Using `tsx 3-read-accounts.ts`, you can get the account IDs for the source and destination. Set the `sourceId`, `destinationId`, `destinationType`, `assetId`, and `amount` in the `config.json` file. `destinationAddress` can be used for external transfers. - ```shell - tsx 4-create-transfer.ts - ``` - -5. Re-sync Connection - - Re-syncs the connection with the provider. This is useful if new Accounts have been created since the connection was established. + Using `tsx 3-read-accounts.ts`, you can get the account IDs for the source + and destination. Set the `sourceId`, `destinationId`, `destinationType`, + `assetId`, and `amount` in the `config.yaml` file. `destinationAddress` can + be used for external transfers. ```shell - tsx 5-sync.ts + tsx 4-create-transfer.ts ``` ## More Info diff --git a/examples/unified-api/config.default.json b/examples/unified-api/config.default.json deleted file mode 100644 index 87384f5d7..000000000 --- a/examples/unified-api/config.default.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "clientId": "YOUR NARVAL CLIENT ID", - "narvalAuthPrivateKey": "YOUR NARVAL AUTH PRIVATE KEY, HEX ENCODED (0x...)", - "baseUrl": "https://vault.armory.playnarval.com", - "connectionPrivateKey": "YOUR ANCHORAGE API SIGNING PRIVATE KEY, HEX ENCODED (0x...)", - "connectionApiKey": "YOUR ANCHORAGE API KEY", - "connectionUrl": "https://api.anchorage-staging.com", - "connectionId": null, - "sourceId": null, - "destinationId": null, - "destinationType": null, - "destinationAddress": null, - "amount": null, - "assetId": null -} diff --git a/examples/unified-api/config.default.yaml b/examples/unified-api/config.default.yaml new file mode 100644 index 000000000..fcf4b54dc --- /dev/null +++ b/examples/unified-api/config.default.yaml @@ -0,0 +1,14 @@ +clientId: "YOUR NARVAL CLIENT ID" +narvalAuthPrivateKey: "YOUR NARVAL AUTH PRIVATE KEY, HEX ENCODED (0x...)" +baseUrl: "https://vault.armory.playnarval.com" +connection: + url: "https://api.anchorage-staging.com" + id: null + credentials: + apiKey: "YOUR ANCHORAGE API KEY" + privateKey: "YOUR ANCHORAGE API SIGNING PRIVATE KEY, HEX ENCODED (0x...)" +destinationId: null +destinationType: null +destinationAddress: null +amount: null +assetId: null diff --git a/examples/unified-api/package-lock.json b/examples/unified-api/package-lock.json index a015a478d..687990ba2 100644 --- a/examples/unified-api/package-lock.json +++ b/examples/unified-api/package-lock.json @@ -9,10 +9,12 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "@narval-xyz/armory-sdk": "0.17.0", + "@narval-xyz/armory-sdk": "0.18.0", "dotenv": "16.4.5", + "lodash": "^4.17.21", "tsx": "4.19.2", - "zod": "^3.24.1" + "yaml": "^2.7.0", + "zod": "3.24.1" } }, "node_modules/@adraffy/ens-normalize": { @@ -381,9 +383,9 @@ } }, "node_modules/@narval-xyz/armory-sdk": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/@narval-xyz/armory-sdk/-/armory-sdk-0.17.0.tgz", - "integrity": "sha512-94AxgbSddeghixiP7fgL/13ECJMezwJti6bvAAxEZscNNK9D9r6BSQdY52dgMGJ8Yu/hSxcrfa1OkWjzTCdZZA==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@narval-xyz/armory-sdk/-/armory-sdk-0.18.0.tgz", + "integrity": "sha512-jKHeVk36wo/XjxGLogxHz3lQp6cJc9YFxZU423t26LVHFIZs4HFeFwYzhGLRR4XgPu1xDEzYfl9DXuMm6r1jmg==", "license": "MPL-2.0", "dependencies": { "@noble/curves": "1.6.0", @@ -715,7 +717,8 @@ "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" }, "node_modules/mime-db": { "version": "1.52.0", @@ -855,6 +858,18 @@ } } }, + "node_modules/yaml": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz", + "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/zod": { "version": "3.24.1", "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz", diff --git a/examples/unified-api/package.json b/examples/unified-api/package.json index 516c33453..c6a146bc2 100644 --- a/examples/unified-api/package.json +++ b/examples/unified-api/package.json @@ -9,9 +9,11 @@ "author": "", "license": "ISC", "dependencies": { - "@narval-xyz/armory-sdk": "0.17.0", + "@narval-xyz/armory-sdk": "0.18.0", "dotenv": "16.4.5", + "lodash": "^4.17.21", "tsx": "4.19.2", + "yaml": "^2.7.0", "zod": "3.24.1" } } diff --git a/examples/unified-api/vault.client.ts b/examples/unified-api/vault.client.ts index b1e817dd2..e5a69a7b4 100644 --- a/examples/unified-api/vault.client.ts +++ b/examples/unified-api/vault.client.ts @@ -1,23 +1,29 @@ -import { Hex, privateKeyToJwk } from '@narval-xyz/armory-sdk' +import { Hex, privateKeyToJwk, VaultClient } from '@narval-xyz/armory-sdk' import { buildSignerEdDSA } from '@narval-xyz/armory-sdk/signature' import dotenv from 'dotenv' import fs from 'fs' +import { cloneDeep, set } from 'lodash' import path from 'path' +import * as YAML from 'yaml' import { z } from 'zod' -import { VaultClient } from '../../packages/armory-sdk/src/lib/vault/client' + dotenv.config() -const configSchema = z.object({ +const Config = z.object({ // Narval variables clientId: z.string(), narvalAuthPrivateKey: z.string(), baseUrl: z.string(), // Connection variables - connectionPrivateKey: z.string(), - connectionApiKey: z.string(), - connectionUrl: z.string(), - connectionId: z.string().nullable(), + connection: z.object({ + url: z.string(), + id: z.string().nullable(), + credentials: z.object({ + apiKey: z.string(), + privateKey: z.string() + }) + }), // Transfer variables sourceId: z.string().nullable(), @@ -27,9 +33,12 @@ const configSchema = z.object({ amount: z.string().nullable(), assetId: z.string().nullable() }) +type Config = z.infer + +let config: Config + +const configPath = path.join(__dirname, 'config.yaml') -let config: z.infer -const configPath = path.join(__dirname, 'config.json') try { if (!fs.existsSync(configPath)) { const CLIENT_ID = process.env.CLIENT_ID @@ -45,43 +54,55 @@ try { clientId: CLIENT_ID, narvalAuthPrivateKey: NARVAL_AUTH_PRIVATE_KEY_HEX, baseUrl: BASE_URL, - connectionId: null, - connectionPrivateKey: '', - connectionApiKey: '', - connectionUrl: 'https://api.anchorage-staging.com', sourceId: null, destinationId: null, destinationType: null, destinationAddress: null, amount: null, - assetId: null + assetId: null, + connection: { + id: null, + url: 'https://api.anchorage-staging.com', + credentials: { + apiKey: '', + privateKey: '' + } + } } - fs.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 2)) + + fs.writeFileSync(configPath, YAML.stringify(defaultConfig)) + config = defaultConfig } else { const configFile = fs.readFileSync(configPath, 'utf8') - config = configSchema.parse(JSON.parse(configFile)) + config = Config.parse(YAML.parse(configFile)) } } catch (error) { - console.error('Error handling config.json:', error) + console.error('Error handling config.yaml:', error) throw error } -if (!config.connectionApiKey || !config.connectionPrivateKey) { - console.error('Missing `connectionApiKey` or `connectionPrivateKey` in config.json. Please add them and try again.') - process.exit(1) -} +type KeyPath = T extends object + ? { + [K in keyof T]: K extends string ? (T[K] extends object ? K | `${K}.${KeyPath}` : K) : never + }[keyof T] + : never -export const setConfig = ( - key: keyof z.infer, - value: z.infer[keyof z.infer] -) => { - const newConfig = configSchema.parse({ ...config, [key]: value }) - fs.writeFileSync(configPath, JSON.stringify(newConfig, null, 2)) - config = newConfig -} +type ValuePath = P extends keyof T + ? T[P] + : P extends `${infer K}.${infer R}` + ? K extends keyof T + ? ValuePath + : never + : never -export { config } +export const setConfig =

>(path: P, value: ValuePath) => { + const newConfig = cloneDeep(config) + set(newConfig, path, value) + const validConfig = Config.parse(newConfig) + fs.writeFileSync(configPath, YAML.stringify(validConfig)) + config = validConfig +} export const vaultClient = new VaultClient({ clientId: config.clientId, @@ -92,3 +113,5 @@ export const vaultClient = new VaultClient({ }, host: config.baseUrl }) + +export { config } From 798e5682d0e55357c38aa76e08c3e4109751189e Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Mon, 27 Jan 2025 16:15:15 +0100 Subject: [PATCH 102/120] Fix findAll network (#108) --- apps/vault/src/broker/core/service/network.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/vault/src/broker/core/service/network.service.ts b/apps/vault/src/broker/core/service/network.service.ts index 969a0480f..6cfd0bc12 100644 --- a/apps/vault/src/broker/core/service/network.service.ts +++ b/apps/vault/src/broker/core/service/network.service.ts @@ -52,7 +52,7 @@ export class NetworkService { this.logger.log('Network list cache not found. Fallback to database', { key }) - const assets = this.networkRepository.findAll(options) + const assets = await this.networkRepository.findAll(options) await this.cacheManager.set(key, assets) From c38b294aba31043de17c5b2f70a80db26d44e9d6 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Tue, 28 Jan 2025 10:55:37 +0100 Subject: [PATCH 103/120] Improve Vault's test speed (#115) * Remove encryption initialization on tests * Remove tracking code * Use VaultTest to create module * Use test provision on broker wallet specs * Add comments explaining the encryption setup --- apps/vault/src/__test__/shared/vault.test.ts | 42 ++++++++++ .../src/broker/__test__/e2e/account.spec.ts | 28 ++----- .../src/broker/__test__/e2e/address.spec.ts | 28 ++----- .../src/broker/__test__/e2e/asset.spec.ts | 28 ++----- .../broker/__test__/e2e/connection.spec.ts | 3 + .../__test__/e2e/known-destinations.spec.ts | 28 ++----- .../src/broker/__test__/e2e/network.spec.ts | 28 ++----- .../src/broker/__test__/e2e/proxy.spec.ts | 28 ++----- .../src/broker/__test__/e2e/transfer.spec.ts | 28 ++----- .../src/broker/__test__/e2e/wallet.spec.ts | 28 ++----- .../anchorage-scoped-sync.service.spec.ts | 29 ++----- .../anchorage-transfer.service.spec.ts | 21 +---- .../fireblocks-scoped-sync.service.spec.ts | 29 ++----- .../fireblocks-transfer.service.spec.ts | 21 +---- .../src/client/__test__/e2e/client.spec.ts | 18 ++-- apps/vault/src/provision.service.ts | 83 ++++++++++++++----- .../src/vault/__test__/e2e/account.spec.ts | 18 ++-- .../vault/src/vault/__test__/e2e/sign.spec.ts | 22 ++--- .../src/vault/__test__/e2e/wallet.spec.ts | 18 ++-- 19 files changed, 186 insertions(+), 342 deletions(-) create mode 100644 apps/vault/src/__test__/shared/vault.test.ts diff --git a/apps/vault/src/__test__/shared/vault.test.ts b/apps/vault/src/__test__/shared/vault.test.ts new file mode 100644 index 000000000..567641bb1 --- /dev/null +++ b/apps/vault/src/__test__/shared/vault.test.ts @@ -0,0 +1,42 @@ +import { EncryptionModuleOptionProvider } from '@narval/encryption-module' +import { LoggerModule } from '@narval/nestjs-shared' +import { ModuleMetadata } from '@nestjs/common' +import { EventEmitter2 } from '@nestjs/event-emitter' +import { Test, TestingModuleBuilder } from '@nestjs/testing' +import { mock } from 'jest-mock-extended' +import { ProvisionService } from '../../provision.service' +import { getTestRawAesKeyring } from '../../shared/testing/encryption.testing' +import { App } from '../../shared/type/domain.type' + +class TestProvisionService extends ProvisionService { + async provision(adminApiKeyHash?: string): Promise { + return this.run({ + adminApiKeyHash, + setupEncryption: undefined + }) + } +} + +export class VaultTest { + static createTestingModule(metadata: ModuleMetadata): TestingModuleBuilder { + const module = Test.createTestingModule(metadata) + .overrideModule(LoggerModule) + .useModule(LoggerModule.forTest()) + .overrideProvider(EncryptionModuleOptionProvider) + .useValue({ + keyring: getTestRawAesKeyring() + }) + // The encryption setup in production takes approximately 550ms. The + // provision is being called on the `beforeEach` hook which drastically + // increases the test time. Since most test cases don't need encryption to + // work correctly, we disable it to save 0.5 seconds per test case. + .overrideProvider(ProvisionService) + .useClass(TestProvisionService) + // Mock the event emitter because we don't want to send a + // connection.activated event after the creation. + .overrideProvider(EventEmitter2) + .useValue(mock()) + + return module + } +} diff --git a/apps/vault/src/broker/__test__/e2e/account.spec.ts b/apps/vault/src/broker/__test__/e2e/account.spec.ts index 56c346fe1..cf528fb43 100644 --- a/apps/vault/src/broker/__test__/e2e/account.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/account.spec.ts @@ -1,15 +1,9 @@ -import { EncryptionModuleOptionProvider } from '@narval/encryption-module' -import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' +import { REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' import { HttpStatus, INestApplication } from '@nestjs/common' -import { EventEmitter2 } from '@nestjs/event-emitter' -import { Test, TestingModule } from '@nestjs/testing' -import { mock } from 'jest-mock-extended' +import { TestingModule } from '@nestjs/testing' import { MainModule } from '../../../main.module' import { ProvisionService } from '../../../provision.service' -import { KeyValueRepository } from '../../../shared/module/key-value/core/repository/key-value.repository' -import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' -import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' import { PaginatedAccountsDto } from '../../http/rest/dto/response/paginated-accounts.dto' import { PaginatedAddressesDto } from '../../http/rest/dto/response/paginated-addresses.dto' import { ProviderAccountDto } from '../../http/rest/dto/response/provider-account.dto' @@ -18,6 +12,7 @@ import { signedRequest } from '../../shared/__test__/request' import { REQUEST_HEADER_CONNECTION_ID } from '../../shared/constant' import { TEST_ACCOUNTS } from '../util/mock-data' +import { VaultTest } from '../../../__test__/shared/vault.test' import '../../shared/__test__/matcher' describe('Account', () => { @@ -27,22 +22,9 @@ describe('Account', () => { let provisionService: ProvisionService beforeAll(async () => { - module = await Test.createTestingModule({ + module = await VaultTest.createTestingModule({ imports: [MainModule] - }) - .overrideModule(LoggerModule) - .useModule(LoggerModule.forTest()) - .overrideProvider(KeyValueRepository) - .useValue(new InMemoryKeyValueRepository()) - .overrideProvider(EncryptionModuleOptionProvider) - .useValue({ - keyring: getTestRawAesKeyring() - }) - // Mock the event emitter because we don't want to send a - // connection.activated event after the creation. - .overrideProvider(EventEmitter2) - .useValue(mock()) - .compile() + }).compile() app = module.createNestApplication() testPrismaService = module.get(TestPrismaService) diff --git a/apps/vault/src/broker/__test__/e2e/address.spec.ts b/apps/vault/src/broker/__test__/e2e/address.spec.ts index 60c881d68..efa9a3d2f 100644 --- a/apps/vault/src/broker/__test__/e2e/address.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/address.spec.ts @@ -1,21 +1,16 @@ -import { EncryptionModuleOptionProvider } from '@narval/encryption-module' -import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' +import { REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' import { HttpStatus, INestApplication } from '@nestjs/common' -import { EventEmitter2 } from '@nestjs/event-emitter' -import { Test, TestingModule } from '@nestjs/testing' -import { mock } from 'jest-mock-extended' +import { TestingModule } from '@nestjs/testing' import { map } from 'lodash' import { MainModule } from '../../../main.module' import { ProvisionService } from '../../../provision.service' -import { KeyValueRepository } from '../../../shared/module/key-value/core/repository/key-value.repository' -import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' -import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' import { PaginatedAddressesDto } from '../../http/rest/dto/response/paginated-addresses.dto' import { anchorageAddressOne, anchorageConnectionOne, seed, userPrivateKey } from '../../shared/__test__/fixture' import { signedRequest } from '../../shared/__test__/request' import { REQUEST_HEADER_CONNECTION_ID } from '../../shared/constant' +import { VaultTest } from '../../../__test__/shared/vault.test' import '../../shared/__test__/matcher' describe('Address', () => { @@ -25,22 +20,9 @@ describe('Address', () => { let provisionService: ProvisionService beforeAll(async () => { - module = await Test.createTestingModule({ + module = await VaultTest.createTestingModule({ imports: [MainModule] - }) - .overrideModule(LoggerModule) - .useModule(LoggerModule.forTest()) - .overrideProvider(KeyValueRepository) - .useValue(new InMemoryKeyValueRepository()) - .overrideProvider(EncryptionModuleOptionProvider) - .useValue({ - keyring: getTestRawAesKeyring() - }) - // Mock the event emitter because we don't want to send a - // connection.activated event after the creation. - .overrideProvider(EventEmitter2) - .useValue(mock()) - .compile() + }).compile() app = module.createNestApplication() testPrismaService = module.get(TestPrismaService) diff --git a/apps/vault/src/broker/__test__/e2e/asset.spec.ts b/apps/vault/src/broker/__test__/e2e/asset.spec.ts index d59d8ed5d..148acfc49 100644 --- a/apps/vault/src/broker/__test__/e2e/asset.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/asset.spec.ts @@ -1,22 +1,17 @@ -import { EncryptionModuleOptionProvider } from '@narval/encryption-module' -import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' +import { REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' import { HttpStatus, INestApplication } from '@nestjs/common' -import { EventEmitter2 } from '@nestjs/event-emitter' -import { Test, TestingModule } from '@nestjs/testing' -import { mock } from 'jest-mock-extended' +import { TestingModule } from '@nestjs/testing' import { ClientService } from '../../../client/core/service/client.service' import { MainModule } from '../../../main.module' import { ProvisionService } from '../../../provision.service' -import { KeyValueRepository } from '../../../shared/module/key-value/core/repository/key-value.repository' -import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' -import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' import { Provider } from '../../core/type/provider.type' import { AssetSeed } from '../../persistence/seed/asset.seed' import { NetworkSeed } from '../../persistence/seed/network.seed' import { signedRequest } from '../../shared/__test__/request' import { TEST_CLIENT_ID, testClient, testUserPrivateJwk } from '../util/mock-data' +import { VaultTest } from '../../../__test__/shared/vault.test' import { PaginatedAssetsDto } from '../../http/rest/dto/response/paginated-assets.dto' import '../../shared/__test__/matcher' @@ -30,22 +25,9 @@ describe('Asset', () => { let assetSeed: AssetSeed beforeAll(async () => { - module = await Test.createTestingModule({ + module = await VaultTest.createTestingModule({ imports: [MainModule] - }) - .overrideModule(LoggerModule) - .useModule(LoggerModule.forTest()) - .overrideProvider(KeyValueRepository) - .useValue(new InMemoryKeyValueRepository()) - .overrideProvider(EncryptionModuleOptionProvider) - .useValue({ - keyring: getTestRawAesKeyring() - }) - // Mock the event emitter because we don't want to send a - // connection.activated event after the creation. - .overrideProvider(EventEmitter2) - .useValue(mock()) - .compile() + }).compile() app = module.createNestApplication() diff --git a/apps/vault/src/broker/__test__/e2e/connection.spec.ts b/apps/vault/src/broker/__test__/e2e/connection.spec.ts index 8fa49af73..e61e66724 100644 --- a/apps/vault/src/broker/__test__/e2e/connection.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/connection.spec.ts @@ -60,6 +60,9 @@ describe('Connection', () => { eventEmitterMock = mock() eventEmitterMock.emit.mockReturnValue(true) + // IMPORTANT: Does not use `VaultTest.createTestingModule` because it would + // disable encryption and testing the connection credentials' encryption is + // critical. module = await Test.createTestingModule({ imports: [MainModule] }) diff --git a/apps/vault/src/broker/__test__/e2e/known-destinations.spec.ts b/apps/vault/src/broker/__test__/e2e/known-destinations.spec.ts index 2a0ee10bc..4c42d6065 100644 --- a/apps/vault/src/broker/__test__/e2e/known-destinations.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/known-destinations.spec.ts @@ -1,19 +1,13 @@ -import { EncryptionModuleOptionProvider } from '@narval/encryption-module' -import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' +import { REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' import { Alg, generateJwk, privateKeyToHex } from '@narval/signature' import { HttpStatus, INestApplication } from '@nestjs/common' -import { EventEmitter2 } from '@nestjs/event-emitter' -import { Test, TestingModule } from '@nestjs/testing' -import { mock } from 'jest-mock-extended' +import { TestingModule } from '@nestjs/testing' import request from 'supertest' import { v4 as uuid } from 'uuid' import { ClientService } from '../../../client/core/service/client.service' import { MainModule } from '../../../main.module' import { ProvisionService } from '../../../provision.service' -import { KeyValueRepository } from '../../../shared/module/key-value/core/repository/key-value.repository' -import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' -import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' import { ANCHORAGE_TEST_API_BASE_URL, getHandlers } from '../../core/provider/anchorage/__test__/server-mock/server' import { ConnectionService } from '../../core/service/connection.service' import { Provider } from '../../core/type/provider.type' @@ -24,6 +18,7 @@ import { setupMockServer } from '../../shared/__test__/mock-server' import { REQUEST_HEADER_CONNECTION_ID } from '../../shared/constant' import { getJwsd, testClient, testUserPrivateJwk } from '../util/mock-data' +import { VaultTest } from '../../../__test__/shared/vault.test' import '../../shared/__test__/matcher' describe('Known Destination', () => { @@ -41,22 +36,9 @@ describe('Known Destination', () => { setupMockServer(getHandlers()) beforeAll(async () => { - module = await Test.createTestingModule({ + module = await VaultTest.createTestingModule({ imports: [MainModule] - }) - .overrideModule(LoggerModule) - .useModule(LoggerModule.forTest()) - .overrideProvider(KeyValueRepository) - .useValue(new InMemoryKeyValueRepository()) - .overrideProvider(EncryptionModuleOptionProvider) - .useValue({ - keyring: getTestRawAesKeyring() - }) - // Mock the event emitter because we don't want to send a - // connection.activated event after the creation. - .overrideProvider(EventEmitter2) - .useValue(mock()) - .compile() + }).compile() app = module.createNestApplication() diff --git a/apps/vault/src/broker/__test__/e2e/network.spec.ts b/apps/vault/src/broker/__test__/e2e/network.spec.ts index 768513618..dc874df15 100644 --- a/apps/vault/src/broker/__test__/e2e/network.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/network.spec.ts @@ -1,21 +1,16 @@ -import { EncryptionModuleOptionProvider } from '@narval/encryption-module' -import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' +import { REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' import { HttpStatus, INestApplication } from '@nestjs/common' -import { EventEmitter2 } from '@nestjs/event-emitter' -import { Test, TestingModule } from '@nestjs/testing' -import { mock } from 'jest-mock-extended' +import { TestingModule } from '@nestjs/testing' import { ClientService } from '../../../client/core/service/client.service' import { MainModule } from '../../../main.module' import { ProvisionService } from '../../../provision.service' -import { KeyValueRepository } from '../../../shared/module/key-value/core/repository/key-value.repository' -import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' -import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' import { PaginatedNetworksDto } from '../../http/rest/dto/response/paginated-networks.dto' import { NetworkSeed } from '../../persistence/seed/network.seed' import { signedRequest } from '../../shared/__test__/request' import { TEST_CLIENT_ID, testClient, testUserPrivateJwk } from '../util/mock-data' +import { VaultTest } from '../../../__test__/shared/vault.test' import '../../shared/__test__/matcher' describe('Network', () => { @@ -28,22 +23,9 @@ describe('Network', () => { let networkSeed: NetworkSeed beforeAll(async () => { - module = await Test.createTestingModule({ + module = await VaultTest.createTestingModule({ imports: [MainModule] - }) - .overrideModule(LoggerModule) - .useModule(LoggerModule.forTest()) - .overrideProvider(KeyValueRepository) - .useValue(new InMemoryKeyValueRepository()) - .overrideProvider(EncryptionModuleOptionProvider) - .useValue({ - keyring: getTestRawAesKeyring() - }) - // Mock the event emitter because we don't want to send a - // connection.activated event after the creation. - .overrideProvider(EventEmitter2) - .useValue(mock()) - .compile() + }).compile() app = module.createNestApplication() diff --git a/apps/vault/src/broker/__test__/e2e/proxy.spec.ts b/apps/vault/src/broker/__test__/e2e/proxy.spec.ts index 0a39901e4..8b0d0dd7e 100644 --- a/apps/vault/src/broker/__test__/e2e/proxy.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/proxy.spec.ts @@ -1,19 +1,14 @@ -import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' +import { REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' import { Alg, generateJwk, privateKeyToHex } from '@narval/signature' import { HttpStatus, INestApplication } from '@nestjs/common' -import { EventEmitter2 } from '@nestjs/event-emitter' -import { Test, TestingModule } from '@nestjs/testing' -import { mock } from 'jest-mock-extended' +import { TestingModule } from '@nestjs/testing' import nock from 'nock' -import { EncryptionModuleOptionProvider } from 'packages/encryption-module/src/lib/encryption.module' import request from 'supertest' +import { VaultTest } from '../../../__test__/shared/vault.test' import { ClientService } from '../../../client/core/service/client.service' import { MainModule } from '../../../main.module' import { ProvisionService } from '../../../provision.service' -import { KeyValueRepository } from '../../../shared/module/key-value/core/repository/key-value.repository' -import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' -import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' import { ConnectionService } from '../../core/service/connection.service' import { Provider } from '../../core/type/provider.type' import { REQUEST_HEADER_CONNECTION_ID } from '../../shared/constant' @@ -32,22 +27,9 @@ describe('Proxy', () => { const MOCK_API_URL = 'https://api.anchorage-staging.com' beforeAll(async () => { - module = await Test.createTestingModule({ + module = await VaultTest.createTestingModule({ imports: [MainModule] - }) - .overrideModule(LoggerModule) - .useModule(LoggerModule.forTest()) - .overrideProvider(KeyValueRepository) - .useValue(new InMemoryKeyValueRepository()) - .overrideProvider(EncryptionModuleOptionProvider) - .useValue({ - keyring: getTestRawAesKeyring() - }) - // Mock the event emitter because we don't want to send a - // connection.activated event after the creation. - .overrideProvider(EventEmitter2) - .useValue(mock()) - .compile() + }).compile() app = module.createNestApplication() testPrismaService = module.get(TestPrismaService) diff --git a/apps/vault/src/broker/__test__/e2e/transfer.spec.ts b/apps/vault/src/broker/__test__/e2e/transfer.spec.ts index 57872f04b..e76c26e0a 100644 --- a/apps/vault/src/broker/__test__/e2e/transfer.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/transfer.spec.ts @@ -1,20 +1,15 @@ -import { EncryptionModuleOptionProvider } from '@narval/encryption-module' -import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' +import { REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' import { Ed25519PrivateKey, getPublicKey } from '@narval/signature' import { HttpStatus, INestApplication } from '@nestjs/common' -import { EventEmitter2 } from '@nestjs/event-emitter' -import { Test, TestingModule } from '@nestjs/testing' -import { mock } from 'jest-mock-extended' +import { TestingModule } from '@nestjs/testing' import { HttpResponse, http } from 'msw' import request from 'supertest' import { v4 as uuid } from 'uuid' +import { VaultTest } from '../../../__test__/shared/vault.test' import { ClientService } from '../../../client/core/service/client.service' import { MainModule } from '../../../main.module' import { ProvisionService } from '../../../provision.service' -import { KeyValueRepository } from '../../../shared/module/key-value/core/repository/key-value.repository' -import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' -import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' import postAnchorageTransferBadRequest from '../../core/provider/anchorage/__test__/server-mock/response/post-transfer-400.json' import { ANCHORAGE_TEST_API_BASE_URL, getHandlers } from '../../core/provider/anchorage/__test__/server-mock/server' import { ConnectionStatus, ConnectionWithCredentials } from '../../core/type/connection.type' @@ -151,22 +146,9 @@ describe('Transfer', () => { const mockServer = setupMockServer(getHandlers()) beforeAll(async () => { - module = await Test.createTestingModule({ + module = await VaultTest.createTestingModule({ imports: [MainModule] - }) - .overrideModule(LoggerModule) - .useModule(LoggerModule.forTest()) - .overrideProvider(KeyValueRepository) - .useValue(new InMemoryKeyValueRepository()) - .overrideProvider(EncryptionModuleOptionProvider) - .useValue({ - keyring: getTestRawAesKeyring() - }) - // Mock the event emitter because we don't want to send a - // connection.activated event after the creation. - .overrideProvider(EventEmitter2) - .useValue(mock()) - .compile() + }).compile() app = module.createNestApplication() diff --git a/apps/vault/src/broker/__test__/e2e/wallet.spec.ts b/apps/vault/src/broker/__test__/e2e/wallet.spec.ts index fe79247f4..12155a055 100644 --- a/apps/vault/src/broker/__test__/e2e/wallet.spec.ts +++ b/apps/vault/src/broker/__test__/e2e/wallet.spec.ts @@ -1,15 +1,10 @@ -import { EncryptionModuleOptionProvider } from '@narval/encryption-module' -import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' +import { REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' import { HttpStatus, INestApplication } from '@nestjs/common' -import { EventEmitter2 } from '@nestjs/event-emitter' -import { Test, TestingModule } from '@nestjs/testing' -import { mock } from 'jest-mock-extended' +import { TestingModule } from '@nestjs/testing' +import { VaultTest } from '../../../__test__/shared/vault.test' import { MainModule } from '../../../main.module' import { ProvisionService } from '../../../provision.service' -import { KeyValueRepository } from '../../../shared/module/key-value/core/repository/key-value.repository' -import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' -import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' import { Account, Wallet } from '../../core/type/indexed-resources.type' import { PaginatedWalletsDto } from '../../http/rest/dto/response/paginated-wallets.dto' import { ProviderWalletDto } from '../../http/rest/dto/response/provider-wallet.dto' @@ -27,22 +22,9 @@ describe('Wallet', () => { let provisionService: ProvisionService beforeAll(async () => { - module = await Test.createTestingModule({ + module = await VaultTest.createTestingModule({ imports: [MainModule] - }) - .overrideModule(LoggerModule) - .useModule(LoggerModule.forTest()) - .overrideProvider(KeyValueRepository) - .useValue(new InMemoryKeyValueRepository()) - .overrideProvider(EncryptionModuleOptionProvider) - .useValue({ - keyring: getTestRawAesKeyring() - }) - // Mock the event emitter because we don't want to send a - // connection.activated event after the creation. - .overrideProvider(EventEmitter2) - .useValue(mock()) - .compile() + }).compile() app = module.createNestApplication() testPrismaService = module.get(TestPrismaService) diff --git a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-scoped-sync.service.spec.ts b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-scoped-sync.service.spec.ts index 930e97d9b..200519cfe 100644 --- a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-scoped-sync.service.spec.ts +++ b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-scoped-sync.service.spec.ts @@ -1,18 +1,12 @@ -import { EncryptionModuleOptionProvider } from '@narval/encryption-module' -import { LoggerModule } from '@narval/nestjs-shared' import { Alg, generateJwk, privateKeyToHex } from '@narval/signature' import { INestApplication } from '@nestjs/common' -import { EventEmitter2 } from '@nestjs/event-emitter' -import { Test, TestingModule } from '@nestjs/testing' -import { mock } from 'jest-mock-extended' +import { TestingModule } from '@nestjs/testing' import { v4 as uuid } from 'uuid' +import { VaultTest } from '../../../../../../__test__/shared/vault.test' import { ClientService } from '../../../../../../client/core/service/client.service' import { MainModule } from '../../../../../../main.module' import { ProvisionService } from '../../../../../../provision.service' -import { KeyValueRepository } from '../../../../../../shared/module/key-value/core/repository/key-value.repository' -import { InMemoryKeyValueRepository } from '../../../../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../../../../shared/module/persistence/service/test-prisma.service' -import { getTestRawAesKeyring } from '../../../../../../shared/testing/encryption.testing' import { testClient } from '../../../../../__test__/util/mock-data' import { NetworkSeed } from '../../../../../persistence/seed/network.seed' import { setupMockServer } from '../../../../../shared/__test__/mock-server' @@ -40,27 +34,14 @@ describe(AnchorageScopedSyncService.name, () => { let provisionService: ProvisionService let testPrismaService: TestPrismaService - const mockServer = setupMockServer(getHandlers()) + setupMockServer(getHandlers()) const clientId = 'test-client-id' beforeAll(async () => { - module = await Test.createTestingModule({ + module = await VaultTest.createTestingModule({ imports: [MainModule] - }) - .overrideModule(LoggerModule) - .useModule(LoggerModule.forTest()) - .overrideProvider(KeyValueRepository) - .useValue(new InMemoryKeyValueRepository()) - .overrideProvider(EncryptionModuleOptionProvider) - .useValue({ - keyring: getTestRawAesKeyring() - }) - // Mock the event emitter because we don't want to send a - // connection.activated event after the creation. - .overrideProvider(EventEmitter2) - .useValue(mock()) - .compile() + }).compile() app = module.createNestApplication() diff --git a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts index cc5beeb12..661947e1a 100644 --- a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts +++ b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-transfer.service.spec.ts @@ -1,17 +1,13 @@ -import { EncryptionModuleOptionProvider } from '@narval/encryption-module' -import { LoggerModule } from '@narval/nestjs-shared' import { Ed25519PrivateKey, getPublicKey } from '@narval/signature' import { INestApplication } from '@nestjs/common' -import { Test, TestingModule } from '@nestjs/testing' +import { TestingModule } from '@nestjs/testing' import { v4 as uuid } from 'uuid' import { generatePrivateKey, privateKeyToAddress } from 'viem/accounts' +import { VaultTest } from '../../../../../../__test__/shared/vault.test' import { ClientService } from '../../../../../../client/core/service/client.service' import { MainModule } from '../../../../../../main.module' import { ProvisionService } from '../../../../../../provision.service' -import { KeyValueRepository } from '../../../../../../shared/module/key-value/core/repository/key-value.repository' -import { InMemoryKeyValueRepository } from '../../../../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../../../../shared/module/persistence/service/test-prisma.service' -import { getTestRawAesKeyring } from '../../../../../../shared/testing/encryption.testing' import { testClient } from '../../../../../__test__/util/mock-data' import { AccountRepository } from '../../../../../persistence/repository/account.repository' import { AddressRepository } from '../../../../../persistence/repository/address.repository' @@ -158,18 +154,9 @@ describe(AnchorageTransferService.name, () => { } beforeAll(async () => { - module = await Test.createTestingModule({ + module = await VaultTest.createTestingModule({ imports: [MainModule] - }) - .overrideModule(LoggerModule) - .useModule(LoggerModule.forTest()) - .overrideProvider(KeyValueRepository) - .useValue(new InMemoryKeyValueRepository()) - .overrideProvider(EncryptionModuleOptionProvider) - .useValue({ - keyring: getTestRawAesKeyring() - }) - .compile() + }).compile() app = module.createNestApplication() diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-scoped-sync.service.spec.ts b/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-scoped-sync.service.spec.ts index ae5d81f90..075ab43a1 100644 --- a/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-scoped-sync.service.spec.ts +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-scoped-sync.service.spec.ts @@ -1,17 +1,11 @@ -import { EncryptionModuleOptionProvider } from '@narval/encryption-module' -import { LoggerModule } from '@narval/nestjs-shared' import { INestApplication } from '@nestjs/common' -import { EventEmitter2 } from '@nestjs/event-emitter' -import { Test, TestingModule } from '@nestjs/testing' -import { mock } from 'jest-mock-extended' +import { TestingModule } from '@nestjs/testing' import { v4 as uuid } from 'uuid' +import { VaultTest } from '../../../../../../__test__/shared/vault.test' import { ClientService } from '../../../../../../client/core/service/client.service' import { MainModule } from '../../../../../../main.module' import { ProvisionService } from '../../../../../../provision.service' -import { KeyValueRepository } from '../../../../../../shared/module/key-value/core/repository/key-value.repository' -import { InMemoryKeyValueRepository } from '../../../../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../../../../shared/module/persistence/service/test-prisma.service' -import { getTestRawAesKeyring } from '../../../../../../shared/testing/encryption.testing' import { testClient } from '../../../../../__test__/util/mock-data' import { NetworkSeed } from '../../../../../persistence/seed/network.seed' import { setupMockServer } from '../../../../../shared/__test__/mock-server' @@ -40,7 +34,7 @@ describe(FireblocksScopedSyncService.name, () => { let provisionService: ProvisionService let testPrismaService: TestPrismaService - const mockServer = setupMockServer(getHandlers()) + setupMockServer(getHandlers()) const privateKeyPem = `-----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDVORyUbWt/yuW4 @@ -76,22 +70,9 @@ iYDlTZ/pWsEotE2yCl/8krs= const clientId = 'test-client-id' beforeAll(async () => { - module = await Test.createTestingModule({ + module = await VaultTest.createTestingModule({ imports: [MainModule] - }) - .overrideModule(LoggerModule) - .useModule(LoggerModule.forTest()) - .overrideProvider(KeyValueRepository) - .useValue(new InMemoryKeyValueRepository()) - .overrideProvider(EncryptionModuleOptionProvider) - .useValue({ - keyring: getTestRawAesKeyring() - }) - // Mock the event emitter because we don't want to send a - // connection.activated event after the creation. - .overrideProvider(EventEmitter2) - .useValue(mock()) - .compile() + }).compile() app = module.createNestApplication() diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-transfer.service.spec.ts b/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-transfer.service.spec.ts index e5623281a..c7df2ef86 100644 --- a/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-transfer.service.spec.ts +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-transfer.service.spec.ts @@ -1,17 +1,13 @@ -import { EncryptionModuleOptionProvider } from '@narval/encryption-module' -import { LoggerModule } from '@narval/nestjs-shared' import { RsaPrivateKey, getPublicKey } from '@narval/signature' import { INestApplication } from '@nestjs/common' -import { Test, TestingModule } from '@nestjs/testing' +import { TestingModule } from '@nestjs/testing' import { randomUUID } from 'crypto' import { generatePrivateKey, privateKeyToAddress } from 'viem/accounts' +import { VaultTest } from '../../../../../../__test__/shared/vault.test' import { ClientService } from '../../../../../../client/core/service/client.service' import { MainModule } from '../../../../../../main.module' import { ProvisionService } from '../../../../../../provision.service' -import { KeyValueRepository } from '../../../../../../shared/module/key-value/core/repository/key-value.repository' -import { InMemoryKeyValueRepository } from '../../../../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../../../../shared/module/persistence/service/test-prisma.service' -import { getTestRawAesKeyring } from '../../../../../../shared/testing/encryption.testing' import { testClient } from '../../../../../__test__/util/mock-data' import { AccountRepository } from '../../../../../persistence/repository/account.repository' import { AddressRepository } from '../../../../../persistence/repository/address.repository' @@ -176,18 +172,9 @@ describe(FireblocksTransferService.name, () => { } beforeAll(async () => { - module = await Test.createTestingModule({ + module = await VaultTest.createTestingModule({ imports: [MainModule] - }) - .overrideModule(LoggerModule) - .useModule(LoggerModule.forTest()) - .overrideProvider(KeyValueRepository) - .useValue(new InMemoryKeyValueRepository()) - .overrideProvider(EncryptionModuleOptionProvider) - .useValue({ - keyring: getTestRawAesKeyring() - }) - .compile() + }).compile() app = module.createNestApplication() diff --git a/apps/vault/src/client/__test__/e2e/client.spec.ts b/apps/vault/src/client/__test__/e2e/client.spec.ts index c2475f484..3f0b48822 100644 --- a/apps/vault/src/client/__test__/e2e/client.spec.ts +++ b/apps/vault/src/client/__test__/e2e/client.spec.ts @@ -1,5 +1,4 @@ -import { EncryptionModuleOptionProvider } from '@narval/encryption-module' -import { LoggerModule, REQUEST_HEADER_ADMIN_API_KEY } from '@narval/nestjs-shared' +import { REQUEST_HEADER_ADMIN_API_KEY } from '@narval/nestjs-shared' import { Alg, SMALLEST_RSA_MODULUS_LENGTH, @@ -8,13 +7,13 @@ import { secp256k1PublicKeySchema } from '@narval/signature' import { HttpStatus, INestApplication } from '@nestjs/common' -import { Test, TestingModule } from '@nestjs/testing' +import { TestingModule } from '@nestjs/testing' import request from 'supertest' import { v4 as uuid } from 'uuid' +import { VaultTest } from '../../../__test__/shared/vault.test' import { MainModule } from '../../../main.module' import { ProvisionService } from '../../../provision.service' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' -import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' import { ClientRepository } from '../../persistence/repository/client.repository' describe('Client', () => { @@ -27,16 +26,9 @@ describe('Client', () => { const adminApiKey = 'test-vault-admin-api-key' beforeAll(async () => { - module = await Test.createTestingModule({ + module = await VaultTest.createTestingModule({ imports: [MainModule] - }) - .overrideModule(LoggerModule) - .useModule(LoggerModule.forTest()) - .overrideProvider(EncryptionModuleOptionProvider) - .useValue({ - keyring: getTestRawAesKeyring() - }) - .compile() + }).compile() app = module.createNestApplication() diff --git a/apps/vault/src/provision.service.ts b/apps/vault/src/provision.service.ts index 15cb2c8ea..76e9c671f 100644 --- a/apps/vault/src/provision.service.ts +++ b/apps/vault/src/provision.service.ts @@ -30,6 +30,40 @@ export class ProvisionService { // NOTE: The `adminApiKeyHash` argument is for test convinience in case it // needs to provision the application. async provision(adminApiKeyHash?: string): Promise { + return this.run({ + adminApiKeyHash, + setupEncryption: async (app, thisApp, keyring) => { + await this.setupEncryption(app, thisApp, keyring) + await this.setupRawEncryption(thisApp, keyring) + } + }) + } + + /** + * Core provisioning logic that sets up or updates the application + * configuration. This includes handling encryption setup and admin + * authentication settings. + * + * @param params Configuration parameters for the provisioning process + * + * @param params.adminApiKeyHash Optional hash of the admin API key for + * authentication + * + * @param params.setupEncryption Optional callback to customize encryption + * setup. Receives current app state, new app config, and keyring + * configuration. **Useful for disabling encryption during tests.** + * + * @returns Promise The provisioned application configuration + * + * @throws ProvisionException If app is already provisioned with different ID + * or if encryption setup fails + */ + protected async run(params: { + adminApiKeyHash?: string + setupEncryption?: (app: App | null, thisApp: App, keyring: Config['keyring']) => Promise + }): Promise { + const { adminApiKeyHash, setupEncryption } = params + // TEMPORARY: Migrate the key-value format of the App config into the table format. // Can be removed once this runs once. await this.appService.migrateV1Data() @@ -46,6 +80,33 @@ export class ProvisionService { }) } + if (setupEncryption) { + await setupEncryption(app, thisApp, keyring) + } + + // Now set the Auth if needed + thisApp.adminApiKeyHash = adminApiKeyHash || this.getAdminApiKeyHash() || null // fallback to null so we _unset_ it if it's not provided. + + // If we have an app already & the adminApiKeyHash has changed, just log that we're changing it. + if (app && thisApp.adminApiKeyHash !== app?.adminApiKeyHash) { + this.logger.log('Admin API Key has been changed', { + previous: app?.adminApiKeyHash, + current: thisApp.adminApiKeyHash + }) + } + + // Check if we disabled all auth + thisApp.authDisabled = this.configService.get('app.auth.disabled') + if (thisApp.authDisabled) { + thisApp.adminApiKeyHash = null + } + + this.logger.log('App configuration saved') + + return this.appService.save(thisApp) + } + + protected async setupEncryption(app: App | null, thisApp: App, keyring: Config['keyring']) { // No encryption set up yet, so initialize encryption if (!app?.encryptionKeyringType || (!app.encryptionMasterKey && !app.encryptionMasterAwsKmsArn)) { thisApp.encryptionKeyringType = keyring.type @@ -70,7 +131,9 @@ export class ProvisionService { throw new ProvisionException('Unsupported keyring type') } } + } + protected async setupRawEncryption(thisApp: App, keyring: Config['keyring']) { // if raw encryption, verify the encryptionMasterPassword in config is the valid kek for the encryptionMasterKey if (thisApp?.encryptionKeyringType === 'raw' && keyring.type === 'raw' && thisApp.encryptionMasterKey) { try { @@ -85,26 +148,6 @@ export class ProvisionService { throw new ProvisionException('Master Encryption Key Verification Failed', { error }) } } - - // Now set the Auth if needed - thisApp.adminApiKeyHash = adminApiKeyHash || this.getAdminApiKeyHash() || null // fallback to null so we _unset_ it if it's not provided. - - // If we have an app already & the adminApiKeyHash has changed, just log that we're changing it. - if (app && thisApp.adminApiKeyHash !== app?.adminApiKeyHash) { - this.logger.log('Admin API Key has been changed', { - previous: app?.adminApiKeyHash, - current: thisApp.adminApiKeyHash - }) - } - - // Check if we disabled all auth - thisApp.authDisabled = this.configService.get('app.auth.disabled') - if (thisApp.authDisabled) { - thisApp.adminApiKeyHash = null - } - - this.logger.log('App configuration saved') - return this.appService.save(thisApp) } private getAdminApiKeyHash(): string | null | undefined { diff --git a/apps/vault/src/vault/__test__/e2e/account.spec.ts b/apps/vault/src/vault/__test__/e2e/account.spec.ts index 85cc0f90d..51b00eccb 100644 --- a/apps/vault/src/vault/__test__/e2e/account.spec.ts +++ b/apps/vault/src/vault/__test__/e2e/account.spec.ts @@ -1,6 +1,5 @@ import { Permission } from '@narval/armory-sdk' -import { EncryptionModuleOptionProvider } from '@narval/encryption-module' -import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' +import { REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' import { Payload, RsaPublicKey, @@ -13,14 +12,14 @@ import { signJwt } from '@narval/signature' import { HttpStatus, INestApplication } from '@nestjs/common' -import { Test, TestingModule } from '@nestjs/testing' +import { TestingModule } from '@nestjs/testing' import request from 'supertest' import { v4 as uuid } from 'uuid' +import { VaultTest } from '../../../__test__/shared/vault.test' import { ClientService } from '../../../client/core/service/client.service' import { MainModule } from '../../../main.module' import { ProvisionService } from '../../../provision.service' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' -import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' import { Client, Origin } from '../../../shared/type/domain.type' const PRIVATE_KEY = '0x7cfef3303797cbc7515d9ce22ffe849c701b0f2812f999b0847229c47951fca5' @@ -97,16 +96,9 @@ describe('Accounts', () => { } beforeAll(async () => { - module = await Test.createTestingModule({ + module = await VaultTest.createTestingModule({ imports: [MainModule] - }) - .overrideModule(LoggerModule) - .useModule(LoggerModule.forTest()) - .overrideProvider(EncryptionModuleOptionProvider) - .useValue({ - keyring: getTestRawAesKeyring() - }) - .compile() + }).compile() app = module.createNestApplication({ logger: false }) diff --git a/apps/vault/src/vault/__test__/e2e/sign.spec.ts b/apps/vault/src/vault/__test__/e2e/sign.spec.ts index 537cc8c62..ba3ad046a 100644 --- a/apps/vault/src/vault/__test__/e2e/sign.spec.ts +++ b/apps/vault/src/vault/__test__/e2e/sign.spec.ts @@ -1,5 +1,4 @@ -import { EncryptionModuleOptionProvider } from '@narval/encryption-module' -import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' +import { REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' import { Action, FIXTURE } from '@narval/policy-engine-shared' import { SigningAlg, @@ -15,17 +14,15 @@ import { type Payload } from '@narval/signature' import { HttpStatus, INestApplication } from '@nestjs/common' -import { Test, TestingModule } from '@nestjs/testing' +import { TestingModule } from '@nestjs/testing' import request from 'supertest' import { v4 as uuid } from 'uuid' import { verifyMessage } from 'viem' +import { VaultTest } from '../../../__test__/shared/vault.test' import { ClientService } from '../../../client/core/service/client.service' import { MainModule } from '../../../main.module' import { ProvisionService } from '../../../provision.service' -import { KeyValueRepository } from '../../../shared/module/key-value/core/repository/key-value.repository' -import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' -import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' import { Client, Origin, PrivateAccount } from '../../../shared/type/domain.type' import { AccountRepository } from '../../persistence/repository/account.repository' @@ -158,18 +155,9 @@ describe('Sign', () => { } beforeAll(async () => { - module = await Test.createTestingModule({ + module = await VaultTest.createTestingModule({ imports: [MainModule] - }) - .overrideModule(LoggerModule) - .useModule(LoggerModule.forTest()) - .overrideProvider(KeyValueRepository) - .useValue(new InMemoryKeyValueRepository()) - .overrideProvider(EncryptionModuleOptionProvider) - .useValue({ - keyring: getTestRawAesKeyring() - }) - .compile() + }).compile() app = module.createNestApplication({ logger: false }) diff --git a/apps/vault/src/vault/__test__/e2e/wallet.spec.ts b/apps/vault/src/vault/__test__/e2e/wallet.spec.ts index 50ed3f3e0..6c42f3b8c 100644 --- a/apps/vault/src/vault/__test__/e2e/wallet.spec.ts +++ b/apps/vault/src/vault/__test__/e2e/wallet.spec.ts @@ -1,6 +1,5 @@ import { Permission, resourceId } from '@narval/armory-sdk' -import { EncryptionModuleOptionProvider } from '@narval/encryption-module' -import { LoggerModule, REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' +import { REQUEST_HEADER_CLIENT_ID } from '@narval/nestjs-shared' import { Alg, Curves, @@ -18,16 +17,16 @@ import { signJwt } from '@narval/signature' import { HttpStatus, INestApplication } from '@nestjs/common' -import { Test, TestingModule } from '@nestjs/testing' +import { TestingModule } from '@nestjs/testing' import { generateMnemonic } from '@scure/bip39' import request from 'supertest' import { v4 as uuid } from 'uuid' import { english } from 'viem/accounts' +import { VaultTest } from '../../../__test__/shared/vault.test' import { ClientService } from '../../../client/core/service/client.service' import { MainModule } from '../../../main.module' import { ProvisionService } from '../../../provision.service' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' -import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' import { Client, Origin } from '../../../shared/type/domain.type' import { ImportService } from '../../core/service/import.service' import { KeyGenerationService } from '../../core/service/key-generation.service' @@ -103,16 +102,9 @@ describe('Generate', () => { } beforeAll(async () => { - module = await Test.createTestingModule({ + module = await VaultTest.createTestingModule({ imports: [MainModule] - }) - .overrideModule(LoggerModule) - .useModule(LoggerModule.forTest()) - .overrideProvider(EncryptionModuleOptionProvider) - .useValue({ - keyring: getTestRawAesKeyring() - }) - .compile() + }).compile() app = module.createNestApplication({ logger: false }) From 67ef11f2714fc609e5ae60f8f36ef09b4aa8d26a Mon Sep 17 00:00:00 2001 From: Ptroger <44851272+Ptroger@users.noreply.github.com> Date: Tue, 28 Jan 2025 15:01:15 +0100 Subject: [PATCH 104/120] Delete sync operations (#110) * removed operations, scope sync can partially succeed * refactor bitgo and fireblocks * tests fixed for new interface * removed unused services imports * adding logs to the wallet bulkUpsert method * networkMap is a map, addressed namings, used constants instead of numbers * namings, complete function handles partial success for scoped sync service * lock sync when there's already an in progresss sync for this connection * Trying larger runner * fixed the network caching, and the lock on scope sync * Revert "Trying larger runner" This reverts commit bda1bb6b3154ae3f71740bbbcf7d0aca263649dc. * raw account errors are more precise * fireblocks raw accounts building use external network id * fixed reads for upserts outside of tx scope * exists take the status as a parameter * removed unused function --------- Co-authored-by: Matt Schoch --- .../core/exception/scoped-sync.exception.ts | 13 + .../anchorage-scoped-sync.service.spec.ts | 109 ++-- .../anchorage-scoped-sync.service.ts | 465 +++++++++--------- .../core/provider/anchorage/anchorage.util.ts | 2 + .../fireblocks-scoped-sync.service.spec.ts | 126 ++--- .../response/get-vault-account-invalid.json | 4 + .../get-wallet-addresses-ethereum-200.json | 2 +- .../fireblocks/__test__/server-mock/server.ts | 24 +- .../fireblocks-scoped-sync.service.ts | 462 +++++++++-------- .../provider/fireblocks/fireblocks.util.ts | 16 +- .../broker/core/service/account.service.ts | 4 + .../broker/core/service/network.service.ts | 4 +- .../core/service/raw-account.service.ts | 100 ++-- .../core/service/scoped-sync.service.ts | 226 +++++---- .../src/broker/core/service/wallet.service.ts | 4 + .../src/broker/core/type/network.type.ts | 5 +- .../src/broker/core/type/provider.type.ts | 214 +------- .../src/broker/core/type/scoped-sync.type.ts | 52 +- .../broker/core/util/provider-sync.util.ts | 16 - .../http/rest/dto/response/scoped-sync.dto.ts | 6 +- .../repository/account.repository.ts | 82 ++- .../repository/address.repository.ts | 23 +- .../repository/scoped-sync.repository.ts | 20 +- .../repository/wallet.repository.ts | 84 +++- .../migration.sql | 2 + .../module/persistence/schema/schema.prisma | 15 +- 26 files changed, 1087 insertions(+), 993 deletions(-) create mode 100644 apps/vault/src/broker/core/exception/scoped-sync.exception.ts create mode 100644 apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-vault-account-invalid.json delete mode 100644 apps/vault/src/broker/core/util/provider-sync.util.ts create mode 100644 apps/vault/src/shared/module/persistence/schema/migrations/20250124164857_store_failed_raw_accounts_requests/migration.sql diff --git a/apps/vault/src/broker/core/exception/scoped-sync.exception.ts b/apps/vault/src/broker/core/exception/scoped-sync.exception.ts new file mode 100644 index 000000000..1044715df --- /dev/null +++ b/apps/vault/src/broker/core/exception/scoped-sync.exception.ts @@ -0,0 +1,13 @@ +import { HttpStatus } from '@nestjs/common' +import { ApplicationExceptionParams } from '../../../shared/exception/application.exception' +import { BrokerException } from './broker.exception' + +export class ScopedSyncException extends BrokerException { + constructor(params?: Partial) { + super({ + message: params?.message || 'Fail to sync provider connection', + suggestedHttpStatusCode: params?.suggestedHttpStatusCode || HttpStatus.UNPROCESSABLE_ENTITY, + ...params + }) + } +} diff --git a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-scoped-sync.service.spec.ts b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-scoped-sync.service.spec.ts index 200519cfe..7d112042a 100644 --- a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-scoped-sync.service.spec.ts +++ b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-scoped-sync.service.spec.ts @@ -10,12 +10,11 @@ import { TestPrismaService } from '../../../../../../shared/module/persistence/s import { testClient } from '../../../../../__test__/util/mock-data' import { NetworkSeed } from '../../../../../persistence/seed/network.seed' import { setupMockServer } from '../../../../../shared/__test__/mock-server' -import { AccountService } from '../../../../service/account.service' -import { AddressService } from '../../../../service/address.service' import { ConnectionService } from '../../../../service/connection.service' -import { WalletService } from '../../../../service/wallet.service' +import { NetworkService } from '../../../../service/network.service' import { ConnectionWithCredentials } from '../../../../type/connection.type' -import { Provider, isCreateOperation } from '../../../../type/provider.type' +import { Provider } from '../../../../type/provider.type' +import { RawAccountError } from '../../../../type/scoped-sync.type' import { AnchorageScopedSyncService } from '../../anchorage-scoped-sync.service' import { ANCHORAGE_TEST_API_BASE_URL, getHandlers } from '../server-mock/server' @@ -26,9 +25,7 @@ describe(AnchorageScopedSyncService.name, () => { let anchorageScopedSyncService: AnchorageScopedSyncService let clientService: ClientService let connection: ConnectionWithCredentials - let walletService: WalletService - let accountService: AccountService - let addressService: AddressService + let networkService: NetworkService let connectionService: ConnectionService let networkSeed: NetworkSeed let provisionService: ProvisionService @@ -48,9 +45,7 @@ describe(AnchorageScopedSyncService.name, () => { testPrismaService = module.get(TestPrismaService) anchorageScopedSyncService = module.get(AnchorageScopedSyncService) connectionService = module.get(ConnectionService) - walletService = module.get(WalletService) - accountService = module.get(AccountService) - addressService = module.get(AddressService) + networkService = module.get(NetworkService) provisionService = module.get(ProvisionService) networkSeed = module.get(NetworkSeed) clientService = module.get(ClientService) @@ -94,7 +89,14 @@ describe(AnchorageScopedSyncService.name, () => { externalId: '6a46a1977959e0529f567e8e927e3895' } ] - const sync = await anchorageScopedSyncService.scopedSync(connection, rawAccounts) + const networks = await networkService.buildProviderExternalIdIndex(Provider.ANCHORAGE) + + const sync = await anchorageScopedSyncService.scopeSync({ + connection, + rawAccounts, + networks, + existingAccounts: [] + }) expect(sync.wallets.length).toBe(1) expect(sync.accounts.length).toBe(1) @@ -103,75 +105,76 @@ describe(AnchorageScopedSyncService.name, () => { // TODO @ptroger: revert that back to 'return empty array' when we completely move towards the scoped connections it('returns full connection sync when empty rawAccounts are provided', async () => { - const sync = await anchorageScopedSyncService.scopedSync(connection, []) + const networks = await networkService.buildProviderExternalIdIndex(Provider.ANCHORAGE) + + const sync = await anchorageScopedSyncService.scopeSync({ + connection, + rawAccounts: [], + networks, + existingAccounts: [] + }) expect(sync.wallets.length).toBe(2) expect(sync.accounts.length).toBe(18) - expect(sync.addresses.length).toBe(2) + expect(sync.addresses.length).toBe(18) }) - it('returns empty array when no wallets are found for the provided rawAccounts', async () => { + it('adds failure when external resource is not found', async () => { const rawAccounts = [ { provider: Provider.ANCHORAGE, externalId: 'notFound' } ] - const sync = await anchorageScopedSyncService.scopedSync(connection, rawAccounts) + const networks = await networkService.buildProviderExternalIdIndex(Provider.ANCHORAGE) + + const sync = await anchorageScopedSyncService.scopeSync({ + connection, + rawAccounts, + networks, + existingAccounts: [] + }) expect(sync.wallets.length).toBe(0) expect(sync.accounts.length).toBe(0) expect(sync.addresses.length).toBe(0) - }) - it('skips duplicate for the same connection', async () => { - const rawAccounts = [ + expect(sync.failures).toEqual([ { - provider: Provider.ANCHORAGE, - externalId: '6a46a1977959e0529f567e8e927e3895' + rawAccount: rawAccounts[0], + message: 'Anchorage wallet not found', + code: RawAccountError.EXTERNAL_RESOURCE_NOT_FOUND, + externalResourceType: 'wallet', + externalResourceId: rawAccounts[0].externalId } - ] - const firstSync = await anchorageScopedSyncService.scopedSync(connection, rawAccounts) - - await walletService.bulkCreate(firstSync.wallets.filter(isCreateOperation).map(({ create }) => create)) - await accountService.bulkCreate(firstSync.accounts.filter(isCreateOperation).map(({ create }) => create)) - await addressService.bulkCreate(firstSync.addresses.filter(isCreateOperation).map(({ create }) => create)) - - const secondSync = await anchorageScopedSyncService.scopedSync(connection, rawAccounts) - - expect(secondSync.wallets.length).toBe(0) - expect(secondSync.accounts.length).toBe(0) - expect(secondSync.addresses.length).toBe(0) + ]) }) - it('duplicates for different connections', async () => { + it('adds failure when network is not found in our list', async () => { const rawAccounts = [ { provider: Provider.ANCHORAGE, externalId: '6a46a1977959e0529f567e8e927e3895' } ] - const firstSync = await anchorageScopedSyncService.scopedSync(connection, rawAccounts) - - await walletService.bulkCreate(firstSync.wallets.filter(isCreateOperation).map(({ create }) => create)) - await accountService.bulkCreate(firstSync.accounts.filter(isCreateOperation).map(({ create }) => create)) - await addressService.bulkCreate(firstSync.addresses.filter(isCreateOperation).map(({ create }) => create)) - - const secondConnection = await connectionService.create(clientId, { - connectionId: uuid(), - provider: Provider.ANCHORAGE, - url: ANCHORAGE_TEST_API_BASE_URL, - label: 'test active connection', - credentials: { - apiKey: 'test-api-key', - privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) - } - }) - const secondSync = await anchorageScopedSyncService.scopedSync(secondConnection, rawAccounts) + const sync = await anchorageScopedSyncService.scopeSync({ + connection, + rawAccounts, + networks: new Map(), + existingAccounts: [] + }) - expect(secondSync.wallets.length).toBe(1) - expect(secondSync.accounts.length).toBe(1) - expect(secondSync.addresses.length).toBe(1) + expect(sync.wallets.length).toBe(0) + expect(sync.accounts.length).toBe(0) + expect(sync.addresses.length).toBe(0) + expect(sync.failures).toEqual([ + { + rawAccount: rawAccounts[0], + message: 'Network for this account is not supported', + code: RawAccountError.UNLISTED_NETWORK, + networkId: 'BTC_S' + } + ]) }) }) }) diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage-scoped-sync.service.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage-scoped-sync.service.ts index c4cfbf0b4..530aa21d3 100644 --- a/apps/vault/src/broker/core/provider/anchorage/anchorage-scoped-sync.service.ts +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage-scoped-sync.service.ts @@ -1,287 +1,278 @@ import { LoggerService } from '@narval/nestjs-shared' import { HttpStatus, Injectable } from '@nestjs/common' import { randomUUID } from 'crypto' -import { filter, find, flatMap, flow, groupBy, isEmpty, map, uniqBy } from 'lodash/fp' +import { chunk, uniqBy } from 'lodash/fp' import { AnchorageClient, Wallet as AnchorageWallet } from '../../../http/client/anchorage.client' -import { UpdateAccount } from '../../../persistence/repository/account.repository' -import { NetworkRepository } from '../../../persistence/repository/network.repository' -import { WalletRepository } from '../../../persistence/repository/wallet.repository' import { ConnectionWithCredentials } from '../../type/connection.type' -import { Account, Address, UpdateWallet, Wallet } from '../../type/indexed-resources.type' +import { Account, Address, Wallet } from '../../type/indexed-resources.type' +import { NetworkMap } from '../../type/network.type' +import { Provider, ProviderScopedSyncService } from '../../type/provider.type' import { - CreateScopedSyncOperation, - Provider, - ProviderScopedSyncService, - ScopedSyncOperation, - ScopedSyncOperationType, + RawAccount, + RawAccountError, + RawAccountSyncFailure, + ScopedSyncContext, ScopedSyncResult -} from '../../type/provider.type' -import { RawAccount } from '../../type/scoped-sync.type' -import { CONCURRENT_ANCHORAGE_REQUESTS, validateConnection } from './anchorage.util' +} from '../../type/scoped-sync.type' +import { CONCURRENT_ANCHORAGE_REQUESTS, ValidConnection, validateConnection } from './anchorage.util' + +type RawAccountSyncSuccess = { + success: true + wallet: Wallet + account: Account + address: Address +} + +type RawAccountSyncFailed = { + success: false + failure: RawAccountSyncFailure +} + +type RawAccountSyncResult = RawAccountSyncSuccess | RawAccountSyncFailed @Injectable() export class AnchorageScopedSyncService implements ProviderScopedSyncService { constructor( private readonly anchorageClient: AnchorageClient, - private readonly networkRepository: NetworkRepository, - private readonly walletRepository: WalletRepository, private readonly logger: LoggerService ) {} - private async fetchRawAccountWallets( - connection: ConnectionWithCredentials, - rawAccounts: RawAccount[] - ): Promise { - validateConnection(connection) + private resolveFailure(failure: RawAccountSyncFailure): RawAccountSyncFailed { + this.logger.log('Failed to sync Raw Account', failure) + return { success: false, failure } + } - const wallets: AnchorageWallet[] = [] + private resolveSuccess({ + rawAccount, + wallet, + account, + address + }: { + wallet: Wallet + address: Address + rawAccount: RawAccount + account: Account + }): RawAccountSyncSuccess { + this.logger.log('Successfully fetched and map Raw Account', { + rawAccount, + account + }) + return { + success: true, + wallet, + account, + address + } + } - for (let i = 0; i < rawAccounts.length; i += CONCURRENT_ANCHORAGE_REQUESTS) { - const batch = rawAccounts.slice(i, i + CONCURRENT_ANCHORAGE_REQUESTS) - const batchPromises = batch.map((rawAccount) => - this.anchorageClient.getWallet({ - url: connection.url, - apiKey: connection.credentials.apiKey, - signKey: connection.credentials.privateKey, - walletId: rawAccount.externalId - }) - ) + private mapAnchorageWalletToNarvalModel( + anchorageWallet: AnchorageWallet, + { + networks, + now, + existingAccounts, + rawAccount, + connection, + existingWallets + }: { + networks: NetworkMap + now: Date + existingAccounts: Account[] + existingWallets: Wallet[] + rawAccount: RawAccount + connection: ValidConnection + } + ): RawAccountSyncResult { + const network = networks.get(anchorageWallet.networkId) + if (!network) { + this.logger.error('Network not found', { + rawAccount, + externalNetwork: anchorageWallet.networkId + }) + return this.resolveFailure({ + rawAccount, + message: 'Network for this account is not supported', + code: RawAccountError.UNLISTED_NETWORK, + networkId: anchorageWallet.networkId + }) + } + const existingAccount = existingAccounts.find((a) => a.externalId === anchorageWallet.walletId) + const existingWallet = existingWallets.find((w) => w.externalId === anchorageWallet.vaultId) - const batchResults = await Promise.allSettled(batchPromises) + const walletId = existingWallet?.walletId || existingAccount?.walletId || randomUUID() + const accountId = existingAccount?.accountId || randomUUID() - const validWallets = batchResults - .map((result, index) => { - if (result.status === 'fulfilled') { - return result.value - } else { - // Handle rejected promises - const error = result.reason - const rawAccount = batch[index] + const wallet: Wallet = { + accounts: [], + clientId: connection.clientId, + connectionId: connection.connectionId, + createdAt: now, + externalId: anchorageWallet.vaultId, + label: anchorageWallet.walletName, + provider: Provider.ANCHORAGE, + updatedAt: now, + walletId + } - if (error.response?.status === HttpStatus.NOT_FOUND) { - this.logger.warn('Anchorage wallet not found', { - connectionId: connection.connectionId, - clientId: connection.clientId, - url: connection.url, - externalId: rawAccount.externalId - }) - return null - } - throw error - } - }) - .filter((wallet): wallet is AnchorageWallet => wallet !== null) as AnchorageWallet[] + const account: Account = { + externalId: anchorageWallet.walletId, + accountId, + addresses: [], + clientId: connection.clientId, + connectionId: connection.connectionId, + createdAt: now, + label: anchorageWallet.walletName, + networkId: network.networkId, + provider: Provider.ANCHORAGE, + updatedAt: now, + walletId + } - wallets.push(...validWallets) + const address: Address = { + accountId, + address: anchorageWallet.depositAddress.address, + addressId: randomUUID(), + clientId: connection.clientId, + connectionId: connection.connectionId, + createdAt: now, + externalId: anchorageWallet.depositAddress.addressId, + provider: Provider.ANCHORAGE, + updatedAt: now } - return wallets + return this.resolveSuccess({ rawAccount, wallet, account, address }) } - async scopedSync(connection: ConnectionWithCredentials, rawAccounts: RawAccount[]): Promise { - const now = new Date() + private async syncRawAccount({ + connection, + rawAccount, + networks, + now, + existingAccounts, + existingWallets + }: { + connection: ConnectionWithCredentials + rawAccount: RawAccount + networks: NetworkMap + now: Date + existingAccounts: Account[] + existingWallets: Wallet[] + }): Promise { + validateConnection(connection) + + try { + const anchorageWallet = await this.anchorageClient.getWallet({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey, + walletId: rawAccount.externalId + }) + + return this.mapAnchorageWalletToNarvalModel(anchorageWallet, { + networks, + now, + existingAccounts, + rawAccount, + connection, + existingWallets + }) + } catch (error) { + if (error.response?.status === HttpStatus.NOT_FOUND) { + return this.resolveFailure({ + rawAccount, + message: 'Anchorage wallet not found', + code: RawAccountError.EXTERNAL_RESOURCE_NOT_FOUND, + externalResourceType: 'wallet', + externalResourceId: rawAccount.externalId + }) + } + throw error + } + } + async scopeSync({ + connection, + rawAccounts, + networks, + existingAccounts + }: ScopedSyncContext): Promise { this.logger.log('Sync Anchorage accounts', { connectionId: connection.connectionId, clientId: connection.clientId, url: connection.url }) - validateConnection(connection) - - const existingWallets = await this.walletRepository.findAll( - { clientId: connection.clientId, connectionId: connection.connectionId }, - { pagination: { disabled: true } } - ) - - const existingWalletMap = new Map(existingWallets.data.map((wallet) => [wallet.externalId, wallet])) - const existingAccountMap = new Map( - existingWallets.data.flatMap( - (wallet) => - wallet.accounts?.map((account) => [account.externalId, { ...account, walletId: wallet.walletId }]) ?? [] - ) - ) - - // TODO @ptroger: revert that back to 'return empty array' when we completely move towards the scoped connections - const scopedAnchorageWallets = isEmpty(rawAccounts) - ? await this.anchorageClient.getWallets({ - url: connection.url, - apiKey: connection.credentials.apiKey, - signKey: connection.credentials.privateKey - }) - : await this.fetchRawAccountWallets(connection, rawAccounts) + const now = new Date() - const walletsByVault = groupBy('vaultId', scopedAnchorageWallets) - const vaultAndWallets = Object.entries(walletsByVault).map(([vaultId, wallets]) => ({ - id: vaultId, - // All wallets in a vault should have the same vault name - name: wallets[0].vaultName, - wallets: wallets.map((wallet) => ({ - walletId: wallet.walletId, - walletName: wallet.walletName, - address: { - address: wallet.depositAddress.address, - addressId: wallet.depositAddress.addressId - }, - assets: wallet.assets.map((asset) => ({ - assetType: asset.assetType, - availableBalance: asset.availableBalance, - totalBalance: asset.totalBalance, - stakedBalance: asset.stakedBalance, - unclaimedBalance: asset.unclaimedBalance - })), - networkId: wallet.networkId - })) - })) + const chunkedRawAccounts = chunk(CONCURRENT_ANCHORAGE_REQUESTS, rawAccounts) + const results: RawAccountSyncResult[] = [] - const walletOperations: ScopedSyncOperation[] = [] - const accountOperations: ScopedSyncOperation[] = [] - const addressOperations: ScopedSyncOperation[] = [] + // TODO @ptroger: remove the if block when we completely move towards picking accounts in UI + if (rawAccounts.length === 0) { + validateConnection(connection) - for (const vault of vaultAndWallets) { - const existingWallet = existingWalletMap.get(vault.id) - const walletId = existingWallet?.walletId || randomUUID() + const anchorageWallets = await this.anchorageClient.getWallets({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey + }) - if (existingWallet) { - // Check if wallet needs update - if (existingWallet.label !== vault.name) { - walletOperations.push({ - type: ScopedSyncOperationType.UPDATE, - update: { - clientId: connection.clientId, - walletId, - label: vault.name, - updatedAt: now - } - }) - } - } else { - // Create new wallet - walletOperations.push({ - type: ScopedSyncOperationType.CREATE, - create: { - accounts: [], - clientId: connection.clientId, - connectionId: connection.connectionId, - createdAt: now, - externalId: vault.id, - label: vault.name, - provider: Provider.ANCHORAGE, - updatedAt: now, - walletId - } + const existingWallets: Wallet[] = [] + const mappedAnchorageWallets = anchorageWallets.map((anchorageWallet) => { + const map = this.mapAnchorageWalletToNarvalModel(anchorageWallet, { + networks, + now, + existingAccounts, + rawAccount: { provider: Provider.ANCHORAGE, externalId: anchorageWallet.walletId }, + connection, + existingWallets }) - } - - const vaultAssetTypes = flow(flatMap('assets'), uniqBy('assetType'), map('assetType'))(vault.wallets) - - for (const anchorageWallet of vault.wallets) { - const existingAccount = existingAccountMap.get(anchorageWallet.walletId) - const accountId = existingAccount?.accountId || randomUUID() - const network = await this.networkRepository.findByExternalId(Provider.ANCHORAGE, anchorageWallet.networkId) + map.success && existingWallets.push(map.wallet) + return map + }) - if (network) { - if (existingAccount) { - // Check if account needs update - if (existingAccount.label !== anchorageWallet.walletName) { - accountOperations.push({ - type: ScopedSyncOperationType.UPDATE, - update: { - clientId: connection.clientId, - accountId: existingAccount.accountId, - label: anchorageWallet.walletName, - updatedAt: now - } - }) - } - } else { - accountOperations.push({ - type: ScopedSyncOperationType.CREATE, - create: { - externalId: anchorageWallet.walletId, - accountId, - addresses: [], - clientId: connection.clientId, - connectionId: connection.connectionId, - createdAt: now, - label: anchorageWallet.walletName, - networkId: network.networkId, - provider: Provider.ANCHORAGE, - updatedAt: now, - walletId - } + results.push(...mappedAnchorageWallets) + } else { + const existingWallets: Wallet[] = [] + for (const chunk of chunkedRawAccounts) { + const chunkResults = await Promise.all( + chunk.map(async (rawAccount) => { + const mapResult = await this.syncRawAccount({ + connection, + rawAccount, + networks, + now, + existingAccounts, + existingWallets }) - } - } else { - accountOperations.push({ - type: ScopedSyncOperationType.FAILED, - externalId: anchorageWallet.walletId, - message: 'Unknown Anchorage wallet network ID', - context: { - externalId: anchorageWallet.walletId, - anchorageNetworkId: anchorageWallet.networkId - } + mapResult.success && existingWallets.push(mapResult.wallet) + return mapResult }) - } + ) + results.push(...chunkResults) } + } - // Process addresses - Anchorage only creates, no updates - for (const assetType of vaultAssetTypes) { - const addresses = await this.anchorageClient.getVaultAddresses({ - signKey: connection.credentials.privateKey, - apiKey: connection.credentials.apiKey, - assetType, - url: connection.url, - vaultId: vault.id - }) - - for (const address of addresses) { - const account = flow( - filter((op: ScopedSyncOperation) => op.type === ScopedSyncOperationType.CREATE), - find((op: CreateScopedSyncOperation) => op.create.externalId === address.walletId) - )(accountOperations) - - const existingAccount = existingAccountMap.get(address.walletId) - const skipAddress = existingAccount?.addresses?.some((a) => a.externalId === address.addressId) + const wallets: Wallet[] = [] + const accounts: Account[] = [] + const addresses: Address[] = [] + const failures: RawAccountSyncFailure[] = [] - const tiedAccount = account?.create?.accountId || existingAccount?.accountId - if (!skipAddress && tiedAccount) { - if (account?.create?.accountId || existingAccount?.accountId) { - addressOperations.push({ - type: ScopedSyncOperationType.CREATE, - create: { - accountId: tiedAccount, - address: address.address, - addressId: randomUUID(), - clientId: connection.clientId, - connectionId: connection.connectionId, - createdAt: now, - externalId: address.addressId, - provider: Provider.ANCHORAGE, - updatedAt: now - } - }) - } else { - addressOperations.push({ - type: ScopedSyncOperationType.FAILED, - externalId: address.addressId, - message: 'Unknown Anchorage wallet address', - context: { - externalId: address.addressId, - address: address.address, - walletId: address.walletId - } - }) - } - } - } + for (const result of results) { + if (result.success) { + wallets.push(result.wallet) + accounts.push(result.account) + addresses.push(result.address) + } else { + failures.push(result.failure) } } return { - wallets: walletOperations, - accounts: accountOperations, - addresses: addressOperations + wallets: uniqBy('externalId', wallets), + accounts: uniqBy('externalId', accounts), + addresses: uniqBy('externalId', addresses), + failures } } } diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage.util.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage.util.ts index 5703365af..cb0ead59f 100644 --- a/apps/vault/src/broker/core/provider/anchorage/anchorage.util.ts +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage.util.ts @@ -15,6 +15,8 @@ export type ValidConnection = { apiKey: string privateKey: Ed25519PrivateKey } + clientId: string + connectionId: string } export function validateConnection( diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-scoped-sync.service.spec.ts b/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-scoped-sync.service.spec.ts index 075ab43a1..dd91c6fc9 100644 --- a/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-scoped-sync.service.spec.ts +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-scoped-sync.service.spec.ts @@ -9,15 +9,18 @@ import { TestPrismaService } from '../../../../../../shared/module/persistence/s import { testClient } from '../../../../../__test__/util/mock-data' import { NetworkSeed } from '../../../../../persistence/seed/network.seed' import { setupMockServer } from '../../../../../shared/__test__/mock-server' -import { AccountService } from '../../../../service/account.service' -import { AddressService } from '../../../../service/address.service' import { ConnectionService } from '../../../../service/connection.service' -import { WalletService } from '../../../../service/wallet.service' +import { NetworkService } from '../../../../service/network.service' import { ConnectionWithCredentials } from '../../../../type/connection.type' -import { Provider, isCreateOperation } from '../../../../type/provider.type' -import { FIREBLOCKS_TEST_API_BASE_URL, getHandlers } from '../../../fireblocks/__test__/server-mock/server' +import { Provider } from '../../../../type/provider.type' +import { RawAccountError } from '../../../../type/scoped-sync.type' +import { + FIREBLOCKS_TEST_API_BASE_URL, + getHandlers, + getVaultAccountHandlers +} from '../../../fireblocks/__test__/server-mock/server' import { FireblocksScopedSyncService } from '../../fireblocks-scoped-sync.service' -import { getFireblocksAssetWalletExternalId } from '../../fireblocks.util' +import { buildFireblocksAssetWalletExternalId } from '../../fireblocks.util' describe(FireblocksScopedSyncService.name, () => { let app: INestApplication @@ -26,11 +29,9 @@ describe(FireblocksScopedSyncService.name, () => { let fireblocksScopedSyncService: FireblocksScopedSyncService let clientService: ClientService let connection: ConnectionWithCredentials - let walletService: WalletService - let accountService: AccountService - let addressService: AddressService let connectionService: ConnectionService let networkSeed: NetworkSeed + let networkService: NetworkService let provisionService: ProvisionService let testPrismaService: TestPrismaService @@ -79,9 +80,7 @@ iYDlTZ/pWsEotE2yCl/8krs= testPrismaService = module.get(TestPrismaService) fireblocksScopedSyncService = module.get(FireblocksScopedSyncService) connectionService = module.get(ConnectionService) - walletService = module.get(WalletService) - accountService = module.get(AccountService) - addressService = module.get(AddressService) + networkService = module.get(NetworkService) provisionService = module.get(ProvisionService) networkSeed = module.get(NetworkSeed) clientService = module.get(ClientService) @@ -122,87 +121,96 @@ iYDlTZ/pWsEotE2yCl/8krs= const rawAccounts = [ { provider: Provider.FIREBLOCKS, - externalId: getFireblocksAssetWalletExternalId({ vaultId: '3', networkId: 'ETHEREUM' }) + externalId: buildFireblocksAssetWalletExternalId({ vaultId: '3', networkId: 'ETH' }) } ] - const sync = await fireblocksScopedSyncService.scopedSync(connection, rawAccounts) + + const networks = await networkService.buildProviderExternalIdIndex(Provider.FIREBLOCKS) + const sync = await fireblocksScopedSyncService.scopeSync({ + connection, + rawAccounts, + networks, + existingAccounts: [] + }) expect(sync.wallets.length).toBe(1) expect(sync.accounts.length).toBe(1) expect(sync.addresses.length).toBe(1) }) - it('returns empty array when no rawAccounts are provided', async () => { - const sync = await fireblocksScopedSyncService.scopedSync(connection, []) + it('returns empty objects when no rawAccounts are provided', async () => { + const networks = await networkService.buildProviderExternalIdIndex(Provider.FIREBLOCKS) + + const sync = await fireblocksScopedSyncService.scopeSync({ + connection, + rawAccounts: [], + networks, + existingAccounts: [] + }) expect(sync.wallets.length).toBe(0) expect(sync.accounts.length).toBe(0) expect(sync.addresses.length).toBe(0) }) - it('returns empty array when no wallets are found for the provided rawAccounts', async () => { + it('adds failure when external resource is not found', async () => { + mockServer.use(getVaultAccountHandlers(FIREBLOCKS_TEST_API_BASE_URL).invalid) const rawAccounts = [ { provider: Provider.FIREBLOCKS, - externalId: getFireblocksAssetWalletExternalId({ vaultId: 'notfound', networkId: 'ETHEREUM' }) + externalId: buildFireblocksAssetWalletExternalId({ vaultId: 'notfound', networkId: 'ETH' }) } ] - const sync = await fireblocksScopedSyncService.scopedSync(connection, rawAccounts) + const networks = await networkService.buildProviderExternalIdIndex(Provider.FIREBLOCKS) + + const sync = await fireblocksScopedSyncService.scopeSync({ + connection, + rawAccounts, + networks, + existingAccounts: [] + }) expect(sync.wallets.length).toBe(0) expect(sync.accounts.length).toBe(0) expect(sync.addresses.length).toBe(0) - }) - - it('skips duplicate for the same connection', async () => { - const rawAccounts = [ + expect(sync.failures).toEqual([ { - provider: Provider.FIREBLOCKS, - externalId: getFireblocksAssetWalletExternalId({ vaultId: '3', networkId: 'ETHEREUM' }) + rawAccount: rawAccounts[0], + message: 'Fireblocks Vault Account not found', + code: RawAccountError.EXTERNAL_RESOURCE_NOT_FOUND, + externalResourceType: 'vaultAccount', + externalResourceId: 'NOTFOUND' } - ] - const firstSync = await fireblocksScopedSyncService.scopedSync(connection, rawAccounts) - - await walletService.bulkCreate(firstSync.wallets.filter(isCreateOperation).map(({ create }) => create)) - await accountService.bulkCreate(firstSync.accounts.filter(isCreateOperation).map(({ create }) => create)) - await addressService.bulkCreate(firstSync.addresses.filter(isCreateOperation).map(({ create }) => create)) - - const secondSync = await fireblocksScopedSyncService.scopedSync(connection, rawAccounts) - - expect(secondSync.wallets.length).toBe(0) - expect(secondSync.accounts.length).toBe(0) - expect(secondSync.addresses.length).toBe(0) + ]) }) - it('duplicates for different connections', async () => { + it('adds failure when network is not found in our list', async () => { const rawAccounts = [ { provider: Provider.FIREBLOCKS, - externalId: getFireblocksAssetWalletExternalId({ vaultId: '3', networkId: 'ETHEREUM' }) + externalId: buildFireblocksAssetWalletExternalId({ vaultId: '3', networkId: 'notFound' }) } ] - const firstSync = await fireblocksScopedSyncService.scopedSync(connection, rawAccounts) - - await walletService.bulkCreate(firstSync.wallets.filter(isCreateOperation).map(({ create }) => create)) - await accountService.bulkCreate(firstSync.accounts.filter(isCreateOperation).map(({ create }) => create)) - await addressService.bulkCreate(firstSync.addresses.filter(isCreateOperation).map(({ create }) => create)) - - const secondConnection = await connectionService.create(clientId, { - connectionId: uuid(), - provider: Provider.FIREBLOCKS, - url: FIREBLOCKS_TEST_API_BASE_URL, - label: 'test active connection', - credentials: { - apiKey: 'test-api-key', - privateKey - } - }) + const networks = await networkService.buildProviderExternalIdIndex(Provider.FIREBLOCKS) - const secondSync = await fireblocksScopedSyncService.scopedSync(secondConnection, rawAccounts) + const sync = await fireblocksScopedSyncService.scopeSync({ + connection, + rawAccounts, + networks, + existingAccounts: [] + }) - expect(secondSync.wallets.length).toBe(1) - expect(secondSync.accounts.length).toBe(1) - expect(secondSync.addresses.length).toBe(1) + expect(sync.wallets.length).toBe(0) + expect(sync.accounts.length).toBe(0) + expect(sync.addresses.length).toBe(0) + expect(sync.failures).toEqual([ + { + rawAccount: rawAccounts[0], + message: 'Network for this account is not supported', + code: RawAccountError.UNLISTED_NETWORK, + networkId: 'NOTFOUND' + } + ]) }) }) }) diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-vault-account-invalid.json b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-vault-account-invalid.json new file mode 100644 index 000000000..141a18b01 --- /dev/null +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-vault-account-invalid.json @@ -0,0 +1,4 @@ +{ + "message": "The Provided Vault Account ID is invalid: 11469", + "code": 11001 +} diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-wallet-addresses-ethereum-200.json b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-wallet-addresses-ethereum-200.json index c02b95088..e38ab060f 100644 --- a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-wallet-addresses-ethereum-200.json +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-wallet-addresses-ethereum-200.json @@ -1,7 +1,7 @@ { "addresses": [ { - "assetId": "ETH-OPT", + "assetId": "ETH", "address": "0x5748EA5ca075734bc7ADc9D8046e897c24829A80", "description": "", "tag": "", diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/server.ts b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/server.ts index 958d9ab7f..46ecad105 100644 --- a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/server.ts +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/server.ts @@ -1,6 +1,8 @@ +import { HttpStatus } from '@nestjs/common' import { HttpResponse, http } from 'msw' import getTransactionOk from './response/get-transaction-200.json' import vaultAccount3 from './response/get-vault-account-3-200.json' +import vaultAccountNotFound from './response/get-vault-account-invalid.json' import getWalletAddressesEthOk from './response/get-wallet-addresses-ethereum-200.json' import getWalletAddressesMaticOk from './response/get-wallet-addresses-matic-200.json' import postTransactionCreated from './response/post-transaction-201.json' @@ -20,6 +22,22 @@ export const getVaultAccount3AddressesHandlers = (baseUrl = FIREBLOCKS_TEST_API_ } } +export const getVaultAccountHandlers = (baseUrl = FIREBLOCKS_TEST_API_BASE_URL) => { + return { + get: http.get(`${baseUrl}/v1/vault/accounts/:vaultAccountId`, () => { + return new HttpResponse(JSON.stringify(vaultAccount3)) + }), + invalid: http.get( + `${baseUrl}/v1/vault/accounts/:vaultAccountId`, + () => + new HttpResponse(JSON.stringify(vaultAccountNotFound), { + status: HttpStatus.BAD_REQUEST + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } as unknown as any) + ) + } +} + export const getHandlers = (baseUrl = FIREBLOCKS_TEST_API_BASE_URL) => [ http.get(`${baseUrl}/v1/transactions/:txId`, () => { return new HttpResponse(JSON.stringify(getTransactionOk)) @@ -29,9 +47,7 @@ export const getHandlers = (baseUrl = FIREBLOCKS_TEST_API_BASE_URL) => [ return new HttpResponse(JSON.stringify(postTransactionCreated)) }), - http.get(`${baseUrl}/v1/vault/accounts/:vaultAccountId`, () => { - return new HttpResponse(JSON.stringify(vaultAccount3)) - }), + getVaultAccountHandlers(baseUrl).get, - getVaultAccount3AddressesHandlers(baseUrl).getMatic + getVaultAccount3AddressesHandlers(baseUrl).getEth ] diff --git a/apps/vault/src/broker/core/provider/fireblocks/fireblocks-scoped-sync.service.ts b/apps/vault/src/broker/core/provider/fireblocks/fireblocks-scoped-sync.service.ts index ae7347d40..fc71960ca 100644 --- a/apps/vault/src/broker/core/provider/fireblocks/fireblocks-scoped-sync.service.ts +++ b/apps/vault/src/broker/core/provider/fireblocks/fireblocks-scoped-sync.service.ts @@ -1,293 +1,269 @@ import { LoggerService } from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' import { randomUUID } from 'crypto' -import { uniqBy } from 'lodash/fp' +import { chunk, uniqBy } from 'lodash/fp' import { FIREBLOCKS_API_ERROR_CODES, FireblocksClient, VaultAccount } from '../../../http/client/fireblocks.client' -import { UpdateAccount } from '../../../persistence/repository/account.repository' -import { NetworkRepository } from '../../../persistence/repository/network.repository' -import { WalletRepository } from '../../../persistence/repository/wallet.repository' import { ConnectionWithCredentials } from '../../type/connection.type' -import { Account, Address, UpdateWallet, Wallet } from '../../type/indexed-resources.type' +import { Account, Address, Wallet } from '../../type/indexed-resources.type' +import { NetworkMap } from '../../type/network.type' +import { Provider, ProviderScopedSyncService } from '../../type/provider.type' import { - Provider, - ProviderScopedSyncService, - ScopedSyncOperation, - ScopedSyncOperationType, + RawAccount, + RawAccountError, + RawAccountSyncFailure, + ScopedSyncContext, ScopedSyncResult -} from '../../type/provider.type' -import { RawAccount } from '../../type/scoped-sync.type' +} from '../../type/scoped-sync.type' import { CONCURRENT_FIREBLOCKS_REQUESTS, - FireblocksAssetWalletId, - getFireblocksAssetAddressExternalId, - getFireblocksAssetWalletExternalId, - toFireblocksAssetWalletExternalId, + buildFireblocksAssetAddressExternalId, + parseFireblocksAssetWalletExternalId, validateConnection } from './fireblocks.util' +type RawAccountSyncSuccess = { + success: true + wallet: Wallet + account: Account + addresses: Address[] +} + +type RawAccountSyncFailed = { + success: false + failure: RawAccountSyncFailure +} + +type RawAccountSyncResult = RawAccountSyncSuccess | RawAccountSyncFailed @Injectable() export class FireblocksScopedSyncService implements ProviderScopedSyncService { constructor( private readonly fireblocksClient: FireblocksClient, - private readonly networkRepository: NetworkRepository, - private readonly walletRepository: WalletRepository, private readonly logger: LoggerService ) {} - private async buildVaultNetworkMap( - assetWalletIds: FireblocksAssetWalletId[] - ): Promise>> { - const result: Record> = {} - - for (const { vaultId, networkId } of assetWalletIds) { - if (!vaultId || !networkId) continue - - try { - const network = await this.networkRepository.findById(networkId) - - if (!network) { - this.logger.log('Network not found', { networkId }) - continue - } - - const fireblocksNetwork = network.externalNetworks?.find((n) => n.provider === Provider.FIREBLOCKS) - if (!fireblocksNetwork) { - this.logger.log('Network not supported', { networkId, provider: Provider.FIREBLOCKS }) - continue - } + private resolveFailure(failure: RawAccountSyncFailure): RawAccountSyncFailed { + this.logger.log('Failed to sync Raw Account', failure) + return { success: false, failure } + } - if (!result[vaultId]) { - result[vaultId] = new Set() - } - result[vaultId].add({ - narvalNetworkId: networkId, - fireblocksNetworkId: fireblocksNetwork.externalId - }) - } catch (error) { - this.logger.log('Error processing network', { networkId, error: String(error) }) - } + private resolveSuccess({ + rawAccount, + wallet, + account, + addresses + }: { + wallet: Wallet + addresses: Address[] + rawAccount: RawAccount + account: Account + }): RawAccountSyncSuccess { + this.logger.log('Successfully fetched and map Raw Account', { + rawAccount, + account + }) + return { + success: true, + wallet, + account, + addresses } - - return result } - - async scopedSync(connection: ConnectionWithCredentials, rawAccounts: RawAccount[]): Promise { - const now = new Date() + private async resolveRawAccount({ + connection, + rawAccount, + networks, + now, + existingAccounts, + existingAddresses, + vaultAccount, + existingWallets + }: { + connection: ConnectionWithCredentials + rawAccount: RawAccount + networks: NetworkMap + now: Date + existingAccounts: Account[] + vaultAccount: VaultAccount + existingWallets: Wallet[] + existingAddresses: Address[] + }): Promise { validateConnection(connection) + const { vaultId, baseAssetId: networkId } = parseFireblocksAssetWalletExternalId(rawAccount.externalId) + const network = networks.get(networkId) - const existingWallets = await this.walletRepository.findAll( - { clientId: connection.clientId, connectionId: connection.connectionId }, - { pagination: { disabled: true } } - ) - - const existingWalletMap = new Map(existingWallets.data.map((wallet) => [wallet.externalId, wallet])) - const existingAccountMap = new Map( - existingWallets.data.flatMap( - (wallet) => - wallet.accounts?.map((account) => [account.externalId, { ...account, walletId: wallet.walletId }]) ?? [] - ) - ) - - const assetWalletIds = uniqBy('externalId', rawAccounts).map((account) => - toFireblocksAssetWalletExternalId(account.externalId) - ) - - const vaultToNetworkMap = await this.buildVaultNetworkMap(assetWalletIds) - const requestedVaultIds = Object.keys(vaultToNetworkMap) - - const vaults: VaultAccount[] = [] - for (let i = 0; i < Object.keys(vaultToNetworkMap).length; i += CONCURRENT_FIREBLOCKS_REQUESTS) { - const batch = Object.keys(vaultToNetworkMap).slice(i, i + CONCURRENT_FIREBLOCKS_REQUESTS) - const batchPromises = batch.map((vaultId) => - this.fireblocksClient.getVaultAccount({ - apiKey: connection.credentials.apiKey, - signKey: connection.credentials.privateKey, - url: connection.url, - vaultAccountId: vaultId - }) - ) - - const batchResults = await Promise.allSettled(batchPromises) + if (!network) { + this.logger.error('Network not found', { + rawAccount, + externalNetwork: networkId + }) + return this.resolveFailure({ + rawAccount, + message: 'Network for this account is not supported', + code: RawAccountError.UNLISTED_NETWORK, + networkId + }) + } - const validVaults = batchResults - .map((result, index) => { - if (result.status === 'fulfilled') { - return result.value - } else { - const error = result.reason - const vaultId = batch[index] + const existingAccount = existingAccounts.find((a) => a.externalId === rawAccount.externalId) + const existingWallet = existingWallets.find((a) => a.externalId === vaultId) - if (error?.response?.body?.code === FIREBLOCKS_API_ERROR_CODES.INVALID_SPECIFIED_VAULT_ACCOUNT) { - this.logger.warn('Vault not found', { - vaultId, - provider: Provider.FIREBLOCKS - }) - return null - } else { - throw error - } - } - }) - .filter((vault): vault is VaultAccount => vault !== null) + const accountLabel = `${vaultAccount.name} - ${networkId}` + const accountId = existingAccount?.accountId || randomUUID() + const walletId = existingWallet?.walletId || existingAccount?.walletId || randomUUID() + const fireblocksAddresses = await this.fireblocksClient.getAddresses({ + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey, + url: connection.url, + vaultAccountId: vaultId, + assetId: networkId + }) - vaults.push(...validVaults) + const wallet: Wallet = { + accounts: [], + clientId: connection.clientId, + connectionId: connection.connectionId, + createdAt: now, + externalId: vaultId, + label: vaultAccount.name, + provider: Provider.FIREBLOCKS, + updatedAt: now, + walletId } - // Filter to only get the vaults we need based on vaultToNetworkMap - const relevantVaults = vaults.filter((vault) => vault.id in vaultToNetworkMap) - const vaultMap = Object.fromEntries(relevantVaults.map((vault) => [vault.id, vault])) + const account: Account = { + externalId: rawAccount.externalId, + accountId, + addresses: [], + clientId: connection.clientId, + createdAt: now, + connectionId: connection.connectionId, + label: accountLabel, + networkId: network.networkId, + provider: Provider.FIREBLOCKS, + updatedAt: now, + walletId + } - // Log each missing vault - const foundVaultIds = relevantVaults.map((vault) => vault.id) - requestedVaultIds.forEach((vaultId) => { - if (!foundVaultIds.includes(vaultId)) { - this.logger.warn('Vault not found', { + const addresses: Address[] = fireblocksAddresses + .map((a) => { + const addressExternalId = buildFireblocksAssetAddressExternalId({ vaultId, - networks: vaultToNetworkMap[vaultId] + networkId, + address: a.address }) - } - }) - - const walletOperations: ScopedSyncOperation[] = [] - const accountOperations: ScopedSyncOperation[] = [] - const addressOperations: ScopedSyncOperation[] = [] - - for (const [vaultId, networkIds] of Object.entries(vaultToNetworkMap)) { - const vault = vaultMap[vaultId] - if (!vault) { - this.logger.warn('raw account was not found', { vaultId }) - continue - } - const existingWallet = existingWalletMap.get(vaultId) - const walletId = existingWallet?.walletId || randomUUID() - - if (existingWallet) { - if (existingWallet.label !== vault.name) { - walletOperations.push({ - type: ScopedSyncOperationType.UPDATE, - update: { - clientId: connection.clientId, - walletId, - label: vault.name, - updatedAt: now - } - }) - } - } else { - walletOperations.push({ - type: ScopedSyncOperationType.CREATE, - create: { - accounts: [], + const existingAddress = existingAddresses.find((a) => a.externalId === addressExternalId) + if (!existingAddress) { + return { + accountId, + address: a.address, + addressId: randomUUID(), clientId: connection.clientId, - connectionId: connection.connectionId, createdAt: now, - externalId: vaultId, - label: vault.name, + connectionId: connection.connectionId, + externalId: addressExternalId, provider: Provider.FIREBLOCKS, - updatedAt: now, - walletId + updatedAt: now } + } + return null + }) + .filter((a) => a !== null) as Address[] + + return this.resolveSuccess({ + rawAccount, + wallet, + account, + addresses + }) + } + + private async fetchVaultAccount({ + connection, + rawAccount + }: { + connection: ConnectionWithCredentials + rawAccount: RawAccount + }): Promise<{ vaultAccount: VaultAccount; rawAccount: RawAccount } | RawAccountSyncFailed> { + validateConnection(connection) + const { vaultId } = parseFireblocksAssetWalletExternalId(rawAccount.externalId) + try { + const vaultAccount = await this.fireblocksClient.getVaultAccount({ + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey, + url: connection.url, + vaultAccountId: vaultId + }) + + return { vaultAccount, rawAccount } + } catch (error) { + if (error?.response?.body?.code === FIREBLOCKS_API_ERROR_CODES.INVALID_SPECIFIED_VAULT_ACCOUNT) { + return this.resolveFailure({ + rawAccount, + message: 'Fireblocks Vault Account not found', + code: RawAccountError.EXTERNAL_RESOURCE_NOT_FOUND, + externalResourceType: 'vaultAccount', + externalResourceId: vaultId }) } + throw error + } + } - // Create accounts for each network - for (const { fireblocksNetworkId, narvalNetworkId } of networkIds) { - const accountExternalId = getFireblocksAssetWalletExternalId({ - vaultId: vault.id, - networkId: fireblocksNetworkId - }) + async scopeSync({ + connection, + rawAccounts, + networks, + existingAccounts + }: ScopedSyncContext): Promise { + validateConnection(connection) - const existingAccount = existingAccountMap.get(accountExternalId) - const accountId = existingAccount?.accountId || randomUUID() - const accountLabel = `${vault.name} - ${fireblocksNetworkId}` + const now = new Date() - try { - if (existingAccount) { - if (existingAccount.label !== accountLabel) { - accountOperations.push({ - type: ScopedSyncOperationType.UPDATE, - update: { - clientId: connection.clientId, - accountId: existingAccount.accountId, - label: accountLabel, - updatedAt: now - } - }) - } - } else { - accountOperations.push({ - type: ScopedSyncOperationType.CREATE, - create: { - externalId: accountExternalId, - accountId, - addresses: [], - clientId: connection.clientId, - createdAt: now, - connectionId: connection.connectionId, - label: accountLabel, - networkId: narvalNetworkId, - provider: Provider.FIREBLOCKS, - updatedAt: now, - walletId - } - }) - } + const chunkedRawAccounts = chunk(CONCURRENT_FIREBLOCKS_REQUESTS, rawAccounts) + const fetchResults = [] - // Fetch and process addresses - try { - const addresses = await this.fireblocksClient.getAddresses({ - apiKey: connection.credentials.apiKey, - signKey: connection.credentials.privateKey, - url: connection.url, - vaultAccountId: vault.id, - assetId: fireblocksNetworkId - }) - addresses.forEach((address) => { - const addressExternalId = getFireblocksAssetAddressExternalId({ - vaultId: vault.id, - networkId: fireblocksNetworkId, - address: address.address - }) - if (!existingAccount?.addresses?.some((a) => a.externalId === addressExternalId)) { - addressOperations.push({ - type: ScopedSyncOperationType.CREATE, - create: { - accountId, - address: address.address, - addressId: randomUUID(), - clientId: connection.clientId, - createdAt: now, - connectionId: connection.connectionId, - externalId: addressExternalId, - provider: Provider.FIREBLOCKS, - updatedAt: now - } - }) - } - }) - } catch (error) { - addressOperations.push({ - type: ScopedSyncOperationType.FAILED, - externalId: accountExternalId, - message: 'Failed to fetch addresses', - context: { error: error.message } - }) - } - } catch (error) { - accountOperations.push({ - type: ScopedSyncOperationType.FAILED, - externalId: accountExternalId, - message: 'Failed to process account', - context: { error: error.message } - }) + for (const currentChunk of chunkedRawAccounts) { + const chunkResults = await Promise.all( + currentChunk.map((rawAccount) => this.fetchVaultAccount({ connection, rawAccount })) + ) + fetchResults.push(...chunkResults) + } + + const wallets: Wallet[] = [] + const accounts: Account[] = [] + const addresses: Address[] = [] + const failures: RawAccountSyncFailure[] = [] + + for (const result of fetchResults) { + if ('success' in result && !result.success) { + failures.push(result.failure) + continue + } else if ('rawAccount' in result) { + const mappedResult = await this.resolveRawAccount({ + connection, + rawAccount: result.rawAccount, + networks, + now, + existingAccounts: [...existingAccounts, ...accounts], + existingWallets: wallets, + existingAddresses: addresses, + vaultAccount: result.vaultAccount + }) + if (mappedResult.success) { + wallets.push(mappedResult.wallet) + accounts.push(mappedResult.account) + addresses.push(...mappedResult.addresses) + } else { + failures.push(mappedResult.failure) } } } return { - wallets: walletOperations, - accounts: accountOperations, - addresses: addressOperations + wallets: uniqBy('externalId', wallets), + accounts: uniqBy('externalId', accounts), + addresses: uniqBy('externalId', addresses), + failures } } } diff --git a/apps/vault/src/broker/core/provider/fireblocks/fireblocks.util.ts b/apps/vault/src/broker/core/provider/fireblocks/fireblocks.util.ts index f6267108e..34948cea5 100644 --- a/apps/vault/src/broker/core/provider/fireblocks/fireblocks.util.ts +++ b/apps/vault/src/broker/core/provider/fireblocks/fireblocks.util.ts @@ -57,18 +57,18 @@ export function validateConnection( } export type FireblocksAccountExternalId = `${string}-${string}` -export function getFireblocksAssetWalletExternalId({ +export function buildFireblocksAssetWalletExternalId({ vaultId, networkId }: { vaultId: string networkId: string }): string { - return `${vaultId.toString()}-${networkId}` + return `${vaultId.toString()}-${networkId}`.toUpperCase() } -export type FireblocksAssetWalletId = { vaultId: string; networkId: string } -export function toFireblocksAssetWalletExternalId(externalId: string): FireblocksAssetWalletId { +export type FireblocksAssetWalletId = { vaultId: string; baseAssetId: string } +export function parseFireblocksAssetWalletExternalId(externalId: string): FireblocksAssetWalletId { const matches = externalId.match(/^([^-]+)-([^-]+)$/) if (!matches) { throw new BrokerException({ @@ -81,12 +81,12 @@ export function toFireblocksAssetWalletExternalId(externalId: string): Fireblock const [, vaultId, networkId] = matches return { vaultId, - networkId + baseAssetId: networkId } } export type FireblocksAddressExternalId = `${string}-${string}-${string}` -export function getFireblocksAssetAddressExternalId({ +export function buildFireblocksAssetAddressExternalId({ vaultId, networkId, address @@ -95,11 +95,11 @@ export function getFireblocksAssetAddressExternalId({ networkId: string address: string }): string { - return `${vaultId}-${networkId}-${address}` + return `${vaultId}-${networkId}-${address}`.toUpperCase() } export type FireblocksAssetAddressId = { vaultId: string; networkId: string; address: string } -export function toFireblocksAssetAddressExternalId(externalId: string): FireblocksAssetAddressId { +export function parseFireblocksAssetAddressExternalId(externalId: string): FireblocksAssetAddressId { const matches = externalId.match(/^([^-]+)-([^-]+)-([^-]+)$/) if (!matches) { throw new BrokerException({ diff --git a/apps/vault/src/broker/core/service/account.service.ts b/apps/vault/src/broker/core/service/account.service.ts index 27837aa06..534bfbf87 100644 --- a/apps/vault/src/broker/core/service/account.service.ts +++ b/apps/vault/src/broker/core/service/account.service.ts @@ -20,6 +20,10 @@ export class AccountService { return this.accountRepository.bulkCreate(accounts) } + async bulkUpsert(accounts: Account[]): Promise { + return this.accountRepository.bulkUpsert(accounts) + } + async bulkUpdate(updateAccounts: UpdateAccount[]): Promise { return this.accountRepository.bulkUpdate(updateAccounts) } diff --git a/apps/vault/src/broker/core/service/network.service.ts b/apps/vault/src/broker/core/service/network.service.ts index 6cfd0bc12..aafc362e8 100644 --- a/apps/vault/src/broker/core/service/network.service.ts +++ b/apps/vault/src/broker/core/service/network.service.ts @@ -3,7 +3,7 @@ import { CACHE_MANAGER, Cache } from '@nestjs/cache-manager' import { Inject, Injectable } from '@nestjs/common' import { uniq } from 'lodash' import { FindAllOptions, NetworkRepository } from '../../persistence/repository/network.repository' -import { ExternalNetwork, Network } from '../type/network.type' +import { ExternalNetwork, Network, NetworkMap } from '../type/network.type' import { Provider } from '../type/provider.type' @Injectable() @@ -114,7 +114,7 @@ export class NetworkService { * traversals on subsequent queries. All lookups become O(1) after indexing * at the cost of O(n) additional memory. */ - async buildProviderExternalIdIndex(provider: Provider): Promise> { + async buildProviderExternalIdIndex(provider: Provider): Promise { const networks = await this.findAll({ filters: { provider } }) const index = new Map() diff --git a/apps/vault/src/broker/core/service/raw-account.service.ts b/apps/vault/src/broker/core/service/raw-account.service.ts index 2faa402ce..9bdec023c 100644 --- a/apps/vault/src/broker/core/service/raw-account.service.ts +++ b/apps/vault/src/broker/core/service/raw-account.service.ts @@ -5,14 +5,17 @@ import { AnchorageClient } from '../../http/client/anchorage.client' import { FireblocksClient } from '../../http/client/fireblocks.client' import { AccountRepository } from '../../persistence/repository/account.repository' import { AssetRepository } from '../../persistence/repository/asset.repository' -import { NetworkRepository } from '../../persistence/repository/network.repository' import { BrokerException } from '../exception/broker.exception' import { validateConnection as validateAnchorageConnection } from '../provider/anchorage/anchorage.util' -import { validateConnection as validateFireblocksConnection } from '../provider/fireblocks/fireblocks.util' +import { + buildFireblocksAssetWalletExternalId, + validateConnection as validateFireblocksConnection +} from '../provider/fireblocks/fireblocks.util' import { Asset } from '../type/asset.type' import { Network } from '../type/network.type' import { Provider } from '../type/provider.type' import { ConnectionService } from './connection.service' +import { NetworkService } from './network.service' export const RawAccount = z.object({ provider: z.nativeEnum(Provider), @@ -49,7 +52,7 @@ export class RawAccountService { constructor( private readonly accountRepository: AccountRepository, private readonly connectionService: ConnectionService, - private readonly networkRepository: NetworkRepository, + private readonly networkService: NetworkService, private readonly assetRepository: AssetRepository, private readonly anchorageClient: AnchorageClient, private readonly fireblocksClient: FireblocksClient, @@ -67,7 +70,7 @@ export class RawAccountService { ? await this.assetRepository.findById(options.filters.assetId) : undefined const networkFilter = options?.filters?.networkId - ? await this.networkRepository.findById(options.filters.networkId) + ? await this.networkService.findById(options.filters.networkId) : undefined if (connection.provider === Provider.ANCHORAGE) { @@ -87,7 +90,7 @@ export class RawAccountService { label: wallet.walletName, subLabel: wallet.vaultName, defaultAddress: wallet.depositAddress.address, - network: await this.networkRepository.findByExternalId(Provider.ANCHORAGE, wallet.networkId), + network: await this.networkService.findByExternalId(Provider.ANCHORAGE, wallet.networkId), assets: await Promise.all( wallet.assets.map(async (a) => ({ asset: await this.assetRepository.findByExternalId(Provider.ANCHORAGE, a.assetType), @@ -154,9 +157,11 @@ export class RawAccountService { } }) // In Fireblocks, a VaultAccount is not network-specific, so we'll map the AssetWallets to get what we call "Accounts" + // Map accounts to our format const rawAccounts = await Promise.all( response.accounts.map(async (account) => { - const assets = await Promise.all( + // 1. First map and filter assets + const mappedAssets = await Promise.all( account.assets .filter((a) => !a.hiddenOnUI) .map(async (asset) => ({ @@ -165,43 +170,62 @@ export class RawAccountService { asset: await this.assetRepository.findByExternalId(Provider.FIREBLOCKS, asset.id) })) ) - // Group assets by network - const assetsByNetwork = assets.reduce( + + // 2. Group assets by network + const assetsByNetwork = mappedAssets.reduce( (acc, asset) => { - if (!asset.asset?.networkId) return acc // Skip assets without a networkId - if (!acc[asset.asset.networkId]) { - acc[asset.asset.networkId] = [] + if (!asset.asset?.networkId) return acc + return { + ...acc, + [asset.asset.networkId]: [...(acc[asset.asset.networkId] || []), asset] } - acc[asset.asset.networkId].push(asset) - return acc }, - {} as Record + {} as Record ) - // Create an account for each network that has assets - return await Promise.all( - Object.entries(assetsByNetwork).map(async ([networkId, networkAssets]) => { - const network = await this.networkRepository.findById(networkId) - return { - provider: Provider.FIREBLOCKS, - externalId: `${account.id}-${networkId}`, - label: account.name || account.id, - subLabel: networkId, - defaultAddress: '', // Fireblocks doesn't provide a default address at account level - network, - assets: networkAssets - .map((a) => - a.asset - ? { - asset: a.asset, - balance: a.balance - } - : undefined - ) - .filter((a) => !!a) - } - }) - ) + // 3. Validate networks and get their Fireblocks IDs + const validNetworks = ( + await Promise.all( + Object.entries(assetsByNetwork).map(async ([networkId, assets]) => { + const network = await this.networkService.findById(networkId) + const fireblocksNetworkId = network?.externalNetworks.find( + (n) => n.provider === Provider.FIREBLOCKS + )?.externalId + + if (!network || !fireblocksNetworkId) return null + + return { + network, + fireblocksNetworkId, + assets + } + }) + ) + ).filter((item): item is NonNullable => item !== null) + + return validNetworks.map(({ network, fireblocksNetworkId, assets }) => { + return { + provider: Provider.FIREBLOCKS, + externalId: buildFireblocksAssetWalletExternalId({ + vaultId: account.id, + networkId: fireblocksNetworkId + }), + label: account.name || account.id, + subLabel: network?.networkId, + defaultAddress: '', // Fireblocks doesn't provide a default address at account level + network: Network.parse(network), + assets: assets + .map((a) => + a.asset + ? { + asset: a.asset, + balance: a.balance + } + : undefined + ) + .filter((a) => !!a) + } + }) }) ).then((a) => a.flat()) diff --git a/apps/vault/src/broker/core/service/scoped-sync.service.ts b/apps/vault/src/broker/core/service/scoped-sync.service.ts index f0c746afd..6969b2ca8 100644 --- a/apps/vault/src/broker/core/service/scoped-sync.service.ts +++ b/apps/vault/src/broker/core/service/scoped-sync.service.ts @@ -1,5 +1,5 @@ import { LoggerService, PaginatedResult, TraceService } from '@narval/nestjs-shared' -import { NotImplementedException } from '@nestjs/common' +import { HttpStatus, NotImplementedException } from '@nestjs/common' import { Inject, Injectable } from '@nestjs/common/decorators' import { EventEmitter2 } from '@nestjs/event-emitter' import { SpanStatusCode } from '@opentelemetry/api' @@ -8,21 +8,24 @@ import { v4 as uuid } from 'uuid' import { FindAllOptions, ScopedSyncRepository } from '../../persistence/repository/scoped-sync.repository' import { OTEL_ATTR_CONNECTION_ID, OTEL_ATTR_CONNECTION_PROVIDER, OTEL_ATTR_SYNC_ID } from '../../shared/constant' import { ScopedSyncStartedEvent } from '../../shared/event/scoped-sync-started.event' +import { ScopedSyncException } from '../exception/scoped-sync.exception' import { AnchorageScopedSyncService } from '../provider/anchorage/anchorage-scoped-sync.service' import { FireblocksScopedSyncService } from '../provider/fireblocks/fireblocks-scoped-sync.service' import { ConnectionWithCredentials } from '../type/connection.type' +import { Provider, ProviderScopedSyncService } from '../type/provider.type' +import { ConnectionScope } from '../type/scope.type' import { - Provider, - ProviderScopedSyncService, + RawAccount, + RawAccountSyncFailure, + ScopedSync, ScopedSyncResult, - isCreateOperation, - isFailedOperation, - isUpdateOperation -} from '../type/provider.type' -import { ConnectionScope } from '../type/scope.type' -import { RawAccount, ScopedSync, ScopedSyncStarted, ScopedSyncStatus, StartScopedSync } from '../type/scoped-sync.type' + ScopedSyncStarted, + ScopedSyncStatus, + StartScopedSync +} from '../type/scoped-sync.type' import { AccountService } from './account.service' import { AddressService } from './address.service' +import { NetworkService } from './network.service' import { WalletService } from './wallet.service' @Injectable() @@ -34,23 +37,45 @@ export class ScopedSyncService { private readonly walletService: WalletService, private readonly accountService: AccountService, private readonly addressService: AddressService, + private readonly networkService: NetworkService, private readonly eventEmitter: EventEmitter2, private readonly logger: LoggerService, @Inject(TraceService) private readonly traceService: TraceService ) {} async start(connections: ConnectionWithCredentials[], rawAccounts: RawAccount[]): Promise { - this.logger.log('Start connections scoped sync', { + this.logger.log('Start connections scopedSync', { connectionsCount: connections.length, - connectionIds: connections.map((connectionId) => connectionId), - rawAccounts: rawAccounts.map(({ provider, externalId }) => ({ provider, externalId })) + connectionIds: connections.map((connectionId) => connectionId) }) - if (connections.length) { + const notSyncingConnections: ConnectionWithCredentials[] = [] + + for (const connection of connections) { + const inProgress = await this.scopedSyncRepository.exists({ + connectionId: connection.connectionId, + clientId: connection.clientId, + status: ScopedSyncStatus.PROCESSING + }) + + if (inProgress) { + throw new ScopedSyncException({ + message: 'There is already a Scoped Sync in progress for requested connections', + suggestedHttpStatusCode: HttpStatus.CONFLICT, + context: { + conflictingConnectionId: connection.connectionId + } + }) + } + + notSyncingConnections.push(connection) + } + + if (notSyncingConnections.length) { const now = new Date() const scopedSyncs = await this.scopedSyncRepository.bulkCreate( - connections.map(({ connectionId, clientId }) => + notSyncingConnections.map(({ connectionId, clientId }) => this.toProcessingScopedSync({ clientId, connectionId, @@ -61,7 +86,7 @@ export class ScopedSyncService { ) ) - for (const [scopedSync, connection] of zip(scopedSyncs, connections)) { + for (const [scopedSync, connection] of zip(scopedSyncs, notSyncingConnections)) { if (scopedSync && connection) { // NOTE: Emits an event that will delegate the scopedSync process to // another worker, allowing to unblock the request. The event handler @@ -73,7 +98,7 @@ export class ScopedSyncService { return { started: true, scopedSyncs } } - this.logger.log('Skip scoped sync because active connections list is empty') + this.logger.log('Skip scopedSync because active connections list is empty') return { started: false, scopedSyncs: [] } } @@ -88,7 +113,7 @@ export class ScopedSyncService { provider } - this.logger.log('Scoped sync connection', context) + this.logger.log('Scoped Sync connection', context) const span = this.traceService.startSpan(`${ScopedSyncService.name}.scopedSync`, { attributes: { @@ -100,31 +125,38 @@ export class ScopedSyncService { let result: ScopedSyncResult | null = null - // Ensure the scopedSync status is updated on failures. The `execute` method is - // not wrapped in the try/catch block because it already handles errors - // internally. try { - result = await this.getProviderScopedSyncService(connection.provider).scopedSync( - connection, - scopedSync.rawAccounts + const networks = await this.networkService.buildProviderExternalIdIndex(provider) + const { data: existingAccounts } = await this.accountService.findAll( + { clientId, connectionId }, + { + pagination: { disabled: true } + } ) + + result = await this.getProviderScopedSyncService(connection.provider).scopeSync({ + rawAccounts: scopedSync.rawAccounts, + connection, + networks, + existingAccounts + }) } catch (error) { - this.logger.error('Scoped sync connection failed', { ...context, error }) + this.logger.error('ScopedSync connection failed', { ...context, error }) span.recordException(error) span.setStatus({ code: SpanStatusCode.ERROR }) - return await this.fail(scopedSync, error) + return await this.fail(scopedSync, error, result?.failures || []) } finally { // The execute method has its own span. span.end() } - if (result) { - return await this.execute(scopedSync, result) + if (result.failures.length && !result.accounts.length) { + this.logger.error('ScopedSync connection failed', { ...context, result }) } - return scopedSync + return await this.execute(scopedSync, result) } private toProcessingScopedSync( @@ -150,103 +182,96 @@ export class ScopedSyncService { } // TODO: pessimist lock if there's already a scopedSync in process for the given - // connection. async execute(scopedSync: ScopedSync, result: ScopedSyncResult): Promise { - // IMPORTANT: Thoroughly test the execution in the integration test - // `scopedSync.service.spec.ts`. - - const { clientId, scopedSyncId } = scopedSync + const { scopedSyncId } = scopedSync const span = this.traceService.startSpan(`${ScopedSyncService.name}.execute`, { attributes: { [OTEL_ATTR_SYNC_ID]: scopedSyncId } }) - const walletCreateOperations = result.wallets.filter(isCreateOperation).map(({ create }) => create) - const walletUpdateOperations = result.wallets.filter(isUpdateOperation).map(({ update }) => update) - const walletFailedOperations = result.wallets.filter(isFailedOperation) + const { wallets, accounts, addresses, failures } = result - const accountCreateOperations = result.accounts.filter(isCreateOperation).map(({ create }) => create) - const accountUpdateOperations = result.accounts.filter(isUpdateOperation).map(({ update }) => update) - const accountFailedOperations = result.accounts.filter(isFailedOperation) + this.logger.log('Raw Account synchronization failures', { + scopedSyncId, + failuresCount: failures?.length, + failures + }) - const addressCreateOperations = result.addresses.filter(isCreateOperation).map(({ create }) => create) - const addressFailedOperations = result.addresses.filter(isFailedOperation) + this.logger.log('Raw Account synchronization successes', { + wallets: wallets.length, + accounts: accounts.length, + addresses: addresses.length + }) - this.logger.log('Execute scoped sync operations', { - clientId, - scopedSyncId, - operations: { - wallet: { - create: walletCreateOperations.length, - update: walletUpdateOperations.length, - failed: walletFailedOperations.length - }, - account: { - create: accountCreateOperations.length, - update: accountUpdateOperations.length, - failed: accountFailedOperations.length - }, - address: { - create: addressCreateOperations.length, - failed: addressFailedOperations.length - } + try { + await this.walletService.bulkUpsert(wallets) + await this.accountService.bulkUpsert(accounts) + await this.addressService.bulkCreate(addresses) + + const totalItems = result.wallets.length + result.accounts.length + result.addresses.length + if (totalItems === 0) { + throw new ScopedSyncException({ + message: 'No raw account was successfully mapped', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, + context: { failures: result.failures } + }) } - }) - if (walletFailedOperations.length) { - this.logger.error('Scoped sync operations contains failures for wallets', { - operations: walletFailedOperations - }) + return await this.complete(scopedSync, result) + } catch (error) { + return await this.fail(scopedSync, error, result.failures) + } finally { + span.end() } + } - if (accountFailedOperations.length) { - this.logger.error('Scoped sync operations contains failures for accounts', { - operations: accountFailedOperations - }) - } + async complete(scopedSync: ScopedSync, result: ScopedSyncResult): Promise { + const { clientId, scopedSyncId } = scopedSync - if (addressFailedOperations.length) { - this.logger.error('Scoped sync operations contains failures for addresses', { - operations: addressFailedOperations - }) - } + const totalItems = result.wallets.length + result.accounts.length + result.addresses.length + const hasSuccesses = totalItems > 0 + const hasFailures = result.failures.length > 0 - try { - this.logger.log('Execute wallet create operations', { scopedSyncId, clientId }) - await this.walletService.bulkCreate(walletCreateOperations) - this.logger.log('Execute wallet update operations', { scopedSyncId, clientId }) - await this.walletService.bulkUpdate(walletUpdateOperations) + const status = hasSuccesses && hasFailures ? ScopedSyncStatus.PARTIAL_SUCCESS : ScopedSyncStatus.SUCCESS - this.logger.log('Execute account create operations', { scopedSyncId, clientId }) - await this.accountService.bulkCreate(accountCreateOperations) - this.logger.log('Execute account update operations', { scopedSyncId, clientId }) - await this.accountService.bulkUpdate(accountUpdateOperations) + if (status === ScopedSyncStatus.PARTIAL_SUCCESS) { + return await this.partialSuccess(scopedSync, result.failures) + } - // TODO: address update - this.logger.log('Execute address create operations', { scopedSyncId, clientId }) - await this.addressService.bulkCreate(addressCreateOperations) + this.logger.log('Scoped Sync completed successfuly', { clientId, scopedSyncId }) - return await this.complete(scopedSync) - } catch (error) { - return await this.fail(scopedSync, error) - } finally { - span.end() + const span = this.traceService.startSpan(`${ScopedSyncService.name}.complete`, { + attributes: { [OTEL_ATTR_SYNC_ID]: scopedSyncId } + }) + + const completedScopedSync = { + ...scopedSync, + status, + completedAt: scopedSync.completedAt || new Date(), + failures: [] } + + await this.scopedSyncRepository.update(completedScopedSync) + + span.end() + + return completedScopedSync } - async complete(scopedSync: ScopedSync): Promise { + async partialSuccess(scopedSync: ScopedSync, failures: RawAccountSyncFailure[]): Promise { const { clientId, scopedSyncId } = scopedSync - this.logger.log('Scoped sync complete', { clientId, scopedSyncId }) + this.logger.log('Scoped Sync partially successful', { clientId, scopedSyncId }) - const span = this.traceService.startSpan(`${ScopedSyncService.name}.complete`, { + const span = this.traceService.startSpan(`${ScopedSyncService.name}.partial_success`, { attributes: { [OTEL_ATTR_SYNC_ID]: scopedSyncId } }) const completedScopedSync = { ...scopedSync, - status: ScopedSyncStatus.SUCCESS, - completedAt: scopedSync.completedAt || new Date() + status: ScopedSyncStatus.PARTIAL_SUCCESS, + completedAt: scopedSync.completedAt || new Date(), + failures } await this.scopedSyncRepository.update(completedScopedSync) @@ -256,10 +281,10 @@ export class ScopedSyncService { return completedScopedSync } - async fail(scopedSync: ScopedSync, error: Error): Promise { + async fail(scopedSync: ScopedSync, error: Error, failures: RawAccountSyncFailure[]): Promise { const { clientId, scopedSyncId } = scopedSync - this.logger.log('Scoped sync fail', { clientId, scopedSyncId, error }) + this.logger.log('Scoped Sync fail', { clientId, scopedSyncId, error }) const span = this.traceService.startSpan(`${ScopedSyncService.name}.fail`, { attributes: { [OTEL_ATTR_SYNC_ID]: scopedSyncId } @@ -276,7 +301,8 @@ export class ScopedSyncService { message: error.message, traceId: this.traceService.getActiveSpan()?.spanContext().traceId }, - completedAt: scopedSync.completedAt || new Date() + completedAt: scopedSync.completedAt || new Date(), + failures } await this.scopedSyncRepository.update(failedScopedSync) @@ -293,7 +319,7 @@ export class ScopedSyncService { case Provider.FIREBLOCKS: return this.fireblocksScopedSyncService default: - throw new NotImplementedException(`Unsupported scoped sync for provider ${provider}`) + throw new NotImplementedException(`Unsupported Scoped Sync for provider ${provider}`) } } } diff --git a/apps/vault/src/broker/core/service/wallet.service.ts b/apps/vault/src/broker/core/service/wallet.service.ts index 75df878e5..35138c46e 100644 --- a/apps/vault/src/broker/core/service/wallet.service.ts +++ b/apps/vault/src/broker/core/service/wallet.service.ts @@ -12,6 +12,10 @@ export class WalletService { return this.walletRepository.bulkCreate(wallets) } + async bulkUpsert(wallets: Wallet[]): Promise { + return this.walletRepository.bulkUpsert(wallets) + } + async bulkUpdate(wallets: UpdateWallet[]): Promise { return Promise.all(wallets.map((wallet) => this.update(wallet))) } diff --git a/apps/vault/src/broker/core/type/network.type.ts b/apps/vault/src/broker/core/type/network.type.ts index d0eed7e4f..a6e5f03f1 100644 --- a/apps/vault/src/broker/core/type/network.type.ts +++ b/apps/vault/src/broker/core/type/network.type.ts @@ -12,6 +12,9 @@ export const Network = z.object({ coinType: z.number().nullable(), name: z.string(), externalNetworks: z.array(ExternalNetwork).default([]), - createdAt: z.date().optional() + createdAt: z.coerce.date().optional() }) export type Network = z.infer + +export const NetworkMap = z.map(z.string(), Network) +export type NetworkMap = z.infer diff --git a/apps/vault/src/broker/core/type/provider.type.ts b/apps/vault/src/broker/core/type/provider.type.ts index 97fd837a4..e374fc00e 100644 --- a/apps/vault/src/broker/core/type/provider.type.ts +++ b/apps/vault/src/broker/core/type/provider.type.ts @@ -2,11 +2,9 @@ import { PaginatedResult } from '@narval/nestjs-shared' import { HttpStatus } from '@nestjs/common' -import { UpdateAccount } from '../../persistence/repository/account.repository' import { ConnectionWithCredentials } from './connection.type' -import { Account, Address, UpdateWallet, Wallet } from './indexed-resources.type' import { KnownDestination as KnownDestinationNext } from './known-destination.type' -import { RawAccount } from './scoped-sync.type' +import { ScopedSyncContext, ScopedSyncResult } from './scoped-sync.type' import { InternalTransfer, SendTransfer, Transfer } from './transfer.type' export const Provider = { @@ -20,216 +18,8 @@ export type Provider = (typeof Provider)[keyof typeof Provider] // Sync // -export const SyncOperationType = { - CREATE: 'create', - UPDATE: 'update', - DELETE: 'delete', - FAILED: 'failed', - SKIP: 'skip' -} as const -export type SyncOperationType = (typeof SyncOperationType)[keyof typeof SyncOperationType] - -export const ScopedSyncOperationType = { - CREATE: 'create', - UPDATE: 'update', - FAILED: 'failed' -} as const -export type ScopedSyncOperationType = (typeof ScopedSyncOperationType)[keyof typeof ScopedSyncOperationType] - -export type CreateScopedSyncOperation = { - type: typeof SyncOperationType.CREATE - create: CreateParams -} -export type UpdateScopedSyncOperation = { - type: typeof ScopedSyncOperationType.UPDATE - update: UpdateParams -} - -export type FailedScopedSyncOperation = { - type: typeof ScopedSyncOperationType.FAILED - externalId: string - message: string - context?: unknown -} - -export type CreateSyncOperation = { - type: typeof SyncOperationType.CREATE - create: CreateParams -} - -export type UpdateSyncOperation = { - type: typeof SyncOperationType.UPDATE - update: UpdateParams -} - -export type DeleteSyncOperation = { - type: typeof SyncOperationType.DELETE - entityId: string -} - -export type FailedSyncOperation = { - type: typeof SyncOperationType.FAILED - externalId: string - message: string - context?: unknown -} - -export type SkipSyncOperation = { - type: typeof SyncOperationType.SKIP - externalId: string - message: string - context?: unknown -} - -/** - * Represents a synchronization operation for a resource, which can be a - * creation, update, or deletion. Each operation type is associated with - * specific parameters. - * - * @template CreateParams - The parameters required for creating an entity. - * @template UpdateParams - The parameters required for updating an entity. - */ -export type SyncOperation = - | CreateSyncOperation - | UpdateSyncOperation - | DeleteSyncOperation - | FailedSyncOperation - | SkipSyncOperation - -export type ScopedSyncOperation = - | CreateScopedSyncOperation - | UpdateScopedSyncOperation - | FailedSyncOperation - -export const isCreateOperation = ( - operation: SyncOperation -): operation is CreateSyncOperation => { - return operation.type === SyncOperationType.CREATE -} - -export const isUpdateOperation = ( - operation: SyncOperation -): operation is UpdateSyncOperation => { - return operation.type === SyncOperationType.UPDATE -} - -export const isDeleteOperation = ( - operation: SyncOperation -): operation is DeleteSyncOperation => { - return operation.type === SyncOperationType.DELETE -} - -export const isFailedOperation = ( - operation: SyncOperation -): operation is FailedSyncOperation => { - return operation.type === SyncOperationType.FAILED -} - -export const isSkipOperation = ( - operation: SyncOperation -): operation is SkipSyncOperation => { - return operation.type === SyncOperationType.SKIP -} - -/** - * Represents the context used during synchronization, containing the active - * connection and maps of synchronization operations for various resource - * types. - */ -export type SyncContext = { - /** - * The active connection with credentials used for synchronization. - */ - connection: ConnectionWithCredentials - - /** - * A map of wallet synchronization operations, keyed by wallet external ID. - */ - wallets: SyncOperation[] - - /** - * A map of account synchronization operations, keyed by account external ID. - */ - accounts: SyncOperation[] - - /** - * A map of address synchronization operations, keyed by address external ID. - */ - addresses: SyncOperation[] - - /** - * An optional timestamp used for setting the `createdAt` and `updatedAt` - * fields during synchronization operations. - */ - now?: Date -} - -export type SyncResult = { - wallets: SyncOperation[] - accounts: SyncOperation[] - addresses: SyncOperation[] -} - -export type ScopedSyncResult = { - wallets: ScopedSyncOperation[] - accounts: ScopedSyncOperation[] - addresses: ScopedSyncOperation[] -} - export interface ProviderScopedSyncService { - scopedSync(connection: ConnectionWithCredentials, rawAccounts: RawAccount[]): Promise -} - -export interface ProviderSyncService { - /** - * The main entry point for synchronization, responsible for coordinating the - * synchronization process across different resources. It orchestrates the - * sync calls and passes the context between them. - * - * IMPORTANT: The synchronization **does not perform the writes** into the - * database. - * - * @param connection - The active connection with credentials required for - * synchronization. - * - * @returns A promise that resolves to an object containing the results of - * the sync operations for wallets, accounts, addresses, and known - * destinations. - */ - sync(connection: ConnectionWithCredentials): Promise - - /** - * Synchronizes wallet data within the provided context and returns an - * updated context. - * - * @param context - The current synchronization context containing existing - * data and operations. - * - * @returns A promise that resolves to the updated synchronization context. - */ - syncWallets(context: SyncContext): Promise - - /** - * Synchronizes account data within the provided context and returns an - * updated context. - * - * @param context - The current synchronization context containing existing - * data and operations. - * - * @returns A promise that resolves to the updated synchronization context. - */ - syncAccounts(context: SyncContext): Promise - - /** - * Synchronizes address data within the provided context and returns an - * updated context. - * - * @param context - The current synchronization context containing existing - * data and operations. - * - * @returns A promise that resolves to the updated synchronization context. - */ - syncAddresses(context: SyncContext): Promise + scopeSync(context: ScopedSyncContext): Promise } // diff --git a/apps/vault/src/broker/core/type/scoped-sync.type.ts b/apps/vault/src/broker/core/type/scoped-sync.type.ts index 5287a4438..98e0c67b3 100644 --- a/apps/vault/src/broker/core/type/scoped-sync.type.ts +++ b/apps/vault/src/broker/core/type/scoped-sync.type.ts @@ -1,4 +1,7 @@ import { z } from 'zod' +import { ConnectionWithCredentials } from './connection.type' +import { Account, Address, Wallet } from './indexed-resources.type' +import { NetworkMap } from './network.type' import { Provider } from './provider.type' export const RawAccount = z.object({ @@ -10,10 +13,56 @@ export type RawAccount = z.infer export const ScopedSyncStatus = { PROCESSING: 'processing', SUCCESS: 'success', + PARTIAL_SUCCESS: 'partial_success', FAILED: 'failed' } as const export type ScopedSyncStatus = (typeof ScopedSyncStatus)[keyof typeof ScopedSyncStatus] +export const RawAccountError = { + EXTERNAL_RESOURCE_NOT_FOUND: 'EXTERNAL_RESOURCE_NOT_FOUND', + UNLISTED_NETWORK: 'UNLISTED_NETWORK' +} as const +export type RawAccountError = (typeof RawAccountError)[keyof typeof RawAccountError] + +export const RawAccountNetworkNotFoundFailure = z.object({ + code: z.literal(RawAccountError.UNLISTED_NETWORK), + rawAccount: RawAccount, + message: z.string(), + networkId: z.string() +}) +export type RawAccountNetworkNotFoundFailure = z.infer + +export const RawAccountExternalResourceNotFoundFailure = z.object({ + code: z.literal(RawAccountError.EXTERNAL_RESOURCE_NOT_FOUND), + rawAccount: RawAccount, + message: z.string(), + externalResourceType: z.string(), + externalResourceId: z.string() +}) +export type RawAccountExternalResourceNotFoundFailure = z.infer + +export const RawAccountSyncFailure = z.discriminatedUnion('code', [ + RawAccountNetworkNotFoundFailure, + RawAccountExternalResourceNotFoundFailure +]) +export type RawAccountSyncFailure = z.infer + +export const ScopedSyncResult = z.object({ + wallets: z.array(Wallet), + accounts: z.array(Account), + addresses: z.array(Address), + failures: z.array(RawAccountSyncFailure) +}) +export type ScopedSyncResult = z.infer + +export const ScopedSyncContext = z.object({ + connection: ConnectionWithCredentials, + rawAccounts: z.array(RawAccount), + networks: NetworkMap, + existingAccounts: z.array(Account) +}) +export type ScopedSyncContext = z.infer + export const ScopedSync = z.object({ clientId: z.string(), completedAt: z.date().optional(), @@ -28,7 +77,8 @@ export const ScopedSync = z.object({ .optional(), status: z.nativeEnum(ScopedSyncStatus).default(ScopedSyncStatus.PROCESSING), scopedSyncId: z.string(), - rawAccounts: z.array(RawAccount) + rawAccounts: z.array(RawAccount), + failures: z.array(RawAccountSyncFailure).optional() }) export type ScopedSync = z.infer diff --git a/apps/vault/src/broker/core/util/provider-sync.util.ts b/apps/vault/src/broker/core/util/provider-sync.util.ts deleted file mode 100644 index e98fd4f12..000000000 --- a/apps/vault/src/broker/core/util/provider-sync.util.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { SetRequired } from 'type-fest' -import { SyncContext } from '../type/provider.type' - -export const buildEmptyContext = ({ - connection, - wallets, - accounts, - addresses, - now -}: SetRequired, 'connection'>): SyncContext => ({ - connection, - wallets: wallets || [], - accounts: accounts || [], - addresses: addresses || [], - now: now || new Date() -}) diff --git a/apps/vault/src/broker/http/rest/dto/response/scoped-sync.dto.ts b/apps/vault/src/broker/http/rest/dto/response/scoped-sync.dto.ts index 529818d1a..d0bed4513 100644 --- a/apps/vault/src/broker/http/rest/dto/response/scoped-sync.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/scoped-sync.dto.ts @@ -1,9 +1,11 @@ import { createZodDto } from 'nestjs-zod' import { z } from 'zod' -import { ScopedSync } from '../../../../core/type/scoped-sync.type' +import { RawAccountSyncFailure, ScopedSync } from '../../../../core/type/scoped-sync.type' export class ScopedSyncDto extends createZodDto( z.object({ - data: ScopedSync + data: ScopedSync.extend({ + failures: z.array(RawAccountSyncFailure) + }) }) ) {} diff --git a/apps/vault/src/broker/persistence/repository/account.repository.ts b/apps/vault/src/broker/persistence/repository/account.repository.ts index 3075b8b11..6ff4edb5a 100644 --- a/apps/vault/src/broker/persistence/repository/account.repository.ts +++ b/apps/vault/src/broker/persistence/repository/account.repository.ts @@ -1,4 +1,10 @@ -import { PaginatedResult, PaginationOptions, applyPagination, getPaginatedResult } from '@narval/nestjs-shared' +import { + LoggerService, + PaginatedResult, + PaginationOptions, + applyPagination, + getPaginatedResult +} from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' import { ProviderAccount, ProviderAddress } from '@prisma/client/vault' import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' @@ -30,7 +36,10 @@ export type UpdateAccount = { @Injectable() export class AccountRepository { - constructor(private prismaService: PrismaService) {} + constructor( + private prismaService: PrismaService, + private readonly logger: LoggerService + ) {} static parseModel(model: ProviderAccountAndRelations): Account { const { id, ...rest } = model @@ -150,6 +159,75 @@ export class AccountRepository { return true } + async bulkUpsert(accounts: Account[]): Promise { + const providerAccounts = accounts.map(AccountRepository.parseEntity) + const stats = { + inserted: 0, + updated: 0 + } + + const existingAccounts = await this.prismaService.providerAccount.findMany({ + where: { + OR: providerAccounts.map((account) => ({ + clientId: account.clientId, + connectionId: account.connectionId, + externalId: account.externalId + })) + } + }) + + const results = await this.prismaService.$transaction(async (tx) => { + const operations = await Promise.all( + providerAccounts.map(async (account) => { + const existing = existingAccounts.find( + (a) => + a.clientId === account.clientId && + a.connectionId === account.connectionId && + a.externalId === account.externalId + ) + + const result = await tx.providerAccount.upsert({ + where: { + clientId_connectionId_externalId: { + clientId: account.clientId, + connectionId: account.connectionId, + externalId: account.externalId + } + }, + create: { + ...account + }, + update: { + label: account.label, + updatedAt: account.updatedAt + }, + include: { + addresses: true + } + }) + + if (!existing) { + stats.inserted++ + } else { + stats.updated++ + } + + return result + }) + ) + + return operations + }) + + this.logger.log('Account bulk upsert operation completed:', { + total: accounts.length, + inserted: stats.inserted, + updated: stats.updated + }) + + return results.map(AccountRepository.parseModel) + } + async findAll( { clientId, connectionId }: ConnectionScope, options?: FindAllOptions diff --git a/apps/vault/src/broker/persistence/repository/address.repository.ts b/apps/vault/src/broker/persistence/repository/address.repository.ts index ffbe4f998..8287e19ed 100644 --- a/apps/vault/src/broker/persistence/repository/address.repository.ts +++ b/apps/vault/src/broker/persistence/repository/address.repository.ts @@ -1,4 +1,10 @@ -import { PaginatedResult, PaginationOptions, applyPagination, getPaginatedResult } from '@narval/nestjs-shared' +import { + LoggerService, + PaginatedResult, + PaginationOptions, + applyPagination, + getPaginatedResult +} from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' import { ProviderAddress } from '@prisma/client/vault' import { z } from 'zod' @@ -21,7 +27,10 @@ export type FindAllOptions = FindAllFilters & { pagination?: PaginationOptions } @Injectable() export class AddressRepository { - constructor(private prismaService: PrismaService) {} + constructor( + private prismaService: PrismaService, + private readonly logger: LoggerService + ) {} static parseModel(model: ProviderAddress): Address { const { id, ...rest } = model @@ -139,10 +148,16 @@ export class AddressRepository { } async bulkCreate(addresses: Address[]): Promise { - await this.prismaService.providerAddress.createMany({ - data: addresses.map(AddressRepository.parseEntity) + const { count } = await this.prismaService.providerAddress.createMany({ + data: addresses.map(AddressRepository.parseEntity), + skipDuplicates: true }) + this.logger.log('Address bulk create operation done', { + addressesLength: addresses.length, + addressesCreated: count, + addressesSkipped: addresses.length - count + }) return addresses } } diff --git a/apps/vault/src/broker/persistence/repository/scoped-sync.repository.ts b/apps/vault/src/broker/persistence/repository/scoped-sync.repository.ts index 792a853fd..41d2d2a3b 100644 --- a/apps/vault/src/broker/persistence/repository/scoped-sync.repository.ts +++ b/apps/vault/src/broker/persistence/repository/scoped-sync.repository.ts @@ -6,7 +6,7 @@ import { PrismaService } from '../../../shared/module/persistence/service/prisma import { ModelInvalidException } from '../../core/exception/model-invalid.exception' import { NotFoundException } from '../../core/exception/not-found.exception' import { ConnectionScope } from '../../core/type/scope.type' -import { RawAccount, ScopedSync, ScopedSyncStatus } from '../../core/type/scoped-sync.type' +import { RawAccount, RawAccountSyncFailure, ScopedSync, ScopedSyncStatus } from '../../core/type/scoped-sync.type' export type FindAllOptions = PaginationOptions & { filters?: { @@ -21,6 +21,7 @@ export type UpdateScopedSync = { completedAt?: Date status?: ScopedSyncStatus error?: ScopedSync['error'] + failures?: RawAccountSyncFailure[] } const parseErrorEntity = ( @@ -47,6 +48,7 @@ export class ScopedSyncRepository { // with how NULL values work in databases. rawAccounts: model.rawAccounts ? z.array(RawAccount).parse(PrismaService.toJson(model.rawAccounts)) : [], completedAt: model.completedAt || undefined, + failures: z.array(RawAccountSyncFailure).parse(PrismaService.toJson(model.failedRawAccounts) || []), error: model.errorName || model.errorMessage || model.errorTraceId ? { @@ -70,6 +72,7 @@ export class ScopedSyncRepository { rawAccounts: z.string().parse(PrismaService.toStringJson(entity.rawAccounts)), createdAt: entity.createdAt, status: entity.status, + failedRawAccounts: PrismaService.toStringJson(entity.failures), ...parseErrorEntity(entity.error) } } @@ -91,6 +94,7 @@ export class ScopedSyncRepository { } async update(updateScopedSync: UpdateScopedSync): Promise { + const failures = updateScopedSync.failures ? PrismaService.toStringJson(updateScopedSync.failures) : null await this.prismaService.providerScopedSync.update({ where: { id: updateScopedSync.scopedSyncId, @@ -99,7 +103,8 @@ export class ScopedSyncRepository { data: { completedAt: updateScopedSync.completedAt, status: updateScopedSync.status, - ...(updateScopedSync.error ? parseErrorEntity(updateScopedSync.error) : {}) + ...(updateScopedSync.error ? parseErrorEntity(updateScopedSync.error) : {}), + failedRawAccounts: failures } }) @@ -144,4 +149,15 @@ export class ScopedSyncRepository { page } } + + async exists({ clientId, connectionId, status }: ConnectionScope & { status?: ScopedSyncStatus }): Promise { + const count = await this.prismaService.providerScopedSync.count({ + where: { + clientId, + connectionId, + ...(status ? { status } : {}) + } + }) + return count > 0 + } } diff --git a/apps/vault/src/broker/persistence/repository/wallet.repository.ts b/apps/vault/src/broker/persistence/repository/wallet.repository.ts index 05c4e9747..93171694c 100644 --- a/apps/vault/src/broker/persistence/repository/wallet.repository.ts +++ b/apps/vault/src/broker/persistence/repository/wallet.repository.ts @@ -1,4 +1,10 @@ -import { PaginatedResult, PaginationOptions, applyPagination, getPaginatedResult } from '@narval/nestjs-shared' +import { + LoggerService, + PaginatedResult, + PaginationOptions, + applyPagination, + getPaginatedResult +} from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' import { ProviderAccount, ProviderAddress, ProviderWallet } from '@prisma/client/vault' import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' @@ -28,7 +34,10 @@ export type FindAllPaginatedOptions = PaginationOptions & FindAllFilters @Injectable() export class WalletRepository { - constructor(private prismaService: PrismaService) {} + constructor( + private prismaService: PrismaService, + private readonly logger: LoggerService + ) {} static parseModel(wallet: ProviderWalletsAndRelations): Wallet { const { accounts, id, ...walletData } = wallet @@ -185,6 +194,77 @@ export class WalletRepository { return wallets } + async bulkUpsert(wallets: Wallet[]): Promise { + const providerWallets: ProviderWallet[] = wallets.map(WalletRepository.parseEntity) + + const stats = { + inserted: 0, + updated: 0 + } + + const existingWallets = await this.prismaService.providerWallet.findMany({ + where: { + OR: providerWallets.map((wallet) => ({ + clientId: wallet.clientId, + connectionId: wallet.connectionId, + externalId: wallet.externalId + })) + } + }) + + const upsertedWallets = await this.prismaService.$transaction(async (tx) => { + const upsertPromises = providerWallets.map(async (wallet) => { + const existing = existingWallets.find( + (w) => + w.clientId === wallet.clientId && + w.connectionId === wallet.connectionId && + w.externalId === wallet.externalId + ) + + const result = tx.providerWallet.upsert({ + where: { + clientId_connectionId_externalId: { + clientId: wallet.clientId, + connectionId: wallet.connectionId, + externalId: wallet.externalId + } + }, + create: { + ...wallet + }, + update: { + label: wallet.label, + updatedAt: wallet.updatedAt + }, + include: { + accounts: { + include: { + addresses: true + } + } + } + }) + + if (!existing) { + stats.inserted++ + } else { + stats.updated++ + } + + return result + }) + return Promise.all(upsertPromises) + }) + + this.logger.log('Wallet bulk upsert operation completed:', { + total: wallets.length, + inserted: stats.inserted, + updated: stats.updated + }) + + return upsertedWallets.map(WalletRepository.parseModel) + } + async update(wallet: UpdateWallet) { const model = await this.prismaService.providerWallet.update({ where: { id: wallet.walletId }, diff --git a/apps/vault/src/shared/module/persistence/schema/migrations/20250124164857_store_failed_raw_accounts_requests/migration.sql b/apps/vault/src/shared/module/persistence/schema/migrations/20250124164857_store_failed_raw_accounts_requests/migration.sql new file mode 100644 index 000000000..2215327bc --- /dev/null +++ b/apps/vault/src/shared/module/persistence/schema/migrations/20250124164857_store_failed_raw_accounts_requests/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "provider_scoped_sync" ADD COLUMN "failed_raw_accounts" TEXT; diff --git a/apps/vault/src/shared/module/persistence/schema/schema.prisma b/apps/vault/src/shared/module/persistence/schema/schema.prisma index 525453ad1..db19dee11 100644 --- a/apps/vault/src/shared/module/persistence/schema/schema.prisma +++ b/apps/vault/src/shared/module/persistence/schema/schema.prisma @@ -124,13 +124,13 @@ model ProviderAccount { connectionId String @map("connection_id") externalId String @map("external_id") provider String - walletId String @map("wallet_id") + walletId String? @map("wallet_id") networkId String @map("network_id") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") connection ProviderConnection @relation(fields: [connectionId], references: [id]) - wallet ProviderWallet @relation(fields: [walletId], references: [id]) + wallet ProviderWallet? @relation(fields: [walletId], references: [id]) addresses ProviderAddress[] sourceTransfers ProviderTransfer[] @relation("SourceAccount") @@ -206,17 +206,20 @@ model ProviderSync { } model ProviderScopedSync { - id String @id - clientId String @map("client_id") - connectionId String @map("connection_id") + id String @id + clientId String @map("client_id") + connectionId String @map("connection_id") status String + rawAccounts String @map("raw_accounts") + errorName String? @map("error_name") errorMessage String? @map("error_message") errorTraceId String? @map("error_trace_id") - rawAccounts String @map("raw_accounts") createdAt DateTime @default(now()) @map("created_at") completedAt DateTime? @map("completed_at") + failedRawAccounts String? @map("failed_raw_accounts") + connection ProviderConnection @relation(fields: [connectionId], references: [id]) @@map("provider_scoped_sync") From 09f92c744fa45df41645dc82fe2c854e8242a27e Mon Sep 17 00:00:00 2001 From: Ptroger <44851272+Ptroger@users.noreply.github.com> Date: Tue, 28 Jan 2025 15:14:16 +0100 Subject: [PATCH 105/120] declare mock-server (#116) --- .../__test__/integration/fireblocks-scoped-sync.service.spec.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-scoped-sync.service.spec.ts b/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-scoped-sync.service.spec.ts index dd91c6fc9..2d011654f 100644 --- a/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-scoped-sync.service.spec.ts +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-scoped-sync.service.spec.ts @@ -68,6 +68,8 @@ iYDlTZ/pWsEotE2yCl/8krs= const privateKey = Buffer.from(privateKeyPem).toString('base64') + const mockServer = setupMockServer(getHandlers()) + const clientId = 'test-client-id' beforeAll(async () => { From 3fdaa09a90813feb6f945710b625d6b83f8d6197 Mon Sep 17 00:00:00 2001 From: Pierre Troger Date: Tue, 28 Jan 2025 15:21:11 +0100 Subject: [PATCH 106/120] Revert "declare mock-server (#116)" This reverts commit 09f92c744fa45df41645dc82fe2c854e8242a27e. --- .../__test__/integration/fireblocks-scoped-sync.service.spec.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-scoped-sync.service.spec.ts b/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-scoped-sync.service.spec.ts index 2d011654f..dd91c6fc9 100644 --- a/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-scoped-sync.service.spec.ts +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-scoped-sync.service.spec.ts @@ -68,8 +68,6 @@ iYDlTZ/pWsEotE2yCl/8krs= const privateKey = Buffer.from(privateKeyPem).toString('base64') - const mockServer = setupMockServer(getHandlers()) - const clientId = 'test-client-id' beforeAll(async () => { From 4b7f22816dd2fe60360f35533f30582f14b13abc Mon Sep 17 00:00:00 2001 From: Pierre Troger Date: Tue, 28 Jan 2025 15:21:18 +0100 Subject: [PATCH 107/120] Revert "Delete sync operations (#110)" This reverts commit 67ef11f2714fc609e5ae60f8f36ef09b4aa8d26a. --- .../core/exception/scoped-sync.exception.ts | 13 - .../anchorage-scoped-sync.service.spec.ts | 109 ++-- .../anchorage-scoped-sync.service.ts | 465 +++++++++--------- .../core/provider/anchorage/anchorage.util.ts | 2 - .../fireblocks-scoped-sync.service.spec.ts | 126 +++-- .../response/get-vault-account-invalid.json | 4 - .../get-wallet-addresses-ethereum-200.json | 2 +- .../fireblocks/__test__/server-mock/server.ts | 24 +- .../fireblocks-scoped-sync.service.ts | 462 ++++++++--------- .../provider/fireblocks/fireblocks.util.ts | 16 +- .../broker/core/service/account.service.ts | 4 - .../broker/core/service/network.service.ts | 4 +- .../core/service/raw-account.service.ts | 100 ++-- .../core/service/scoped-sync.service.ts | 226 ++++----- .../src/broker/core/service/wallet.service.ts | 4 - .../src/broker/core/type/network.type.ts | 5 +- .../src/broker/core/type/provider.type.ts | 214 +++++++- .../src/broker/core/type/scoped-sync.type.ts | 52 +- .../broker/core/util/provider-sync.util.ts | 16 + .../http/rest/dto/response/scoped-sync.dto.ts | 6 +- .../repository/account.repository.ts | 82 +-- .../repository/address.repository.ts | 23 +- .../repository/scoped-sync.repository.ts | 20 +- .../repository/wallet.repository.ts | 84 +--- .../migration.sql | 2 - .../module/persistence/schema/schema.prisma | 15 +- 26 files changed, 993 insertions(+), 1087 deletions(-) delete mode 100644 apps/vault/src/broker/core/exception/scoped-sync.exception.ts delete mode 100644 apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-vault-account-invalid.json create mode 100644 apps/vault/src/broker/core/util/provider-sync.util.ts delete mode 100644 apps/vault/src/shared/module/persistence/schema/migrations/20250124164857_store_failed_raw_accounts_requests/migration.sql diff --git a/apps/vault/src/broker/core/exception/scoped-sync.exception.ts b/apps/vault/src/broker/core/exception/scoped-sync.exception.ts deleted file mode 100644 index 1044715df..000000000 --- a/apps/vault/src/broker/core/exception/scoped-sync.exception.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { HttpStatus } from '@nestjs/common' -import { ApplicationExceptionParams } from '../../../shared/exception/application.exception' -import { BrokerException } from './broker.exception' - -export class ScopedSyncException extends BrokerException { - constructor(params?: Partial) { - super({ - message: params?.message || 'Fail to sync provider connection', - suggestedHttpStatusCode: params?.suggestedHttpStatusCode || HttpStatus.UNPROCESSABLE_ENTITY, - ...params - }) - } -} diff --git a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-scoped-sync.service.spec.ts b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-scoped-sync.service.spec.ts index 7d112042a..200519cfe 100644 --- a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-scoped-sync.service.spec.ts +++ b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-scoped-sync.service.spec.ts @@ -10,11 +10,12 @@ import { TestPrismaService } from '../../../../../../shared/module/persistence/s import { testClient } from '../../../../../__test__/util/mock-data' import { NetworkSeed } from '../../../../../persistence/seed/network.seed' import { setupMockServer } from '../../../../../shared/__test__/mock-server' +import { AccountService } from '../../../../service/account.service' +import { AddressService } from '../../../../service/address.service' import { ConnectionService } from '../../../../service/connection.service' -import { NetworkService } from '../../../../service/network.service' +import { WalletService } from '../../../../service/wallet.service' import { ConnectionWithCredentials } from '../../../../type/connection.type' -import { Provider } from '../../../../type/provider.type' -import { RawAccountError } from '../../../../type/scoped-sync.type' +import { Provider, isCreateOperation } from '../../../../type/provider.type' import { AnchorageScopedSyncService } from '../../anchorage-scoped-sync.service' import { ANCHORAGE_TEST_API_BASE_URL, getHandlers } from '../server-mock/server' @@ -25,7 +26,9 @@ describe(AnchorageScopedSyncService.name, () => { let anchorageScopedSyncService: AnchorageScopedSyncService let clientService: ClientService let connection: ConnectionWithCredentials - let networkService: NetworkService + let walletService: WalletService + let accountService: AccountService + let addressService: AddressService let connectionService: ConnectionService let networkSeed: NetworkSeed let provisionService: ProvisionService @@ -45,7 +48,9 @@ describe(AnchorageScopedSyncService.name, () => { testPrismaService = module.get(TestPrismaService) anchorageScopedSyncService = module.get(AnchorageScopedSyncService) connectionService = module.get(ConnectionService) - networkService = module.get(NetworkService) + walletService = module.get(WalletService) + accountService = module.get(AccountService) + addressService = module.get(AddressService) provisionService = module.get(ProvisionService) networkSeed = module.get(NetworkSeed) clientService = module.get(ClientService) @@ -89,14 +94,7 @@ describe(AnchorageScopedSyncService.name, () => { externalId: '6a46a1977959e0529f567e8e927e3895' } ] - const networks = await networkService.buildProviderExternalIdIndex(Provider.ANCHORAGE) - - const sync = await anchorageScopedSyncService.scopeSync({ - connection, - rawAccounts, - networks, - existingAccounts: [] - }) + const sync = await anchorageScopedSyncService.scopedSync(connection, rawAccounts) expect(sync.wallets.length).toBe(1) expect(sync.accounts.length).toBe(1) @@ -105,76 +103,75 @@ describe(AnchorageScopedSyncService.name, () => { // TODO @ptroger: revert that back to 'return empty array' when we completely move towards the scoped connections it('returns full connection sync when empty rawAccounts are provided', async () => { - const networks = await networkService.buildProviderExternalIdIndex(Provider.ANCHORAGE) - - const sync = await anchorageScopedSyncService.scopeSync({ - connection, - rawAccounts: [], - networks, - existingAccounts: [] - }) + const sync = await anchorageScopedSyncService.scopedSync(connection, []) expect(sync.wallets.length).toBe(2) expect(sync.accounts.length).toBe(18) - expect(sync.addresses.length).toBe(18) + expect(sync.addresses.length).toBe(2) }) - it('adds failure when external resource is not found', async () => { + it('returns empty array when no wallets are found for the provided rawAccounts', async () => { const rawAccounts = [ { provider: Provider.ANCHORAGE, externalId: 'notFound' } ] - const networks = await networkService.buildProviderExternalIdIndex(Provider.ANCHORAGE) - - const sync = await anchorageScopedSyncService.scopeSync({ - connection, - rawAccounts, - networks, - existingAccounts: [] - }) + const sync = await anchorageScopedSyncService.scopedSync(connection, rawAccounts) expect(sync.wallets.length).toBe(0) expect(sync.accounts.length).toBe(0) expect(sync.addresses.length).toBe(0) - expect(sync.failures).toEqual([ + }) + it('skips duplicate for the same connection', async () => { + const rawAccounts = [ { - rawAccount: rawAccounts[0], - message: 'Anchorage wallet not found', - code: RawAccountError.EXTERNAL_RESOURCE_NOT_FOUND, - externalResourceType: 'wallet', - externalResourceId: rawAccounts[0].externalId + provider: Provider.ANCHORAGE, + externalId: '6a46a1977959e0529f567e8e927e3895' } - ]) + ] + const firstSync = await anchorageScopedSyncService.scopedSync(connection, rawAccounts) + + await walletService.bulkCreate(firstSync.wallets.filter(isCreateOperation).map(({ create }) => create)) + await accountService.bulkCreate(firstSync.accounts.filter(isCreateOperation).map(({ create }) => create)) + await addressService.bulkCreate(firstSync.addresses.filter(isCreateOperation).map(({ create }) => create)) + + const secondSync = await anchorageScopedSyncService.scopedSync(connection, rawAccounts) + + expect(secondSync.wallets.length).toBe(0) + expect(secondSync.accounts.length).toBe(0) + expect(secondSync.addresses.length).toBe(0) }) - it('adds failure when network is not found in our list', async () => { + it('duplicates for different connections', async () => { const rawAccounts = [ { provider: Provider.ANCHORAGE, externalId: '6a46a1977959e0529f567e8e927e3895' } ] - - const sync = await anchorageScopedSyncService.scopeSync({ - connection, - rawAccounts, - networks: new Map(), - existingAccounts: [] + const firstSync = await anchorageScopedSyncService.scopedSync(connection, rawAccounts) + + await walletService.bulkCreate(firstSync.wallets.filter(isCreateOperation).map(({ create }) => create)) + await accountService.bulkCreate(firstSync.accounts.filter(isCreateOperation).map(({ create }) => create)) + await addressService.bulkCreate(firstSync.addresses.filter(isCreateOperation).map(({ create }) => create)) + + const secondConnection = await connectionService.create(clientId, { + connectionId: uuid(), + provider: Provider.ANCHORAGE, + url: ANCHORAGE_TEST_API_BASE_URL, + label: 'test active connection', + credentials: { + apiKey: 'test-api-key', + privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) + } }) - expect(sync.wallets.length).toBe(0) - expect(sync.accounts.length).toBe(0) - expect(sync.addresses.length).toBe(0) - expect(sync.failures).toEqual([ - { - rawAccount: rawAccounts[0], - message: 'Network for this account is not supported', - code: RawAccountError.UNLISTED_NETWORK, - networkId: 'BTC_S' - } - ]) + const secondSync = await anchorageScopedSyncService.scopedSync(secondConnection, rawAccounts) + + expect(secondSync.wallets.length).toBe(1) + expect(secondSync.accounts.length).toBe(1) + expect(secondSync.addresses.length).toBe(1) }) }) }) diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage-scoped-sync.service.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage-scoped-sync.service.ts index 530aa21d3..c4cfbf0b4 100644 --- a/apps/vault/src/broker/core/provider/anchorage/anchorage-scoped-sync.service.ts +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage-scoped-sync.service.ts @@ -1,278 +1,287 @@ import { LoggerService } from '@narval/nestjs-shared' import { HttpStatus, Injectable } from '@nestjs/common' import { randomUUID } from 'crypto' -import { chunk, uniqBy } from 'lodash/fp' +import { filter, find, flatMap, flow, groupBy, isEmpty, map, uniqBy } from 'lodash/fp' import { AnchorageClient, Wallet as AnchorageWallet } from '../../../http/client/anchorage.client' +import { UpdateAccount } from '../../../persistence/repository/account.repository' +import { NetworkRepository } from '../../../persistence/repository/network.repository' +import { WalletRepository } from '../../../persistence/repository/wallet.repository' import { ConnectionWithCredentials } from '../../type/connection.type' -import { Account, Address, Wallet } from '../../type/indexed-resources.type' -import { NetworkMap } from '../../type/network.type' -import { Provider, ProviderScopedSyncService } from '../../type/provider.type' +import { Account, Address, UpdateWallet, Wallet } from '../../type/indexed-resources.type' import { - RawAccount, - RawAccountError, - RawAccountSyncFailure, - ScopedSyncContext, + CreateScopedSyncOperation, + Provider, + ProviderScopedSyncService, + ScopedSyncOperation, + ScopedSyncOperationType, ScopedSyncResult -} from '../../type/scoped-sync.type' -import { CONCURRENT_ANCHORAGE_REQUESTS, ValidConnection, validateConnection } from './anchorage.util' - -type RawAccountSyncSuccess = { - success: true - wallet: Wallet - account: Account - address: Address -} - -type RawAccountSyncFailed = { - success: false - failure: RawAccountSyncFailure -} - -type RawAccountSyncResult = RawAccountSyncSuccess | RawAccountSyncFailed +} from '../../type/provider.type' +import { RawAccount } from '../../type/scoped-sync.type' +import { CONCURRENT_ANCHORAGE_REQUESTS, validateConnection } from './anchorage.util' @Injectable() export class AnchorageScopedSyncService implements ProviderScopedSyncService { constructor( private readonly anchorageClient: AnchorageClient, + private readonly networkRepository: NetworkRepository, + private readonly walletRepository: WalletRepository, private readonly logger: LoggerService ) {} - private resolveFailure(failure: RawAccountSyncFailure): RawAccountSyncFailed { - this.logger.log('Failed to sync Raw Account', failure) - return { success: false, failure } - } + private async fetchRawAccountWallets( + connection: ConnectionWithCredentials, + rawAccounts: RawAccount[] + ): Promise { + validateConnection(connection) - private resolveSuccess({ - rawAccount, - wallet, - account, - address - }: { - wallet: Wallet - address: Address - rawAccount: RawAccount - account: Account - }): RawAccountSyncSuccess { - this.logger.log('Successfully fetched and map Raw Account', { - rawAccount, - account - }) - return { - success: true, - wallet, - account, - address - } - } + const wallets: AnchorageWallet[] = [] - private mapAnchorageWalletToNarvalModel( - anchorageWallet: AnchorageWallet, - { - networks, - now, - existingAccounts, - rawAccount, - connection, - existingWallets - }: { - networks: NetworkMap - now: Date - existingAccounts: Account[] - existingWallets: Wallet[] - rawAccount: RawAccount - connection: ValidConnection - } - ): RawAccountSyncResult { - const network = networks.get(anchorageWallet.networkId) - if (!network) { - this.logger.error('Network not found', { - rawAccount, - externalNetwork: anchorageWallet.networkId - }) - return this.resolveFailure({ - rawAccount, - message: 'Network for this account is not supported', - code: RawAccountError.UNLISTED_NETWORK, - networkId: anchorageWallet.networkId - }) - } - const existingAccount = existingAccounts.find((a) => a.externalId === anchorageWallet.walletId) - const existingWallet = existingWallets.find((w) => w.externalId === anchorageWallet.vaultId) + for (let i = 0; i < rawAccounts.length; i += CONCURRENT_ANCHORAGE_REQUESTS) { + const batch = rawAccounts.slice(i, i + CONCURRENT_ANCHORAGE_REQUESTS) + const batchPromises = batch.map((rawAccount) => + this.anchorageClient.getWallet({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey, + walletId: rawAccount.externalId + }) + ) - const walletId = existingWallet?.walletId || existingAccount?.walletId || randomUUID() - const accountId = existingAccount?.accountId || randomUUID() + const batchResults = await Promise.allSettled(batchPromises) - const wallet: Wallet = { - accounts: [], - clientId: connection.clientId, - connectionId: connection.connectionId, - createdAt: now, - externalId: anchorageWallet.vaultId, - label: anchorageWallet.walletName, - provider: Provider.ANCHORAGE, - updatedAt: now, - walletId - } + const validWallets = batchResults + .map((result, index) => { + if (result.status === 'fulfilled') { + return result.value + } else { + // Handle rejected promises + const error = result.reason + const rawAccount = batch[index] - const account: Account = { - externalId: anchorageWallet.walletId, - accountId, - addresses: [], - clientId: connection.clientId, - connectionId: connection.connectionId, - createdAt: now, - label: anchorageWallet.walletName, - networkId: network.networkId, - provider: Provider.ANCHORAGE, - updatedAt: now, - walletId - } + if (error.response?.status === HttpStatus.NOT_FOUND) { + this.logger.warn('Anchorage wallet not found', { + connectionId: connection.connectionId, + clientId: connection.clientId, + url: connection.url, + externalId: rawAccount.externalId + }) + return null + } + throw error + } + }) + .filter((wallet): wallet is AnchorageWallet => wallet !== null) as AnchorageWallet[] - const address: Address = { - accountId, - address: anchorageWallet.depositAddress.address, - addressId: randomUUID(), - clientId: connection.clientId, - connectionId: connection.connectionId, - createdAt: now, - externalId: anchorageWallet.depositAddress.addressId, - provider: Provider.ANCHORAGE, - updatedAt: now + wallets.push(...validWallets) } - return this.resolveSuccess({ rawAccount, wallet, account, address }) + return wallets } - private async syncRawAccount({ - connection, - rawAccount, - networks, - now, - existingAccounts, - existingWallets - }: { - connection: ConnectionWithCredentials - rawAccount: RawAccount - networks: NetworkMap - now: Date - existingAccounts: Account[] - existingWallets: Wallet[] - }): Promise { - validateConnection(connection) - - try { - const anchorageWallet = await this.anchorageClient.getWallet({ - url: connection.url, - apiKey: connection.credentials.apiKey, - signKey: connection.credentials.privateKey, - walletId: rawAccount.externalId - }) - - return this.mapAnchorageWalletToNarvalModel(anchorageWallet, { - networks, - now, - existingAccounts, - rawAccount, - connection, - existingWallets - }) - } catch (error) { - if (error.response?.status === HttpStatus.NOT_FOUND) { - return this.resolveFailure({ - rawAccount, - message: 'Anchorage wallet not found', - code: RawAccountError.EXTERNAL_RESOURCE_NOT_FOUND, - externalResourceType: 'wallet', - externalResourceId: rawAccount.externalId - }) - } - throw error - } - } + async scopedSync(connection: ConnectionWithCredentials, rawAccounts: RawAccount[]): Promise { + const now = new Date() - async scopeSync({ - connection, - rawAccounts, - networks, - existingAccounts - }: ScopedSyncContext): Promise { this.logger.log('Sync Anchorage accounts', { connectionId: connection.connectionId, clientId: connection.clientId, url: connection.url }) - const now = new Date() + validateConnection(connection) - const chunkedRawAccounts = chunk(CONCURRENT_ANCHORAGE_REQUESTS, rawAccounts) - const results: RawAccountSyncResult[] = [] + const existingWallets = await this.walletRepository.findAll( + { clientId: connection.clientId, connectionId: connection.connectionId }, + { pagination: { disabled: true } } + ) + + const existingWalletMap = new Map(existingWallets.data.map((wallet) => [wallet.externalId, wallet])) + const existingAccountMap = new Map( + existingWallets.data.flatMap( + (wallet) => + wallet.accounts?.map((account) => [account.externalId, { ...account, walletId: wallet.walletId }]) ?? [] + ) + ) + + // TODO @ptroger: revert that back to 'return empty array' when we completely move towards the scoped connections + const scopedAnchorageWallets = isEmpty(rawAccounts) + ? await this.anchorageClient.getWallets({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey + }) + : await this.fetchRawAccountWallets(connection, rawAccounts) - // TODO @ptroger: remove the if block when we completely move towards picking accounts in UI - if (rawAccounts.length === 0) { - validateConnection(connection) + const walletsByVault = groupBy('vaultId', scopedAnchorageWallets) + const vaultAndWallets = Object.entries(walletsByVault).map(([vaultId, wallets]) => ({ + id: vaultId, + // All wallets in a vault should have the same vault name + name: wallets[0].vaultName, + wallets: wallets.map((wallet) => ({ + walletId: wallet.walletId, + walletName: wallet.walletName, + address: { + address: wallet.depositAddress.address, + addressId: wallet.depositAddress.addressId + }, + assets: wallet.assets.map((asset) => ({ + assetType: asset.assetType, + availableBalance: asset.availableBalance, + totalBalance: asset.totalBalance, + stakedBalance: asset.stakedBalance, + unclaimedBalance: asset.unclaimedBalance + })), + networkId: wallet.networkId + })) + })) - const anchorageWallets = await this.anchorageClient.getWallets({ - url: connection.url, - apiKey: connection.credentials.apiKey, - signKey: connection.credentials.privateKey - }) + const walletOperations: ScopedSyncOperation[] = [] + const accountOperations: ScopedSyncOperation[] = [] + const addressOperations: ScopedSyncOperation[] = [] - const existingWallets: Wallet[] = [] - const mappedAnchorageWallets = anchorageWallets.map((anchorageWallet) => { - const map = this.mapAnchorageWalletToNarvalModel(anchorageWallet, { - networks, - now, - existingAccounts, - rawAccount: { provider: Provider.ANCHORAGE, externalId: anchorageWallet.walletId }, - connection, - existingWallets + for (const vault of vaultAndWallets) { + const existingWallet = existingWalletMap.get(vault.id) + const walletId = existingWallet?.walletId || randomUUID() + + if (existingWallet) { + // Check if wallet needs update + if (existingWallet.label !== vault.name) { + walletOperations.push({ + type: ScopedSyncOperationType.UPDATE, + update: { + clientId: connection.clientId, + walletId, + label: vault.name, + updatedAt: now + } + }) + } + } else { + // Create new wallet + walletOperations.push({ + type: ScopedSyncOperationType.CREATE, + create: { + accounts: [], + clientId: connection.clientId, + connectionId: connection.connectionId, + createdAt: now, + externalId: vault.id, + label: vault.name, + provider: Provider.ANCHORAGE, + updatedAt: now, + walletId + } }) - map.success && existingWallets.push(map.wallet) - return map - }) + } + + const vaultAssetTypes = flow(flatMap('assets'), uniqBy('assetType'), map('assetType'))(vault.wallets) + + for (const anchorageWallet of vault.wallets) { + const existingAccount = existingAccountMap.get(anchorageWallet.walletId) + const accountId = existingAccount?.accountId || randomUUID() + const network = await this.networkRepository.findByExternalId(Provider.ANCHORAGE, anchorageWallet.networkId) - results.push(...mappedAnchorageWallets) - } else { - const existingWallets: Wallet[] = [] - for (const chunk of chunkedRawAccounts) { - const chunkResults = await Promise.all( - chunk.map(async (rawAccount) => { - const mapResult = await this.syncRawAccount({ - connection, - rawAccount, - networks, - now, - existingAccounts, - existingWallets + if (network) { + if (existingAccount) { + // Check if account needs update + if (existingAccount.label !== anchorageWallet.walletName) { + accountOperations.push({ + type: ScopedSyncOperationType.UPDATE, + update: { + clientId: connection.clientId, + accountId: existingAccount.accountId, + label: anchorageWallet.walletName, + updatedAt: now + } + }) + } + } else { + accountOperations.push({ + type: ScopedSyncOperationType.CREATE, + create: { + externalId: anchorageWallet.walletId, + accountId, + addresses: [], + clientId: connection.clientId, + connectionId: connection.connectionId, + createdAt: now, + label: anchorageWallet.walletName, + networkId: network.networkId, + provider: Provider.ANCHORAGE, + updatedAt: now, + walletId + } }) - mapResult.success && existingWallets.push(mapResult.wallet) - return mapResult + } + } else { + accountOperations.push({ + type: ScopedSyncOperationType.FAILED, + externalId: anchorageWallet.walletId, + message: 'Unknown Anchorage wallet network ID', + context: { + externalId: anchorageWallet.walletId, + anchorageNetworkId: anchorageWallet.networkId + } }) - ) - results.push(...chunkResults) + } } - } - const wallets: Wallet[] = [] - const accounts: Account[] = [] - const addresses: Address[] = [] - const failures: RawAccountSyncFailure[] = [] + // Process addresses - Anchorage only creates, no updates + for (const assetType of vaultAssetTypes) { + const addresses = await this.anchorageClient.getVaultAddresses({ + signKey: connection.credentials.privateKey, + apiKey: connection.credentials.apiKey, + assetType, + url: connection.url, + vaultId: vault.id + }) - for (const result of results) { - if (result.success) { - wallets.push(result.wallet) - accounts.push(result.account) - addresses.push(result.address) - } else { - failures.push(result.failure) + for (const address of addresses) { + const account = flow( + filter((op: ScopedSyncOperation) => op.type === ScopedSyncOperationType.CREATE), + find((op: CreateScopedSyncOperation) => op.create.externalId === address.walletId) + )(accountOperations) + + const existingAccount = existingAccountMap.get(address.walletId) + const skipAddress = existingAccount?.addresses?.some((a) => a.externalId === address.addressId) + + const tiedAccount = account?.create?.accountId || existingAccount?.accountId + if (!skipAddress && tiedAccount) { + if (account?.create?.accountId || existingAccount?.accountId) { + addressOperations.push({ + type: ScopedSyncOperationType.CREATE, + create: { + accountId: tiedAccount, + address: address.address, + addressId: randomUUID(), + clientId: connection.clientId, + connectionId: connection.connectionId, + createdAt: now, + externalId: address.addressId, + provider: Provider.ANCHORAGE, + updatedAt: now + } + }) + } else { + addressOperations.push({ + type: ScopedSyncOperationType.FAILED, + externalId: address.addressId, + message: 'Unknown Anchorage wallet address', + context: { + externalId: address.addressId, + address: address.address, + walletId: address.walletId + } + }) + } + } + } } } return { - wallets: uniqBy('externalId', wallets), - accounts: uniqBy('externalId', accounts), - addresses: uniqBy('externalId', addresses), - failures + wallets: walletOperations, + accounts: accountOperations, + addresses: addressOperations } } } diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage.util.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage.util.ts index cb0ead59f..5703365af 100644 --- a/apps/vault/src/broker/core/provider/anchorage/anchorage.util.ts +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage.util.ts @@ -15,8 +15,6 @@ export type ValidConnection = { apiKey: string privateKey: Ed25519PrivateKey } - clientId: string - connectionId: string } export function validateConnection( diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-scoped-sync.service.spec.ts b/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-scoped-sync.service.spec.ts index dd91c6fc9..075ab43a1 100644 --- a/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-scoped-sync.service.spec.ts +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-scoped-sync.service.spec.ts @@ -9,18 +9,15 @@ import { TestPrismaService } from '../../../../../../shared/module/persistence/s import { testClient } from '../../../../../__test__/util/mock-data' import { NetworkSeed } from '../../../../../persistence/seed/network.seed' import { setupMockServer } from '../../../../../shared/__test__/mock-server' +import { AccountService } from '../../../../service/account.service' +import { AddressService } from '../../../../service/address.service' import { ConnectionService } from '../../../../service/connection.service' -import { NetworkService } from '../../../../service/network.service' +import { WalletService } from '../../../../service/wallet.service' import { ConnectionWithCredentials } from '../../../../type/connection.type' -import { Provider } from '../../../../type/provider.type' -import { RawAccountError } from '../../../../type/scoped-sync.type' -import { - FIREBLOCKS_TEST_API_BASE_URL, - getHandlers, - getVaultAccountHandlers -} from '../../../fireblocks/__test__/server-mock/server' +import { Provider, isCreateOperation } from '../../../../type/provider.type' +import { FIREBLOCKS_TEST_API_BASE_URL, getHandlers } from '../../../fireblocks/__test__/server-mock/server' import { FireblocksScopedSyncService } from '../../fireblocks-scoped-sync.service' -import { buildFireblocksAssetWalletExternalId } from '../../fireblocks.util' +import { getFireblocksAssetWalletExternalId } from '../../fireblocks.util' describe(FireblocksScopedSyncService.name, () => { let app: INestApplication @@ -29,9 +26,11 @@ describe(FireblocksScopedSyncService.name, () => { let fireblocksScopedSyncService: FireblocksScopedSyncService let clientService: ClientService let connection: ConnectionWithCredentials + let walletService: WalletService + let accountService: AccountService + let addressService: AddressService let connectionService: ConnectionService let networkSeed: NetworkSeed - let networkService: NetworkService let provisionService: ProvisionService let testPrismaService: TestPrismaService @@ -80,7 +79,9 @@ iYDlTZ/pWsEotE2yCl/8krs= testPrismaService = module.get(TestPrismaService) fireblocksScopedSyncService = module.get(FireblocksScopedSyncService) connectionService = module.get(ConnectionService) - networkService = module.get(NetworkService) + walletService = module.get(WalletService) + accountService = module.get(AccountService) + addressService = module.get(AddressService) provisionService = module.get(ProvisionService) networkSeed = module.get(NetworkSeed) clientService = module.get(ClientService) @@ -121,96 +122,87 @@ iYDlTZ/pWsEotE2yCl/8krs= const rawAccounts = [ { provider: Provider.FIREBLOCKS, - externalId: buildFireblocksAssetWalletExternalId({ vaultId: '3', networkId: 'ETH' }) + externalId: getFireblocksAssetWalletExternalId({ vaultId: '3', networkId: 'ETHEREUM' }) } ] - - const networks = await networkService.buildProviderExternalIdIndex(Provider.FIREBLOCKS) - const sync = await fireblocksScopedSyncService.scopeSync({ - connection, - rawAccounts, - networks, - existingAccounts: [] - }) + const sync = await fireblocksScopedSyncService.scopedSync(connection, rawAccounts) expect(sync.wallets.length).toBe(1) expect(sync.accounts.length).toBe(1) expect(sync.addresses.length).toBe(1) }) - it('returns empty objects when no rawAccounts are provided', async () => { - const networks = await networkService.buildProviderExternalIdIndex(Provider.FIREBLOCKS) - - const sync = await fireblocksScopedSyncService.scopeSync({ - connection, - rawAccounts: [], - networks, - existingAccounts: [] - }) + it('returns empty array when no rawAccounts are provided', async () => { + const sync = await fireblocksScopedSyncService.scopedSync(connection, []) expect(sync.wallets.length).toBe(0) expect(sync.accounts.length).toBe(0) expect(sync.addresses.length).toBe(0) }) - it('adds failure when external resource is not found', async () => { - mockServer.use(getVaultAccountHandlers(FIREBLOCKS_TEST_API_BASE_URL).invalid) + it('returns empty array when no wallets are found for the provided rawAccounts', async () => { const rawAccounts = [ { provider: Provider.FIREBLOCKS, - externalId: buildFireblocksAssetWalletExternalId({ vaultId: 'notfound', networkId: 'ETH' }) + externalId: getFireblocksAssetWalletExternalId({ vaultId: 'notfound', networkId: 'ETHEREUM' }) } ] - const networks = await networkService.buildProviderExternalIdIndex(Provider.FIREBLOCKS) - - const sync = await fireblocksScopedSyncService.scopeSync({ - connection, - rawAccounts, - networks, - existingAccounts: [] - }) + const sync = await fireblocksScopedSyncService.scopedSync(connection, rawAccounts) expect(sync.wallets.length).toBe(0) expect(sync.accounts.length).toBe(0) expect(sync.addresses.length).toBe(0) - expect(sync.failures).toEqual([ - { - rawAccount: rawAccounts[0], - message: 'Fireblocks Vault Account not found', - code: RawAccountError.EXTERNAL_RESOURCE_NOT_FOUND, - externalResourceType: 'vaultAccount', - externalResourceId: 'NOTFOUND' - } - ]) }) - it('adds failure when network is not found in our list', async () => { + it('skips duplicate for the same connection', async () => { const rawAccounts = [ { provider: Provider.FIREBLOCKS, - externalId: buildFireblocksAssetWalletExternalId({ vaultId: '3', networkId: 'notFound' }) + externalId: getFireblocksAssetWalletExternalId({ vaultId: '3', networkId: 'ETHEREUM' }) } ] - const networks = await networkService.buildProviderExternalIdIndex(Provider.FIREBLOCKS) + const firstSync = await fireblocksScopedSyncService.scopedSync(connection, rawAccounts) - const sync = await fireblocksScopedSyncService.scopeSync({ - connection, - rawAccounts, - networks, - existingAccounts: [] - }) + await walletService.bulkCreate(firstSync.wallets.filter(isCreateOperation).map(({ create }) => create)) + await accountService.bulkCreate(firstSync.accounts.filter(isCreateOperation).map(({ create }) => create)) + await addressService.bulkCreate(firstSync.addresses.filter(isCreateOperation).map(({ create }) => create)) - expect(sync.wallets.length).toBe(0) - expect(sync.accounts.length).toBe(0) - expect(sync.addresses.length).toBe(0) - expect(sync.failures).toEqual([ + const secondSync = await fireblocksScopedSyncService.scopedSync(connection, rawAccounts) + + expect(secondSync.wallets.length).toBe(0) + expect(secondSync.accounts.length).toBe(0) + expect(secondSync.addresses.length).toBe(0) + }) + + it('duplicates for different connections', async () => { + const rawAccounts = [ { - rawAccount: rawAccounts[0], - message: 'Network for this account is not supported', - code: RawAccountError.UNLISTED_NETWORK, - networkId: 'NOTFOUND' + provider: Provider.FIREBLOCKS, + externalId: getFireblocksAssetWalletExternalId({ vaultId: '3', networkId: 'ETHEREUM' }) } - ]) + ] + const firstSync = await fireblocksScopedSyncService.scopedSync(connection, rawAccounts) + + await walletService.bulkCreate(firstSync.wallets.filter(isCreateOperation).map(({ create }) => create)) + await accountService.bulkCreate(firstSync.accounts.filter(isCreateOperation).map(({ create }) => create)) + await addressService.bulkCreate(firstSync.addresses.filter(isCreateOperation).map(({ create }) => create)) + + const secondConnection = await connectionService.create(clientId, { + connectionId: uuid(), + provider: Provider.FIREBLOCKS, + url: FIREBLOCKS_TEST_API_BASE_URL, + label: 'test active connection', + credentials: { + apiKey: 'test-api-key', + privateKey + } + }) + + const secondSync = await fireblocksScopedSyncService.scopedSync(secondConnection, rawAccounts) + + expect(secondSync.wallets.length).toBe(1) + expect(secondSync.accounts.length).toBe(1) + expect(secondSync.addresses.length).toBe(1) }) }) }) diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-vault-account-invalid.json b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-vault-account-invalid.json deleted file mode 100644 index 141a18b01..000000000 --- a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-vault-account-invalid.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "message": "The Provided Vault Account ID is invalid: 11469", - "code": 11001 -} diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-wallet-addresses-ethereum-200.json b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-wallet-addresses-ethereum-200.json index e38ab060f..c02b95088 100644 --- a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-wallet-addresses-ethereum-200.json +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-wallet-addresses-ethereum-200.json @@ -1,7 +1,7 @@ { "addresses": [ { - "assetId": "ETH", + "assetId": "ETH-OPT", "address": "0x5748EA5ca075734bc7ADc9D8046e897c24829A80", "description": "", "tag": "", diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/server.ts b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/server.ts index 46ecad105..958d9ab7f 100644 --- a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/server.ts +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/server.ts @@ -1,8 +1,6 @@ -import { HttpStatus } from '@nestjs/common' import { HttpResponse, http } from 'msw' import getTransactionOk from './response/get-transaction-200.json' import vaultAccount3 from './response/get-vault-account-3-200.json' -import vaultAccountNotFound from './response/get-vault-account-invalid.json' import getWalletAddressesEthOk from './response/get-wallet-addresses-ethereum-200.json' import getWalletAddressesMaticOk from './response/get-wallet-addresses-matic-200.json' import postTransactionCreated from './response/post-transaction-201.json' @@ -22,22 +20,6 @@ export const getVaultAccount3AddressesHandlers = (baseUrl = FIREBLOCKS_TEST_API_ } } -export const getVaultAccountHandlers = (baseUrl = FIREBLOCKS_TEST_API_BASE_URL) => { - return { - get: http.get(`${baseUrl}/v1/vault/accounts/:vaultAccountId`, () => { - return new HttpResponse(JSON.stringify(vaultAccount3)) - }), - invalid: http.get( - `${baseUrl}/v1/vault/accounts/:vaultAccountId`, - () => - new HttpResponse(JSON.stringify(vaultAccountNotFound), { - status: HttpStatus.BAD_REQUEST - // eslint-disable-next-line @typescript-eslint/no-explicit-any - } as unknown as any) - ) - } -} - export const getHandlers = (baseUrl = FIREBLOCKS_TEST_API_BASE_URL) => [ http.get(`${baseUrl}/v1/transactions/:txId`, () => { return new HttpResponse(JSON.stringify(getTransactionOk)) @@ -47,7 +29,9 @@ export const getHandlers = (baseUrl = FIREBLOCKS_TEST_API_BASE_URL) => [ return new HttpResponse(JSON.stringify(postTransactionCreated)) }), - getVaultAccountHandlers(baseUrl).get, + http.get(`${baseUrl}/v1/vault/accounts/:vaultAccountId`, () => { + return new HttpResponse(JSON.stringify(vaultAccount3)) + }), - getVaultAccount3AddressesHandlers(baseUrl).getEth + getVaultAccount3AddressesHandlers(baseUrl).getMatic ] diff --git a/apps/vault/src/broker/core/provider/fireblocks/fireblocks-scoped-sync.service.ts b/apps/vault/src/broker/core/provider/fireblocks/fireblocks-scoped-sync.service.ts index fc71960ca..ae7347d40 100644 --- a/apps/vault/src/broker/core/provider/fireblocks/fireblocks-scoped-sync.service.ts +++ b/apps/vault/src/broker/core/provider/fireblocks/fireblocks-scoped-sync.service.ts @@ -1,269 +1,293 @@ import { LoggerService } from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' import { randomUUID } from 'crypto' -import { chunk, uniqBy } from 'lodash/fp' +import { uniqBy } from 'lodash/fp' import { FIREBLOCKS_API_ERROR_CODES, FireblocksClient, VaultAccount } from '../../../http/client/fireblocks.client' +import { UpdateAccount } from '../../../persistence/repository/account.repository' +import { NetworkRepository } from '../../../persistence/repository/network.repository' +import { WalletRepository } from '../../../persistence/repository/wallet.repository' import { ConnectionWithCredentials } from '../../type/connection.type' -import { Account, Address, Wallet } from '../../type/indexed-resources.type' -import { NetworkMap } from '../../type/network.type' -import { Provider, ProviderScopedSyncService } from '../../type/provider.type' +import { Account, Address, UpdateWallet, Wallet } from '../../type/indexed-resources.type' import { - RawAccount, - RawAccountError, - RawAccountSyncFailure, - ScopedSyncContext, + Provider, + ProviderScopedSyncService, + ScopedSyncOperation, + ScopedSyncOperationType, ScopedSyncResult -} from '../../type/scoped-sync.type' +} from '../../type/provider.type' +import { RawAccount } from '../../type/scoped-sync.type' import { CONCURRENT_FIREBLOCKS_REQUESTS, - buildFireblocksAssetAddressExternalId, - parseFireblocksAssetWalletExternalId, + FireblocksAssetWalletId, + getFireblocksAssetAddressExternalId, + getFireblocksAssetWalletExternalId, + toFireblocksAssetWalletExternalId, validateConnection } from './fireblocks.util' -type RawAccountSyncSuccess = { - success: true - wallet: Wallet - account: Account - addresses: Address[] -} - -type RawAccountSyncFailed = { - success: false - failure: RawAccountSyncFailure -} - -type RawAccountSyncResult = RawAccountSyncSuccess | RawAccountSyncFailed @Injectable() export class FireblocksScopedSyncService implements ProviderScopedSyncService { constructor( private readonly fireblocksClient: FireblocksClient, + private readonly networkRepository: NetworkRepository, + private readonly walletRepository: WalletRepository, private readonly logger: LoggerService ) {} - private resolveFailure(failure: RawAccountSyncFailure): RawAccountSyncFailed { - this.logger.log('Failed to sync Raw Account', failure) - return { success: false, failure } - } + private async buildVaultNetworkMap( + assetWalletIds: FireblocksAssetWalletId[] + ): Promise>> { + const result: Record> = {} - private resolveSuccess({ - rawAccount, - wallet, - account, - addresses - }: { - wallet: Wallet - addresses: Address[] - rawAccount: RawAccount - account: Account - }): RawAccountSyncSuccess { - this.logger.log('Successfully fetched and map Raw Account', { - rawAccount, - account - }) - return { - success: true, - wallet, - account, - addresses + for (const { vaultId, networkId } of assetWalletIds) { + if (!vaultId || !networkId) continue + + try { + const network = await this.networkRepository.findById(networkId) + + if (!network) { + this.logger.log('Network not found', { networkId }) + continue + } + + const fireblocksNetwork = network.externalNetworks?.find((n) => n.provider === Provider.FIREBLOCKS) + if (!fireblocksNetwork) { + this.logger.log('Network not supported', { networkId, provider: Provider.FIREBLOCKS }) + continue + } + + if (!result[vaultId]) { + result[vaultId] = new Set() + } + result[vaultId].add({ + narvalNetworkId: networkId, + fireblocksNetworkId: fireblocksNetwork.externalId + }) + } catch (error) { + this.logger.log('Error processing network', { networkId, error: String(error) }) + } } + + return result } - private async resolveRawAccount({ - connection, - rawAccount, - networks, - now, - existingAccounts, - existingAddresses, - vaultAccount, - existingWallets - }: { - connection: ConnectionWithCredentials - rawAccount: RawAccount - networks: NetworkMap - now: Date - existingAccounts: Account[] - vaultAccount: VaultAccount - existingWallets: Wallet[] - existingAddresses: Address[] - }): Promise { + + async scopedSync(connection: ConnectionWithCredentials, rawAccounts: RawAccount[]): Promise { + const now = new Date() validateConnection(connection) - const { vaultId, baseAssetId: networkId } = parseFireblocksAssetWalletExternalId(rawAccount.externalId) - const network = networks.get(networkId) - if (!network) { - this.logger.error('Network not found', { - rawAccount, - externalNetwork: networkId - }) - return this.resolveFailure({ - rawAccount, - message: 'Network for this account is not supported', - code: RawAccountError.UNLISTED_NETWORK, - networkId - }) - } + const existingWallets = await this.walletRepository.findAll( + { clientId: connection.clientId, connectionId: connection.connectionId }, + { pagination: { disabled: true } } + ) - const existingAccount = existingAccounts.find((a) => a.externalId === rawAccount.externalId) - const existingWallet = existingWallets.find((a) => a.externalId === vaultId) + const existingWalletMap = new Map(existingWallets.data.map((wallet) => [wallet.externalId, wallet])) + const existingAccountMap = new Map( + existingWallets.data.flatMap( + (wallet) => + wallet.accounts?.map((account) => [account.externalId, { ...account, walletId: wallet.walletId }]) ?? [] + ) + ) - const accountLabel = `${vaultAccount.name} - ${networkId}` - const accountId = existingAccount?.accountId || randomUUID() - const walletId = existingWallet?.walletId || existingAccount?.walletId || randomUUID() - const fireblocksAddresses = await this.fireblocksClient.getAddresses({ - apiKey: connection.credentials.apiKey, - signKey: connection.credentials.privateKey, - url: connection.url, - vaultAccountId: vaultId, - assetId: networkId - }) + const assetWalletIds = uniqBy('externalId', rawAccounts).map((account) => + toFireblocksAssetWalletExternalId(account.externalId) + ) - const wallet: Wallet = { - accounts: [], - clientId: connection.clientId, - connectionId: connection.connectionId, - createdAt: now, - externalId: vaultId, - label: vaultAccount.name, - provider: Provider.FIREBLOCKS, - updatedAt: now, - walletId - } + const vaultToNetworkMap = await this.buildVaultNetworkMap(assetWalletIds) + const requestedVaultIds = Object.keys(vaultToNetworkMap) + + const vaults: VaultAccount[] = [] + for (let i = 0; i < Object.keys(vaultToNetworkMap).length; i += CONCURRENT_FIREBLOCKS_REQUESTS) { + const batch = Object.keys(vaultToNetworkMap).slice(i, i + CONCURRENT_FIREBLOCKS_REQUESTS) + const batchPromises = batch.map((vaultId) => + this.fireblocksClient.getVaultAccount({ + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey, + url: connection.url, + vaultAccountId: vaultId + }) + ) + + const batchResults = await Promise.allSettled(batchPromises) + + const validVaults = batchResults + .map((result, index) => { + if (result.status === 'fulfilled') { + return result.value + } else { + const error = result.reason + const vaultId = batch[index] + + if (error?.response?.body?.code === FIREBLOCKS_API_ERROR_CODES.INVALID_SPECIFIED_VAULT_ACCOUNT) { + this.logger.warn('Vault not found', { + vaultId, + provider: Provider.FIREBLOCKS + }) + return null + } else { + throw error + } + } + }) + .filter((vault): vault is VaultAccount => vault !== null) - const account: Account = { - externalId: rawAccount.externalId, - accountId, - addresses: [], - clientId: connection.clientId, - createdAt: now, - connectionId: connection.connectionId, - label: accountLabel, - networkId: network.networkId, - provider: Provider.FIREBLOCKS, - updatedAt: now, - walletId + vaults.push(...validVaults) } - const addresses: Address[] = fireblocksAddresses - .map((a) => { - const addressExternalId = buildFireblocksAssetAddressExternalId({ + // Filter to only get the vaults we need based on vaultToNetworkMap + const relevantVaults = vaults.filter((vault) => vault.id in vaultToNetworkMap) + const vaultMap = Object.fromEntries(relevantVaults.map((vault) => [vault.id, vault])) + + // Log each missing vault + const foundVaultIds = relevantVaults.map((vault) => vault.id) + requestedVaultIds.forEach((vaultId) => { + if (!foundVaultIds.includes(vaultId)) { + this.logger.warn('Vault not found', { vaultId, - networkId, - address: a.address + networks: vaultToNetworkMap[vaultId] }) - const existingAddress = existingAddresses.find((a) => a.externalId === addressExternalId) - if (!existingAddress) { - return { - accountId, - address: a.address, - addressId: randomUUID(), + } + }) + + const walletOperations: ScopedSyncOperation[] = [] + const accountOperations: ScopedSyncOperation[] = [] + const addressOperations: ScopedSyncOperation[] = [] + + for (const [vaultId, networkIds] of Object.entries(vaultToNetworkMap)) { + const vault = vaultMap[vaultId] + if (!vault) { + this.logger.warn('raw account was not found', { vaultId }) + continue + } + const existingWallet = existingWalletMap.get(vaultId) + const walletId = existingWallet?.walletId || randomUUID() + + if (existingWallet) { + if (existingWallet.label !== vault.name) { + walletOperations.push({ + type: ScopedSyncOperationType.UPDATE, + update: { + clientId: connection.clientId, + walletId, + label: vault.name, + updatedAt: now + } + }) + } + } else { + walletOperations.push({ + type: ScopedSyncOperationType.CREATE, + create: { + accounts: [], clientId: connection.clientId, - createdAt: now, connectionId: connection.connectionId, - externalId: addressExternalId, + createdAt: now, + externalId: vaultId, + label: vault.name, provider: Provider.FIREBLOCKS, - updatedAt: now + updatedAt: now, + walletId } - } - return null - }) - .filter((a) => a !== null) as Address[] - - return this.resolveSuccess({ - rawAccount, - wallet, - account, - addresses - }) - } - - private async fetchVaultAccount({ - connection, - rawAccount - }: { - connection: ConnectionWithCredentials - rawAccount: RawAccount - }): Promise<{ vaultAccount: VaultAccount; rawAccount: RawAccount } | RawAccountSyncFailed> { - validateConnection(connection) - const { vaultId } = parseFireblocksAssetWalletExternalId(rawAccount.externalId) - try { - const vaultAccount = await this.fireblocksClient.getVaultAccount({ - apiKey: connection.credentials.apiKey, - signKey: connection.credentials.privateKey, - url: connection.url, - vaultAccountId: vaultId - }) - - return { vaultAccount, rawAccount } - } catch (error) { - if (error?.response?.body?.code === FIREBLOCKS_API_ERROR_CODES.INVALID_SPECIFIED_VAULT_ACCOUNT) { - return this.resolveFailure({ - rawAccount, - message: 'Fireblocks Vault Account not found', - code: RawAccountError.EXTERNAL_RESOURCE_NOT_FOUND, - externalResourceType: 'vaultAccount', - externalResourceId: vaultId }) } - throw error - } - } - - async scopeSync({ - connection, - rawAccounts, - networks, - existingAccounts - }: ScopedSyncContext): Promise { - validateConnection(connection) - - const now = new Date() - const chunkedRawAccounts = chunk(CONCURRENT_FIREBLOCKS_REQUESTS, rawAccounts) - const fetchResults = [] + // Create accounts for each network + for (const { fireblocksNetworkId, narvalNetworkId } of networkIds) { + const accountExternalId = getFireblocksAssetWalletExternalId({ + vaultId: vault.id, + networkId: fireblocksNetworkId + }) - for (const currentChunk of chunkedRawAccounts) { - const chunkResults = await Promise.all( - currentChunk.map((rawAccount) => this.fetchVaultAccount({ connection, rawAccount })) - ) - fetchResults.push(...chunkResults) - } + const existingAccount = existingAccountMap.get(accountExternalId) + const accountId = existingAccount?.accountId || randomUUID() + const accountLabel = `${vault.name} - ${fireblocksNetworkId}` - const wallets: Wallet[] = [] - const accounts: Account[] = [] - const addresses: Address[] = [] - const failures: RawAccountSyncFailure[] = [] + try { + if (existingAccount) { + if (existingAccount.label !== accountLabel) { + accountOperations.push({ + type: ScopedSyncOperationType.UPDATE, + update: { + clientId: connection.clientId, + accountId: existingAccount.accountId, + label: accountLabel, + updatedAt: now + } + }) + } + } else { + accountOperations.push({ + type: ScopedSyncOperationType.CREATE, + create: { + externalId: accountExternalId, + accountId, + addresses: [], + clientId: connection.clientId, + createdAt: now, + connectionId: connection.connectionId, + label: accountLabel, + networkId: narvalNetworkId, + provider: Provider.FIREBLOCKS, + updatedAt: now, + walletId + } + }) + } - for (const result of fetchResults) { - if ('success' in result && !result.success) { - failures.push(result.failure) - continue - } else if ('rawAccount' in result) { - const mappedResult = await this.resolveRawAccount({ - connection, - rawAccount: result.rawAccount, - networks, - now, - existingAccounts: [...existingAccounts, ...accounts], - existingWallets: wallets, - existingAddresses: addresses, - vaultAccount: result.vaultAccount - }) - if (mappedResult.success) { - wallets.push(mappedResult.wallet) - accounts.push(mappedResult.account) - addresses.push(...mappedResult.addresses) - } else { - failures.push(mappedResult.failure) + // Fetch and process addresses + try { + const addresses = await this.fireblocksClient.getAddresses({ + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey, + url: connection.url, + vaultAccountId: vault.id, + assetId: fireblocksNetworkId + }) + addresses.forEach((address) => { + const addressExternalId = getFireblocksAssetAddressExternalId({ + vaultId: vault.id, + networkId: fireblocksNetworkId, + address: address.address + }) + if (!existingAccount?.addresses?.some((a) => a.externalId === addressExternalId)) { + addressOperations.push({ + type: ScopedSyncOperationType.CREATE, + create: { + accountId, + address: address.address, + addressId: randomUUID(), + clientId: connection.clientId, + createdAt: now, + connectionId: connection.connectionId, + externalId: addressExternalId, + provider: Provider.FIREBLOCKS, + updatedAt: now + } + }) + } + }) + } catch (error) { + addressOperations.push({ + type: ScopedSyncOperationType.FAILED, + externalId: accountExternalId, + message: 'Failed to fetch addresses', + context: { error: error.message } + }) + } + } catch (error) { + accountOperations.push({ + type: ScopedSyncOperationType.FAILED, + externalId: accountExternalId, + message: 'Failed to process account', + context: { error: error.message } + }) } } } return { - wallets: uniqBy('externalId', wallets), - accounts: uniqBy('externalId', accounts), - addresses: uniqBy('externalId', addresses), - failures + wallets: walletOperations, + accounts: accountOperations, + addresses: addressOperations } } } diff --git a/apps/vault/src/broker/core/provider/fireblocks/fireblocks.util.ts b/apps/vault/src/broker/core/provider/fireblocks/fireblocks.util.ts index 34948cea5..f6267108e 100644 --- a/apps/vault/src/broker/core/provider/fireblocks/fireblocks.util.ts +++ b/apps/vault/src/broker/core/provider/fireblocks/fireblocks.util.ts @@ -57,18 +57,18 @@ export function validateConnection( } export type FireblocksAccountExternalId = `${string}-${string}` -export function buildFireblocksAssetWalletExternalId({ +export function getFireblocksAssetWalletExternalId({ vaultId, networkId }: { vaultId: string networkId: string }): string { - return `${vaultId.toString()}-${networkId}`.toUpperCase() + return `${vaultId.toString()}-${networkId}` } -export type FireblocksAssetWalletId = { vaultId: string; baseAssetId: string } -export function parseFireblocksAssetWalletExternalId(externalId: string): FireblocksAssetWalletId { +export type FireblocksAssetWalletId = { vaultId: string; networkId: string } +export function toFireblocksAssetWalletExternalId(externalId: string): FireblocksAssetWalletId { const matches = externalId.match(/^([^-]+)-([^-]+)$/) if (!matches) { throw new BrokerException({ @@ -81,12 +81,12 @@ export function parseFireblocksAssetWalletExternalId(externalId: string): Firebl const [, vaultId, networkId] = matches return { vaultId, - baseAssetId: networkId + networkId } } export type FireblocksAddressExternalId = `${string}-${string}-${string}` -export function buildFireblocksAssetAddressExternalId({ +export function getFireblocksAssetAddressExternalId({ vaultId, networkId, address @@ -95,11 +95,11 @@ export function buildFireblocksAssetAddressExternalId({ networkId: string address: string }): string { - return `${vaultId}-${networkId}-${address}`.toUpperCase() + return `${vaultId}-${networkId}-${address}` } export type FireblocksAssetAddressId = { vaultId: string; networkId: string; address: string } -export function parseFireblocksAssetAddressExternalId(externalId: string): FireblocksAssetAddressId { +export function toFireblocksAssetAddressExternalId(externalId: string): FireblocksAssetAddressId { const matches = externalId.match(/^([^-]+)-([^-]+)-([^-]+)$/) if (!matches) { throw new BrokerException({ diff --git a/apps/vault/src/broker/core/service/account.service.ts b/apps/vault/src/broker/core/service/account.service.ts index 534bfbf87..27837aa06 100644 --- a/apps/vault/src/broker/core/service/account.service.ts +++ b/apps/vault/src/broker/core/service/account.service.ts @@ -20,10 +20,6 @@ export class AccountService { return this.accountRepository.bulkCreate(accounts) } - async bulkUpsert(accounts: Account[]): Promise { - return this.accountRepository.bulkUpsert(accounts) - } - async bulkUpdate(updateAccounts: UpdateAccount[]): Promise { return this.accountRepository.bulkUpdate(updateAccounts) } diff --git a/apps/vault/src/broker/core/service/network.service.ts b/apps/vault/src/broker/core/service/network.service.ts index aafc362e8..6cfd0bc12 100644 --- a/apps/vault/src/broker/core/service/network.service.ts +++ b/apps/vault/src/broker/core/service/network.service.ts @@ -3,7 +3,7 @@ import { CACHE_MANAGER, Cache } from '@nestjs/cache-manager' import { Inject, Injectable } from '@nestjs/common' import { uniq } from 'lodash' import { FindAllOptions, NetworkRepository } from '../../persistence/repository/network.repository' -import { ExternalNetwork, Network, NetworkMap } from '../type/network.type' +import { ExternalNetwork, Network } from '../type/network.type' import { Provider } from '../type/provider.type' @Injectable() @@ -114,7 +114,7 @@ export class NetworkService { * traversals on subsequent queries. All lookups become O(1) after indexing * at the cost of O(n) additional memory. */ - async buildProviderExternalIdIndex(provider: Provider): Promise { + async buildProviderExternalIdIndex(provider: Provider): Promise> { const networks = await this.findAll({ filters: { provider } }) const index = new Map() diff --git a/apps/vault/src/broker/core/service/raw-account.service.ts b/apps/vault/src/broker/core/service/raw-account.service.ts index 9bdec023c..2faa402ce 100644 --- a/apps/vault/src/broker/core/service/raw-account.service.ts +++ b/apps/vault/src/broker/core/service/raw-account.service.ts @@ -5,17 +5,14 @@ import { AnchorageClient } from '../../http/client/anchorage.client' import { FireblocksClient } from '../../http/client/fireblocks.client' import { AccountRepository } from '../../persistence/repository/account.repository' import { AssetRepository } from '../../persistence/repository/asset.repository' +import { NetworkRepository } from '../../persistence/repository/network.repository' import { BrokerException } from '../exception/broker.exception' import { validateConnection as validateAnchorageConnection } from '../provider/anchorage/anchorage.util' -import { - buildFireblocksAssetWalletExternalId, - validateConnection as validateFireblocksConnection -} from '../provider/fireblocks/fireblocks.util' +import { validateConnection as validateFireblocksConnection } from '../provider/fireblocks/fireblocks.util' import { Asset } from '../type/asset.type' import { Network } from '../type/network.type' import { Provider } from '../type/provider.type' import { ConnectionService } from './connection.service' -import { NetworkService } from './network.service' export const RawAccount = z.object({ provider: z.nativeEnum(Provider), @@ -52,7 +49,7 @@ export class RawAccountService { constructor( private readonly accountRepository: AccountRepository, private readonly connectionService: ConnectionService, - private readonly networkService: NetworkService, + private readonly networkRepository: NetworkRepository, private readonly assetRepository: AssetRepository, private readonly anchorageClient: AnchorageClient, private readonly fireblocksClient: FireblocksClient, @@ -70,7 +67,7 @@ export class RawAccountService { ? await this.assetRepository.findById(options.filters.assetId) : undefined const networkFilter = options?.filters?.networkId - ? await this.networkService.findById(options.filters.networkId) + ? await this.networkRepository.findById(options.filters.networkId) : undefined if (connection.provider === Provider.ANCHORAGE) { @@ -90,7 +87,7 @@ export class RawAccountService { label: wallet.walletName, subLabel: wallet.vaultName, defaultAddress: wallet.depositAddress.address, - network: await this.networkService.findByExternalId(Provider.ANCHORAGE, wallet.networkId), + network: await this.networkRepository.findByExternalId(Provider.ANCHORAGE, wallet.networkId), assets: await Promise.all( wallet.assets.map(async (a) => ({ asset: await this.assetRepository.findByExternalId(Provider.ANCHORAGE, a.assetType), @@ -157,11 +154,9 @@ export class RawAccountService { } }) // In Fireblocks, a VaultAccount is not network-specific, so we'll map the AssetWallets to get what we call "Accounts" - // Map accounts to our format const rawAccounts = await Promise.all( response.accounts.map(async (account) => { - // 1. First map and filter assets - const mappedAssets = await Promise.all( + const assets = await Promise.all( account.assets .filter((a) => !a.hiddenOnUI) .map(async (asset) => ({ @@ -170,62 +165,43 @@ export class RawAccountService { asset: await this.assetRepository.findByExternalId(Provider.FIREBLOCKS, asset.id) })) ) - - // 2. Group assets by network - const assetsByNetwork = mappedAssets.reduce( + // Group assets by network + const assetsByNetwork = assets.reduce( (acc, asset) => { - if (!asset.asset?.networkId) return acc - return { - ...acc, - [asset.asset.networkId]: [...(acc[asset.asset.networkId] || []), asset] + if (!asset.asset?.networkId) return acc // Skip assets without a networkId + if (!acc[asset.asset.networkId]) { + acc[asset.asset.networkId] = [] } + acc[asset.asset.networkId].push(asset) + return acc }, - {} as Record + {} as Record ) - // 3. Validate networks and get their Fireblocks IDs - const validNetworks = ( - await Promise.all( - Object.entries(assetsByNetwork).map(async ([networkId, assets]) => { - const network = await this.networkService.findById(networkId) - const fireblocksNetworkId = network?.externalNetworks.find( - (n) => n.provider === Provider.FIREBLOCKS - )?.externalId - - if (!network || !fireblocksNetworkId) return null - - return { - network, - fireblocksNetworkId, - assets - } - }) - ) - ).filter((item): item is NonNullable => item !== null) - - return validNetworks.map(({ network, fireblocksNetworkId, assets }) => { - return { - provider: Provider.FIREBLOCKS, - externalId: buildFireblocksAssetWalletExternalId({ - vaultId: account.id, - networkId: fireblocksNetworkId - }), - label: account.name || account.id, - subLabel: network?.networkId, - defaultAddress: '', // Fireblocks doesn't provide a default address at account level - network: Network.parse(network), - assets: assets - .map((a) => - a.asset - ? { - asset: a.asset, - balance: a.balance - } - : undefined - ) - .filter((a) => !!a) - } - }) + // Create an account for each network that has assets + return await Promise.all( + Object.entries(assetsByNetwork).map(async ([networkId, networkAssets]) => { + const network = await this.networkRepository.findById(networkId) + return { + provider: Provider.FIREBLOCKS, + externalId: `${account.id}-${networkId}`, + label: account.name || account.id, + subLabel: networkId, + defaultAddress: '', // Fireblocks doesn't provide a default address at account level + network, + assets: networkAssets + .map((a) => + a.asset + ? { + asset: a.asset, + balance: a.balance + } + : undefined + ) + .filter((a) => !!a) + } + }) + ) }) ).then((a) => a.flat()) diff --git a/apps/vault/src/broker/core/service/scoped-sync.service.ts b/apps/vault/src/broker/core/service/scoped-sync.service.ts index 6969b2ca8..f0c746afd 100644 --- a/apps/vault/src/broker/core/service/scoped-sync.service.ts +++ b/apps/vault/src/broker/core/service/scoped-sync.service.ts @@ -1,5 +1,5 @@ import { LoggerService, PaginatedResult, TraceService } from '@narval/nestjs-shared' -import { HttpStatus, NotImplementedException } from '@nestjs/common' +import { NotImplementedException } from '@nestjs/common' import { Inject, Injectable } from '@nestjs/common/decorators' import { EventEmitter2 } from '@nestjs/event-emitter' import { SpanStatusCode } from '@opentelemetry/api' @@ -8,24 +8,21 @@ import { v4 as uuid } from 'uuid' import { FindAllOptions, ScopedSyncRepository } from '../../persistence/repository/scoped-sync.repository' import { OTEL_ATTR_CONNECTION_ID, OTEL_ATTR_CONNECTION_PROVIDER, OTEL_ATTR_SYNC_ID } from '../../shared/constant' import { ScopedSyncStartedEvent } from '../../shared/event/scoped-sync-started.event' -import { ScopedSyncException } from '../exception/scoped-sync.exception' import { AnchorageScopedSyncService } from '../provider/anchorage/anchorage-scoped-sync.service' import { FireblocksScopedSyncService } from '../provider/fireblocks/fireblocks-scoped-sync.service' import { ConnectionWithCredentials } from '../type/connection.type' -import { Provider, ProviderScopedSyncService } from '../type/provider.type' -import { ConnectionScope } from '../type/scope.type' import { - RawAccount, - RawAccountSyncFailure, - ScopedSync, + Provider, + ProviderScopedSyncService, ScopedSyncResult, - ScopedSyncStarted, - ScopedSyncStatus, - StartScopedSync -} from '../type/scoped-sync.type' + isCreateOperation, + isFailedOperation, + isUpdateOperation +} from '../type/provider.type' +import { ConnectionScope } from '../type/scope.type' +import { RawAccount, ScopedSync, ScopedSyncStarted, ScopedSyncStatus, StartScopedSync } from '../type/scoped-sync.type' import { AccountService } from './account.service' import { AddressService } from './address.service' -import { NetworkService } from './network.service' import { WalletService } from './wallet.service' @Injectable() @@ -37,45 +34,23 @@ export class ScopedSyncService { private readonly walletService: WalletService, private readonly accountService: AccountService, private readonly addressService: AddressService, - private readonly networkService: NetworkService, private readonly eventEmitter: EventEmitter2, private readonly logger: LoggerService, @Inject(TraceService) private readonly traceService: TraceService ) {} async start(connections: ConnectionWithCredentials[], rawAccounts: RawAccount[]): Promise { - this.logger.log('Start connections scopedSync', { + this.logger.log('Start connections scoped sync', { connectionsCount: connections.length, - connectionIds: connections.map((connectionId) => connectionId) + connectionIds: connections.map((connectionId) => connectionId), + rawAccounts: rawAccounts.map(({ provider, externalId }) => ({ provider, externalId })) }) - const notSyncingConnections: ConnectionWithCredentials[] = [] - - for (const connection of connections) { - const inProgress = await this.scopedSyncRepository.exists({ - connectionId: connection.connectionId, - clientId: connection.clientId, - status: ScopedSyncStatus.PROCESSING - }) - - if (inProgress) { - throw new ScopedSyncException({ - message: 'There is already a Scoped Sync in progress for requested connections', - suggestedHttpStatusCode: HttpStatus.CONFLICT, - context: { - conflictingConnectionId: connection.connectionId - } - }) - } - - notSyncingConnections.push(connection) - } - - if (notSyncingConnections.length) { + if (connections.length) { const now = new Date() const scopedSyncs = await this.scopedSyncRepository.bulkCreate( - notSyncingConnections.map(({ connectionId, clientId }) => + connections.map(({ connectionId, clientId }) => this.toProcessingScopedSync({ clientId, connectionId, @@ -86,7 +61,7 @@ export class ScopedSyncService { ) ) - for (const [scopedSync, connection] of zip(scopedSyncs, notSyncingConnections)) { + for (const [scopedSync, connection] of zip(scopedSyncs, connections)) { if (scopedSync && connection) { // NOTE: Emits an event that will delegate the scopedSync process to // another worker, allowing to unblock the request. The event handler @@ -98,7 +73,7 @@ export class ScopedSyncService { return { started: true, scopedSyncs } } - this.logger.log('Skip scopedSync because active connections list is empty') + this.logger.log('Skip scoped sync because active connections list is empty') return { started: false, scopedSyncs: [] } } @@ -113,7 +88,7 @@ export class ScopedSyncService { provider } - this.logger.log('Scoped Sync connection', context) + this.logger.log('Scoped sync connection', context) const span = this.traceService.startSpan(`${ScopedSyncService.name}.scopedSync`, { attributes: { @@ -125,38 +100,31 @@ export class ScopedSyncService { let result: ScopedSyncResult | null = null + // Ensure the scopedSync status is updated on failures. The `execute` method is + // not wrapped in the try/catch block because it already handles errors + // internally. try { - const networks = await this.networkService.buildProviderExternalIdIndex(provider) - const { data: existingAccounts } = await this.accountService.findAll( - { clientId, connectionId }, - { - pagination: { disabled: true } - } - ) - - result = await this.getProviderScopedSyncService(connection.provider).scopeSync({ - rawAccounts: scopedSync.rawAccounts, + result = await this.getProviderScopedSyncService(connection.provider).scopedSync( connection, - networks, - existingAccounts - }) + scopedSync.rawAccounts + ) } catch (error) { - this.logger.error('ScopedSync connection failed', { ...context, error }) + this.logger.error('Scoped sync connection failed', { ...context, error }) span.recordException(error) span.setStatus({ code: SpanStatusCode.ERROR }) - return await this.fail(scopedSync, error, result?.failures || []) + return await this.fail(scopedSync, error) } finally { // The execute method has its own span. span.end() } - if (result.failures.length && !result.accounts.length) { - this.logger.error('ScopedSync connection failed', { ...context, result }) + if (result) { + return await this.execute(scopedSync, result) } - return await this.execute(scopedSync, result) + return scopedSync } private toProcessingScopedSync( @@ -182,96 +150,103 @@ export class ScopedSyncService { } // TODO: pessimist lock if there's already a scopedSync in process for the given + // connection. async execute(scopedSync: ScopedSync, result: ScopedSyncResult): Promise { - const { scopedSyncId } = scopedSync + // IMPORTANT: Thoroughly test the execution in the integration test + // `scopedSync.service.spec.ts`. + + const { clientId, scopedSyncId } = scopedSync const span = this.traceService.startSpan(`${ScopedSyncService.name}.execute`, { attributes: { [OTEL_ATTR_SYNC_ID]: scopedSyncId } }) - const { wallets, accounts, addresses, failures } = result + const walletCreateOperations = result.wallets.filter(isCreateOperation).map(({ create }) => create) + const walletUpdateOperations = result.wallets.filter(isUpdateOperation).map(({ update }) => update) + const walletFailedOperations = result.wallets.filter(isFailedOperation) - this.logger.log('Raw Account synchronization failures', { - scopedSyncId, - failuresCount: failures?.length, - failures - }) + const accountCreateOperations = result.accounts.filter(isCreateOperation).map(({ create }) => create) + const accountUpdateOperations = result.accounts.filter(isUpdateOperation).map(({ update }) => update) + const accountFailedOperations = result.accounts.filter(isFailedOperation) - this.logger.log('Raw Account synchronization successes', { - wallets: wallets.length, - accounts: accounts.length, - addresses: addresses.length - }) + const addressCreateOperations = result.addresses.filter(isCreateOperation).map(({ create }) => create) + const addressFailedOperations = result.addresses.filter(isFailedOperation) - try { - await this.walletService.bulkUpsert(wallets) - await this.accountService.bulkUpsert(accounts) - await this.addressService.bulkCreate(addresses) - - const totalItems = result.wallets.length + result.accounts.length + result.addresses.length - if (totalItems === 0) { - throw new ScopedSyncException({ - message: 'No raw account was successfully mapped', - suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, - context: { failures: result.failures } - }) + this.logger.log('Execute scoped sync operations', { + clientId, + scopedSyncId, + operations: { + wallet: { + create: walletCreateOperations.length, + update: walletUpdateOperations.length, + failed: walletFailedOperations.length + }, + account: { + create: accountCreateOperations.length, + update: accountUpdateOperations.length, + failed: accountFailedOperations.length + }, + address: { + create: addressCreateOperations.length, + failed: addressFailedOperations.length + } } + }) - return await this.complete(scopedSync, result) - } catch (error) { - return await this.fail(scopedSync, error, result.failures) - } finally { - span.end() + if (walletFailedOperations.length) { + this.logger.error('Scoped sync operations contains failures for wallets', { + operations: walletFailedOperations + }) } - } - - async complete(scopedSync: ScopedSync, result: ScopedSyncResult): Promise { - const { clientId, scopedSyncId } = scopedSync - - const totalItems = result.wallets.length + result.accounts.length + result.addresses.length - const hasSuccesses = totalItems > 0 - const hasFailures = result.failures.length > 0 - - const status = hasSuccesses && hasFailures ? ScopedSyncStatus.PARTIAL_SUCCESS : ScopedSyncStatus.SUCCESS - if (status === ScopedSyncStatus.PARTIAL_SUCCESS) { - return await this.partialSuccess(scopedSync, result.failures) + if (accountFailedOperations.length) { + this.logger.error('Scoped sync operations contains failures for accounts', { + operations: accountFailedOperations + }) } - this.logger.log('Scoped Sync completed successfuly', { clientId, scopedSyncId }) - - const span = this.traceService.startSpan(`${ScopedSyncService.name}.complete`, { - attributes: { [OTEL_ATTR_SYNC_ID]: scopedSyncId } - }) - - const completedScopedSync = { - ...scopedSync, - status, - completedAt: scopedSync.completedAt || new Date(), - failures: [] + if (addressFailedOperations.length) { + this.logger.error('Scoped sync operations contains failures for addresses', { + operations: addressFailedOperations + }) } - await this.scopedSyncRepository.update(completedScopedSync) + try { + this.logger.log('Execute wallet create operations', { scopedSyncId, clientId }) + await this.walletService.bulkCreate(walletCreateOperations) + this.logger.log('Execute wallet update operations', { scopedSyncId, clientId }) + await this.walletService.bulkUpdate(walletUpdateOperations) - span.end() + this.logger.log('Execute account create operations', { scopedSyncId, clientId }) + await this.accountService.bulkCreate(accountCreateOperations) + this.logger.log('Execute account update operations', { scopedSyncId, clientId }) + await this.accountService.bulkUpdate(accountUpdateOperations) - return completedScopedSync + // TODO: address update + this.logger.log('Execute address create operations', { scopedSyncId, clientId }) + await this.addressService.bulkCreate(addressCreateOperations) + + return await this.complete(scopedSync) + } catch (error) { + return await this.fail(scopedSync, error) + } finally { + span.end() + } } - async partialSuccess(scopedSync: ScopedSync, failures: RawAccountSyncFailure[]): Promise { + async complete(scopedSync: ScopedSync): Promise { const { clientId, scopedSyncId } = scopedSync - this.logger.log('Scoped Sync partially successful', { clientId, scopedSyncId }) + this.logger.log('Scoped sync complete', { clientId, scopedSyncId }) - const span = this.traceService.startSpan(`${ScopedSyncService.name}.partial_success`, { + const span = this.traceService.startSpan(`${ScopedSyncService.name}.complete`, { attributes: { [OTEL_ATTR_SYNC_ID]: scopedSyncId } }) const completedScopedSync = { ...scopedSync, - status: ScopedSyncStatus.PARTIAL_SUCCESS, - completedAt: scopedSync.completedAt || new Date(), - failures + status: ScopedSyncStatus.SUCCESS, + completedAt: scopedSync.completedAt || new Date() } await this.scopedSyncRepository.update(completedScopedSync) @@ -281,10 +256,10 @@ export class ScopedSyncService { return completedScopedSync } - async fail(scopedSync: ScopedSync, error: Error, failures: RawAccountSyncFailure[]): Promise { + async fail(scopedSync: ScopedSync, error: Error): Promise { const { clientId, scopedSyncId } = scopedSync - this.logger.log('Scoped Sync fail', { clientId, scopedSyncId, error }) + this.logger.log('Scoped sync fail', { clientId, scopedSyncId, error }) const span = this.traceService.startSpan(`${ScopedSyncService.name}.fail`, { attributes: { [OTEL_ATTR_SYNC_ID]: scopedSyncId } @@ -301,8 +276,7 @@ export class ScopedSyncService { message: error.message, traceId: this.traceService.getActiveSpan()?.spanContext().traceId }, - completedAt: scopedSync.completedAt || new Date(), - failures + completedAt: scopedSync.completedAt || new Date() } await this.scopedSyncRepository.update(failedScopedSync) @@ -319,7 +293,7 @@ export class ScopedSyncService { case Provider.FIREBLOCKS: return this.fireblocksScopedSyncService default: - throw new NotImplementedException(`Unsupported Scoped Sync for provider ${provider}`) + throw new NotImplementedException(`Unsupported scoped sync for provider ${provider}`) } } } diff --git a/apps/vault/src/broker/core/service/wallet.service.ts b/apps/vault/src/broker/core/service/wallet.service.ts index 35138c46e..75df878e5 100644 --- a/apps/vault/src/broker/core/service/wallet.service.ts +++ b/apps/vault/src/broker/core/service/wallet.service.ts @@ -12,10 +12,6 @@ export class WalletService { return this.walletRepository.bulkCreate(wallets) } - async bulkUpsert(wallets: Wallet[]): Promise { - return this.walletRepository.bulkUpsert(wallets) - } - async bulkUpdate(wallets: UpdateWallet[]): Promise { return Promise.all(wallets.map((wallet) => this.update(wallet))) } diff --git a/apps/vault/src/broker/core/type/network.type.ts b/apps/vault/src/broker/core/type/network.type.ts index a6e5f03f1..d0eed7e4f 100644 --- a/apps/vault/src/broker/core/type/network.type.ts +++ b/apps/vault/src/broker/core/type/network.type.ts @@ -12,9 +12,6 @@ export const Network = z.object({ coinType: z.number().nullable(), name: z.string(), externalNetworks: z.array(ExternalNetwork).default([]), - createdAt: z.coerce.date().optional() + createdAt: z.date().optional() }) export type Network = z.infer - -export const NetworkMap = z.map(z.string(), Network) -export type NetworkMap = z.infer diff --git a/apps/vault/src/broker/core/type/provider.type.ts b/apps/vault/src/broker/core/type/provider.type.ts index e374fc00e..97fd837a4 100644 --- a/apps/vault/src/broker/core/type/provider.type.ts +++ b/apps/vault/src/broker/core/type/provider.type.ts @@ -2,9 +2,11 @@ import { PaginatedResult } from '@narval/nestjs-shared' import { HttpStatus } from '@nestjs/common' +import { UpdateAccount } from '../../persistence/repository/account.repository' import { ConnectionWithCredentials } from './connection.type' +import { Account, Address, UpdateWallet, Wallet } from './indexed-resources.type' import { KnownDestination as KnownDestinationNext } from './known-destination.type' -import { ScopedSyncContext, ScopedSyncResult } from './scoped-sync.type' +import { RawAccount } from './scoped-sync.type' import { InternalTransfer, SendTransfer, Transfer } from './transfer.type' export const Provider = { @@ -18,8 +20,216 @@ export type Provider = (typeof Provider)[keyof typeof Provider] // Sync // +export const SyncOperationType = { + CREATE: 'create', + UPDATE: 'update', + DELETE: 'delete', + FAILED: 'failed', + SKIP: 'skip' +} as const +export type SyncOperationType = (typeof SyncOperationType)[keyof typeof SyncOperationType] + +export const ScopedSyncOperationType = { + CREATE: 'create', + UPDATE: 'update', + FAILED: 'failed' +} as const +export type ScopedSyncOperationType = (typeof ScopedSyncOperationType)[keyof typeof ScopedSyncOperationType] + +export type CreateScopedSyncOperation = { + type: typeof SyncOperationType.CREATE + create: CreateParams +} +export type UpdateScopedSyncOperation = { + type: typeof ScopedSyncOperationType.UPDATE + update: UpdateParams +} + +export type FailedScopedSyncOperation = { + type: typeof ScopedSyncOperationType.FAILED + externalId: string + message: string + context?: unknown +} + +export type CreateSyncOperation = { + type: typeof SyncOperationType.CREATE + create: CreateParams +} + +export type UpdateSyncOperation = { + type: typeof SyncOperationType.UPDATE + update: UpdateParams +} + +export type DeleteSyncOperation = { + type: typeof SyncOperationType.DELETE + entityId: string +} + +export type FailedSyncOperation = { + type: typeof SyncOperationType.FAILED + externalId: string + message: string + context?: unknown +} + +export type SkipSyncOperation = { + type: typeof SyncOperationType.SKIP + externalId: string + message: string + context?: unknown +} + +/** + * Represents a synchronization operation for a resource, which can be a + * creation, update, or deletion. Each operation type is associated with + * specific parameters. + * + * @template CreateParams - The parameters required for creating an entity. + * @template UpdateParams - The parameters required for updating an entity. + */ +export type SyncOperation = + | CreateSyncOperation + | UpdateSyncOperation + | DeleteSyncOperation + | FailedSyncOperation + | SkipSyncOperation + +export type ScopedSyncOperation = + | CreateScopedSyncOperation + | UpdateScopedSyncOperation + | FailedSyncOperation + +export const isCreateOperation = ( + operation: SyncOperation +): operation is CreateSyncOperation => { + return operation.type === SyncOperationType.CREATE +} + +export const isUpdateOperation = ( + operation: SyncOperation +): operation is UpdateSyncOperation => { + return operation.type === SyncOperationType.UPDATE +} + +export const isDeleteOperation = ( + operation: SyncOperation +): operation is DeleteSyncOperation => { + return operation.type === SyncOperationType.DELETE +} + +export const isFailedOperation = ( + operation: SyncOperation +): operation is FailedSyncOperation => { + return operation.type === SyncOperationType.FAILED +} + +export const isSkipOperation = ( + operation: SyncOperation +): operation is SkipSyncOperation => { + return operation.type === SyncOperationType.SKIP +} + +/** + * Represents the context used during synchronization, containing the active + * connection and maps of synchronization operations for various resource + * types. + */ +export type SyncContext = { + /** + * The active connection with credentials used for synchronization. + */ + connection: ConnectionWithCredentials + + /** + * A map of wallet synchronization operations, keyed by wallet external ID. + */ + wallets: SyncOperation[] + + /** + * A map of account synchronization operations, keyed by account external ID. + */ + accounts: SyncOperation[] + + /** + * A map of address synchronization operations, keyed by address external ID. + */ + addresses: SyncOperation[] + + /** + * An optional timestamp used for setting the `createdAt` and `updatedAt` + * fields during synchronization operations. + */ + now?: Date +} + +export type SyncResult = { + wallets: SyncOperation[] + accounts: SyncOperation[] + addresses: SyncOperation[] +} + +export type ScopedSyncResult = { + wallets: ScopedSyncOperation[] + accounts: ScopedSyncOperation[] + addresses: ScopedSyncOperation[] +} + export interface ProviderScopedSyncService { - scopeSync(context: ScopedSyncContext): Promise + scopedSync(connection: ConnectionWithCredentials, rawAccounts: RawAccount[]): Promise +} + +export interface ProviderSyncService { + /** + * The main entry point for synchronization, responsible for coordinating the + * synchronization process across different resources. It orchestrates the + * sync calls and passes the context between them. + * + * IMPORTANT: The synchronization **does not perform the writes** into the + * database. + * + * @param connection - The active connection with credentials required for + * synchronization. + * + * @returns A promise that resolves to an object containing the results of + * the sync operations for wallets, accounts, addresses, and known + * destinations. + */ + sync(connection: ConnectionWithCredentials): Promise + + /** + * Synchronizes wallet data within the provided context and returns an + * updated context. + * + * @param context - The current synchronization context containing existing + * data and operations. + * + * @returns A promise that resolves to the updated synchronization context. + */ + syncWallets(context: SyncContext): Promise + + /** + * Synchronizes account data within the provided context and returns an + * updated context. + * + * @param context - The current synchronization context containing existing + * data and operations. + * + * @returns A promise that resolves to the updated synchronization context. + */ + syncAccounts(context: SyncContext): Promise + + /** + * Synchronizes address data within the provided context and returns an + * updated context. + * + * @param context - The current synchronization context containing existing + * data and operations. + * + * @returns A promise that resolves to the updated synchronization context. + */ + syncAddresses(context: SyncContext): Promise } // diff --git a/apps/vault/src/broker/core/type/scoped-sync.type.ts b/apps/vault/src/broker/core/type/scoped-sync.type.ts index 98e0c67b3..5287a4438 100644 --- a/apps/vault/src/broker/core/type/scoped-sync.type.ts +++ b/apps/vault/src/broker/core/type/scoped-sync.type.ts @@ -1,7 +1,4 @@ import { z } from 'zod' -import { ConnectionWithCredentials } from './connection.type' -import { Account, Address, Wallet } from './indexed-resources.type' -import { NetworkMap } from './network.type' import { Provider } from './provider.type' export const RawAccount = z.object({ @@ -13,56 +10,10 @@ export type RawAccount = z.infer export const ScopedSyncStatus = { PROCESSING: 'processing', SUCCESS: 'success', - PARTIAL_SUCCESS: 'partial_success', FAILED: 'failed' } as const export type ScopedSyncStatus = (typeof ScopedSyncStatus)[keyof typeof ScopedSyncStatus] -export const RawAccountError = { - EXTERNAL_RESOURCE_NOT_FOUND: 'EXTERNAL_RESOURCE_NOT_FOUND', - UNLISTED_NETWORK: 'UNLISTED_NETWORK' -} as const -export type RawAccountError = (typeof RawAccountError)[keyof typeof RawAccountError] - -export const RawAccountNetworkNotFoundFailure = z.object({ - code: z.literal(RawAccountError.UNLISTED_NETWORK), - rawAccount: RawAccount, - message: z.string(), - networkId: z.string() -}) -export type RawAccountNetworkNotFoundFailure = z.infer - -export const RawAccountExternalResourceNotFoundFailure = z.object({ - code: z.literal(RawAccountError.EXTERNAL_RESOURCE_NOT_FOUND), - rawAccount: RawAccount, - message: z.string(), - externalResourceType: z.string(), - externalResourceId: z.string() -}) -export type RawAccountExternalResourceNotFoundFailure = z.infer - -export const RawAccountSyncFailure = z.discriminatedUnion('code', [ - RawAccountNetworkNotFoundFailure, - RawAccountExternalResourceNotFoundFailure -]) -export type RawAccountSyncFailure = z.infer - -export const ScopedSyncResult = z.object({ - wallets: z.array(Wallet), - accounts: z.array(Account), - addresses: z.array(Address), - failures: z.array(RawAccountSyncFailure) -}) -export type ScopedSyncResult = z.infer - -export const ScopedSyncContext = z.object({ - connection: ConnectionWithCredentials, - rawAccounts: z.array(RawAccount), - networks: NetworkMap, - existingAccounts: z.array(Account) -}) -export type ScopedSyncContext = z.infer - export const ScopedSync = z.object({ clientId: z.string(), completedAt: z.date().optional(), @@ -77,8 +28,7 @@ export const ScopedSync = z.object({ .optional(), status: z.nativeEnum(ScopedSyncStatus).default(ScopedSyncStatus.PROCESSING), scopedSyncId: z.string(), - rawAccounts: z.array(RawAccount), - failures: z.array(RawAccountSyncFailure).optional() + rawAccounts: z.array(RawAccount) }) export type ScopedSync = z.infer diff --git a/apps/vault/src/broker/core/util/provider-sync.util.ts b/apps/vault/src/broker/core/util/provider-sync.util.ts new file mode 100644 index 000000000..e98fd4f12 --- /dev/null +++ b/apps/vault/src/broker/core/util/provider-sync.util.ts @@ -0,0 +1,16 @@ +import { SetRequired } from 'type-fest' +import { SyncContext } from '../type/provider.type' + +export const buildEmptyContext = ({ + connection, + wallets, + accounts, + addresses, + now +}: SetRequired, 'connection'>): SyncContext => ({ + connection, + wallets: wallets || [], + accounts: accounts || [], + addresses: addresses || [], + now: now || new Date() +}) diff --git a/apps/vault/src/broker/http/rest/dto/response/scoped-sync.dto.ts b/apps/vault/src/broker/http/rest/dto/response/scoped-sync.dto.ts index d0bed4513..529818d1a 100644 --- a/apps/vault/src/broker/http/rest/dto/response/scoped-sync.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/scoped-sync.dto.ts @@ -1,11 +1,9 @@ import { createZodDto } from 'nestjs-zod' import { z } from 'zod' -import { RawAccountSyncFailure, ScopedSync } from '../../../../core/type/scoped-sync.type' +import { ScopedSync } from '../../../../core/type/scoped-sync.type' export class ScopedSyncDto extends createZodDto( z.object({ - data: ScopedSync.extend({ - failures: z.array(RawAccountSyncFailure) - }) + data: ScopedSync }) ) {} diff --git a/apps/vault/src/broker/persistence/repository/account.repository.ts b/apps/vault/src/broker/persistence/repository/account.repository.ts index 6ff4edb5a..3075b8b11 100644 --- a/apps/vault/src/broker/persistence/repository/account.repository.ts +++ b/apps/vault/src/broker/persistence/repository/account.repository.ts @@ -1,10 +1,4 @@ -import { - LoggerService, - PaginatedResult, - PaginationOptions, - applyPagination, - getPaginatedResult -} from '@narval/nestjs-shared' +import { PaginatedResult, PaginationOptions, applyPagination, getPaginatedResult } from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' import { ProviderAccount, ProviderAddress } from '@prisma/client/vault' import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' @@ -36,10 +30,7 @@ export type UpdateAccount = { @Injectable() export class AccountRepository { - constructor( - private prismaService: PrismaService, - private readonly logger: LoggerService - ) {} + constructor(private prismaService: PrismaService) {} static parseModel(model: ProviderAccountAndRelations): Account { const { id, ...rest } = model @@ -159,75 +150,6 @@ export class AccountRepository { return true } - async bulkUpsert(accounts: Account[]): Promise { - const providerAccounts = accounts.map(AccountRepository.parseEntity) - const stats = { - inserted: 0, - updated: 0 - } - - const existingAccounts = await this.prismaService.providerAccount.findMany({ - where: { - OR: providerAccounts.map((account) => ({ - clientId: account.clientId, - connectionId: account.connectionId, - externalId: account.externalId - })) - } - }) - - const results = await this.prismaService.$transaction(async (tx) => { - const operations = await Promise.all( - providerAccounts.map(async (account) => { - const existing = existingAccounts.find( - (a) => - a.clientId === account.clientId && - a.connectionId === account.connectionId && - a.externalId === account.externalId - ) - - const result = await tx.providerAccount.upsert({ - where: { - clientId_connectionId_externalId: { - clientId: account.clientId, - connectionId: account.connectionId, - externalId: account.externalId - } - }, - create: { - ...account - }, - update: { - label: account.label, - updatedAt: account.updatedAt - }, - include: { - addresses: true - } - }) - - if (!existing) { - stats.inserted++ - } else { - stats.updated++ - } - - return result - }) - ) - - return operations - }) - - this.logger.log('Account bulk upsert operation completed:', { - total: accounts.length, - inserted: stats.inserted, - updated: stats.updated - }) - - return results.map(AccountRepository.parseModel) - } - async findAll( { clientId, connectionId }: ConnectionScope, options?: FindAllOptions diff --git a/apps/vault/src/broker/persistence/repository/address.repository.ts b/apps/vault/src/broker/persistence/repository/address.repository.ts index 8287e19ed..ffbe4f998 100644 --- a/apps/vault/src/broker/persistence/repository/address.repository.ts +++ b/apps/vault/src/broker/persistence/repository/address.repository.ts @@ -1,10 +1,4 @@ -import { - LoggerService, - PaginatedResult, - PaginationOptions, - applyPagination, - getPaginatedResult -} from '@narval/nestjs-shared' +import { PaginatedResult, PaginationOptions, applyPagination, getPaginatedResult } from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' import { ProviderAddress } from '@prisma/client/vault' import { z } from 'zod' @@ -27,10 +21,7 @@ export type FindAllOptions = FindAllFilters & { pagination?: PaginationOptions } @Injectable() export class AddressRepository { - constructor( - private prismaService: PrismaService, - private readonly logger: LoggerService - ) {} + constructor(private prismaService: PrismaService) {} static parseModel(model: ProviderAddress): Address { const { id, ...rest } = model @@ -148,16 +139,10 @@ export class AddressRepository { } async bulkCreate(addresses: Address[]): Promise { - const { count } = await this.prismaService.providerAddress.createMany({ - data: addresses.map(AddressRepository.parseEntity), - skipDuplicates: true + await this.prismaService.providerAddress.createMany({ + data: addresses.map(AddressRepository.parseEntity) }) - this.logger.log('Address bulk create operation done', { - addressesLength: addresses.length, - addressesCreated: count, - addressesSkipped: addresses.length - count - }) return addresses } } diff --git a/apps/vault/src/broker/persistence/repository/scoped-sync.repository.ts b/apps/vault/src/broker/persistence/repository/scoped-sync.repository.ts index 41d2d2a3b..792a853fd 100644 --- a/apps/vault/src/broker/persistence/repository/scoped-sync.repository.ts +++ b/apps/vault/src/broker/persistence/repository/scoped-sync.repository.ts @@ -6,7 +6,7 @@ import { PrismaService } from '../../../shared/module/persistence/service/prisma import { ModelInvalidException } from '../../core/exception/model-invalid.exception' import { NotFoundException } from '../../core/exception/not-found.exception' import { ConnectionScope } from '../../core/type/scope.type' -import { RawAccount, RawAccountSyncFailure, ScopedSync, ScopedSyncStatus } from '../../core/type/scoped-sync.type' +import { RawAccount, ScopedSync, ScopedSyncStatus } from '../../core/type/scoped-sync.type' export type FindAllOptions = PaginationOptions & { filters?: { @@ -21,7 +21,6 @@ export type UpdateScopedSync = { completedAt?: Date status?: ScopedSyncStatus error?: ScopedSync['error'] - failures?: RawAccountSyncFailure[] } const parseErrorEntity = ( @@ -48,7 +47,6 @@ export class ScopedSyncRepository { // with how NULL values work in databases. rawAccounts: model.rawAccounts ? z.array(RawAccount).parse(PrismaService.toJson(model.rawAccounts)) : [], completedAt: model.completedAt || undefined, - failures: z.array(RawAccountSyncFailure).parse(PrismaService.toJson(model.failedRawAccounts) || []), error: model.errorName || model.errorMessage || model.errorTraceId ? { @@ -72,7 +70,6 @@ export class ScopedSyncRepository { rawAccounts: z.string().parse(PrismaService.toStringJson(entity.rawAccounts)), createdAt: entity.createdAt, status: entity.status, - failedRawAccounts: PrismaService.toStringJson(entity.failures), ...parseErrorEntity(entity.error) } } @@ -94,7 +91,6 @@ export class ScopedSyncRepository { } async update(updateScopedSync: UpdateScopedSync): Promise { - const failures = updateScopedSync.failures ? PrismaService.toStringJson(updateScopedSync.failures) : null await this.prismaService.providerScopedSync.update({ where: { id: updateScopedSync.scopedSyncId, @@ -103,8 +99,7 @@ export class ScopedSyncRepository { data: { completedAt: updateScopedSync.completedAt, status: updateScopedSync.status, - ...(updateScopedSync.error ? parseErrorEntity(updateScopedSync.error) : {}), - failedRawAccounts: failures + ...(updateScopedSync.error ? parseErrorEntity(updateScopedSync.error) : {}) } }) @@ -149,15 +144,4 @@ export class ScopedSyncRepository { page } } - - async exists({ clientId, connectionId, status }: ConnectionScope & { status?: ScopedSyncStatus }): Promise { - const count = await this.prismaService.providerScopedSync.count({ - where: { - clientId, - connectionId, - ...(status ? { status } : {}) - } - }) - return count > 0 - } } diff --git a/apps/vault/src/broker/persistence/repository/wallet.repository.ts b/apps/vault/src/broker/persistence/repository/wallet.repository.ts index 93171694c..05c4e9747 100644 --- a/apps/vault/src/broker/persistence/repository/wallet.repository.ts +++ b/apps/vault/src/broker/persistence/repository/wallet.repository.ts @@ -1,10 +1,4 @@ -import { - LoggerService, - PaginatedResult, - PaginationOptions, - applyPagination, - getPaginatedResult -} from '@narval/nestjs-shared' +import { PaginatedResult, PaginationOptions, applyPagination, getPaginatedResult } from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' import { ProviderAccount, ProviderAddress, ProviderWallet } from '@prisma/client/vault' import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' @@ -34,10 +28,7 @@ export type FindAllPaginatedOptions = PaginationOptions & FindAllFilters @Injectable() export class WalletRepository { - constructor( - private prismaService: PrismaService, - private readonly logger: LoggerService - ) {} + constructor(private prismaService: PrismaService) {} static parseModel(wallet: ProviderWalletsAndRelations): Wallet { const { accounts, id, ...walletData } = wallet @@ -194,77 +185,6 @@ export class WalletRepository { return wallets } - async bulkUpsert(wallets: Wallet[]): Promise { - const providerWallets: ProviderWallet[] = wallets.map(WalletRepository.parseEntity) - - const stats = { - inserted: 0, - updated: 0 - } - - const existingWallets = await this.prismaService.providerWallet.findMany({ - where: { - OR: providerWallets.map((wallet) => ({ - clientId: wallet.clientId, - connectionId: wallet.connectionId, - externalId: wallet.externalId - })) - } - }) - - const upsertedWallets = await this.prismaService.$transaction(async (tx) => { - const upsertPromises = providerWallets.map(async (wallet) => { - const existing = existingWallets.find( - (w) => - w.clientId === wallet.clientId && - w.connectionId === wallet.connectionId && - w.externalId === wallet.externalId - ) - - const result = tx.providerWallet.upsert({ - where: { - clientId_connectionId_externalId: { - clientId: wallet.clientId, - connectionId: wallet.connectionId, - externalId: wallet.externalId - } - }, - create: { - ...wallet - }, - update: { - label: wallet.label, - updatedAt: wallet.updatedAt - }, - include: { - accounts: { - include: { - addresses: true - } - } - } - }) - - if (!existing) { - stats.inserted++ - } else { - stats.updated++ - } - - return result - }) - return Promise.all(upsertPromises) - }) - - this.logger.log('Wallet bulk upsert operation completed:', { - total: wallets.length, - inserted: stats.inserted, - updated: stats.updated - }) - - return upsertedWallets.map(WalletRepository.parseModel) - } - async update(wallet: UpdateWallet) { const model = await this.prismaService.providerWallet.update({ where: { id: wallet.walletId }, diff --git a/apps/vault/src/shared/module/persistence/schema/migrations/20250124164857_store_failed_raw_accounts_requests/migration.sql b/apps/vault/src/shared/module/persistence/schema/migrations/20250124164857_store_failed_raw_accounts_requests/migration.sql deleted file mode 100644 index 2215327bc..000000000 --- a/apps/vault/src/shared/module/persistence/schema/migrations/20250124164857_store_failed_raw_accounts_requests/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "provider_scoped_sync" ADD COLUMN "failed_raw_accounts" TEXT; diff --git a/apps/vault/src/shared/module/persistence/schema/schema.prisma b/apps/vault/src/shared/module/persistence/schema/schema.prisma index db19dee11..525453ad1 100644 --- a/apps/vault/src/shared/module/persistence/schema/schema.prisma +++ b/apps/vault/src/shared/module/persistence/schema/schema.prisma @@ -124,13 +124,13 @@ model ProviderAccount { connectionId String @map("connection_id") externalId String @map("external_id") provider String - walletId String? @map("wallet_id") + walletId String @map("wallet_id") networkId String @map("network_id") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") connection ProviderConnection @relation(fields: [connectionId], references: [id]) - wallet ProviderWallet? @relation(fields: [walletId], references: [id]) + wallet ProviderWallet @relation(fields: [walletId], references: [id]) addresses ProviderAddress[] sourceTransfers ProviderTransfer[] @relation("SourceAccount") @@ -206,20 +206,17 @@ model ProviderSync { } model ProviderScopedSync { - id String @id - clientId String @map("client_id") - connectionId String @map("connection_id") + id String @id + clientId String @map("client_id") + connectionId String @map("connection_id") status String - rawAccounts String @map("raw_accounts") - errorName String? @map("error_name") errorMessage String? @map("error_message") errorTraceId String? @map("error_trace_id") + rawAccounts String @map("raw_accounts") createdAt DateTime @default(now()) @map("created_at") completedAt DateTime? @map("completed_at") - failedRawAccounts String? @map("failed_raw_accounts") - connection ProviderConnection @relation(fields: [connectionId], references: [id]) @@map("provider_scoped_sync") From 6a5e2e9ad6e3ab969c27cb270371c175f60267b4 Mon Sep 17 00:00:00 2001 From: Ptroger <44851272+Ptroger@users.noreply.github.com> Date: Tue, 28 Jan 2025 15:44:25 +0100 Subject: [PATCH 108/120] Delete sync operation rebased (#117) * removed operations, scope sync can partially succeed * refactor bitgo and fireblocks * tests fixed for new interface * removed unused services imports * adding logs to the wallet bulkUpsert method * networkMap is a map, addressed namings, used constants instead of numbers * namings, complete function handles partial success for scoped sync service * lock sync when there's already an in progresss sync for this connection * Trying larger runner * fixed the network caching, and the lock on scope sync * Revert "Trying larger runner" This reverts commit bda1bb6b3154ae3f71740bbbcf7d0aca263649dc. * raw account errors are more precise * fireblocks raw accounts building use external network id * fixed reads for upserts outside of tx scope * exists take the status as a parameter * removed unused function * fixed fireblocks scoped sync mock server declaration --------- Co-authored-by: Matt Schoch --- .../core/exception/scoped-sync.exception.ts | 13 + .../anchorage-scoped-sync.service.spec.ts | 109 ++-- .../anchorage-scoped-sync.service.ts | 465 +++++++++--------- .../core/provider/anchorage/anchorage.util.ts | 2 + .../fireblocks-scoped-sync.service.spec.ts | 130 ++--- .../response/get-vault-account-invalid.json | 4 + .../get-wallet-addresses-ethereum-200.json | 2 +- .../fireblocks/__test__/server-mock/server.ts | 24 +- .../fireblocks-scoped-sync.service.ts | 462 +++++++++-------- .../provider/fireblocks/fireblocks.util.ts | 16 +- .../broker/core/service/account.service.ts | 4 + .../broker/core/service/network.service.ts | 4 +- .../core/service/raw-account.service.ts | 100 ++-- .../core/service/scoped-sync.service.ts | 226 +++++---- .../src/broker/core/service/wallet.service.ts | 4 + .../src/broker/core/type/network.type.ts | 5 +- .../src/broker/core/type/provider.type.ts | 214 +------- .../src/broker/core/type/scoped-sync.type.ts | 52 +- .../broker/core/util/provider-sync.util.ts | 16 - .../http/rest/dto/response/scoped-sync.dto.ts | 6 +- .../repository/account.repository.ts | 82 ++- .../repository/address.repository.ts | 23 +- .../repository/scoped-sync.repository.ts | 20 +- .../repository/wallet.repository.ts | 84 +++- .../migration.sql | 2 + .../module/persistence/schema/schema.prisma | 15 +- 26 files changed, 1089 insertions(+), 995 deletions(-) create mode 100644 apps/vault/src/broker/core/exception/scoped-sync.exception.ts create mode 100644 apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-vault-account-invalid.json delete mode 100644 apps/vault/src/broker/core/util/provider-sync.util.ts create mode 100644 apps/vault/src/shared/module/persistence/schema/migrations/20250124164857_store_failed_raw_accounts_requests/migration.sql diff --git a/apps/vault/src/broker/core/exception/scoped-sync.exception.ts b/apps/vault/src/broker/core/exception/scoped-sync.exception.ts new file mode 100644 index 000000000..1044715df --- /dev/null +++ b/apps/vault/src/broker/core/exception/scoped-sync.exception.ts @@ -0,0 +1,13 @@ +import { HttpStatus } from '@nestjs/common' +import { ApplicationExceptionParams } from '../../../shared/exception/application.exception' +import { BrokerException } from './broker.exception' + +export class ScopedSyncException extends BrokerException { + constructor(params?: Partial) { + super({ + message: params?.message || 'Fail to sync provider connection', + suggestedHttpStatusCode: params?.suggestedHttpStatusCode || HttpStatus.UNPROCESSABLE_ENTITY, + ...params + }) + } +} diff --git a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-scoped-sync.service.spec.ts b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-scoped-sync.service.spec.ts index 200519cfe..7d112042a 100644 --- a/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-scoped-sync.service.spec.ts +++ b/apps/vault/src/broker/core/provider/anchorage/__test__/integration/anchorage-scoped-sync.service.spec.ts @@ -10,12 +10,11 @@ import { TestPrismaService } from '../../../../../../shared/module/persistence/s import { testClient } from '../../../../../__test__/util/mock-data' import { NetworkSeed } from '../../../../../persistence/seed/network.seed' import { setupMockServer } from '../../../../../shared/__test__/mock-server' -import { AccountService } from '../../../../service/account.service' -import { AddressService } from '../../../../service/address.service' import { ConnectionService } from '../../../../service/connection.service' -import { WalletService } from '../../../../service/wallet.service' +import { NetworkService } from '../../../../service/network.service' import { ConnectionWithCredentials } from '../../../../type/connection.type' -import { Provider, isCreateOperation } from '../../../../type/provider.type' +import { Provider } from '../../../../type/provider.type' +import { RawAccountError } from '../../../../type/scoped-sync.type' import { AnchorageScopedSyncService } from '../../anchorage-scoped-sync.service' import { ANCHORAGE_TEST_API_BASE_URL, getHandlers } from '../server-mock/server' @@ -26,9 +25,7 @@ describe(AnchorageScopedSyncService.name, () => { let anchorageScopedSyncService: AnchorageScopedSyncService let clientService: ClientService let connection: ConnectionWithCredentials - let walletService: WalletService - let accountService: AccountService - let addressService: AddressService + let networkService: NetworkService let connectionService: ConnectionService let networkSeed: NetworkSeed let provisionService: ProvisionService @@ -48,9 +45,7 @@ describe(AnchorageScopedSyncService.name, () => { testPrismaService = module.get(TestPrismaService) anchorageScopedSyncService = module.get(AnchorageScopedSyncService) connectionService = module.get(ConnectionService) - walletService = module.get(WalletService) - accountService = module.get(AccountService) - addressService = module.get(AddressService) + networkService = module.get(NetworkService) provisionService = module.get(ProvisionService) networkSeed = module.get(NetworkSeed) clientService = module.get(ClientService) @@ -94,7 +89,14 @@ describe(AnchorageScopedSyncService.name, () => { externalId: '6a46a1977959e0529f567e8e927e3895' } ] - const sync = await anchorageScopedSyncService.scopedSync(connection, rawAccounts) + const networks = await networkService.buildProviderExternalIdIndex(Provider.ANCHORAGE) + + const sync = await anchorageScopedSyncService.scopeSync({ + connection, + rawAccounts, + networks, + existingAccounts: [] + }) expect(sync.wallets.length).toBe(1) expect(sync.accounts.length).toBe(1) @@ -103,75 +105,76 @@ describe(AnchorageScopedSyncService.name, () => { // TODO @ptroger: revert that back to 'return empty array' when we completely move towards the scoped connections it('returns full connection sync when empty rawAccounts are provided', async () => { - const sync = await anchorageScopedSyncService.scopedSync(connection, []) + const networks = await networkService.buildProviderExternalIdIndex(Provider.ANCHORAGE) + + const sync = await anchorageScopedSyncService.scopeSync({ + connection, + rawAccounts: [], + networks, + existingAccounts: [] + }) expect(sync.wallets.length).toBe(2) expect(sync.accounts.length).toBe(18) - expect(sync.addresses.length).toBe(2) + expect(sync.addresses.length).toBe(18) }) - it('returns empty array when no wallets are found for the provided rawAccounts', async () => { + it('adds failure when external resource is not found', async () => { const rawAccounts = [ { provider: Provider.ANCHORAGE, externalId: 'notFound' } ] - const sync = await anchorageScopedSyncService.scopedSync(connection, rawAccounts) + const networks = await networkService.buildProviderExternalIdIndex(Provider.ANCHORAGE) + + const sync = await anchorageScopedSyncService.scopeSync({ + connection, + rawAccounts, + networks, + existingAccounts: [] + }) expect(sync.wallets.length).toBe(0) expect(sync.accounts.length).toBe(0) expect(sync.addresses.length).toBe(0) - }) - it('skips duplicate for the same connection', async () => { - const rawAccounts = [ + expect(sync.failures).toEqual([ { - provider: Provider.ANCHORAGE, - externalId: '6a46a1977959e0529f567e8e927e3895' + rawAccount: rawAccounts[0], + message: 'Anchorage wallet not found', + code: RawAccountError.EXTERNAL_RESOURCE_NOT_FOUND, + externalResourceType: 'wallet', + externalResourceId: rawAccounts[0].externalId } - ] - const firstSync = await anchorageScopedSyncService.scopedSync(connection, rawAccounts) - - await walletService.bulkCreate(firstSync.wallets.filter(isCreateOperation).map(({ create }) => create)) - await accountService.bulkCreate(firstSync.accounts.filter(isCreateOperation).map(({ create }) => create)) - await addressService.bulkCreate(firstSync.addresses.filter(isCreateOperation).map(({ create }) => create)) - - const secondSync = await anchorageScopedSyncService.scopedSync(connection, rawAccounts) - - expect(secondSync.wallets.length).toBe(0) - expect(secondSync.accounts.length).toBe(0) - expect(secondSync.addresses.length).toBe(0) + ]) }) - it('duplicates for different connections', async () => { + it('adds failure when network is not found in our list', async () => { const rawAccounts = [ { provider: Provider.ANCHORAGE, externalId: '6a46a1977959e0529f567e8e927e3895' } ] - const firstSync = await anchorageScopedSyncService.scopedSync(connection, rawAccounts) - - await walletService.bulkCreate(firstSync.wallets.filter(isCreateOperation).map(({ create }) => create)) - await accountService.bulkCreate(firstSync.accounts.filter(isCreateOperation).map(({ create }) => create)) - await addressService.bulkCreate(firstSync.addresses.filter(isCreateOperation).map(({ create }) => create)) - - const secondConnection = await connectionService.create(clientId, { - connectionId: uuid(), - provider: Provider.ANCHORAGE, - url: ANCHORAGE_TEST_API_BASE_URL, - label: 'test active connection', - credentials: { - apiKey: 'test-api-key', - privateKey: await privateKeyToHex(await generateJwk(Alg.EDDSA)) - } - }) - const secondSync = await anchorageScopedSyncService.scopedSync(secondConnection, rawAccounts) + const sync = await anchorageScopedSyncService.scopeSync({ + connection, + rawAccounts, + networks: new Map(), + existingAccounts: [] + }) - expect(secondSync.wallets.length).toBe(1) - expect(secondSync.accounts.length).toBe(1) - expect(secondSync.addresses.length).toBe(1) + expect(sync.wallets.length).toBe(0) + expect(sync.accounts.length).toBe(0) + expect(sync.addresses.length).toBe(0) + expect(sync.failures).toEqual([ + { + rawAccount: rawAccounts[0], + message: 'Network for this account is not supported', + code: RawAccountError.UNLISTED_NETWORK, + networkId: 'BTC_S' + } + ]) }) }) }) diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage-scoped-sync.service.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage-scoped-sync.service.ts index c4cfbf0b4..530aa21d3 100644 --- a/apps/vault/src/broker/core/provider/anchorage/anchorage-scoped-sync.service.ts +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage-scoped-sync.service.ts @@ -1,287 +1,278 @@ import { LoggerService } from '@narval/nestjs-shared' import { HttpStatus, Injectable } from '@nestjs/common' import { randomUUID } from 'crypto' -import { filter, find, flatMap, flow, groupBy, isEmpty, map, uniqBy } from 'lodash/fp' +import { chunk, uniqBy } from 'lodash/fp' import { AnchorageClient, Wallet as AnchorageWallet } from '../../../http/client/anchorage.client' -import { UpdateAccount } from '../../../persistence/repository/account.repository' -import { NetworkRepository } from '../../../persistence/repository/network.repository' -import { WalletRepository } from '../../../persistence/repository/wallet.repository' import { ConnectionWithCredentials } from '../../type/connection.type' -import { Account, Address, UpdateWallet, Wallet } from '../../type/indexed-resources.type' +import { Account, Address, Wallet } from '../../type/indexed-resources.type' +import { NetworkMap } from '../../type/network.type' +import { Provider, ProviderScopedSyncService } from '../../type/provider.type' import { - CreateScopedSyncOperation, - Provider, - ProviderScopedSyncService, - ScopedSyncOperation, - ScopedSyncOperationType, + RawAccount, + RawAccountError, + RawAccountSyncFailure, + ScopedSyncContext, ScopedSyncResult -} from '../../type/provider.type' -import { RawAccount } from '../../type/scoped-sync.type' -import { CONCURRENT_ANCHORAGE_REQUESTS, validateConnection } from './anchorage.util' +} from '../../type/scoped-sync.type' +import { CONCURRENT_ANCHORAGE_REQUESTS, ValidConnection, validateConnection } from './anchorage.util' + +type RawAccountSyncSuccess = { + success: true + wallet: Wallet + account: Account + address: Address +} + +type RawAccountSyncFailed = { + success: false + failure: RawAccountSyncFailure +} + +type RawAccountSyncResult = RawAccountSyncSuccess | RawAccountSyncFailed @Injectable() export class AnchorageScopedSyncService implements ProviderScopedSyncService { constructor( private readonly anchorageClient: AnchorageClient, - private readonly networkRepository: NetworkRepository, - private readonly walletRepository: WalletRepository, private readonly logger: LoggerService ) {} - private async fetchRawAccountWallets( - connection: ConnectionWithCredentials, - rawAccounts: RawAccount[] - ): Promise { - validateConnection(connection) + private resolveFailure(failure: RawAccountSyncFailure): RawAccountSyncFailed { + this.logger.log('Failed to sync Raw Account', failure) + return { success: false, failure } + } - const wallets: AnchorageWallet[] = [] + private resolveSuccess({ + rawAccount, + wallet, + account, + address + }: { + wallet: Wallet + address: Address + rawAccount: RawAccount + account: Account + }): RawAccountSyncSuccess { + this.logger.log('Successfully fetched and map Raw Account', { + rawAccount, + account + }) + return { + success: true, + wallet, + account, + address + } + } - for (let i = 0; i < rawAccounts.length; i += CONCURRENT_ANCHORAGE_REQUESTS) { - const batch = rawAccounts.slice(i, i + CONCURRENT_ANCHORAGE_REQUESTS) - const batchPromises = batch.map((rawAccount) => - this.anchorageClient.getWallet({ - url: connection.url, - apiKey: connection.credentials.apiKey, - signKey: connection.credentials.privateKey, - walletId: rawAccount.externalId - }) - ) + private mapAnchorageWalletToNarvalModel( + anchorageWallet: AnchorageWallet, + { + networks, + now, + existingAccounts, + rawAccount, + connection, + existingWallets + }: { + networks: NetworkMap + now: Date + existingAccounts: Account[] + existingWallets: Wallet[] + rawAccount: RawAccount + connection: ValidConnection + } + ): RawAccountSyncResult { + const network = networks.get(anchorageWallet.networkId) + if (!network) { + this.logger.error('Network not found', { + rawAccount, + externalNetwork: anchorageWallet.networkId + }) + return this.resolveFailure({ + rawAccount, + message: 'Network for this account is not supported', + code: RawAccountError.UNLISTED_NETWORK, + networkId: anchorageWallet.networkId + }) + } + const existingAccount = existingAccounts.find((a) => a.externalId === anchorageWallet.walletId) + const existingWallet = existingWallets.find((w) => w.externalId === anchorageWallet.vaultId) - const batchResults = await Promise.allSettled(batchPromises) + const walletId = existingWallet?.walletId || existingAccount?.walletId || randomUUID() + const accountId = existingAccount?.accountId || randomUUID() - const validWallets = batchResults - .map((result, index) => { - if (result.status === 'fulfilled') { - return result.value - } else { - // Handle rejected promises - const error = result.reason - const rawAccount = batch[index] + const wallet: Wallet = { + accounts: [], + clientId: connection.clientId, + connectionId: connection.connectionId, + createdAt: now, + externalId: anchorageWallet.vaultId, + label: anchorageWallet.walletName, + provider: Provider.ANCHORAGE, + updatedAt: now, + walletId + } - if (error.response?.status === HttpStatus.NOT_FOUND) { - this.logger.warn('Anchorage wallet not found', { - connectionId: connection.connectionId, - clientId: connection.clientId, - url: connection.url, - externalId: rawAccount.externalId - }) - return null - } - throw error - } - }) - .filter((wallet): wallet is AnchorageWallet => wallet !== null) as AnchorageWallet[] + const account: Account = { + externalId: anchorageWallet.walletId, + accountId, + addresses: [], + clientId: connection.clientId, + connectionId: connection.connectionId, + createdAt: now, + label: anchorageWallet.walletName, + networkId: network.networkId, + provider: Provider.ANCHORAGE, + updatedAt: now, + walletId + } - wallets.push(...validWallets) + const address: Address = { + accountId, + address: anchorageWallet.depositAddress.address, + addressId: randomUUID(), + clientId: connection.clientId, + connectionId: connection.connectionId, + createdAt: now, + externalId: anchorageWallet.depositAddress.addressId, + provider: Provider.ANCHORAGE, + updatedAt: now } - return wallets + return this.resolveSuccess({ rawAccount, wallet, account, address }) } - async scopedSync(connection: ConnectionWithCredentials, rawAccounts: RawAccount[]): Promise { - const now = new Date() + private async syncRawAccount({ + connection, + rawAccount, + networks, + now, + existingAccounts, + existingWallets + }: { + connection: ConnectionWithCredentials + rawAccount: RawAccount + networks: NetworkMap + now: Date + existingAccounts: Account[] + existingWallets: Wallet[] + }): Promise { + validateConnection(connection) + + try { + const anchorageWallet = await this.anchorageClient.getWallet({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey, + walletId: rawAccount.externalId + }) + + return this.mapAnchorageWalletToNarvalModel(anchorageWallet, { + networks, + now, + existingAccounts, + rawAccount, + connection, + existingWallets + }) + } catch (error) { + if (error.response?.status === HttpStatus.NOT_FOUND) { + return this.resolveFailure({ + rawAccount, + message: 'Anchorage wallet not found', + code: RawAccountError.EXTERNAL_RESOURCE_NOT_FOUND, + externalResourceType: 'wallet', + externalResourceId: rawAccount.externalId + }) + } + throw error + } + } + async scopeSync({ + connection, + rawAccounts, + networks, + existingAccounts + }: ScopedSyncContext): Promise { this.logger.log('Sync Anchorage accounts', { connectionId: connection.connectionId, clientId: connection.clientId, url: connection.url }) - validateConnection(connection) - - const existingWallets = await this.walletRepository.findAll( - { clientId: connection.clientId, connectionId: connection.connectionId }, - { pagination: { disabled: true } } - ) - - const existingWalletMap = new Map(existingWallets.data.map((wallet) => [wallet.externalId, wallet])) - const existingAccountMap = new Map( - existingWallets.data.flatMap( - (wallet) => - wallet.accounts?.map((account) => [account.externalId, { ...account, walletId: wallet.walletId }]) ?? [] - ) - ) - - // TODO @ptroger: revert that back to 'return empty array' when we completely move towards the scoped connections - const scopedAnchorageWallets = isEmpty(rawAccounts) - ? await this.anchorageClient.getWallets({ - url: connection.url, - apiKey: connection.credentials.apiKey, - signKey: connection.credentials.privateKey - }) - : await this.fetchRawAccountWallets(connection, rawAccounts) + const now = new Date() - const walletsByVault = groupBy('vaultId', scopedAnchorageWallets) - const vaultAndWallets = Object.entries(walletsByVault).map(([vaultId, wallets]) => ({ - id: vaultId, - // All wallets in a vault should have the same vault name - name: wallets[0].vaultName, - wallets: wallets.map((wallet) => ({ - walletId: wallet.walletId, - walletName: wallet.walletName, - address: { - address: wallet.depositAddress.address, - addressId: wallet.depositAddress.addressId - }, - assets: wallet.assets.map((asset) => ({ - assetType: asset.assetType, - availableBalance: asset.availableBalance, - totalBalance: asset.totalBalance, - stakedBalance: asset.stakedBalance, - unclaimedBalance: asset.unclaimedBalance - })), - networkId: wallet.networkId - })) - })) + const chunkedRawAccounts = chunk(CONCURRENT_ANCHORAGE_REQUESTS, rawAccounts) + const results: RawAccountSyncResult[] = [] - const walletOperations: ScopedSyncOperation[] = [] - const accountOperations: ScopedSyncOperation[] = [] - const addressOperations: ScopedSyncOperation[] = [] + // TODO @ptroger: remove the if block when we completely move towards picking accounts in UI + if (rawAccounts.length === 0) { + validateConnection(connection) - for (const vault of vaultAndWallets) { - const existingWallet = existingWalletMap.get(vault.id) - const walletId = existingWallet?.walletId || randomUUID() + const anchorageWallets = await this.anchorageClient.getWallets({ + url: connection.url, + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey + }) - if (existingWallet) { - // Check if wallet needs update - if (existingWallet.label !== vault.name) { - walletOperations.push({ - type: ScopedSyncOperationType.UPDATE, - update: { - clientId: connection.clientId, - walletId, - label: vault.name, - updatedAt: now - } - }) - } - } else { - // Create new wallet - walletOperations.push({ - type: ScopedSyncOperationType.CREATE, - create: { - accounts: [], - clientId: connection.clientId, - connectionId: connection.connectionId, - createdAt: now, - externalId: vault.id, - label: vault.name, - provider: Provider.ANCHORAGE, - updatedAt: now, - walletId - } + const existingWallets: Wallet[] = [] + const mappedAnchorageWallets = anchorageWallets.map((anchorageWallet) => { + const map = this.mapAnchorageWalletToNarvalModel(anchorageWallet, { + networks, + now, + existingAccounts, + rawAccount: { provider: Provider.ANCHORAGE, externalId: anchorageWallet.walletId }, + connection, + existingWallets }) - } - - const vaultAssetTypes = flow(flatMap('assets'), uniqBy('assetType'), map('assetType'))(vault.wallets) - - for (const anchorageWallet of vault.wallets) { - const existingAccount = existingAccountMap.get(anchorageWallet.walletId) - const accountId = existingAccount?.accountId || randomUUID() - const network = await this.networkRepository.findByExternalId(Provider.ANCHORAGE, anchorageWallet.networkId) + map.success && existingWallets.push(map.wallet) + return map + }) - if (network) { - if (existingAccount) { - // Check if account needs update - if (existingAccount.label !== anchorageWallet.walletName) { - accountOperations.push({ - type: ScopedSyncOperationType.UPDATE, - update: { - clientId: connection.clientId, - accountId: existingAccount.accountId, - label: anchorageWallet.walletName, - updatedAt: now - } - }) - } - } else { - accountOperations.push({ - type: ScopedSyncOperationType.CREATE, - create: { - externalId: anchorageWallet.walletId, - accountId, - addresses: [], - clientId: connection.clientId, - connectionId: connection.connectionId, - createdAt: now, - label: anchorageWallet.walletName, - networkId: network.networkId, - provider: Provider.ANCHORAGE, - updatedAt: now, - walletId - } + results.push(...mappedAnchorageWallets) + } else { + const existingWallets: Wallet[] = [] + for (const chunk of chunkedRawAccounts) { + const chunkResults = await Promise.all( + chunk.map(async (rawAccount) => { + const mapResult = await this.syncRawAccount({ + connection, + rawAccount, + networks, + now, + existingAccounts, + existingWallets }) - } - } else { - accountOperations.push({ - type: ScopedSyncOperationType.FAILED, - externalId: anchorageWallet.walletId, - message: 'Unknown Anchorage wallet network ID', - context: { - externalId: anchorageWallet.walletId, - anchorageNetworkId: anchorageWallet.networkId - } + mapResult.success && existingWallets.push(mapResult.wallet) + return mapResult }) - } + ) + results.push(...chunkResults) } + } - // Process addresses - Anchorage only creates, no updates - for (const assetType of vaultAssetTypes) { - const addresses = await this.anchorageClient.getVaultAddresses({ - signKey: connection.credentials.privateKey, - apiKey: connection.credentials.apiKey, - assetType, - url: connection.url, - vaultId: vault.id - }) - - for (const address of addresses) { - const account = flow( - filter((op: ScopedSyncOperation) => op.type === ScopedSyncOperationType.CREATE), - find((op: CreateScopedSyncOperation) => op.create.externalId === address.walletId) - )(accountOperations) - - const existingAccount = existingAccountMap.get(address.walletId) - const skipAddress = existingAccount?.addresses?.some((a) => a.externalId === address.addressId) + const wallets: Wallet[] = [] + const accounts: Account[] = [] + const addresses: Address[] = [] + const failures: RawAccountSyncFailure[] = [] - const tiedAccount = account?.create?.accountId || existingAccount?.accountId - if (!skipAddress && tiedAccount) { - if (account?.create?.accountId || existingAccount?.accountId) { - addressOperations.push({ - type: ScopedSyncOperationType.CREATE, - create: { - accountId: tiedAccount, - address: address.address, - addressId: randomUUID(), - clientId: connection.clientId, - connectionId: connection.connectionId, - createdAt: now, - externalId: address.addressId, - provider: Provider.ANCHORAGE, - updatedAt: now - } - }) - } else { - addressOperations.push({ - type: ScopedSyncOperationType.FAILED, - externalId: address.addressId, - message: 'Unknown Anchorage wallet address', - context: { - externalId: address.addressId, - address: address.address, - walletId: address.walletId - } - }) - } - } - } + for (const result of results) { + if (result.success) { + wallets.push(result.wallet) + accounts.push(result.account) + addresses.push(result.address) + } else { + failures.push(result.failure) } } return { - wallets: walletOperations, - accounts: accountOperations, - addresses: addressOperations + wallets: uniqBy('externalId', wallets), + accounts: uniqBy('externalId', accounts), + addresses: uniqBy('externalId', addresses), + failures } } } diff --git a/apps/vault/src/broker/core/provider/anchorage/anchorage.util.ts b/apps/vault/src/broker/core/provider/anchorage/anchorage.util.ts index 5703365af..cb0ead59f 100644 --- a/apps/vault/src/broker/core/provider/anchorage/anchorage.util.ts +++ b/apps/vault/src/broker/core/provider/anchorage/anchorage.util.ts @@ -15,6 +15,8 @@ export type ValidConnection = { apiKey: string privateKey: Ed25519PrivateKey } + clientId: string + connectionId: string } export function validateConnection( diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-scoped-sync.service.spec.ts b/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-scoped-sync.service.spec.ts index 075ab43a1..ff3c03313 100644 --- a/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-scoped-sync.service.spec.ts +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/integration/fireblocks-scoped-sync.service.spec.ts @@ -9,15 +9,18 @@ import { TestPrismaService } from '../../../../../../shared/module/persistence/s import { testClient } from '../../../../../__test__/util/mock-data' import { NetworkSeed } from '../../../../../persistence/seed/network.seed' import { setupMockServer } from '../../../../../shared/__test__/mock-server' -import { AccountService } from '../../../../service/account.service' -import { AddressService } from '../../../../service/address.service' import { ConnectionService } from '../../../../service/connection.service' -import { WalletService } from '../../../../service/wallet.service' +import { NetworkService } from '../../../../service/network.service' import { ConnectionWithCredentials } from '../../../../type/connection.type' -import { Provider, isCreateOperation } from '../../../../type/provider.type' -import { FIREBLOCKS_TEST_API_BASE_URL, getHandlers } from '../../../fireblocks/__test__/server-mock/server' +import { Provider } from '../../../../type/provider.type' +import { RawAccountError } from '../../../../type/scoped-sync.type' +import { + FIREBLOCKS_TEST_API_BASE_URL, + getHandlers, + getVaultAccountHandlers +} from '../../../fireblocks/__test__/server-mock/server' import { FireblocksScopedSyncService } from '../../fireblocks-scoped-sync.service' -import { getFireblocksAssetWalletExternalId } from '../../fireblocks.util' +import { buildFireblocksAssetWalletExternalId } from '../../fireblocks.util' describe(FireblocksScopedSyncService.name, () => { let app: INestApplication @@ -26,16 +29,12 @@ describe(FireblocksScopedSyncService.name, () => { let fireblocksScopedSyncService: FireblocksScopedSyncService let clientService: ClientService let connection: ConnectionWithCredentials - let walletService: WalletService - let accountService: AccountService - let addressService: AddressService let connectionService: ConnectionService let networkSeed: NetworkSeed + let networkService: NetworkService let provisionService: ProvisionService let testPrismaService: TestPrismaService - setupMockServer(getHandlers()) - const privateKeyPem = `-----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDVORyUbWt/yuW4 29mXtJBC3PEisQN3BQhtKp6jHa89YeWBct43g6tUTwcvdj7HXJOmp1FLbbPzE/pe @@ -69,6 +68,8 @@ iYDlTZ/pWsEotE2yCl/8krs= const clientId = 'test-client-id' + const mockServer = setupMockServer(getHandlers()) + beforeAll(async () => { module = await VaultTest.createTestingModule({ imports: [MainModule] @@ -79,9 +80,7 @@ iYDlTZ/pWsEotE2yCl/8krs= testPrismaService = module.get(TestPrismaService) fireblocksScopedSyncService = module.get(FireblocksScopedSyncService) connectionService = module.get(ConnectionService) - walletService = module.get(WalletService) - accountService = module.get(AccountService) - addressService = module.get(AddressService) + networkService = module.get(NetworkService) provisionService = module.get(ProvisionService) networkSeed = module.get(NetworkSeed) clientService = module.get(ClientService) @@ -122,87 +121,96 @@ iYDlTZ/pWsEotE2yCl/8krs= const rawAccounts = [ { provider: Provider.FIREBLOCKS, - externalId: getFireblocksAssetWalletExternalId({ vaultId: '3', networkId: 'ETHEREUM' }) + externalId: buildFireblocksAssetWalletExternalId({ vaultId: '3', networkId: 'ETH' }) } ] - const sync = await fireblocksScopedSyncService.scopedSync(connection, rawAccounts) + + const networks = await networkService.buildProviderExternalIdIndex(Provider.FIREBLOCKS) + const sync = await fireblocksScopedSyncService.scopeSync({ + connection, + rawAccounts, + networks, + existingAccounts: [] + }) expect(sync.wallets.length).toBe(1) expect(sync.accounts.length).toBe(1) expect(sync.addresses.length).toBe(1) }) - it('returns empty array when no rawAccounts are provided', async () => { - const sync = await fireblocksScopedSyncService.scopedSync(connection, []) + it('returns empty objects when no rawAccounts are provided', async () => { + const networks = await networkService.buildProviderExternalIdIndex(Provider.FIREBLOCKS) + + const sync = await fireblocksScopedSyncService.scopeSync({ + connection, + rawAccounts: [], + networks, + existingAccounts: [] + }) expect(sync.wallets.length).toBe(0) expect(sync.accounts.length).toBe(0) expect(sync.addresses.length).toBe(0) }) - it('returns empty array when no wallets are found for the provided rawAccounts', async () => { + it('adds failure when external resource is not found', async () => { + mockServer.use(getVaultAccountHandlers(FIREBLOCKS_TEST_API_BASE_URL).invalid) const rawAccounts = [ { provider: Provider.FIREBLOCKS, - externalId: getFireblocksAssetWalletExternalId({ vaultId: 'notfound', networkId: 'ETHEREUM' }) + externalId: buildFireblocksAssetWalletExternalId({ vaultId: 'notfound', networkId: 'ETH' }) } ] - const sync = await fireblocksScopedSyncService.scopedSync(connection, rawAccounts) + const networks = await networkService.buildProviderExternalIdIndex(Provider.FIREBLOCKS) + + const sync = await fireblocksScopedSyncService.scopeSync({ + connection, + rawAccounts, + networks, + existingAccounts: [] + }) expect(sync.wallets.length).toBe(0) expect(sync.accounts.length).toBe(0) expect(sync.addresses.length).toBe(0) - }) - - it('skips duplicate for the same connection', async () => { - const rawAccounts = [ + expect(sync.failures).toEqual([ { - provider: Provider.FIREBLOCKS, - externalId: getFireblocksAssetWalletExternalId({ vaultId: '3', networkId: 'ETHEREUM' }) + rawAccount: rawAccounts[0], + message: 'Fireblocks Vault Account not found', + code: RawAccountError.EXTERNAL_RESOURCE_NOT_FOUND, + externalResourceType: 'vaultAccount', + externalResourceId: 'NOTFOUND' } - ] - const firstSync = await fireblocksScopedSyncService.scopedSync(connection, rawAccounts) - - await walletService.bulkCreate(firstSync.wallets.filter(isCreateOperation).map(({ create }) => create)) - await accountService.bulkCreate(firstSync.accounts.filter(isCreateOperation).map(({ create }) => create)) - await addressService.bulkCreate(firstSync.addresses.filter(isCreateOperation).map(({ create }) => create)) - - const secondSync = await fireblocksScopedSyncService.scopedSync(connection, rawAccounts) - - expect(secondSync.wallets.length).toBe(0) - expect(secondSync.accounts.length).toBe(0) - expect(secondSync.addresses.length).toBe(0) + ]) }) - it('duplicates for different connections', async () => { + it('adds failure when network is not found in our list', async () => { const rawAccounts = [ { provider: Provider.FIREBLOCKS, - externalId: getFireblocksAssetWalletExternalId({ vaultId: '3', networkId: 'ETHEREUM' }) + externalId: buildFireblocksAssetWalletExternalId({ vaultId: '3', networkId: 'notFound' }) } ] - const firstSync = await fireblocksScopedSyncService.scopedSync(connection, rawAccounts) - - await walletService.bulkCreate(firstSync.wallets.filter(isCreateOperation).map(({ create }) => create)) - await accountService.bulkCreate(firstSync.accounts.filter(isCreateOperation).map(({ create }) => create)) - await addressService.bulkCreate(firstSync.addresses.filter(isCreateOperation).map(({ create }) => create)) - - const secondConnection = await connectionService.create(clientId, { - connectionId: uuid(), - provider: Provider.FIREBLOCKS, - url: FIREBLOCKS_TEST_API_BASE_URL, - label: 'test active connection', - credentials: { - apiKey: 'test-api-key', - privateKey - } - }) + const networks = await networkService.buildProviderExternalIdIndex(Provider.FIREBLOCKS) - const secondSync = await fireblocksScopedSyncService.scopedSync(secondConnection, rawAccounts) + const sync = await fireblocksScopedSyncService.scopeSync({ + connection, + rawAccounts, + networks, + existingAccounts: [] + }) - expect(secondSync.wallets.length).toBe(1) - expect(secondSync.accounts.length).toBe(1) - expect(secondSync.addresses.length).toBe(1) + expect(sync.wallets.length).toBe(0) + expect(sync.accounts.length).toBe(0) + expect(sync.addresses.length).toBe(0) + expect(sync.failures).toEqual([ + { + rawAccount: rawAccounts[0], + message: 'Network for this account is not supported', + code: RawAccountError.UNLISTED_NETWORK, + networkId: 'NOTFOUND' + } + ]) }) }) }) diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-vault-account-invalid.json b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-vault-account-invalid.json new file mode 100644 index 000000000..141a18b01 --- /dev/null +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-vault-account-invalid.json @@ -0,0 +1,4 @@ +{ + "message": "The Provided Vault Account ID is invalid: 11469", + "code": 11001 +} diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-wallet-addresses-ethereum-200.json b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-wallet-addresses-ethereum-200.json index c02b95088..e38ab060f 100644 --- a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-wallet-addresses-ethereum-200.json +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/response/get-wallet-addresses-ethereum-200.json @@ -1,7 +1,7 @@ { "addresses": [ { - "assetId": "ETH-OPT", + "assetId": "ETH", "address": "0x5748EA5ca075734bc7ADc9D8046e897c24829A80", "description": "", "tag": "", diff --git a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/server.ts b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/server.ts index 958d9ab7f..46ecad105 100644 --- a/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/server.ts +++ b/apps/vault/src/broker/core/provider/fireblocks/__test__/server-mock/server.ts @@ -1,6 +1,8 @@ +import { HttpStatus } from '@nestjs/common' import { HttpResponse, http } from 'msw' import getTransactionOk from './response/get-transaction-200.json' import vaultAccount3 from './response/get-vault-account-3-200.json' +import vaultAccountNotFound from './response/get-vault-account-invalid.json' import getWalletAddressesEthOk from './response/get-wallet-addresses-ethereum-200.json' import getWalletAddressesMaticOk from './response/get-wallet-addresses-matic-200.json' import postTransactionCreated from './response/post-transaction-201.json' @@ -20,6 +22,22 @@ export const getVaultAccount3AddressesHandlers = (baseUrl = FIREBLOCKS_TEST_API_ } } +export const getVaultAccountHandlers = (baseUrl = FIREBLOCKS_TEST_API_BASE_URL) => { + return { + get: http.get(`${baseUrl}/v1/vault/accounts/:vaultAccountId`, () => { + return new HttpResponse(JSON.stringify(vaultAccount3)) + }), + invalid: http.get( + `${baseUrl}/v1/vault/accounts/:vaultAccountId`, + () => + new HttpResponse(JSON.stringify(vaultAccountNotFound), { + status: HttpStatus.BAD_REQUEST + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } as unknown as any) + ) + } +} + export const getHandlers = (baseUrl = FIREBLOCKS_TEST_API_BASE_URL) => [ http.get(`${baseUrl}/v1/transactions/:txId`, () => { return new HttpResponse(JSON.stringify(getTransactionOk)) @@ -29,9 +47,7 @@ export const getHandlers = (baseUrl = FIREBLOCKS_TEST_API_BASE_URL) => [ return new HttpResponse(JSON.stringify(postTransactionCreated)) }), - http.get(`${baseUrl}/v1/vault/accounts/:vaultAccountId`, () => { - return new HttpResponse(JSON.stringify(vaultAccount3)) - }), + getVaultAccountHandlers(baseUrl).get, - getVaultAccount3AddressesHandlers(baseUrl).getMatic + getVaultAccount3AddressesHandlers(baseUrl).getEth ] diff --git a/apps/vault/src/broker/core/provider/fireblocks/fireblocks-scoped-sync.service.ts b/apps/vault/src/broker/core/provider/fireblocks/fireblocks-scoped-sync.service.ts index ae7347d40..fc71960ca 100644 --- a/apps/vault/src/broker/core/provider/fireblocks/fireblocks-scoped-sync.service.ts +++ b/apps/vault/src/broker/core/provider/fireblocks/fireblocks-scoped-sync.service.ts @@ -1,293 +1,269 @@ import { LoggerService } from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' import { randomUUID } from 'crypto' -import { uniqBy } from 'lodash/fp' +import { chunk, uniqBy } from 'lodash/fp' import { FIREBLOCKS_API_ERROR_CODES, FireblocksClient, VaultAccount } from '../../../http/client/fireblocks.client' -import { UpdateAccount } from '../../../persistence/repository/account.repository' -import { NetworkRepository } from '../../../persistence/repository/network.repository' -import { WalletRepository } from '../../../persistence/repository/wallet.repository' import { ConnectionWithCredentials } from '../../type/connection.type' -import { Account, Address, UpdateWallet, Wallet } from '../../type/indexed-resources.type' +import { Account, Address, Wallet } from '../../type/indexed-resources.type' +import { NetworkMap } from '../../type/network.type' +import { Provider, ProviderScopedSyncService } from '../../type/provider.type' import { - Provider, - ProviderScopedSyncService, - ScopedSyncOperation, - ScopedSyncOperationType, + RawAccount, + RawAccountError, + RawAccountSyncFailure, + ScopedSyncContext, ScopedSyncResult -} from '../../type/provider.type' -import { RawAccount } from '../../type/scoped-sync.type' +} from '../../type/scoped-sync.type' import { CONCURRENT_FIREBLOCKS_REQUESTS, - FireblocksAssetWalletId, - getFireblocksAssetAddressExternalId, - getFireblocksAssetWalletExternalId, - toFireblocksAssetWalletExternalId, + buildFireblocksAssetAddressExternalId, + parseFireblocksAssetWalletExternalId, validateConnection } from './fireblocks.util' +type RawAccountSyncSuccess = { + success: true + wallet: Wallet + account: Account + addresses: Address[] +} + +type RawAccountSyncFailed = { + success: false + failure: RawAccountSyncFailure +} + +type RawAccountSyncResult = RawAccountSyncSuccess | RawAccountSyncFailed @Injectable() export class FireblocksScopedSyncService implements ProviderScopedSyncService { constructor( private readonly fireblocksClient: FireblocksClient, - private readonly networkRepository: NetworkRepository, - private readonly walletRepository: WalletRepository, private readonly logger: LoggerService ) {} - private async buildVaultNetworkMap( - assetWalletIds: FireblocksAssetWalletId[] - ): Promise>> { - const result: Record> = {} - - for (const { vaultId, networkId } of assetWalletIds) { - if (!vaultId || !networkId) continue - - try { - const network = await this.networkRepository.findById(networkId) - - if (!network) { - this.logger.log('Network not found', { networkId }) - continue - } - - const fireblocksNetwork = network.externalNetworks?.find((n) => n.provider === Provider.FIREBLOCKS) - if (!fireblocksNetwork) { - this.logger.log('Network not supported', { networkId, provider: Provider.FIREBLOCKS }) - continue - } + private resolveFailure(failure: RawAccountSyncFailure): RawAccountSyncFailed { + this.logger.log('Failed to sync Raw Account', failure) + return { success: false, failure } + } - if (!result[vaultId]) { - result[vaultId] = new Set() - } - result[vaultId].add({ - narvalNetworkId: networkId, - fireblocksNetworkId: fireblocksNetwork.externalId - }) - } catch (error) { - this.logger.log('Error processing network', { networkId, error: String(error) }) - } + private resolveSuccess({ + rawAccount, + wallet, + account, + addresses + }: { + wallet: Wallet + addresses: Address[] + rawAccount: RawAccount + account: Account + }): RawAccountSyncSuccess { + this.logger.log('Successfully fetched and map Raw Account', { + rawAccount, + account + }) + return { + success: true, + wallet, + account, + addresses } - - return result } - - async scopedSync(connection: ConnectionWithCredentials, rawAccounts: RawAccount[]): Promise { - const now = new Date() + private async resolveRawAccount({ + connection, + rawAccount, + networks, + now, + existingAccounts, + existingAddresses, + vaultAccount, + existingWallets + }: { + connection: ConnectionWithCredentials + rawAccount: RawAccount + networks: NetworkMap + now: Date + existingAccounts: Account[] + vaultAccount: VaultAccount + existingWallets: Wallet[] + existingAddresses: Address[] + }): Promise { validateConnection(connection) + const { vaultId, baseAssetId: networkId } = parseFireblocksAssetWalletExternalId(rawAccount.externalId) + const network = networks.get(networkId) - const existingWallets = await this.walletRepository.findAll( - { clientId: connection.clientId, connectionId: connection.connectionId }, - { pagination: { disabled: true } } - ) - - const existingWalletMap = new Map(existingWallets.data.map((wallet) => [wallet.externalId, wallet])) - const existingAccountMap = new Map( - existingWallets.data.flatMap( - (wallet) => - wallet.accounts?.map((account) => [account.externalId, { ...account, walletId: wallet.walletId }]) ?? [] - ) - ) - - const assetWalletIds = uniqBy('externalId', rawAccounts).map((account) => - toFireblocksAssetWalletExternalId(account.externalId) - ) - - const vaultToNetworkMap = await this.buildVaultNetworkMap(assetWalletIds) - const requestedVaultIds = Object.keys(vaultToNetworkMap) - - const vaults: VaultAccount[] = [] - for (let i = 0; i < Object.keys(vaultToNetworkMap).length; i += CONCURRENT_FIREBLOCKS_REQUESTS) { - const batch = Object.keys(vaultToNetworkMap).slice(i, i + CONCURRENT_FIREBLOCKS_REQUESTS) - const batchPromises = batch.map((vaultId) => - this.fireblocksClient.getVaultAccount({ - apiKey: connection.credentials.apiKey, - signKey: connection.credentials.privateKey, - url: connection.url, - vaultAccountId: vaultId - }) - ) - - const batchResults = await Promise.allSettled(batchPromises) + if (!network) { + this.logger.error('Network not found', { + rawAccount, + externalNetwork: networkId + }) + return this.resolveFailure({ + rawAccount, + message: 'Network for this account is not supported', + code: RawAccountError.UNLISTED_NETWORK, + networkId + }) + } - const validVaults = batchResults - .map((result, index) => { - if (result.status === 'fulfilled') { - return result.value - } else { - const error = result.reason - const vaultId = batch[index] + const existingAccount = existingAccounts.find((a) => a.externalId === rawAccount.externalId) + const existingWallet = existingWallets.find((a) => a.externalId === vaultId) - if (error?.response?.body?.code === FIREBLOCKS_API_ERROR_CODES.INVALID_SPECIFIED_VAULT_ACCOUNT) { - this.logger.warn('Vault not found', { - vaultId, - provider: Provider.FIREBLOCKS - }) - return null - } else { - throw error - } - } - }) - .filter((vault): vault is VaultAccount => vault !== null) + const accountLabel = `${vaultAccount.name} - ${networkId}` + const accountId = existingAccount?.accountId || randomUUID() + const walletId = existingWallet?.walletId || existingAccount?.walletId || randomUUID() + const fireblocksAddresses = await this.fireblocksClient.getAddresses({ + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey, + url: connection.url, + vaultAccountId: vaultId, + assetId: networkId + }) - vaults.push(...validVaults) + const wallet: Wallet = { + accounts: [], + clientId: connection.clientId, + connectionId: connection.connectionId, + createdAt: now, + externalId: vaultId, + label: vaultAccount.name, + provider: Provider.FIREBLOCKS, + updatedAt: now, + walletId } - // Filter to only get the vaults we need based on vaultToNetworkMap - const relevantVaults = vaults.filter((vault) => vault.id in vaultToNetworkMap) - const vaultMap = Object.fromEntries(relevantVaults.map((vault) => [vault.id, vault])) + const account: Account = { + externalId: rawAccount.externalId, + accountId, + addresses: [], + clientId: connection.clientId, + createdAt: now, + connectionId: connection.connectionId, + label: accountLabel, + networkId: network.networkId, + provider: Provider.FIREBLOCKS, + updatedAt: now, + walletId + } - // Log each missing vault - const foundVaultIds = relevantVaults.map((vault) => vault.id) - requestedVaultIds.forEach((vaultId) => { - if (!foundVaultIds.includes(vaultId)) { - this.logger.warn('Vault not found', { + const addresses: Address[] = fireblocksAddresses + .map((a) => { + const addressExternalId = buildFireblocksAssetAddressExternalId({ vaultId, - networks: vaultToNetworkMap[vaultId] + networkId, + address: a.address }) - } - }) - - const walletOperations: ScopedSyncOperation[] = [] - const accountOperations: ScopedSyncOperation[] = [] - const addressOperations: ScopedSyncOperation[] = [] - - for (const [vaultId, networkIds] of Object.entries(vaultToNetworkMap)) { - const vault = vaultMap[vaultId] - if (!vault) { - this.logger.warn('raw account was not found', { vaultId }) - continue - } - const existingWallet = existingWalletMap.get(vaultId) - const walletId = existingWallet?.walletId || randomUUID() - - if (existingWallet) { - if (existingWallet.label !== vault.name) { - walletOperations.push({ - type: ScopedSyncOperationType.UPDATE, - update: { - clientId: connection.clientId, - walletId, - label: vault.name, - updatedAt: now - } - }) - } - } else { - walletOperations.push({ - type: ScopedSyncOperationType.CREATE, - create: { - accounts: [], + const existingAddress = existingAddresses.find((a) => a.externalId === addressExternalId) + if (!existingAddress) { + return { + accountId, + address: a.address, + addressId: randomUUID(), clientId: connection.clientId, - connectionId: connection.connectionId, createdAt: now, - externalId: vaultId, - label: vault.name, + connectionId: connection.connectionId, + externalId: addressExternalId, provider: Provider.FIREBLOCKS, - updatedAt: now, - walletId + updatedAt: now } + } + return null + }) + .filter((a) => a !== null) as Address[] + + return this.resolveSuccess({ + rawAccount, + wallet, + account, + addresses + }) + } + + private async fetchVaultAccount({ + connection, + rawAccount + }: { + connection: ConnectionWithCredentials + rawAccount: RawAccount + }): Promise<{ vaultAccount: VaultAccount; rawAccount: RawAccount } | RawAccountSyncFailed> { + validateConnection(connection) + const { vaultId } = parseFireblocksAssetWalletExternalId(rawAccount.externalId) + try { + const vaultAccount = await this.fireblocksClient.getVaultAccount({ + apiKey: connection.credentials.apiKey, + signKey: connection.credentials.privateKey, + url: connection.url, + vaultAccountId: vaultId + }) + + return { vaultAccount, rawAccount } + } catch (error) { + if (error?.response?.body?.code === FIREBLOCKS_API_ERROR_CODES.INVALID_SPECIFIED_VAULT_ACCOUNT) { + return this.resolveFailure({ + rawAccount, + message: 'Fireblocks Vault Account not found', + code: RawAccountError.EXTERNAL_RESOURCE_NOT_FOUND, + externalResourceType: 'vaultAccount', + externalResourceId: vaultId }) } + throw error + } + } - // Create accounts for each network - for (const { fireblocksNetworkId, narvalNetworkId } of networkIds) { - const accountExternalId = getFireblocksAssetWalletExternalId({ - vaultId: vault.id, - networkId: fireblocksNetworkId - }) + async scopeSync({ + connection, + rawAccounts, + networks, + existingAccounts + }: ScopedSyncContext): Promise { + validateConnection(connection) - const existingAccount = existingAccountMap.get(accountExternalId) - const accountId = existingAccount?.accountId || randomUUID() - const accountLabel = `${vault.name} - ${fireblocksNetworkId}` + const now = new Date() - try { - if (existingAccount) { - if (existingAccount.label !== accountLabel) { - accountOperations.push({ - type: ScopedSyncOperationType.UPDATE, - update: { - clientId: connection.clientId, - accountId: existingAccount.accountId, - label: accountLabel, - updatedAt: now - } - }) - } - } else { - accountOperations.push({ - type: ScopedSyncOperationType.CREATE, - create: { - externalId: accountExternalId, - accountId, - addresses: [], - clientId: connection.clientId, - createdAt: now, - connectionId: connection.connectionId, - label: accountLabel, - networkId: narvalNetworkId, - provider: Provider.FIREBLOCKS, - updatedAt: now, - walletId - } - }) - } + const chunkedRawAccounts = chunk(CONCURRENT_FIREBLOCKS_REQUESTS, rawAccounts) + const fetchResults = [] - // Fetch and process addresses - try { - const addresses = await this.fireblocksClient.getAddresses({ - apiKey: connection.credentials.apiKey, - signKey: connection.credentials.privateKey, - url: connection.url, - vaultAccountId: vault.id, - assetId: fireblocksNetworkId - }) - addresses.forEach((address) => { - const addressExternalId = getFireblocksAssetAddressExternalId({ - vaultId: vault.id, - networkId: fireblocksNetworkId, - address: address.address - }) - if (!existingAccount?.addresses?.some((a) => a.externalId === addressExternalId)) { - addressOperations.push({ - type: ScopedSyncOperationType.CREATE, - create: { - accountId, - address: address.address, - addressId: randomUUID(), - clientId: connection.clientId, - createdAt: now, - connectionId: connection.connectionId, - externalId: addressExternalId, - provider: Provider.FIREBLOCKS, - updatedAt: now - } - }) - } - }) - } catch (error) { - addressOperations.push({ - type: ScopedSyncOperationType.FAILED, - externalId: accountExternalId, - message: 'Failed to fetch addresses', - context: { error: error.message } - }) - } - } catch (error) { - accountOperations.push({ - type: ScopedSyncOperationType.FAILED, - externalId: accountExternalId, - message: 'Failed to process account', - context: { error: error.message } - }) + for (const currentChunk of chunkedRawAccounts) { + const chunkResults = await Promise.all( + currentChunk.map((rawAccount) => this.fetchVaultAccount({ connection, rawAccount })) + ) + fetchResults.push(...chunkResults) + } + + const wallets: Wallet[] = [] + const accounts: Account[] = [] + const addresses: Address[] = [] + const failures: RawAccountSyncFailure[] = [] + + for (const result of fetchResults) { + if ('success' in result && !result.success) { + failures.push(result.failure) + continue + } else if ('rawAccount' in result) { + const mappedResult = await this.resolveRawAccount({ + connection, + rawAccount: result.rawAccount, + networks, + now, + existingAccounts: [...existingAccounts, ...accounts], + existingWallets: wallets, + existingAddresses: addresses, + vaultAccount: result.vaultAccount + }) + if (mappedResult.success) { + wallets.push(mappedResult.wallet) + accounts.push(mappedResult.account) + addresses.push(...mappedResult.addresses) + } else { + failures.push(mappedResult.failure) } } } return { - wallets: walletOperations, - accounts: accountOperations, - addresses: addressOperations + wallets: uniqBy('externalId', wallets), + accounts: uniqBy('externalId', accounts), + addresses: uniqBy('externalId', addresses), + failures } } } diff --git a/apps/vault/src/broker/core/provider/fireblocks/fireblocks.util.ts b/apps/vault/src/broker/core/provider/fireblocks/fireblocks.util.ts index f6267108e..34948cea5 100644 --- a/apps/vault/src/broker/core/provider/fireblocks/fireblocks.util.ts +++ b/apps/vault/src/broker/core/provider/fireblocks/fireblocks.util.ts @@ -57,18 +57,18 @@ export function validateConnection( } export type FireblocksAccountExternalId = `${string}-${string}` -export function getFireblocksAssetWalletExternalId({ +export function buildFireblocksAssetWalletExternalId({ vaultId, networkId }: { vaultId: string networkId: string }): string { - return `${vaultId.toString()}-${networkId}` + return `${vaultId.toString()}-${networkId}`.toUpperCase() } -export type FireblocksAssetWalletId = { vaultId: string; networkId: string } -export function toFireblocksAssetWalletExternalId(externalId: string): FireblocksAssetWalletId { +export type FireblocksAssetWalletId = { vaultId: string; baseAssetId: string } +export function parseFireblocksAssetWalletExternalId(externalId: string): FireblocksAssetWalletId { const matches = externalId.match(/^([^-]+)-([^-]+)$/) if (!matches) { throw new BrokerException({ @@ -81,12 +81,12 @@ export function toFireblocksAssetWalletExternalId(externalId: string): Fireblock const [, vaultId, networkId] = matches return { vaultId, - networkId + baseAssetId: networkId } } export type FireblocksAddressExternalId = `${string}-${string}-${string}` -export function getFireblocksAssetAddressExternalId({ +export function buildFireblocksAssetAddressExternalId({ vaultId, networkId, address @@ -95,11 +95,11 @@ export function getFireblocksAssetAddressExternalId({ networkId: string address: string }): string { - return `${vaultId}-${networkId}-${address}` + return `${vaultId}-${networkId}-${address}`.toUpperCase() } export type FireblocksAssetAddressId = { vaultId: string; networkId: string; address: string } -export function toFireblocksAssetAddressExternalId(externalId: string): FireblocksAssetAddressId { +export function parseFireblocksAssetAddressExternalId(externalId: string): FireblocksAssetAddressId { const matches = externalId.match(/^([^-]+)-([^-]+)-([^-]+)$/) if (!matches) { throw new BrokerException({ diff --git a/apps/vault/src/broker/core/service/account.service.ts b/apps/vault/src/broker/core/service/account.service.ts index 27837aa06..534bfbf87 100644 --- a/apps/vault/src/broker/core/service/account.service.ts +++ b/apps/vault/src/broker/core/service/account.service.ts @@ -20,6 +20,10 @@ export class AccountService { return this.accountRepository.bulkCreate(accounts) } + async bulkUpsert(accounts: Account[]): Promise { + return this.accountRepository.bulkUpsert(accounts) + } + async bulkUpdate(updateAccounts: UpdateAccount[]): Promise { return this.accountRepository.bulkUpdate(updateAccounts) } diff --git a/apps/vault/src/broker/core/service/network.service.ts b/apps/vault/src/broker/core/service/network.service.ts index 6cfd0bc12..aafc362e8 100644 --- a/apps/vault/src/broker/core/service/network.service.ts +++ b/apps/vault/src/broker/core/service/network.service.ts @@ -3,7 +3,7 @@ import { CACHE_MANAGER, Cache } from '@nestjs/cache-manager' import { Inject, Injectable } from '@nestjs/common' import { uniq } from 'lodash' import { FindAllOptions, NetworkRepository } from '../../persistence/repository/network.repository' -import { ExternalNetwork, Network } from '../type/network.type' +import { ExternalNetwork, Network, NetworkMap } from '../type/network.type' import { Provider } from '../type/provider.type' @Injectable() @@ -114,7 +114,7 @@ export class NetworkService { * traversals on subsequent queries. All lookups become O(1) after indexing * at the cost of O(n) additional memory. */ - async buildProviderExternalIdIndex(provider: Provider): Promise> { + async buildProviderExternalIdIndex(provider: Provider): Promise { const networks = await this.findAll({ filters: { provider } }) const index = new Map() diff --git a/apps/vault/src/broker/core/service/raw-account.service.ts b/apps/vault/src/broker/core/service/raw-account.service.ts index 2faa402ce..9bdec023c 100644 --- a/apps/vault/src/broker/core/service/raw-account.service.ts +++ b/apps/vault/src/broker/core/service/raw-account.service.ts @@ -5,14 +5,17 @@ import { AnchorageClient } from '../../http/client/anchorage.client' import { FireblocksClient } from '../../http/client/fireblocks.client' import { AccountRepository } from '../../persistence/repository/account.repository' import { AssetRepository } from '../../persistence/repository/asset.repository' -import { NetworkRepository } from '../../persistence/repository/network.repository' import { BrokerException } from '../exception/broker.exception' import { validateConnection as validateAnchorageConnection } from '../provider/anchorage/anchorage.util' -import { validateConnection as validateFireblocksConnection } from '../provider/fireblocks/fireblocks.util' +import { + buildFireblocksAssetWalletExternalId, + validateConnection as validateFireblocksConnection +} from '../provider/fireblocks/fireblocks.util' import { Asset } from '../type/asset.type' import { Network } from '../type/network.type' import { Provider } from '../type/provider.type' import { ConnectionService } from './connection.service' +import { NetworkService } from './network.service' export const RawAccount = z.object({ provider: z.nativeEnum(Provider), @@ -49,7 +52,7 @@ export class RawAccountService { constructor( private readonly accountRepository: AccountRepository, private readonly connectionService: ConnectionService, - private readonly networkRepository: NetworkRepository, + private readonly networkService: NetworkService, private readonly assetRepository: AssetRepository, private readonly anchorageClient: AnchorageClient, private readonly fireblocksClient: FireblocksClient, @@ -67,7 +70,7 @@ export class RawAccountService { ? await this.assetRepository.findById(options.filters.assetId) : undefined const networkFilter = options?.filters?.networkId - ? await this.networkRepository.findById(options.filters.networkId) + ? await this.networkService.findById(options.filters.networkId) : undefined if (connection.provider === Provider.ANCHORAGE) { @@ -87,7 +90,7 @@ export class RawAccountService { label: wallet.walletName, subLabel: wallet.vaultName, defaultAddress: wallet.depositAddress.address, - network: await this.networkRepository.findByExternalId(Provider.ANCHORAGE, wallet.networkId), + network: await this.networkService.findByExternalId(Provider.ANCHORAGE, wallet.networkId), assets: await Promise.all( wallet.assets.map(async (a) => ({ asset: await this.assetRepository.findByExternalId(Provider.ANCHORAGE, a.assetType), @@ -154,9 +157,11 @@ export class RawAccountService { } }) // In Fireblocks, a VaultAccount is not network-specific, so we'll map the AssetWallets to get what we call "Accounts" + // Map accounts to our format const rawAccounts = await Promise.all( response.accounts.map(async (account) => { - const assets = await Promise.all( + // 1. First map and filter assets + const mappedAssets = await Promise.all( account.assets .filter((a) => !a.hiddenOnUI) .map(async (asset) => ({ @@ -165,43 +170,62 @@ export class RawAccountService { asset: await this.assetRepository.findByExternalId(Provider.FIREBLOCKS, asset.id) })) ) - // Group assets by network - const assetsByNetwork = assets.reduce( + + // 2. Group assets by network + const assetsByNetwork = mappedAssets.reduce( (acc, asset) => { - if (!asset.asset?.networkId) return acc // Skip assets without a networkId - if (!acc[asset.asset.networkId]) { - acc[asset.asset.networkId] = [] + if (!asset.asset?.networkId) return acc + return { + ...acc, + [asset.asset.networkId]: [...(acc[asset.asset.networkId] || []), asset] } - acc[asset.asset.networkId].push(asset) - return acc }, - {} as Record + {} as Record ) - // Create an account for each network that has assets - return await Promise.all( - Object.entries(assetsByNetwork).map(async ([networkId, networkAssets]) => { - const network = await this.networkRepository.findById(networkId) - return { - provider: Provider.FIREBLOCKS, - externalId: `${account.id}-${networkId}`, - label: account.name || account.id, - subLabel: networkId, - defaultAddress: '', // Fireblocks doesn't provide a default address at account level - network, - assets: networkAssets - .map((a) => - a.asset - ? { - asset: a.asset, - balance: a.balance - } - : undefined - ) - .filter((a) => !!a) - } - }) - ) + // 3. Validate networks and get their Fireblocks IDs + const validNetworks = ( + await Promise.all( + Object.entries(assetsByNetwork).map(async ([networkId, assets]) => { + const network = await this.networkService.findById(networkId) + const fireblocksNetworkId = network?.externalNetworks.find( + (n) => n.provider === Provider.FIREBLOCKS + )?.externalId + + if (!network || !fireblocksNetworkId) return null + + return { + network, + fireblocksNetworkId, + assets + } + }) + ) + ).filter((item): item is NonNullable => item !== null) + + return validNetworks.map(({ network, fireblocksNetworkId, assets }) => { + return { + provider: Provider.FIREBLOCKS, + externalId: buildFireblocksAssetWalletExternalId({ + vaultId: account.id, + networkId: fireblocksNetworkId + }), + label: account.name || account.id, + subLabel: network?.networkId, + defaultAddress: '', // Fireblocks doesn't provide a default address at account level + network: Network.parse(network), + assets: assets + .map((a) => + a.asset + ? { + asset: a.asset, + balance: a.balance + } + : undefined + ) + .filter((a) => !!a) + } + }) }) ).then((a) => a.flat()) diff --git a/apps/vault/src/broker/core/service/scoped-sync.service.ts b/apps/vault/src/broker/core/service/scoped-sync.service.ts index f0c746afd..6969b2ca8 100644 --- a/apps/vault/src/broker/core/service/scoped-sync.service.ts +++ b/apps/vault/src/broker/core/service/scoped-sync.service.ts @@ -1,5 +1,5 @@ import { LoggerService, PaginatedResult, TraceService } from '@narval/nestjs-shared' -import { NotImplementedException } from '@nestjs/common' +import { HttpStatus, NotImplementedException } from '@nestjs/common' import { Inject, Injectable } from '@nestjs/common/decorators' import { EventEmitter2 } from '@nestjs/event-emitter' import { SpanStatusCode } from '@opentelemetry/api' @@ -8,21 +8,24 @@ import { v4 as uuid } from 'uuid' import { FindAllOptions, ScopedSyncRepository } from '../../persistence/repository/scoped-sync.repository' import { OTEL_ATTR_CONNECTION_ID, OTEL_ATTR_CONNECTION_PROVIDER, OTEL_ATTR_SYNC_ID } from '../../shared/constant' import { ScopedSyncStartedEvent } from '../../shared/event/scoped-sync-started.event' +import { ScopedSyncException } from '../exception/scoped-sync.exception' import { AnchorageScopedSyncService } from '../provider/anchorage/anchorage-scoped-sync.service' import { FireblocksScopedSyncService } from '../provider/fireblocks/fireblocks-scoped-sync.service' import { ConnectionWithCredentials } from '../type/connection.type' +import { Provider, ProviderScopedSyncService } from '../type/provider.type' +import { ConnectionScope } from '../type/scope.type' import { - Provider, - ProviderScopedSyncService, + RawAccount, + RawAccountSyncFailure, + ScopedSync, ScopedSyncResult, - isCreateOperation, - isFailedOperation, - isUpdateOperation -} from '../type/provider.type' -import { ConnectionScope } from '../type/scope.type' -import { RawAccount, ScopedSync, ScopedSyncStarted, ScopedSyncStatus, StartScopedSync } from '../type/scoped-sync.type' + ScopedSyncStarted, + ScopedSyncStatus, + StartScopedSync +} from '../type/scoped-sync.type' import { AccountService } from './account.service' import { AddressService } from './address.service' +import { NetworkService } from './network.service' import { WalletService } from './wallet.service' @Injectable() @@ -34,23 +37,45 @@ export class ScopedSyncService { private readonly walletService: WalletService, private readonly accountService: AccountService, private readonly addressService: AddressService, + private readonly networkService: NetworkService, private readonly eventEmitter: EventEmitter2, private readonly logger: LoggerService, @Inject(TraceService) private readonly traceService: TraceService ) {} async start(connections: ConnectionWithCredentials[], rawAccounts: RawAccount[]): Promise { - this.logger.log('Start connections scoped sync', { + this.logger.log('Start connections scopedSync', { connectionsCount: connections.length, - connectionIds: connections.map((connectionId) => connectionId), - rawAccounts: rawAccounts.map(({ provider, externalId }) => ({ provider, externalId })) + connectionIds: connections.map((connectionId) => connectionId) }) - if (connections.length) { + const notSyncingConnections: ConnectionWithCredentials[] = [] + + for (const connection of connections) { + const inProgress = await this.scopedSyncRepository.exists({ + connectionId: connection.connectionId, + clientId: connection.clientId, + status: ScopedSyncStatus.PROCESSING + }) + + if (inProgress) { + throw new ScopedSyncException({ + message: 'There is already a Scoped Sync in progress for requested connections', + suggestedHttpStatusCode: HttpStatus.CONFLICT, + context: { + conflictingConnectionId: connection.connectionId + } + }) + } + + notSyncingConnections.push(connection) + } + + if (notSyncingConnections.length) { const now = new Date() const scopedSyncs = await this.scopedSyncRepository.bulkCreate( - connections.map(({ connectionId, clientId }) => + notSyncingConnections.map(({ connectionId, clientId }) => this.toProcessingScopedSync({ clientId, connectionId, @@ -61,7 +86,7 @@ export class ScopedSyncService { ) ) - for (const [scopedSync, connection] of zip(scopedSyncs, connections)) { + for (const [scopedSync, connection] of zip(scopedSyncs, notSyncingConnections)) { if (scopedSync && connection) { // NOTE: Emits an event that will delegate the scopedSync process to // another worker, allowing to unblock the request. The event handler @@ -73,7 +98,7 @@ export class ScopedSyncService { return { started: true, scopedSyncs } } - this.logger.log('Skip scoped sync because active connections list is empty') + this.logger.log('Skip scopedSync because active connections list is empty') return { started: false, scopedSyncs: [] } } @@ -88,7 +113,7 @@ export class ScopedSyncService { provider } - this.logger.log('Scoped sync connection', context) + this.logger.log('Scoped Sync connection', context) const span = this.traceService.startSpan(`${ScopedSyncService.name}.scopedSync`, { attributes: { @@ -100,31 +125,38 @@ export class ScopedSyncService { let result: ScopedSyncResult | null = null - // Ensure the scopedSync status is updated on failures. The `execute` method is - // not wrapped in the try/catch block because it already handles errors - // internally. try { - result = await this.getProviderScopedSyncService(connection.provider).scopedSync( - connection, - scopedSync.rawAccounts + const networks = await this.networkService.buildProviderExternalIdIndex(provider) + const { data: existingAccounts } = await this.accountService.findAll( + { clientId, connectionId }, + { + pagination: { disabled: true } + } ) + + result = await this.getProviderScopedSyncService(connection.provider).scopeSync({ + rawAccounts: scopedSync.rawAccounts, + connection, + networks, + existingAccounts + }) } catch (error) { - this.logger.error('Scoped sync connection failed', { ...context, error }) + this.logger.error('ScopedSync connection failed', { ...context, error }) span.recordException(error) span.setStatus({ code: SpanStatusCode.ERROR }) - return await this.fail(scopedSync, error) + return await this.fail(scopedSync, error, result?.failures || []) } finally { // The execute method has its own span. span.end() } - if (result) { - return await this.execute(scopedSync, result) + if (result.failures.length && !result.accounts.length) { + this.logger.error('ScopedSync connection failed', { ...context, result }) } - return scopedSync + return await this.execute(scopedSync, result) } private toProcessingScopedSync( @@ -150,103 +182,96 @@ export class ScopedSyncService { } // TODO: pessimist lock if there's already a scopedSync in process for the given - // connection. async execute(scopedSync: ScopedSync, result: ScopedSyncResult): Promise { - // IMPORTANT: Thoroughly test the execution in the integration test - // `scopedSync.service.spec.ts`. - - const { clientId, scopedSyncId } = scopedSync + const { scopedSyncId } = scopedSync const span = this.traceService.startSpan(`${ScopedSyncService.name}.execute`, { attributes: { [OTEL_ATTR_SYNC_ID]: scopedSyncId } }) - const walletCreateOperations = result.wallets.filter(isCreateOperation).map(({ create }) => create) - const walletUpdateOperations = result.wallets.filter(isUpdateOperation).map(({ update }) => update) - const walletFailedOperations = result.wallets.filter(isFailedOperation) + const { wallets, accounts, addresses, failures } = result - const accountCreateOperations = result.accounts.filter(isCreateOperation).map(({ create }) => create) - const accountUpdateOperations = result.accounts.filter(isUpdateOperation).map(({ update }) => update) - const accountFailedOperations = result.accounts.filter(isFailedOperation) + this.logger.log('Raw Account synchronization failures', { + scopedSyncId, + failuresCount: failures?.length, + failures + }) - const addressCreateOperations = result.addresses.filter(isCreateOperation).map(({ create }) => create) - const addressFailedOperations = result.addresses.filter(isFailedOperation) + this.logger.log('Raw Account synchronization successes', { + wallets: wallets.length, + accounts: accounts.length, + addresses: addresses.length + }) - this.logger.log('Execute scoped sync operations', { - clientId, - scopedSyncId, - operations: { - wallet: { - create: walletCreateOperations.length, - update: walletUpdateOperations.length, - failed: walletFailedOperations.length - }, - account: { - create: accountCreateOperations.length, - update: accountUpdateOperations.length, - failed: accountFailedOperations.length - }, - address: { - create: addressCreateOperations.length, - failed: addressFailedOperations.length - } + try { + await this.walletService.bulkUpsert(wallets) + await this.accountService.bulkUpsert(accounts) + await this.addressService.bulkCreate(addresses) + + const totalItems = result.wallets.length + result.accounts.length + result.addresses.length + if (totalItems === 0) { + throw new ScopedSyncException({ + message: 'No raw account was successfully mapped', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, + context: { failures: result.failures } + }) } - }) - if (walletFailedOperations.length) { - this.logger.error('Scoped sync operations contains failures for wallets', { - operations: walletFailedOperations - }) + return await this.complete(scopedSync, result) + } catch (error) { + return await this.fail(scopedSync, error, result.failures) + } finally { + span.end() } + } - if (accountFailedOperations.length) { - this.logger.error('Scoped sync operations contains failures for accounts', { - operations: accountFailedOperations - }) - } + async complete(scopedSync: ScopedSync, result: ScopedSyncResult): Promise { + const { clientId, scopedSyncId } = scopedSync - if (addressFailedOperations.length) { - this.logger.error('Scoped sync operations contains failures for addresses', { - operations: addressFailedOperations - }) - } + const totalItems = result.wallets.length + result.accounts.length + result.addresses.length + const hasSuccesses = totalItems > 0 + const hasFailures = result.failures.length > 0 - try { - this.logger.log('Execute wallet create operations', { scopedSyncId, clientId }) - await this.walletService.bulkCreate(walletCreateOperations) - this.logger.log('Execute wallet update operations', { scopedSyncId, clientId }) - await this.walletService.bulkUpdate(walletUpdateOperations) + const status = hasSuccesses && hasFailures ? ScopedSyncStatus.PARTIAL_SUCCESS : ScopedSyncStatus.SUCCESS - this.logger.log('Execute account create operations', { scopedSyncId, clientId }) - await this.accountService.bulkCreate(accountCreateOperations) - this.logger.log('Execute account update operations', { scopedSyncId, clientId }) - await this.accountService.bulkUpdate(accountUpdateOperations) + if (status === ScopedSyncStatus.PARTIAL_SUCCESS) { + return await this.partialSuccess(scopedSync, result.failures) + } - // TODO: address update - this.logger.log('Execute address create operations', { scopedSyncId, clientId }) - await this.addressService.bulkCreate(addressCreateOperations) + this.logger.log('Scoped Sync completed successfuly', { clientId, scopedSyncId }) - return await this.complete(scopedSync) - } catch (error) { - return await this.fail(scopedSync, error) - } finally { - span.end() + const span = this.traceService.startSpan(`${ScopedSyncService.name}.complete`, { + attributes: { [OTEL_ATTR_SYNC_ID]: scopedSyncId } + }) + + const completedScopedSync = { + ...scopedSync, + status, + completedAt: scopedSync.completedAt || new Date(), + failures: [] } + + await this.scopedSyncRepository.update(completedScopedSync) + + span.end() + + return completedScopedSync } - async complete(scopedSync: ScopedSync): Promise { + async partialSuccess(scopedSync: ScopedSync, failures: RawAccountSyncFailure[]): Promise { const { clientId, scopedSyncId } = scopedSync - this.logger.log('Scoped sync complete', { clientId, scopedSyncId }) + this.logger.log('Scoped Sync partially successful', { clientId, scopedSyncId }) - const span = this.traceService.startSpan(`${ScopedSyncService.name}.complete`, { + const span = this.traceService.startSpan(`${ScopedSyncService.name}.partial_success`, { attributes: { [OTEL_ATTR_SYNC_ID]: scopedSyncId } }) const completedScopedSync = { ...scopedSync, - status: ScopedSyncStatus.SUCCESS, - completedAt: scopedSync.completedAt || new Date() + status: ScopedSyncStatus.PARTIAL_SUCCESS, + completedAt: scopedSync.completedAt || new Date(), + failures } await this.scopedSyncRepository.update(completedScopedSync) @@ -256,10 +281,10 @@ export class ScopedSyncService { return completedScopedSync } - async fail(scopedSync: ScopedSync, error: Error): Promise { + async fail(scopedSync: ScopedSync, error: Error, failures: RawAccountSyncFailure[]): Promise { const { clientId, scopedSyncId } = scopedSync - this.logger.log('Scoped sync fail', { clientId, scopedSyncId, error }) + this.logger.log('Scoped Sync fail', { clientId, scopedSyncId, error }) const span = this.traceService.startSpan(`${ScopedSyncService.name}.fail`, { attributes: { [OTEL_ATTR_SYNC_ID]: scopedSyncId } @@ -276,7 +301,8 @@ export class ScopedSyncService { message: error.message, traceId: this.traceService.getActiveSpan()?.spanContext().traceId }, - completedAt: scopedSync.completedAt || new Date() + completedAt: scopedSync.completedAt || new Date(), + failures } await this.scopedSyncRepository.update(failedScopedSync) @@ -293,7 +319,7 @@ export class ScopedSyncService { case Provider.FIREBLOCKS: return this.fireblocksScopedSyncService default: - throw new NotImplementedException(`Unsupported scoped sync for provider ${provider}`) + throw new NotImplementedException(`Unsupported Scoped Sync for provider ${provider}`) } } } diff --git a/apps/vault/src/broker/core/service/wallet.service.ts b/apps/vault/src/broker/core/service/wallet.service.ts index 75df878e5..35138c46e 100644 --- a/apps/vault/src/broker/core/service/wallet.service.ts +++ b/apps/vault/src/broker/core/service/wallet.service.ts @@ -12,6 +12,10 @@ export class WalletService { return this.walletRepository.bulkCreate(wallets) } + async bulkUpsert(wallets: Wallet[]): Promise { + return this.walletRepository.bulkUpsert(wallets) + } + async bulkUpdate(wallets: UpdateWallet[]): Promise { return Promise.all(wallets.map((wallet) => this.update(wallet))) } diff --git a/apps/vault/src/broker/core/type/network.type.ts b/apps/vault/src/broker/core/type/network.type.ts index d0eed7e4f..a6e5f03f1 100644 --- a/apps/vault/src/broker/core/type/network.type.ts +++ b/apps/vault/src/broker/core/type/network.type.ts @@ -12,6 +12,9 @@ export const Network = z.object({ coinType: z.number().nullable(), name: z.string(), externalNetworks: z.array(ExternalNetwork).default([]), - createdAt: z.date().optional() + createdAt: z.coerce.date().optional() }) export type Network = z.infer + +export const NetworkMap = z.map(z.string(), Network) +export type NetworkMap = z.infer diff --git a/apps/vault/src/broker/core/type/provider.type.ts b/apps/vault/src/broker/core/type/provider.type.ts index 97fd837a4..e374fc00e 100644 --- a/apps/vault/src/broker/core/type/provider.type.ts +++ b/apps/vault/src/broker/core/type/provider.type.ts @@ -2,11 +2,9 @@ import { PaginatedResult } from '@narval/nestjs-shared' import { HttpStatus } from '@nestjs/common' -import { UpdateAccount } from '../../persistence/repository/account.repository' import { ConnectionWithCredentials } from './connection.type' -import { Account, Address, UpdateWallet, Wallet } from './indexed-resources.type' import { KnownDestination as KnownDestinationNext } from './known-destination.type' -import { RawAccount } from './scoped-sync.type' +import { ScopedSyncContext, ScopedSyncResult } from './scoped-sync.type' import { InternalTransfer, SendTransfer, Transfer } from './transfer.type' export const Provider = { @@ -20,216 +18,8 @@ export type Provider = (typeof Provider)[keyof typeof Provider] // Sync // -export const SyncOperationType = { - CREATE: 'create', - UPDATE: 'update', - DELETE: 'delete', - FAILED: 'failed', - SKIP: 'skip' -} as const -export type SyncOperationType = (typeof SyncOperationType)[keyof typeof SyncOperationType] - -export const ScopedSyncOperationType = { - CREATE: 'create', - UPDATE: 'update', - FAILED: 'failed' -} as const -export type ScopedSyncOperationType = (typeof ScopedSyncOperationType)[keyof typeof ScopedSyncOperationType] - -export type CreateScopedSyncOperation = { - type: typeof SyncOperationType.CREATE - create: CreateParams -} -export type UpdateScopedSyncOperation = { - type: typeof ScopedSyncOperationType.UPDATE - update: UpdateParams -} - -export type FailedScopedSyncOperation = { - type: typeof ScopedSyncOperationType.FAILED - externalId: string - message: string - context?: unknown -} - -export type CreateSyncOperation = { - type: typeof SyncOperationType.CREATE - create: CreateParams -} - -export type UpdateSyncOperation = { - type: typeof SyncOperationType.UPDATE - update: UpdateParams -} - -export type DeleteSyncOperation = { - type: typeof SyncOperationType.DELETE - entityId: string -} - -export type FailedSyncOperation = { - type: typeof SyncOperationType.FAILED - externalId: string - message: string - context?: unknown -} - -export type SkipSyncOperation = { - type: typeof SyncOperationType.SKIP - externalId: string - message: string - context?: unknown -} - -/** - * Represents a synchronization operation for a resource, which can be a - * creation, update, or deletion. Each operation type is associated with - * specific parameters. - * - * @template CreateParams - The parameters required for creating an entity. - * @template UpdateParams - The parameters required for updating an entity. - */ -export type SyncOperation = - | CreateSyncOperation - | UpdateSyncOperation - | DeleteSyncOperation - | FailedSyncOperation - | SkipSyncOperation - -export type ScopedSyncOperation = - | CreateScopedSyncOperation - | UpdateScopedSyncOperation - | FailedSyncOperation - -export const isCreateOperation = ( - operation: SyncOperation -): operation is CreateSyncOperation => { - return operation.type === SyncOperationType.CREATE -} - -export const isUpdateOperation = ( - operation: SyncOperation -): operation is UpdateSyncOperation => { - return operation.type === SyncOperationType.UPDATE -} - -export const isDeleteOperation = ( - operation: SyncOperation -): operation is DeleteSyncOperation => { - return operation.type === SyncOperationType.DELETE -} - -export const isFailedOperation = ( - operation: SyncOperation -): operation is FailedSyncOperation => { - return operation.type === SyncOperationType.FAILED -} - -export const isSkipOperation = ( - operation: SyncOperation -): operation is SkipSyncOperation => { - return operation.type === SyncOperationType.SKIP -} - -/** - * Represents the context used during synchronization, containing the active - * connection and maps of synchronization operations for various resource - * types. - */ -export type SyncContext = { - /** - * The active connection with credentials used for synchronization. - */ - connection: ConnectionWithCredentials - - /** - * A map of wallet synchronization operations, keyed by wallet external ID. - */ - wallets: SyncOperation[] - - /** - * A map of account synchronization operations, keyed by account external ID. - */ - accounts: SyncOperation[] - - /** - * A map of address synchronization operations, keyed by address external ID. - */ - addresses: SyncOperation[] - - /** - * An optional timestamp used for setting the `createdAt` and `updatedAt` - * fields during synchronization operations. - */ - now?: Date -} - -export type SyncResult = { - wallets: SyncOperation[] - accounts: SyncOperation[] - addresses: SyncOperation[] -} - -export type ScopedSyncResult = { - wallets: ScopedSyncOperation[] - accounts: ScopedSyncOperation[] - addresses: ScopedSyncOperation[] -} - export interface ProviderScopedSyncService { - scopedSync(connection: ConnectionWithCredentials, rawAccounts: RawAccount[]): Promise -} - -export interface ProviderSyncService { - /** - * The main entry point for synchronization, responsible for coordinating the - * synchronization process across different resources. It orchestrates the - * sync calls and passes the context between them. - * - * IMPORTANT: The synchronization **does not perform the writes** into the - * database. - * - * @param connection - The active connection with credentials required for - * synchronization. - * - * @returns A promise that resolves to an object containing the results of - * the sync operations for wallets, accounts, addresses, and known - * destinations. - */ - sync(connection: ConnectionWithCredentials): Promise - - /** - * Synchronizes wallet data within the provided context and returns an - * updated context. - * - * @param context - The current synchronization context containing existing - * data and operations. - * - * @returns A promise that resolves to the updated synchronization context. - */ - syncWallets(context: SyncContext): Promise - - /** - * Synchronizes account data within the provided context and returns an - * updated context. - * - * @param context - The current synchronization context containing existing - * data and operations. - * - * @returns A promise that resolves to the updated synchronization context. - */ - syncAccounts(context: SyncContext): Promise - - /** - * Synchronizes address data within the provided context and returns an - * updated context. - * - * @param context - The current synchronization context containing existing - * data and operations. - * - * @returns A promise that resolves to the updated synchronization context. - */ - syncAddresses(context: SyncContext): Promise + scopeSync(context: ScopedSyncContext): Promise } // diff --git a/apps/vault/src/broker/core/type/scoped-sync.type.ts b/apps/vault/src/broker/core/type/scoped-sync.type.ts index 5287a4438..98e0c67b3 100644 --- a/apps/vault/src/broker/core/type/scoped-sync.type.ts +++ b/apps/vault/src/broker/core/type/scoped-sync.type.ts @@ -1,4 +1,7 @@ import { z } from 'zod' +import { ConnectionWithCredentials } from './connection.type' +import { Account, Address, Wallet } from './indexed-resources.type' +import { NetworkMap } from './network.type' import { Provider } from './provider.type' export const RawAccount = z.object({ @@ -10,10 +13,56 @@ export type RawAccount = z.infer export const ScopedSyncStatus = { PROCESSING: 'processing', SUCCESS: 'success', + PARTIAL_SUCCESS: 'partial_success', FAILED: 'failed' } as const export type ScopedSyncStatus = (typeof ScopedSyncStatus)[keyof typeof ScopedSyncStatus] +export const RawAccountError = { + EXTERNAL_RESOURCE_NOT_FOUND: 'EXTERNAL_RESOURCE_NOT_FOUND', + UNLISTED_NETWORK: 'UNLISTED_NETWORK' +} as const +export type RawAccountError = (typeof RawAccountError)[keyof typeof RawAccountError] + +export const RawAccountNetworkNotFoundFailure = z.object({ + code: z.literal(RawAccountError.UNLISTED_NETWORK), + rawAccount: RawAccount, + message: z.string(), + networkId: z.string() +}) +export type RawAccountNetworkNotFoundFailure = z.infer + +export const RawAccountExternalResourceNotFoundFailure = z.object({ + code: z.literal(RawAccountError.EXTERNAL_RESOURCE_NOT_FOUND), + rawAccount: RawAccount, + message: z.string(), + externalResourceType: z.string(), + externalResourceId: z.string() +}) +export type RawAccountExternalResourceNotFoundFailure = z.infer + +export const RawAccountSyncFailure = z.discriminatedUnion('code', [ + RawAccountNetworkNotFoundFailure, + RawAccountExternalResourceNotFoundFailure +]) +export type RawAccountSyncFailure = z.infer + +export const ScopedSyncResult = z.object({ + wallets: z.array(Wallet), + accounts: z.array(Account), + addresses: z.array(Address), + failures: z.array(RawAccountSyncFailure) +}) +export type ScopedSyncResult = z.infer + +export const ScopedSyncContext = z.object({ + connection: ConnectionWithCredentials, + rawAccounts: z.array(RawAccount), + networks: NetworkMap, + existingAccounts: z.array(Account) +}) +export type ScopedSyncContext = z.infer + export const ScopedSync = z.object({ clientId: z.string(), completedAt: z.date().optional(), @@ -28,7 +77,8 @@ export const ScopedSync = z.object({ .optional(), status: z.nativeEnum(ScopedSyncStatus).default(ScopedSyncStatus.PROCESSING), scopedSyncId: z.string(), - rawAccounts: z.array(RawAccount) + rawAccounts: z.array(RawAccount), + failures: z.array(RawAccountSyncFailure).optional() }) export type ScopedSync = z.infer diff --git a/apps/vault/src/broker/core/util/provider-sync.util.ts b/apps/vault/src/broker/core/util/provider-sync.util.ts deleted file mode 100644 index e98fd4f12..000000000 --- a/apps/vault/src/broker/core/util/provider-sync.util.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { SetRequired } from 'type-fest' -import { SyncContext } from '../type/provider.type' - -export const buildEmptyContext = ({ - connection, - wallets, - accounts, - addresses, - now -}: SetRequired, 'connection'>): SyncContext => ({ - connection, - wallets: wallets || [], - accounts: accounts || [], - addresses: addresses || [], - now: now || new Date() -}) diff --git a/apps/vault/src/broker/http/rest/dto/response/scoped-sync.dto.ts b/apps/vault/src/broker/http/rest/dto/response/scoped-sync.dto.ts index 529818d1a..d0bed4513 100644 --- a/apps/vault/src/broker/http/rest/dto/response/scoped-sync.dto.ts +++ b/apps/vault/src/broker/http/rest/dto/response/scoped-sync.dto.ts @@ -1,9 +1,11 @@ import { createZodDto } from 'nestjs-zod' import { z } from 'zod' -import { ScopedSync } from '../../../../core/type/scoped-sync.type' +import { RawAccountSyncFailure, ScopedSync } from '../../../../core/type/scoped-sync.type' export class ScopedSyncDto extends createZodDto( z.object({ - data: ScopedSync + data: ScopedSync.extend({ + failures: z.array(RawAccountSyncFailure) + }) }) ) {} diff --git a/apps/vault/src/broker/persistence/repository/account.repository.ts b/apps/vault/src/broker/persistence/repository/account.repository.ts index 3075b8b11..6ff4edb5a 100644 --- a/apps/vault/src/broker/persistence/repository/account.repository.ts +++ b/apps/vault/src/broker/persistence/repository/account.repository.ts @@ -1,4 +1,10 @@ -import { PaginatedResult, PaginationOptions, applyPagination, getPaginatedResult } from '@narval/nestjs-shared' +import { + LoggerService, + PaginatedResult, + PaginationOptions, + applyPagination, + getPaginatedResult +} from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' import { ProviderAccount, ProviderAddress } from '@prisma/client/vault' import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' @@ -30,7 +36,10 @@ export type UpdateAccount = { @Injectable() export class AccountRepository { - constructor(private prismaService: PrismaService) {} + constructor( + private prismaService: PrismaService, + private readonly logger: LoggerService + ) {} static parseModel(model: ProviderAccountAndRelations): Account { const { id, ...rest } = model @@ -150,6 +159,75 @@ export class AccountRepository { return true } + async bulkUpsert(accounts: Account[]): Promise { + const providerAccounts = accounts.map(AccountRepository.parseEntity) + const stats = { + inserted: 0, + updated: 0 + } + + const existingAccounts = await this.prismaService.providerAccount.findMany({ + where: { + OR: providerAccounts.map((account) => ({ + clientId: account.clientId, + connectionId: account.connectionId, + externalId: account.externalId + })) + } + }) + + const results = await this.prismaService.$transaction(async (tx) => { + const operations = await Promise.all( + providerAccounts.map(async (account) => { + const existing = existingAccounts.find( + (a) => + a.clientId === account.clientId && + a.connectionId === account.connectionId && + a.externalId === account.externalId + ) + + const result = await tx.providerAccount.upsert({ + where: { + clientId_connectionId_externalId: { + clientId: account.clientId, + connectionId: account.connectionId, + externalId: account.externalId + } + }, + create: { + ...account + }, + update: { + label: account.label, + updatedAt: account.updatedAt + }, + include: { + addresses: true + } + }) + + if (!existing) { + stats.inserted++ + } else { + stats.updated++ + } + + return result + }) + ) + + return operations + }) + + this.logger.log('Account bulk upsert operation completed:', { + total: accounts.length, + inserted: stats.inserted, + updated: stats.updated + }) + + return results.map(AccountRepository.parseModel) + } + async findAll( { clientId, connectionId }: ConnectionScope, options?: FindAllOptions diff --git a/apps/vault/src/broker/persistence/repository/address.repository.ts b/apps/vault/src/broker/persistence/repository/address.repository.ts index ffbe4f998..8287e19ed 100644 --- a/apps/vault/src/broker/persistence/repository/address.repository.ts +++ b/apps/vault/src/broker/persistence/repository/address.repository.ts @@ -1,4 +1,10 @@ -import { PaginatedResult, PaginationOptions, applyPagination, getPaginatedResult } from '@narval/nestjs-shared' +import { + LoggerService, + PaginatedResult, + PaginationOptions, + applyPagination, + getPaginatedResult +} from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' import { ProviderAddress } from '@prisma/client/vault' import { z } from 'zod' @@ -21,7 +27,10 @@ export type FindAllOptions = FindAllFilters & { pagination?: PaginationOptions } @Injectable() export class AddressRepository { - constructor(private prismaService: PrismaService) {} + constructor( + private prismaService: PrismaService, + private readonly logger: LoggerService + ) {} static parseModel(model: ProviderAddress): Address { const { id, ...rest } = model @@ -139,10 +148,16 @@ export class AddressRepository { } async bulkCreate(addresses: Address[]): Promise { - await this.prismaService.providerAddress.createMany({ - data: addresses.map(AddressRepository.parseEntity) + const { count } = await this.prismaService.providerAddress.createMany({ + data: addresses.map(AddressRepository.parseEntity), + skipDuplicates: true }) + this.logger.log('Address bulk create operation done', { + addressesLength: addresses.length, + addressesCreated: count, + addressesSkipped: addresses.length - count + }) return addresses } } diff --git a/apps/vault/src/broker/persistence/repository/scoped-sync.repository.ts b/apps/vault/src/broker/persistence/repository/scoped-sync.repository.ts index 792a853fd..41d2d2a3b 100644 --- a/apps/vault/src/broker/persistence/repository/scoped-sync.repository.ts +++ b/apps/vault/src/broker/persistence/repository/scoped-sync.repository.ts @@ -6,7 +6,7 @@ import { PrismaService } from '../../../shared/module/persistence/service/prisma import { ModelInvalidException } from '../../core/exception/model-invalid.exception' import { NotFoundException } from '../../core/exception/not-found.exception' import { ConnectionScope } from '../../core/type/scope.type' -import { RawAccount, ScopedSync, ScopedSyncStatus } from '../../core/type/scoped-sync.type' +import { RawAccount, RawAccountSyncFailure, ScopedSync, ScopedSyncStatus } from '../../core/type/scoped-sync.type' export type FindAllOptions = PaginationOptions & { filters?: { @@ -21,6 +21,7 @@ export type UpdateScopedSync = { completedAt?: Date status?: ScopedSyncStatus error?: ScopedSync['error'] + failures?: RawAccountSyncFailure[] } const parseErrorEntity = ( @@ -47,6 +48,7 @@ export class ScopedSyncRepository { // with how NULL values work in databases. rawAccounts: model.rawAccounts ? z.array(RawAccount).parse(PrismaService.toJson(model.rawAccounts)) : [], completedAt: model.completedAt || undefined, + failures: z.array(RawAccountSyncFailure).parse(PrismaService.toJson(model.failedRawAccounts) || []), error: model.errorName || model.errorMessage || model.errorTraceId ? { @@ -70,6 +72,7 @@ export class ScopedSyncRepository { rawAccounts: z.string().parse(PrismaService.toStringJson(entity.rawAccounts)), createdAt: entity.createdAt, status: entity.status, + failedRawAccounts: PrismaService.toStringJson(entity.failures), ...parseErrorEntity(entity.error) } } @@ -91,6 +94,7 @@ export class ScopedSyncRepository { } async update(updateScopedSync: UpdateScopedSync): Promise { + const failures = updateScopedSync.failures ? PrismaService.toStringJson(updateScopedSync.failures) : null await this.prismaService.providerScopedSync.update({ where: { id: updateScopedSync.scopedSyncId, @@ -99,7 +103,8 @@ export class ScopedSyncRepository { data: { completedAt: updateScopedSync.completedAt, status: updateScopedSync.status, - ...(updateScopedSync.error ? parseErrorEntity(updateScopedSync.error) : {}) + ...(updateScopedSync.error ? parseErrorEntity(updateScopedSync.error) : {}), + failedRawAccounts: failures } }) @@ -144,4 +149,15 @@ export class ScopedSyncRepository { page } } + + async exists({ clientId, connectionId, status }: ConnectionScope & { status?: ScopedSyncStatus }): Promise { + const count = await this.prismaService.providerScopedSync.count({ + where: { + clientId, + connectionId, + ...(status ? { status } : {}) + } + }) + return count > 0 + } } diff --git a/apps/vault/src/broker/persistence/repository/wallet.repository.ts b/apps/vault/src/broker/persistence/repository/wallet.repository.ts index 05c4e9747..93171694c 100644 --- a/apps/vault/src/broker/persistence/repository/wallet.repository.ts +++ b/apps/vault/src/broker/persistence/repository/wallet.repository.ts @@ -1,4 +1,10 @@ -import { PaginatedResult, PaginationOptions, applyPagination, getPaginatedResult } from '@narval/nestjs-shared' +import { + LoggerService, + PaginatedResult, + PaginationOptions, + applyPagination, + getPaginatedResult +} from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' import { ProviderAccount, ProviderAddress, ProviderWallet } from '@prisma/client/vault' import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' @@ -28,7 +34,10 @@ export type FindAllPaginatedOptions = PaginationOptions & FindAllFilters @Injectable() export class WalletRepository { - constructor(private prismaService: PrismaService) {} + constructor( + private prismaService: PrismaService, + private readonly logger: LoggerService + ) {} static parseModel(wallet: ProviderWalletsAndRelations): Wallet { const { accounts, id, ...walletData } = wallet @@ -185,6 +194,77 @@ export class WalletRepository { return wallets } + async bulkUpsert(wallets: Wallet[]): Promise { + const providerWallets: ProviderWallet[] = wallets.map(WalletRepository.parseEntity) + + const stats = { + inserted: 0, + updated: 0 + } + + const existingWallets = await this.prismaService.providerWallet.findMany({ + where: { + OR: providerWallets.map((wallet) => ({ + clientId: wallet.clientId, + connectionId: wallet.connectionId, + externalId: wallet.externalId + })) + } + }) + + const upsertedWallets = await this.prismaService.$transaction(async (tx) => { + const upsertPromises = providerWallets.map(async (wallet) => { + const existing = existingWallets.find( + (w) => + w.clientId === wallet.clientId && + w.connectionId === wallet.connectionId && + w.externalId === wallet.externalId + ) + + const result = tx.providerWallet.upsert({ + where: { + clientId_connectionId_externalId: { + clientId: wallet.clientId, + connectionId: wallet.connectionId, + externalId: wallet.externalId + } + }, + create: { + ...wallet + }, + update: { + label: wallet.label, + updatedAt: wallet.updatedAt + }, + include: { + accounts: { + include: { + addresses: true + } + } + } + }) + + if (!existing) { + stats.inserted++ + } else { + stats.updated++ + } + + return result + }) + return Promise.all(upsertPromises) + }) + + this.logger.log('Wallet bulk upsert operation completed:', { + total: wallets.length, + inserted: stats.inserted, + updated: stats.updated + }) + + return upsertedWallets.map(WalletRepository.parseModel) + } + async update(wallet: UpdateWallet) { const model = await this.prismaService.providerWallet.update({ where: { id: wallet.walletId }, diff --git a/apps/vault/src/shared/module/persistence/schema/migrations/20250124164857_store_failed_raw_accounts_requests/migration.sql b/apps/vault/src/shared/module/persistence/schema/migrations/20250124164857_store_failed_raw_accounts_requests/migration.sql new file mode 100644 index 000000000..2215327bc --- /dev/null +++ b/apps/vault/src/shared/module/persistence/schema/migrations/20250124164857_store_failed_raw_accounts_requests/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "provider_scoped_sync" ADD COLUMN "failed_raw_accounts" TEXT; diff --git a/apps/vault/src/shared/module/persistence/schema/schema.prisma b/apps/vault/src/shared/module/persistence/schema/schema.prisma index 525453ad1..db19dee11 100644 --- a/apps/vault/src/shared/module/persistence/schema/schema.prisma +++ b/apps/vault/src/shared/module/persistence/schema/schema.prisma @@ -124,13 +124,13 @@ model ProviderAccount { connectionId String @map("connection_id") externalId String @map("external_id") provider String - walletId String @map("wallet_id") + walletId String? @map("wallet_id") networkId String @map("network_id") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") connection ProviderConnection @relation(fields: [connectionId], references: [id]) - wallet ProviderWallet @relation(fields: [walletId], references: [id]) + wallet ProviderWallet? @relation(fields: [walletId], references: [id]) addresses ProviderAddress[] sourceTransfers ProviderTransfer[] @relation("SourceAccount") @@ -206,17 +206,20 @@ model ProviderSync { } model ProviderScopedSync { - id String @id - clientId String @map("client_id") - connectionId String @map("connection_id") + id String @id + clientId String @map("client_id") + connectionId String @map("connection_id") status String + rawAccounts String @map("raw_accounts") + errorName String? @map("error_name") errorMessage String? @map("error_message") errorTraceId String? @map("error_trace_id") - rawAccounts String @map("raw_accounts") createdAt DateTime @default(now()) @map("created_at") completedAt DateTime? @map("completed_at") + failedRawAccounts String? @map("failed_raw_accounts") + connection ProviderConnection @relation(fields: [connectionId], references: [id]) @@map("provider_scoped_sync") From b4c55a1423a5000d766cb8b32ba2b5d09d448cf3 Mon Sep 17 00:00:00 2001 From: Matt Schoch Date: Thu, 30 Jan 2025 16:12:03 +0100 Subject: [PATCH 109/120] misc hotfix on transfer example --- .../engine/core/service/data-store.service.ts | 2 +- .../4-transfer-a-to-b.ts | 3 +- examples/approvals-by-spending-limit/data.ts | 23 +++--- .../package-lock.json | 79 +++++++++++++------ .../approvals-by-spending-limit/package.json | 2 +- 5 files changed, 66 insertions(+), 43 deletions(-) diff --git a/apps/policy-engine/src/engine/core/service/data-store.service.ts b/apps/policy-engine/src/engine/core/service/data-store.service.ts index cefce5330..63237a773 100644 --- a/apps/policy-engine/src/engine/core/service/data-store.service.ts +++ b/apps/policy-engine/src/engine/core/service/data-store.service.ts @@ -153,7 +153,7 @@ export class DataStoreService { }): Promise<{ success: true } | { success: false; error: DataStoreException }> { try { const jwt = decodeJwt(params.signature) - const jwk = params.keys.find(({ kid }) => kid === jwt.header.kid) + const jwk = params.keys.find(({ kid }) => kid?.toLowerCase() === jwt.header.kid?.toLowerCase()) if (!jwk) { return { diff --git a/examples/approvals-by-spending-limit/4-transfer-a-to-b.ts b/examples/approvals-by-spending-limit/4-transfer-a-to-b.ts index 24940b65d..419a60d70 100644 --- a/examples/approvals-by-spending-limit/4-transfer-a-to-b.ts +++ b/examples/approvals-by-spending-limit/4-transfer-a-to-b.ts @@ -2,13 +2,12 @@ import { AuthClient, AuthConfig, - Decision, Request, TransactionRequest, buildSignerEip191, privateKeyToJwk } from '@narval-xyz/armory-sdk' -import { hexSchema } from '@narval-xyz/armory-sdk/policy-engine-shared' +import { Decision, hexSchema } from '@narval-xyz/armory-sdk/policy-engine-shared' import 'dotenv/config' import { v4 } from 'uuid' diff --git a/examples/approvals-by-spending-limit/data.ts b/examples/approvals-by-spending-limit/data.ts index b53e363bb..53a5cea3a 100644 --- a/examples/approvals-by-spending-limit/data.ts +++ b/examples/approvals-by-spending-limit/data.ts @@ -29,26 +29,21 @@ const baseEntities: Partial = { accountType: 'eoa' } ], - userGroups: [ + groups: [ { - id: 'ug-treasury-group' + id: 'treasury-group' } ], - userGroupMembers: [ + groupMembers: [ { - groupId: 'ug-treasury-group', + type: 'user', + groupId: 'treasury-group', userId: '2-member-user-q' - } - ], - accountGroups: [ - { - id: 'ag-treasury-group' - } - ], - accountGroupMembers: [ + }, { - accountId: 'acct-treasury-account-a', - groupId: 'ag-treasury-group' + type: 'account', + groupId: 'treasury-group', + accountId: 'acct-treasury-account-a' } ], addressBook: [] diff --git a/examples/approvals-by-spending-limit/package-lock.json b/examples/approvals-by-spending-limit/package-lock.json index afc2c2f46..fc516cb35 100644 --- a/examples/approvals-by-spending-limit/package-lock.json +++ b/examples/approvals-by-spending-limit/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "@narval-xyz/armory-sdk": "0.8.1", + "@narval-xyz/armory-sdk": "0.18.0", "dotenv": "^16.4.5", "minimist": "^1.2.8", "tsx": "^4.16.2", @@ -385,12 +385,15 @@ } }, "node_modules/@narval-xyz/armory-sdk": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@narval-xyz/armory-sdk/-/armory-sdk-0.8.1.tgz", - "integrity": "sha512-LF2OWE2YwZ9Ju3JGSDkPh276/sjcuOBmJzZa40ymZog36XZGhaPCHDjOWRg2OAsrN4A/A5Vue+BSudCt8RxD+w==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@narval-xyz/armory-sdk/-/armory-sdk-0.18.0.tgz", + "integrity": "sha512-jKHeVk36wo/XjxGLogxHz3lQp6cJc9YFxZU423t26LVHFIZs4HFeFwYzhGLRR4XgPu1xDEzYfl9DXuMm6r1jmg==", + "license": "MPL-2.0", "dependencies": { - "@noble/curves": "1.5.0", - "axios": "1.7.2", + "@noble/curves": "1.6.0", + "@noble/ed25519": "1.7.1", + "@noble/hashes": "1.4.0", + "axios": "1.7.7", "jose": "5.5.0", "lodash": "4.17.21", "tslib": "2.6.3", @@ -400,22 +403,27 @@ } }, "node_modules/@narval-xyz/armory-sdk/node_modules/@noble/curves": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.5.0.tgz", - "integrity": "sha512-J5EKamIHnKPyClwVrzmaf5wSdQXgdHcPZIZLu3bwnbeCx8/7NPK5q2ZBWF+5FvYGByjiQQsJYX6jfgB2wDPn3A==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.6.0.tgz", + "integrity": "sha512-TlaHRXDehJuRNR9TfZDNQ45mMEd5dwUwmicsafcIX4SsNiqnCHKjE/1alYPd/lDRVhxdhUAlv8uEhMCI5zjIJQ==", + "license": "MIT", "dependencies": { - "@noble/hashes": "1.4.0" + "@noble/hashes": "1.5.0" + }, + "engines": { + "node": "^14.21.3 || >=16" }, "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/@narval-xyz/armory-sdk/node_modules/@noble/curves/node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.5.0.tgz", + "integrity": "sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==", + "license": "MIT", "engines": { - "node": ">= 16" + "node": "^14.21.3 || >=16" }, "funding": { "url": "https://paulmillr.com/funding/" @@ -539,6 +547,18 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/@noble/ed25519": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/ed25519/-/ed25519-1.7.1.tgz", + "integrity": "sha512-Rk4SkJFaXZiznFyC/t77Q0NKS4FL7TLJJsVG2V2oiEq3kJVeTdxysEe/yRWSpnWMe808XRDJ+VFh5pt/FN5plw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT" + }, "node_modules/@noble/hashes": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", @@ -612,12 +632,14 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" }, "node_modules/axios": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", - "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", @@ -628,6 +650,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" }, @@ -639,6 +662,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", "engines": { "node": ">=0.4.0" } @@ -693,15 +717,16 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", "funding": [ { "type": "individual", "url": "https://github.com/sponsors/RubenVerborgh" } ], + "license": "MIT", "engines": { "node": ">=4.0" }, @@ -712,9 +737,10 @@ } }, "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -779,6 +805,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -787,6 +814,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -805,7 +833,8 @@ "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" }, "node_modules/resolve-pkg-maps": { "version": "1.0.0", diff --git a/examples/approvals-by-spending-limit/package.json b/examples/approvals-by-spending-limit/package.json index b4d6661c6..d634ab5e6 100644 --- a/examples/approvals-by-spending-limit/package.json +++ b/examples/approvals-by-spending-limit/package.json @@ -13,7 +13,7 @@ "author": "", "license": "ISC", "dependencies": { - "@narval-xyz/armory-sdk": "0.8.1", + "@narval-xyz/armory-sdk": "0.18.0", "dotenv": "^16.4.5", "minimist": "^1.2.8", "tsx": "^4.16.2", From 5b3f7d99b9938fd7de9eab43c62ab91544d05abe Mon Sep 17 00:00:00 2001 From: Matt Schoch Date: Thu, 30 Jan 2025 19:08:27 +0100 Subject: [PATCH 110/120] HOTFIX ensuring we upsert provider networks --- .../repository/network.repository.ts | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/apps/vault/src/broker/persistence/repository/network.repository.ts b/apps/vault/src/broker/persistence/repository/network.repository.ts index 776eec896..3d775e67c 100644 --- a/apps/vault/src/broker/persistence/repository/network.repository.ts +++ b/apps/vault/src/broker/persistence/repository/network.repository.ts @@ -62,11 +62,18 @@ export class NetworkRepository { createdAt })) - // Ensure we have them all inserted - await this.prismaService.providerNetwork.createMany({ - data: externalNetworks, - skipDuplicates: true - }) + for (const externalNetwork of externalNetworks) { + await this.prismaService.providerNetwork.upsert({ + where: { + provider_networkId: { + provider: externalNetwork.provider, + networkId: externalNetwork.networkId + } + }, + create: externalNetwork, + update: externalNetwork + }) + } } return networks From 8060b94d2c6445408ec9f94f82e63aed0f5c9c35 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Fri, 31 Jan 2025 14:51:22 +0100 Subject: [PATCH 111/120] Bind access token to a given public key (#120) * Bind request to a given public key * Fix test description to match the option name * Add bind access token acceptance test * Fix authorization request E2E test * Move confirmation claim to the request metadata * Bump SDK to 0.19.0 * Test sign transaction with bound access token --- .../e2e/authorization-request.spec.ts | 1 - .../src/orchestration/http/rest/util.ts | 2 + .../decode/authorization-request.decode.ts | 18 +- .../authorization-request.repository.spec.ts | 172 +- .../persistence/schema/signature.schema.ts | 4 - .../schema/transaction-request.schema.ts | 13 +- .../open-policy-agent-engine.factory.ts | 33 + .../__test__/unit/evaluation.service.spec.ts | 168 +- .../engine/core/service/evaluation.service.ts | 52 +- .../policy-engine/src/engine/engine.module.ts | 6 +- .../unit/open-policy-agent.engine.spec.ts | 68 +- .../core/open-policy-agent.engine.ts | 7 +- .../__test__/unit/authorization.guard.spec.ts | 18 +- package-lock.json | 372 +-- .../e2e/scenario/bind-access-token.spec.ts | 394 ++++ packages/armory-sdk/package.json | 2 +- packages/armory-sdk/src/lib/auth/client.ts | 55 +- packages/armory-sdk/src/lib/auth/type.ts | 2 +- .../armory-sdk/src/lib/data-store/client.ts | 82 +- .../src/lib/http/client/auth/api.ts | 2091 +++++++++-------- .../src/lib/http/client/auth/base.ts | 2 +- packages/policy-engine-shared/src/index.ts | 1 + .../src/lib/type/authorization-server.type.ts | 5 +- .../src/lib/type/domain.type.ts | 32 +- .../unit/confirmation-claim.util.spec.ts | 129 + .../src/lib/util/confirmation-claim.util.ts | 31 + 26 files changed, 2423 insertions(+), 1337 deletions(-) delete mode 100644 apps/armory/src/orchestration/persistence/schema/signature.schema.ts create mode 100644 apps/policy-engine/src/engine/core/factory/open-policy-agent-engine.factory.ts create mode 100644 packages/armory-e2e-testing/src/__test__/e2e/scenario/bind-access-token.spec.ts create mode 100644 packages/policy-engine-shared/src/lib/util/__test__/unit/confirmation-claim.util.spec.ts create mode 100644 packages/policy-engine-shared/src/lib/util/confirmation-claim.util.ts diff --git a/apps/armory/src/orchestration/__test__/e2e/authorization-request.spec.ts b/apps/armory/src/orchestration/__test__/e2e/authorization-request.spec.ts index 2da92b3b5..e91a54619 100644 --- a/apps/armory/src/orchestration/__test__/e2e/authorization-request.spec.ts +++ b/apps/armory/src/orchestration/__test__/e2e/authorization-request.spec.ts @@ -409,7 +409,6 @@ describe('Authorization Request', () => { idempotencyKey: '8dcbb7ad-82a2-4eca-b2f0-b1415c1d4a17', evaluations: [], approvals: [], - errors: [], createdAt: new Date(), updatedAt: new Date() } diff --git a/apps/armory/src/orchestration/http/rest/util.ts b/apps/armory/src/orchestration/http/rest/util.ts index ea3644eaf..d02d884f5 100644 --- a/apps/armory/src/orchestration/http/rest/util.ts +++ b/apps/armory/src/orchestration/http/rest/util.ts @@ -17,8 +17,10 @@ export const toCreateAuthorizationRequest = ( const authentication = dto.authentication const approvals = dto.approvals || [] const audience = dto.metadata?.audience + const confirmation = dto.metadata?.confirmation const metadata = { ...(audience && { audience }), + ...(confirmation && { confirmation }), expiresIn: dto.metadata?.expiresIn || TEN_MINUTES, issuedAt: nowSeconds(), issuer: `${clientId}.armory.narval.xyz` diff --git a/apps/armory/src/orchestration/persistence/decode/authorization-request.decode.ts b/apps/armory/src/orchestration/persistence/decode/authorization-request.decode.ts index 607173a35..9ec4db4e9 100644 --- a/apps/armory/src/orchestration/persistence/decode/authorization-request.decode.ts +++ b/apps/armory/src/orchestration/persistence/decode/authorization-request.decode.ts @@ -4,12 +4,12 @@ import { Approvals, AuthorizationRequest, AuthorizationRequestError, + AuthorizationRequestMetadata, Evaluation } from '@narval/policy-engine-shared' import { ApprovalRequirement as ApprovalRequirementModel, - AuthorizationRequestError as AuthorizationRequestErrorModel, - Prisma + AuthorizationRequestError as AuthorizationRequestErrorModel } from '@prisma/client/armory' import { ZodIssueCode, ZodSchema, z } from 'zod' import { ACTION_REQUEST } from '../../orchestration.constant' @@ -33,10 +33,18 @@ const buildSharedAttributes = (model: AuthorizationRequestModel): Omit !error).map((approval) => approval.sig)), evaluations: (model.evaluationLog || []).map(decodeEvaluationLog), - metadata: model.metadata as Prisma.InputJsonObject, - errors: (model.errors || []).map(buildError), createdAt: model.createdAt, - updatedAt: model.updatedAt + updatedAt: model.updatedAt, + ...(model.errors && model.errors.length + ? { + errors: model.errors.map(buildError) + } + : {}), + ...(model.metadata + ? { + metadata: AuthorizationRequestMetadata.parse(model.metadata) + } + : {}) } } diff --git a/apps/armory/src/orchestration/persistence/repository/__test__/integration/authorization-request.repository.spec.ts b/apps/armory/src/orchestration/persistence/repository/__test__/integration/authorization-request.repository.spec.ts index 9b755d9d8..b3c8c795d 100644 --- a/apps/armory/src/orchestration/persistence/repository/__test__/integration/authorization-request.repository.spec.ts +++ b/apps/armory/src/orchestration/persistence/repository/__test__/integration/authorization-request.repository.spec.ts @@ -9,6 +9,7 @@ import { FIXTURE, SignTransaction } from '@narval/policy-engine-shared' +import { Alg, generateJwk, getPublicKey, hash, signJwt } from '@narval/signature' import { Test, TestingModule } from '@nestjs/testing' import { AuthorizationRequestStatus, Client, Prisma } from '@prisma/client/armory' import { omit } from 'lodash/fp' @@ -35,7 +36,7 @@ describe(AuthorizationRequestRepository.name, () => { const authentication = '0xe24d097cea880a40f8be2cf42f497b9fbda5f9e4a31b596827e051d78dce75c032fa7e5ee3046f7c6f116e5b98cb8d268fa9b9d222ff44719e2ec2a0d9159d0d1c' - const signMessageRequest: AuthorizationRequest = { + const baseAuthzRequest: AuthorizationRequest = { authentication, id: '6c7e92fc-d2b0-4840-8e9b-485393ecdf89', clientId: client.id, @@ -96,24 +97,24 @@ describe(AuthorizationRequestRepository.name, () => { describe('create', () => { it('creates a new authorization request', async () => { - await repository.create(signMessageRequest) + await repository.create(baseAuthzRequest) const request = await testPrismaService.getClient().authorizationRequest.findFirst({ where: { - id: signMessageRequest.id + id: baseAuthzRequest.id } }) - expect(request).toMatchObject(omit(['evaluations', 'approvals', 'authentication'], signMessageRequest)) + expect(request).toMatchObject(omit(['evaluations', 'approvals', 'authentication'], baseAuthzRequest)) expect(request?.authnSig).toEqual(authentication) }) it('defaults status to CREATED', async () => { - await repository.create(omit('status', signMessageRequest)) + await repository.create(omit('status', baseAuthzRequest)) const request = await testPrismaService.getClient().authorizationRequest.findFirst({ where: { - id: signMessageRequest.id + id: baseAuthzRequest.id } }) @@ -154,7 +155,7 @@ describe(AuthorizationRequestRepository.name, () => { } const { evaluations } = await repository.create({ - ...signMessageRequest, + ...baseAuthzRequest, evaluations: [permit] }) @@ -165,20 +166,20 @@ describe(AuthorizationRequestRepository.name, () => { const approval = 'test-signature' await repository.create({ - ...signMessageRequest, + ...baseAuthzRequest, approvals: [approval] }) const approvals = await testPrismaService.getClient().authorizationRequestApproval.findMany({ where: { - requestId: signMessageRequest.id + requestId: baseAuthzRequest.id } }) expect(approvals.map(omit(['id', 'createdAt', 'error']))).toEqual([ { sig: approval, - requestId: signMessageRequest.id + requestId: baseAuthzRequest.id } ]) }) @@ -191,19 +192,48 @@ describe(AuthorizationRequestRepository.name, () => { } await repository.create({ - ...signMessageRequest, + ...baseAuthzRequest, errors: [error] }) const errors = await testPrismaService.getClient().authorizationRequestError.findMany({ where: { - requestId: signMessageRequest.id + requestId: baseAuthzRequest.id } }) expect(errors.map(omit(['createdAt', 'clientId', 'requestId']))).toEqual([error]) }) + it('creates request with confirmation claim metadata', async () => { + const privateKey = await generateJwk(Alg.EDDSA) + + const authzRequest: AuthorizationRequest = { + ...baseAuthzRequest, + metadata: { + confirmation: { + key: { + jwk: getPublicKey(privateKey), + proof: 'jws', + jws: await signJwt({ requestHash: hash({ it: 'does not matter here' }) }, privateKey) + } + } + }, + request: { + action: Action.SIGN_MESSAGE, + nonce: '99', + resourceId: '3be0c61d-9b41-423f-80b8-ea6f7624d917', + message: 'sign me!' + } + } + + await repository.create(authzRequest) + + const createdAuthzRequest = await repository.findById(authzRequest.id) + + expect(createdAuthzRequest).toEqual(authzRequest) + }) + describe(`when action is ${Action.SIGN_TRANSACTION}`, () => { const signTransaction: SignTransaction = { action: Action.SIGN_TRANSACTION, @@ -218,7 +248,7 @@ describe(AuthorizationRequestRepository.name, () => { } const signTransactionRequest: AuthorizationRequest = { - ...signMessageRequest, + ...baseAuthzRequest, request: signTransaction } @@ -231,23 +261,115 @@ describe(AuthorizationRequestRepository.name, () => { if (authzRequest && authzRequest.request.action === Action.SIGN_TRANSACTION) { expect(authzRequest?.request.transactionRequest.gas).toEqual(signTransaction.transactionRequest.gas) + } else { + fail(`expect authorization request action equals to ${Action.SIGN_TRANSACTION}`) + } + }) + }) + + describe(`when action is ${Action.SIGN_MESSAGE}`, () => { + const authzRequest: AuthorizationRequest = { + ...baseAuthzRequest, + request: { + action: Action.SIGN_MESSAGE, + nonce: '99', + resourceId: '3be0c61d-9b41-423f-80b8-ea6f7624d917', + message: 'sign me!' + } + } + + it('decodes request correctly', async () => { + await repository.create(authzRequest) + + const createdAuthzRequest = await repository.findById(authzRequest.id) + + expect(createdAuthzRequest).toEqual(authzRequest) + }) + }) + + describe(`when action is ${Action.SIGN_RAW}`, () => { + const authzRequest: AuthorizationRequest = { + ...baseAuthzRequest, + request: { + action: Action.SIGN_RAW, + nonce: '99', + resourceId: '3be0c61d-9b41-423f-80b8-ea6f7624d917', + rawMessage: '0x123' } + } + + it('decodes correctly', async () => { + await repository.create(authzRequest) + + const createdAuthzRequest = await repository.findById(authzRequest.id) + + expect(createdAuthzRequest).toEqual(authzRequest) + }) + }) + + describe(`when action is ${Action.SIGN_TYPED_DATA}`, () => { + const authzRequest: AuthorizationRequest = { + ...baseAuthzRequest, + request: { + action: Action.SIGN_TYPED_DATA, + nonce: '99', + resourceId: '3be0c61d-9b41-423f-80b8-ea6f7624d917', + typedData: { + domain: { + name: 'Ether Mail', + version: '1', + chainId: 1, + verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC' + }, + types: { + Person: [ + { name: 'name', type: 'string' }, + { name: 'account', type: 'address' } + ], + Mail: [ + { name: 'from', type: 'Person' }, + { name: 'to', type: 'Person' }, + { name: 'contents', type: 'string' } + ] + }, + primaryType: 'Mail', + message: { + from: { + name: 'Cow', + account: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826' + }, + to: { + name: 'Bob', + account: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB' + }, + contents: 'Hello, Bob!' + } + } + } + } + + it('decodes request correctly', async () => { + await repository.create(authzRequest) + + const createdAuthzRequest = await repository.findById(authzRequest.id) + + expect(createdAuthzRequest).toEqual(authzRequest) }) }) }) describe('update', () => { beforeEach(async () => { - await repository.create(signMessageRequest) + await repository.create(baseAuthzRequest) }) it('updates status', async () => { const authzRequest = await repository.update({ - ...signMessageRequest, + ...baseAuthzRequest, status: AuthorizationRequestStatus.PERMITTED }) - const actual = await repository.findById(signMessageRequest.id) + const actual = await repository.findById(baseAuthzRequest.id) expect(authzRequest.status).toEqual(AuthorizationRequestStatus.PERMITTED) expect(actual?.status).toEqual(AuthorizationRequestStatus.PERMITTED) @@ -255,7 +377,7 @@ describe(AuthorizationRequestRepository.name, () => { it('appends evaluations', async () => { const authzRequestOne = await repository.update({ - ...signMessageRequest, + ...baseAuthzRequest, evaluations: [ { id: '404853b2-1338-47f5-be17-a1aa78da8010', @@ -287,7 +409,7 @@ describe(AuthorizationRequestRepository.name, () => { }) const authzRequestTwo = await repository.update({ - ...signMessageRequest, + ...baseAuthzRequest, evaluations: [ { id: 'cc329386-a2dd-4024-86fd-323a630ed703', @@ -318,7 +440,7 @@ describe(AuthorizationRequestRepository.name, () => { ] }) - const actual = await repository.findById(signMessageRequest.id) + const actual = await repository.findById(baseAuthzRequest.id) expect(authzRequestOne.evaluations.length).toEqual(1) expect(authzRequestTwo.evaluations.length).toEqual(2) @@ -335,16 +457,16 @@ describe(AuthorizationRequestRepository.name, () => { it('appends approvals', async () => { const authzRequestOne = await repository.update({ - ...signMessageRequest, + ...baseAuthzRequest, approvals: ['test-signature'] }) const authzRequestTwo = await repository.update({ - ...signMessageRequest, + ...baseAuthzRequest, approvals: ['test-signature'] }) - const actual = await repository.findById(signMessageRequest.id) + const actual = await repository.findById(baseAuthzRequest.id) expect(authzRequestOne.approvals?.length).toEqual(1) expect(authzRequestTwo.approvals?.length).toEqual(2) @@ -353,7 +475,7 @@ describe(AuthorizationRequestRepository.name, () => { it('appends errors', async () => { const authzRequestOne = await repository.update({ - ...signMessageRequest, + ...baseAuthzRequest, errors: [ { id: 'test-error-id-one', @@ -364,7 +486,7 @@ describe(AuthorizationRequestRepository.name, () => { }) const authzRequestTwo = await repository.update({ - ...signMessageRequest, + ...baseAuthzRequest, errors: [ { id: 'test-error-id-two', @@ -374,7 +496,7 @@ describe(AuthorizationRequestRepository.name, () => { ] }) - const actual = await repository.findById(signMessageRequest.id) + const actual = await repository.findById(baseAuthzRequest.id) expect(authzRequestOne?.errors?.length).toEqual(1) expect(authzRequestTwo?.errors?.length).toEqual(2) diff --git a/apps/armory/src/orchestration/persistence/schema/signature.schema.ts b/apps/armory/src/orchestration/persistence/schema/signature.schema.ts deleted file mode 100644 index 8d1928b34..000000000 --- a/apps/armory/src/orchestration/persistence/schema/signature.schema.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { Alg } from '@narval/signature' -import { z } from 'zod' - -export const algSchema = z.nativeEnum(Alg) diff --git a/apps/armory/src/orchestration/persistence/schema/transaction-request.schema.ts b/apps/armory/src/orchestration/persistence/schema/transaction-request.schema.ts index ad96cae17..d3993aeb8 100644 --- a/apps/armory/src/orchestration/persistence/schema/transaction-request.schema.ts +++ b/apps/armory/src/orchestration/persistence/schema/transaction-request.schema.ts @@ -1,15 +1,4 @@ -import { - SerializedTransactionRequest, - TransactionRequest, - addressSchema, - hexSchema -} from '@narval/policy-engine-shared' -import { z } from 'zod' - -export const accessListSchema = z.object({ - address: addressSchema, - storageKeys: z.array(hexSchema) -}) +import { SerializedTransactionRequest, TransactionRequest } from '@narval/policy-engine-shared' export const readTransactionRequestSchema = TransactionRequest diff --git a/apps/policy-engine/src/engine/core/factory/open-policy-agent-engine.factory.ts b/apps/policy-engine/src/engine/core/factory/open-policy-agent-engine.factory.ts new file mode 100644 index 000000000..a9834bcb3 --- /dev/null +++ b/apps/policy-engine/src/engine/core/factory/open-policy-agent-engine.factory.ts @@ -0,0 +1,33 @@ +import { ConfigService } from '@narval/config-module' +import { TraceService } from '@narval/nestjs-shared' +import { Entities, Policy } from '@narval/policy-engine-shared' +import { Inject, Injectable } from '@nestjs/common' +import { resolve } from 'path' +import { OpenPolicyAgentEngine } from '../../../open-policy-agent/core/open-policy-agent.engine' +import { Config } from '../../../policy-engine.config' + +@Injectable() +/** + * Factory responsible for creating OpenPolicyAgentEngine instances. + * + * This factory exists primarily to improve the testability of the + * EvaluationService by abstracting engine creation. This allows tests to + * easily mock the engine creation process. + */ +export class OpenPolicyAgentEngineFactory { + constructor( + private configService: ConfigService, + @Inject(TraceService) private traceService: TraceService + ) {} + + async create(entities: Entities, policies: Policy[]): Promise { + return this.traceService.startActiveSpan(`${OpenPolicyAgentEngineFactory.name}.create`, () => { + return new OpenPolicyAgentEngine({ + entities, + policies, + resourcePath: resolve(this.configService.get('resourcePath')), + tracer: this.traceService.getTracer() + }).load() + }) + } +} diff --git a/apps/policy-engine/src/engine/core/service/__test__/unit/evaluation.service.spec.ts b/apps/policy-engine/src/engine/core/service/__test__/unit/evaluation.service.spec.ts index 92ba59653..866a7ba36 100644 --- a/apps/policy-engine/src/engine/core/service/__test__/unit/evaluation.service.spec.ts +++ b/apps/policy-engine/src/engine/core/service/__test__/unit/evaluation.service.spec.ts @@ -1,14 +1,26 @@ +import { LoggerModule, OpenTelemetryModule } from '@narval/nestjs-shared' import { + Action, + Client, + DataStoreConfiguration, Decision, + EntityUtil, + EvaluationRequest, EvaluationResponse, FIXTURE, GrantPermissionAction, Request, SignTransactionAction } from '@narval/policy-engine-shared' -import { nowSeconds } from '@narval/signature' +import { Alg, PrivateKey, decodeJwt, generateJwk, getPublicKey, nowSeconds } from '@narval/signature' +import { Test } from '@nestjs/testing' +import { MockProxy, mock } from 'jest-mock-extended' +import { OpenPolicyAgentEngine } from '../../../../../open-policy-agent/core/open-policy-agent.engine' import { ApplicationException } from '../../../../../shared/exception/application.exception' -import { buildPermitTokenPayload } from '../../evaluation.service' +import { OpenPolicyAgentEngineFactory } from '../../../factory/open-policy-agent-engine.factory' +import { ClientService } from '../../client.service' +import { EvaluationService, buildPermitTokenPayload } from '../../evaluation.service' +import { SimpleSigningService } from '../../signing-basic.service' const ONE_DAY = 86400 @@ -48,22 +60,22 @@ describe('buildPermitTokenPayload for signTransaction action', () => { request } - it('should throw an error if decision is not PERMIT', async () => { + it('throws an error if decision is not PERMIT', async () => { const evaluation: EvaluationResponse = { ...evalResponse, decision: Decision.FORBID } await expect(buildPermitTokenPayload('clientId', evaluation)).rejects.toThrow(ApplicationException) }) - it('should throw an error if principal is missing', async () => { + it('throws an error if principal is missing', async () => { const evaluation: EvaluationResponse = { ...evalResponse, principal: undefined } await expect(buildPermitTokenPayload('clientId', evaluation)).rejects.toThrow(ApplicationException) }) - it('should throw an error if request is missing', async () => { + it('throws an error if request is missing', async () => { const evaluation: EvaluationResponse = { ...evalResponse, request: undefined } await expect(buildPermitTokenPayload('clientId', evaluation)).rejects.toThrow(ApplicationException) }) - it('should return a jwt payload if all conditions are met', async () => { + it('returns a jwt payload if all conditions are met', async () => { const payload = await buildPermitTokenPayload('clientId', evalResponse) expect(payload).toEqual({ @@ -96,22 +108,22 @@ describe('buildPermitTokenPayload for grantPermission action', () => { issuer: 'clientId.armory.narval.xyz' } } - it('should throw an error if decision is not PERMIT', async () => { + it('throws an error if decision is not PERMIT', async () => { const evaluation: EvaluationResponse = { ...evalResponse, decision: Decision.FORBID } await expect(buildPermitTokenPayload('clientId', evaluation)).rejects.toThrow(ApplicationException) }) - it('should throw an error if principal is missing', async () => { + it('throws an error if principal is missing', async () => { const evaluation: EvaluationResponse = { ...evalResponse, principal: undefined } await expect(buildPermitTokenPayload('clientId', evaluation)).rejects.toThrow(ApplicationException) }) - it('should throw an error if request is missing', async () => { + it('throws an error if request is missing', async () => { const evaluation: EvaluationResponse = { ...evalResponse, request: undefined } await expect(buildPermitTokenPayload('clientId', evaluation)).rejects.toThrow(ApplicationException) }) - it('should return a jwt payload if all conditions are met', async () => { + it('returns a jwt payload if all conditions are met', async () => { const payload = await buildPermitTokenPayload('clientId', evalResponse) const iat = nowSeconds() @@ -130,3 +142,139 @@ describe('buildPermitTokenPayload for grantPermission action', () => { }) }) }) + +describe(EvaluationService.name, () => { + let service: EvaluationService + let client: Client + let clientSignerPrivateKey: PrivateKey + let openPolicyAgentEngineMock: MockProxy + + const evaluationResponse: EvaluationResponse = { + decision: Decision.PERMIT, + request: { + action: Action.SIGN_MESSAGE, + nonce: '99', + resourceId: 'test-resource-id', + message: 'sign me' + }, + accessToken: { + value: '' + }, + principal: FIXTURE.CREDENTIAL.Bob + } + + beforeEach(async () => { + clientSignerPrivateKey = await generateJwk(Alg.ES256K) + + client = { + clientId: 'test-client-id', + clientSecret: 'test-client-secret', + dataStore: { + entity: {} as DataStoreConfiguration, + policy: {} as DataStoreConfiguration + }, + signer: { + publicKey: getPublicKey(clientSignerPrivateKey), + privateKey: clientSignerPrivateKey + }, + createdAt: new Date(), + updatedAt: new Date() + } + + openPolicyAgentEngineMock = mock() + openPolicyAgentEngineMock.evaluate.mockResolvedValue(evaluationResponse) + + const openPolicyAgentEngineFactoryMock = mock() + openPolicyAgentEngineFactoryMock.create.mockResolvedValue(openPolicyAgentEngineMock) + + const clientServiceMock = mock() + clientServiceMock.findById.mockResolvedValue(client) + clientServiceMock.findEntityStore.mockResolvedValue({ + data: EntityUtil.empty(), + signature: '' + }) + clientServiceMock.findPolicyStore.mockResolvedValue({ + data: [], + signature: '' + }) + + const module = await Test.createTestingModule({ + imports: [LoggerModule.forTest(), OpenTelemetryModule.forTest()], + providers: [ + EvaluationService, + { + provide: OpenPolicyAgentEngineFactory, + useValue: openPolicyAgentEngineFactoryMock + }, + { + provide: 'SigningService', + useClass: SimpleSigningService + }, + { + provide: ClientService, + useValue: clientServiceMock + } + ] + }).compile() + + service = module.get(EvaluationService) + }) + + describe('evaluate', () => { + describe('when confirmation (cnf) claim metadata is given', () => { + let bindPrivateKey: PrivateKey + + let request: EvaluationRequest + let response: EvaluationResponse + + beforeEach(async () => { + bindPrivateKey = await generateJwk(Alg.EDDSA) + + const action = { + action: Action.SIGN_MESSAGE, + nonce: '99', + resourceId: 'test-resource-id', + message: 'sign me' + } + + request = { + authentication: 'fake-jwt', + metadata: { + confirmation: { + key: { + jwk: getPublicKey(bindPrivateKey) + } + } + }, + approvals: [], + request: action, + feeds: [] + } + + response = { + decision: Decision.PERMIT, + request: action, + metadata: request.metadata, + accessToken: { + value: '' + }, + principal: FIXTURE.CREDENTIAL.Bob + } + + openPolicyAgentEngineMock.evaluate.mockResolvedValue(response) + }) + + it('adds the public key as the cnf in the access token', async () => { + const response = await service.evaluate(client.clientId, request) + + if (response.accessToken) { + const jwt = decodeJwt(response.accessToken.value) + + expect(jwt.payload.cnf).toEqual(getPublicKey(bindPrivateKey)) + } else { + fail('expect response to contain an access token') + } + }) + }) + }) +}) diff --git a/apps/policy-engine/src/engine/core/service/evaluation.service.ts b/apps/policy-engine/src/engine/core/service/evaluation.service.ts index c47732af4..36feea796 100644 --- a/apps/policy-engine/src/engine/core/service/evaluation.service.ts +++ b/apps/policy-engine/src/engine/core/service/evaluation.service.ts @@ -1,12 +1,9 @@ -import { ConfigService } from '@narval/config-module' import { TraceService } from '@narval/nestjs-shared' import { Action, Decision, EvaluationRequest, EvaluationResponse } from '@narval/policy-engine-shared' import { Payload, SigningAlg, hash, nowSeconds, signJwt } from '@narval/signature' import { HttpStatus, Inject, Injectable } from '@nestjs/common' -import { resolve } from 'path' -import { OpenPolicyAgentEngine } from '../../../open-policy-agent/core/open-policy-agent.engine' -import { Config } from '../../../policy-engine.config' import { ApplicationException } from '../../../shared/exception/application.exception' +import { OpenPolicyAgentEngineFactory } from '../factory/open-policy-agent-engine.factory' import { buildTransactionRequestHashWildcard } from '../util/wildcard-transaction-fields.util' import { ClientService } from './client.service' import { SigningService } from './signing.service.interface' @@ -19,6 +16,7 @@ export async function buildPermitTokenPayload(clientId: string, evaluation: Eval context: { clientId } }) } + if (!evaluation.principal) { throw new ApplicationException({ message: 'Principal is missing', @@ -26,6 +24,7 @@ export async function buildPermitTokenPayload(clientId: string, evaluation: Eval context: { clientId } }) } + if (!evaluation.request) { throw new ApplicationException({ message: 'Request is missing', @@ -37,18 +36,34 @@ export async function buildPermitTokenPayload(clientId: string, evaluation: Eval const { audience, issuer } = evaluation.metadata || {} const iat = evaluation.metadata?.issuedAt || nowSeconds() const exp = evaluation.metadata?.expiresIn ? evaluation.metadata.expiresIn + iat : null - const hashWildcard = buildTransactionRequestHashWildcard(evaluation.request) const payload: Payload = { - sub: evaluation.principal.userId, + // jti: TODO iat, + hashWildcard, + /** + * Confirmation (cnf) claim handling for token binding: + * + * Two scenarios are supported: + * 1. Standard flow: Uses principal's key as the confirmation claim + * 2. Delegation flow: Uses a provided confirmation key for token binding + * + * The delegation flow enables secure token delegation where: + * - A client generates a key pair + * - Passes the public key (metadata.confirmation) to the server + * - Server issues a token bound to this specific key with the auth server + * - Only the holder of the corresponding private key can use the token + * with the resource server + * + * The cnf claim is used in the JWSD header to cryptographically bind the + * token to a specific key. + */ + cnf: evaluation.metadata?.confirmation?.key.jwk || evaluation.principal.key, + sub: evaluation.principal.userId, ...(exp && { exp }), ...(audience && { aud: audience }), - ...(issuer && { iss: issuer }), - hashWildcard, - // jti: TODO - cnf: evaluation.principal.key + ...(issuer && { iss: issuer }) } // Action-specific payload claims @@ -73,10 +88,10 @@ export async function buildPermitTokenPayload(clientId: string, evaluation: Eval @Injectable() export class EvaluationService { constructor( - private configService: ConfigService, - private clientService: ClientService, - @Inject(TraceService) private traceService: TraceService, - @Inject('SigningService') private signingService: SigningService + private readonly clientService: ClientService, + private readonly openPolicyAgentEngineFactory: OpenPolicyAgentEngineFactory, + @Inject(TraceService) private readonly traceService: TraceService, + @Inject('SigningService') private readonly signingService: SigningService ) {} async evaluate(clientId: string, evaluation: EvaluationRequest): Promise { @@ -121,16 +136,9 @@ export class EvaluationService { }) } - const engineLoadSpan = this.traceService.startSpan(`${EvaluationService.name}.evaluate.engineLoad`) // WARN: Loading a new engine is an IO bounded process due to the Rego // transpilation and WASM build. - const engine = await new OpenPolicyAgentEngine({ - entities: entityStore.data, - policies: policyStore.data, - resourcePath: resolve(this.configService.get('resourcePath')), - tracer: this.traceService.getTracer() - }).load() - engineLoadSpan.end() + const engine = await this.openPolicyAgentEngineFactory.create(entityStore.data, policyStore.data) const engineEvaluationSpan = this.traceService.startSpan(`${EvaluationService.name}.evaluate.engineEvaluation`) const evaluationResponse = await engine.evaluate(evaluation) diff --git a/apps/policy-engine/src/engine/engine.module.ts b/apps/policy-engine/src/engine/engine.module.ts index ef91cfaad..937cec0e8 100644 --- a/apps/policy-engine/src/engine/engine.module.ts +++ b/apps/policy-engine/src/engine/engine.module.ts @@ -9,6 +9,7 @@ import { AdminApiKeyGuard } from '../shared/guard/admin-api-key.guard' import { KeyValueModule } from '../shared/module/key-value/key-value.module' import { AppController } from './app.controller' import { DataStoreRepositoryFactory } from './core/factory/data-store-repository.factory' +import { OpenPolicyAgentEngineFactory } from './core/factory/open-policy-agent-engine.factory' import { signingServiceFactory } from './core/factory/signing-service.factory' import { BootstrapService } from './core/service/bootstrap.service' import { ClientService } from './core/service/client.service' @@ -38,6 +39,8 @@ import { HttpDataStoreRepository } from './persistence/repository/http-data-stor providers: [ AdminApiKeyGuard, BootstrapService, + ClientRepository, + ClientService, DataStoreRepositoryFactory, DataStoreService, EngineRepository, @@ -45,9 +48,8 @@ import { HttpDataStoreRepository } from './persistence/repository/http-data-stor EvaluationService, FileSystemDataStoreRepository, HttpDataStoreRepository, + OpenPolicyAgentEngineFactory, ProvisionService, - ClientRepository, - ClientService, { provide: 'SigningService', useFactory: signingServiceFactory, diff --git a/apps/policy-engine/src/open-policy-agent/core/__test__/unit/open-policy-agent.engine.spec.ts b/apps/policy-engine/src/open-policy-agent/core/__test__/unit/open-policy-agent.engine.spec.ts index 9bc513fdd..dad22039c 100644 --- a/apps/policy-engine/src/open-policy-agent/core/__test__/unit/open-policy-agent.engine.spec.ts +++ b/apps/policy-engine/src/open-policy-agent/core/__test__/unit/open-policy-agent.engine.spec.ts @@ -1,6 +1,7 @@ import { ConfigModule, ConfigService } from '@narval/config-module' import { Action, + ConfirmationClaimProofMethod, Criterion, Decision, Eip712TypedData, @@ -14,10 +15,20 @@ import { Request, SignMessageAction, Then, + UserRole, ValueOperators, toHex } from '@narval/policy-engine-shared' -import { SigningAlg, buildSignerEip191, hash, secp256k1PrivateKeyToJwk, signJwt } from '@narval/signature' +import { + Alg, + SigningAlg, + buildSignerEip191, + generateJwk, + getPublicKey, + hash, + secp256k1PrivateKeyToJwk, + signJwt +} from '@narval/signature' import { Path, PathValue } from '@nestjs/config' import { Test, TestingModule } from '@nestjs/testing' import { Config, load } from '../../../../policy-engine.config' @@ -229,6 +240,61 @@ describe('OpenPolicyAgentEngine', () => { expect(response.decision).toEqual(Decision.PERMIT) expect(response.principal).toEqual(FIXTURE.CREDENTIAL.Alice) }) + + it('throws when confirmation claim proof is invalid', async () => { + const e = await new OpenPolicyAgentEngine({ + policies: [ + { + id: 'test-permit-policy-uid', + description: 'test-policy', + when: [ + { + criterion: Criterion.CHECK_PRINCIPAL_ROLE, + args: [UserRole.ROOT, UserRole.ADMIN] + } + ], + then: Then.PERMIT + } + ], + entities: FIXTURE.ENTITIES, + resourcePath: await getConfig('resourcePath') + }).load() + + const request = { + action: Action.SIGN_MESSAGE, + nonce: 'test-nonce', + resourceId: FIXTURE.ACCOUNT.Engineering.id, + message: 'sign me' + } + + const bindPrivateKeyOne = await generateJwk(Alg.EDDSA) + const bindPrivateKeyTwo = await generateJwk(Alg.EDDSA) + + const evaluation: EvaluationRequest = { + authentication: await getJwt({ + privateKey: FIXTURE.UNSAFE_PRIVATE_KEY.Alice, + sub: FIXTURE.USER.Alice.id, + request + }), + request, + metadata: { + confirmation: { + key: { + jwk: getPublicKey(bindPrivateKeyOne), + proof: ConfirmationClaimProofMethod.JWS, + jws: await signJwt( + { + requestHash: hash(request) + }, + bindPrivateKeyTwo + ) + } + } + } + } + + await expect(() => e.evaluate(evaluation)).rejects.toThrow('Invalid confirmation claim jws: Invalid signature') + }) }) describe('decide', () => { diff --git a/apps/policy-engine/src/open-policy-agent/core/open-policy-agent.engine.ts b/apps/policy-engine/src/open-policy-agent/core/open-policy-agent.engine.ts index a6b43c3ae..d6c146553 100644 --- a/apps/policy-engine/src/open-policy-agent/core/open-policy-agent.engine.ts +++ b/apps/policy-engine/src/open-policy-agent/core/open-policy-agent.engine.ts @@ -8,7 +8,8 @@ import { EvaluationRequest, EvaluationResponse, JwtString, - Policy + Policy, + verifyConfirmationClaimProofOfPossession } from '@narval/policy-engine-shared' import { decodeJwt, hash, verifyJwt } from '@narval/signature' import { Intent } from '@narval/transaction-request-intent' @@ -121,6 +122,10 @@ export class OpenPolicyAgentEngine implements Engine { const principalCredential = await this.verifySignature(evaluation.authentication, message) + if (evaluation.metadata?.confirmation) { + await verifyConfirmationClaimProofOfPossession(evaluation) + } + const approvalsCredential = await Promise.all( (evaluation.approvals || []).map((signature) => this.verifySignature(signature, message)) ) diff --git a/apps/vault/src/shared/guard/__test__/unit/authorization.guard.spec.ts b/apps/vault/src/shared/guard/__test__/unit/authorization.guard.spec.ts index 6407c255b..74c1c5dbc 100644 --- a/apps/vault/src/shared/guard/__test__/unit/authorization.guard.spec.ts +++ b/apps/vault/src/shared/guard/__test__/unit/authorization.guard.spec.ts @@ -155,12 +155,12 @@ describe('AuthorizationGuard', () => { } as unknown as ExecutionContext } - it('should throw when client-id header is missing', async () => { + it('throws when client-id header is missing', async () => { const guard = new AuthorizationGuard(mockClientService, mockConfigService, mockReflector, mockLogger) await expect(guard.canActivate(mockExecutionContext())).rejects.toThrow('Missing or invalid x-client-id header') }) - it('should throw when client is not found', async () => { + it('throws when client is not found', async () => { const guard = new AuthorizationGuard(mockClientService, mockConfigService, mockReflector, mockLogger) const mockRequest = { headers: { 'x-client-id': 'client-that-does-not-exist' }, @@ -173,7 +173,7 @@ describe('AuthorizationGuard', () => { await expect(guard.canActivate(context)).rejects.toThrow('Client not found') }) - it('should pass when client auth is disabled', async () => { + it('passes when client auth is disabled', async () => { const client = getBaseClient() client.auth.disabled = true mockClientService.findById.mockResolvedValue(client) @@ -192,7 +192,7 @@ describe('AuthorizationGuard', () => { }) // For this scenario, we don't yet support JWKS, so if you disable tokenValidation you must pin the allowed users - it('should throw when client auth is enabled AND token validation is disabled AND no allowed users are configured', async () => { + it('throws when client auth is enabled AND token validation is disabled AND no allowed users are configured', async () => { const client = getBaseClient() client.auth.tokenValidation.disabled = true mockClientService.findById.mockResolvedValue(client) @@ -210,7 +210,7 @@ describe('AuthorizationGuard', () => { expect(mockLogger.warn).toHaveBeenCalled() }) - it('should throw when client auth is enabled AND token validation is disabled AND invalid jwsd for allowedUsers', async () => { + it('throws when client auth is enabled AND token validation is disabled AND invalid jwsd for allowedUsers', async () => { const client = getBaseClient() client.auth.tokenValidation.disabled = true client.auth.local = { @@ -238,7 +238,7 @@ describe('AuthorizationGuard', () => { expect(mockLogger.warn).toHaveBeenCalled() }) - it('should pass when client auth is enabled AND token validation is disabled AND jwsd is valid for allowedUsers', async () => { + it('passes when client auth is enabled AND token validation is disabled AND jwsd is valid for allowedUsers', async () => { const userPrivateJwk = secp256k1PrivateKeyToJwk(FIXTURE.UNSAFE_PRIVATE_KEY.Alice) const userJwk = secp256k1PublicKeyToJwk(FIXTURE.VIEM_ACCOUNT.Alice.publicKey) const client = getBaseClient() @@ -309,7 +309,7 @@ describe('AuthorizationGuard', () => { }) // JWT Validation - it('should throw when no pinnedPublicKey is configured', async () => { + it('throws when no pinnedPublicKey is configured', async () => { const client = getBaseClient() client.auth.tokenValidation.pinnedPublicKey = null mockClientService.findById.mockResolvedValue(client) @@ -361,7 +361,7 @@ describe('AuthorizationGuard', () => { ) }) - it('should pass when token is bound but used by a different user', async () => { + it('passes when token is bound but used by a different user', async () => { const userJwk = secp256k1PublicKeyToJwk(FIXTURE.VIEM_ACCOUNT.Alice.publicKey) const client = getBaseClient() mockClientService.findById.mockResolvedValue(client) @@ -389,7 +389,7 @@ describe('AuthorizationGuard', () => { await expect(guard.canActivate(context)).rejects.toThrow('Invalid signature') }) - it('should pass when token is valid & request is bound with jwsd', async () => { + it('passes when token is valid & request is bound with jwsd', async () => { const userPrivateJwk = secp256k1PrivateKeyToJwk(FIXTURE.UNSAFE_PRIVATE_KEY.Alice) const userJwk = secp256k1PublicKeyToJwk(FIXTURE.VIEM_ACCOUNT.Alice.publicKey) const client = getBaseClient() diff --git a/package-lock.json b/package-lock.json index f761c6795..da253687a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1640,12 +1640,12 @@ } }, "node_modules/@babel/parser": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.5.tgz", - "integrity": "sha512-SRJ4jYmXRqV1/Xc+TIVG84WjHBXKlxO9sHQnA2Pf12QQEAp1LOh6kDzNHXcUnbH1QI0FDoPPVOt+vyUDucxpaw==", + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.7.tgz", + "integrity": "sha512-kEvgGGgEjRUutvdVvZhbn/BxVt+5VSpwXz1j3WYXQbXDo8KzFOPNG2GQbdAiNq8g6wn1yKk7C/qrke03a84V+w==", "license": "MIT", "dependencies": { - "@babel/types": "^7.26.5" + "@babel/types": "^7.26.7" }, "bin": { "parser": "bin/babel-parser.js" @@ -3340,17 +3340,17 @@ }, "node_modules/@babel/traverse--for-generate-function-map": { "name": "@babel/traverse", - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.5.tgz", - "integrity": "sha512-rkOSPOw+AXbgtwUga3U4u8RpoK9FEFWBNAlTpcnkLFjL5CT+oyHNuUUC/xx6XefEJ16r38r8Bc/lfp6rYuHeJQ==", + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.7.tgz", + "integrity": "sha512-1x1sgeyRLC3r5fQOM0/xtQKsYjyxmFjaOrLJNtZ81inNjyJHGIolTULPiSc/2qe1/qfpFLisLQYFnnZl7QoedA==", "license": "MIT", "peer": true, "dependencies": { "@babel/code-frame": "^7.26.2", "@babel/generator": "^7.26.5", - "@babel/parser": "^7.26.5", + "@babel/parser": "^7.26.7", "@babel/template": "^7.25.9", - "@babel/types": "^7.26.5", + "@babel/types": "^7.26.7", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -3359,9 +3359,9 @@ } }, "node_modules/@babel/types": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.5.tgz", - "integrity": "sha512-L6mZmwFDK6Cjh1nRCLXpa6no13ZIioJDz7mdkzHv399pThrTa/k0nUlNaenOeh2kWu/iaOQYElEpKPUswUa9Vg==", + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.7.tgz", + "integrity": "sha512-t8kDRGrKXyp6+tjUh7hw2RLyclsW4TRoRvRHtSyAX9Bb5ldlFh+90YAYY6awRXrlB4G5G2izNeGySpATlFzmOg==", "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.25.9", @@ -17769,16 +17769,6 @@ "@babel/core": "*" } }, - "node_modules/@react-native/babel-preset/node_modules/react-refresh": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", - "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/@react-native/codegen": { "version": "0.77.0", "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.77.0.tgz", @@ -17900,9 +17890,9 @@ "peer": true }, "node_modules/@react-native/community-cli-plugin/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.0.tgz", + "integrity": "sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ==", "license": "ISC", "peer": true, "bin": { @@ -25166,13 +25156,6 @@ "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", "dev": true }, - "node_modules/denodeify": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz", - "integrity": "sha512-KNTihKNmQENUZeKu5fzfpzRqR5S2VMp4gl9RFHiWzj9DfvYQPMJ6XHKNaQxaGCXwPk6y9yme3aUoaiAe+KX+vg==", - "license": "MIT", - "peer": true - }, "node_modules/denque": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", @@ -25674,31 +25657,6 @@ "node": ">= 0.8" } }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, - "node_modules/encoding/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -34068,9 +34026,9 @@ } }, "node_modules/metro": { - "version": "0.81.0", - "resolved": "https://registry.npmjs.org/metro/-/metro-0.81.0.tgz", - "integrity": "sha512-kzdzmpL0gKhEthZ9aOV7sTqvg6NuTxDV8SIm9pf9sO8VVEbKrQk5DNcwupOUjgPPFAuKUc2NkT0suyT62hm2xg==", + "version": "0.81.1", + "resolved": "https://registry.npmjs.org/metro/-/metro-0.81.1.tgz", + "integrity": "sha512-fqRu4fg8ONW7VfqWFMGgKAcOuMzyoQah2azv9Y3VyFXAmG+AoTU6YIFWqAADESCGVWuWEIvxTJhMf3jxU6jwjA==", "license": "MIT", "peer": true, "dependencies": { @@ -34086,33 +34044,31 @@ "ci-info": "^2.0.0", "connect": "^3.6.5", "debug": "^2.2.0", - "denodeify": "^1.2.1", "error-stack-parser": "^2.0.6", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", - "hermes-parser": "0.24.0", + "hermes-parser": "0.25.1", "image-size": "^1.0.2", "invariant": "^2.2.4", "jest-worker": "^29.6.3", "jsc-safe-url": "^0.2.2", "lodash.throttle": "^4.1.1", - "metro-babel-transformer": "0.81.0", - "metro-cache": "0.81.0", - "metro-cache-key": "0.81.0", - "metro-config": "0.81.0", - "metro-core": "0.81.0", - "metro-file-map": "0.81.0", - "metro-resolver": "0.81.0", - "metro-runtime": "0.81.0", - "metro-source-map": "0.81.0", - "metro-symbolicate": "0.81.0", - "metro-transform-plugins": "0.81.0", - "metro-transform-worker": "0.81.0", + "metro-babel-transformer": "0.81.1", + "metro-cache": "0.81.1", + "metro-cache-key": "0.81.1", + "metro-config": "0.81.1", + "metro-core": "0.81.1", + "metro-file-map": "0.81.1", + "metro-resolver": "0.81.1", + "metro-runtime": "0.81.1", + "metro-source-map": "0.81.1", + "metro-symbolicate": "0.81.1", + "metro-transform-plugins": "0.81.1", + "metro-transform-worker": "0.81.1", "mime-types": "^2.1.27", "nullthrows": "^1.1.1", "serialize-error": "^2.1.0", "source-map": "^0.5.6", - "strip-ansi": "^6.0.0", "throat": "^5.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" @@ -34125,57 +34081,40 @@ } }, "node_modules/metro-babel-transformer": { - "version": "0.81.0", - "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.81.0.tgz", - "integrity": "sha512-Dc0QWK4wZIeHnyZ3sevWGTnnSkIDDn/SWyfrn99zbKbDOCoCYy71PAn9uCRrP/hduKLJQOy+tebd63Rr9D8tXg==", + "version": "0.81.1", + "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.81.1.tgz", + "integrity": "sha512-JECKDrQaUnDmj0x/Q/c8c5YwsatVx38Lu+BfCwX9fR8bWipAzkvJocBpq5rOAJRDXRgDcPv2VO4Q4nFYrpYNQg==", "license": "MIT", "peer": true, "dependencies": { "@babel/core": "^7.25.2", "flow-enums-runtime": "^0.0.6", - "hermes-parser": "0.24.0", + "hermes-parser": "0.25.1", "nullthrows": "^1.1.1" }, "engines": { "node": ">=18.18" } }, - "node_modules/metro-babel-transformer/node_modules/hermes-estree": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.24.0.tgz", - "integrity": "sha512-LyoXLB7IFzeZW0EvAbGZacbxBN7t6KKSDqFJPo3Ydow7wDlrDjXwsdiAHV6XOdvEN9MEuWXsSIFN4tzpyrXIHw==", - "license": "MIT", - "peer": true - }, - "node_modules/metro-babel-transformer/node_modules/hermes-parser": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.24.0.tgz", - "integrity": "sha512-IJooSvvu2qNRe7oo9Rb04sUT4omtZqZqf9uq9WM25Tb6v3usmvA93UqfnnoWs5V0uYjEl9Al6MNU10MCGKLwpg==", - "license": "MIT", - "peer": true, - "dependencies": { - "hermes-estree": "0.24.0" - } - }, "node_modules/metro-cache": { - "version": "0.81.0", - "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.81.0.tgz", - "integrity": "sha512-DyuqySicHXkHUDZFVJmh0ygxBSx6pCKUrTcSgb884oiscV/ROt1Vhye+x+OIHcsodyA10gzZtrVtxIFV4l9I4g==", + "version": "0.81.1", + "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.81.1.tgz", + "integrity": "sha512-Uqcmn6sZ+Y0VJHM88VrG5xCvSeU7RnuvmjPmSOpEcyJJBe02QkfHL05MX2ZyGDTyZdbKCzaX0IijrTe4hN3F0Q==", "license": "MIT", "peer": true, "dependencies": { "exponential-backoff": "^3.1.1", "flow-enums-runtime": "^0.0.6", - "metro-core": "0.81.0" + "metro-core": "0.81.1" }, "engines": { "node": ">=18.18" } }, "node_modules/metro-cache-key": { - "version": "0.81.0", - "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.81.0.tgz", - "integrity": "sha512-qX/IwtknP9bQZL78OK9xeSvLM/xlGfrs6SlUGgHvrxtmGTRSsxcyqxR+c+7ch1xr05n62Gin/O44QKg5V70rNQ==", + "version": "0.81.1", + "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.81.1.tgz", + "integrity": "sha512-5fDaHR1yTvpaQuwMAeEoZGsVyvjrkw9IFAS7WixSPvaNY5YfleqoJICPc6hbXFJjvwCCpwmIYFkjqzR/qJ6yqA==", "license": "MIT", "peer": true, "dependencies": { @@ -34186,9 +34125,9 @@ } }, "node_modules/metro-config": { - "version": "0.81.0", - "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.81.0.tgz", - "integrity": "sha512-6CinEaBe3WLpRlKlYXXu8r1UblJhbwD6Gtnoib5U8j6Pjp7XxMG9h/DGMeNp9aGLDu1OieUqiXpFo7O0/rR5Kg==", + "version": "0.81.1", + "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.81.1.tgz", + "integrity": "sha512-VAAJmxsKIZ+Fz5/z1LVgxa32gE6+2TvrDSSx45g85WoX4EtLmdBGP3DSlpQW3DqFUfNHJCGwMLGXpJnxifd08g==", "license": "MIT", "peer": true, "dependencies": { @@ -34196,10 +34135,10 @@ "cosmiconfig": "^5.0.5", "flow-enums-runtime": "^0.0.6", "jest-validate": "^29.6.3", - "metro": "0.81.0", - "metro-cache": "0.81.0", - "metro-core": "0.81.0", - "metro-runtime": "0.81.0" + "metro": "0.81.1", + "metro-cache": "0.81.1", + "metro-core": "0.81.1", + "metro-runtime": "0.81.1" }, "engines": { "node": ">=18.18" @@ -34291,28 +34230,27 @@ "peer": true }, "node_modules/metro-core": { - "version": "0.81.0", - "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.81.0.tgz", - "integrity": "sha512-CVkM5YCOAFkNMvJai6KzA0RpztzfEKRX62/PFMOJ9J7K0uq/UkOFLxcgpcncMIrfy0PbfEj811b69tjULUQe1Q==", + "version": "0.81.1", + "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.81.1.tgz", + "integrity": "sha512-4d2/+02IYqOwJs4dmM0dC8hIZqTzgnx2nzN4GTCaXb3Dhtmi/SJ3v6744zZRnithhN4lxf8TTJSHnQV75M7SSA==", "license": "MIT", "peer": true, "dependencies": { "flow-enums-runtime": "^0.0.6", "lodash.throttle": "^4.1.1", - "metro-resolver": "0.81.0" + "metro-resolver": "0.81.1" }, "engines": { "node": ">=18.18" } }, "node_modules/metro-file-map": { - "version": "0.81.0", - "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.81.0.tgz", - "integrity": "sha512-zMDI5uYhQCyxbye/AuFx/pAbsz9K+vKL7h1ShUXdN2fz4VUPiyQYRsRqOoVG1DsiCgzd5B6LW0YW77NFpjDQeg==", + "version": "0.81.1", + "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.81.1.tgz", + "integrity": "sha512-aY72H2ujmRfFxcsbyh83JgqFF+uQ4HFN1VhV2FmcfQG4s1bGKf2Vbkk+vtZ1+EswcBwDZFbkpvAjN49oqwGzAA==", "license": "MIT", "peer": true, "dependencies": { - "anymatch": "^3.0.3", "debug": "^2.2.0", "fb-watchman": "^2.0.0", "flow-enums-runtime": "^0.0.6", @@ -34320,15 +34258,11 @@ "invariant": "^2.2.4", "jest-worker": "^29.6.3", "micromatch": "^4.0.4", - "node-abort-controller": "^3.1.1", "nullthrows": "^1.1.1", "walker": "^1.0.7" }, "engines": { "node": ">=18.18" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" } }, "node_modules/metro-file-map/node_modules/debug": { @@ -34349,9 +34283,9 @@ "peer": true }, "node_modules/metro-minify-terser": { - "version": "0.81.0", - "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.81.0.tgz", - "integrity": "sha512-U2ramh3W822ZR1nfXgIk+emxsf5eZSg10GbQrT0ZizImK8IZ5BmJY+BHRIkQgHzWFpExOVxC7kWbGL1bZALswA==", + "version": "0.81.1", + "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.81.1.tgz", + "integrity": "sha512-p/Qz3NNh1nebSqMlxlUALAnESo6heQrnvgHtAuxufRPtKvghnVDq9hGGex8H7z7YYLsqe42PWdt4JxTA3mgkvg==", "license": "MIT", "peer": true, "dependencies": { @@ -34363,9 +34297,9 @@ } }, "node_modules/metro-resolver": { - "version": "0.81.0", - "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.81.0.tgz", - "integrity": "sha512-Uu2Q+buHhm571cEwpPek8egMbdSTqmwT/5U7ZVNpK6Z2ElQBBCxd7HmFAslKXa7wgpTO2FAn6MqGeERbAtVDUA==", + "version": "0.81.1", + "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.81.1.tgz", + "integrity": "sha512-E61t6fxRoYRkl6Zo3iUfCKW4DYfum/bLjcejXBMt1y3I7LFkK84TCR/Rs9OAwsMCY/7GOPB4+CREYZOtCC7CNA==", "license": "MIT", "peer": true, "dependencies": { @@ -34376,9 +34310,9 @@ } }, "node_modules/metro-runtime": { - "version": "0.81.0", - "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.81.0.tgz", - "integrity": "sha512-6oYB5HOt37RuGz2eV4A6yhcl+PUTwJYLDlY9vhT+aVjbUWI6MdBCf69vc4f5K5Vpt+yOkjy+2LDwLS0ykWFwYw==", + "version": "0.81.1", + "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.81.1.tgz", + "integrity": "sha512-pqu5j5d01rjF85V/K8SDDJ0NR3dRp6bE3z5bKVVb5O2Rx0nbR9KreUxYALQCRCcQHaYySqCg5fYbGKBHC295YQ==", "license": "MIT", "peer": true, "dependencies": { @@ -34390,9 +34324,9 @@ } }, "node_modules/metro-source-map": { - "version": "0.81.0", - "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.81.0.tgz", - "integrity": "sha512-TzsVxhH83dyxg4A4+L1nzNO12I7ps5IHLjKGZH3Hrf549eiZivkdjYiq/S5lOB+p2HiQ+Ykcwtmcja95LIC62g==", + "version": "0.81.1", + "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.81.1.tgz", + "integrity": "sha512-1i8ROpNNiga43F0ZixAXoFE/SS3RqcRDCCslpynb+ytym0VI7pkTH1woAN2HI9pczYtPrp3Nq0AjRpsuY35ieA==", "license": "MIT", "peer": true, "dependencies": { @@ -34401,9 +34335,9 @@ "@babel/types": "^7.25.2", "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", - "metro-symbolicate": "0.81.0", + "metro-symbolicate": "0.81.1", "nullthrows": "^1.1.1", - "ob1": "0.81.0", + "ob1": "0.81.1", "source-map": "^0.5.6", "vlq": "^1.0.0" }, @@ -34422,18 +34356,17 @@ } }, "node_modules/metro-symbolicate": { - "version": "0.81.0", - "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.81.0.tgz", - "integrity": "sha512-C/1rWbNTPYp6yzID8IPuQPpVGzJ2rbWYBATxlvQ9dfK5lVNoxcwz77hjcY8ISLsRRR15hyd/zbjCNKPKeNgE1Q==", + "version": "0.81.1", + "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.81.1.tgz", + "integrity": "sha512-Lgk0qjEigtFtsM7C0miXITbcV47E1ZYIfB+m/hCraihiwRWkNUQEPCWvqZmwXKSwVE5mXA0EzQtghAvQSjZDxw==", "license": "MIT", "peer": true, "dependencies": { "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", - "metro-source-map": "0.81.0", + "metro-source-map": "0.81.1", "nullthrows": "^1.1.1", "source-map": "^0.5.6", - "through2": "^2.0.1", "vlq": "^1.0.0" }, "bin": { @@ -34454,9 +34387,9 @@ } }, "node_modules/metro-transform-plugins": { - "version": "0.81.0", - "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.81.0.tgz", - "integrity": "sha512-uErLAPBvttGCrmGSCa0dNHlOTk3uJFVEVWa5WDg6tQ79PRmuYRwzUgLhVzn/9/kyr75eUX3QWXN79Jvu4txt6Q==", + "version": "0.81.1", + "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.81.1.tgz", + "integrity": "sha512-7L1lI44/CyjIoBaORhY9fVkoNe8hrzgxjSCQ/lQlcfrV31cZb7u0RGOQrKmUX7Bw4FpejrB70ArQ7Mse9mk7+Q==", "license": "MIT", "peer": true, "dependencies": { @@ -34472,9 +34405,9 @@ } }, "node_modules/metro-transform-worker": { - "version": "0.81.0", - "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.81.0.tgz", - "integrity": "sha512-HrQ0twiruhKy0yA+9nK5bIe3WQXZcC66PXTvRIos61/EASLAP2DzEmW7IxN/MGsfZegN2UzqL2CG38+mOB45vg==", + "version": "0.81.1", + "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.81.1.tgz", + "integrity": "sha512-M+2hVT3rEy5K7PBmGDgQNq3Zx53TjScOcO/CieyLnCRFtBGWZiSJ2+bLAXXOKyKa/y3bI3i0owxtyxuPGDwbZg==", "license": "MIT", "peer": true, "dependencies": { @@ -34483,13 +34416,13 @@ "@babel/parser": "^7.25.3", "@babel/types": "^7.25.2", "flow-enums-runtime": "^0.0.6", - "metro": "0.81.0", - "metro-babel-transformer": "0.81.0", - "metro-cache": "0.81.0", - "metro-cache-key": "0.81.0", - "metro-minify-terser": "0.81.0", - "metro-source-map": "0.81.0", - "metro-transform-plugins": "0.81.0", + "metro": "0.81.1", + "metro-babel-transformer": "0.81.1", + "metro-cache": "0.81.1", + "metro-cache-key": "0.81.1", + "metro-minify-terser": "0.81.1", + "metro-source-map": "0.81.1", + "metro-transform-plugins": "0.81.1", "nullthrows": "^1.1.1" }, "engines": { @@ -34520,23 +34453,6 @@ "license": "MIT", "peer": true }, - "node_modules/metro/node_modules/hermes-estree": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.24.0.tgz", - "integrity": "sha512-LyoXLB7IFzeZW0EvAbGZacbxBN7t6KKSDqFJPo3Ydow7wDlrDjXwsdiAHV6XOdvEN9MEuWXsSIFN4tzpyrXIHw==", - "license": "MIT", - "peer": true - }, - "node_modules/metro/node_modules/hermes-parser": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.24.0.tgz", - "integrity": "sha512-IJooSvvu2qNRe7oo9Rb04sUT4omtZqZqf9uq9WM25Tb6v3usmvA93UqfnnoWs5V0uYjEl9Al6MNU10MCGKLwpg==", - "license": "MIT", - "peer": true, - "dependencies": { - "hermes-estree": "0.24.0" - } - }, "node_modules/metro/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -36941,7 +36857,8 @@ "node_modules/node-abort-controller": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", - "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==" + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", + "dev": true }, "node_modules/node-addon-api": { "version": "2.0.2", @@ -37308,9 +37225,9 @@ } }, "node_modules/ob1": { - "version": "0.81.0", - "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.81.0.tgz", - "integrity": "sha512-6Cvrkxt1tqaRdWqTAMcVYEiO5i1xcF9y7t06nFdjFqkfPsEloCf8WwhXdwBpNUkVYSQlSGS7cDgVQR86miBfBQ==", + "version": "0.81.1", + "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.81.1.tgz", + "integrity": "sha512-1PEbvI+AFvOcgdNcO79FtDI1TUO8S3lhiKOyAiyWQF3sFDDKS+aw2/BZvGlArFnSmqckwOOB9chQuIX0/OahoQ==", "license": "MIT", "peer": true, "dependencies": { @@ -39286,6 +39203,16 @@ "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-1.0.0.tgz", "integrity": "sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==" }, + "node_modules/promise": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", + "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", + "license": "MIT", + "peer": true, + "dependencies": { + "asap": "~2.0.6" + } + }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -40037,9 +39964,9 @@ } }, "node_modules/react-devtools-core": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-6.0.1.tgz", - "integrity": "sha512-II3iSJhnR5nAscYDa9FCgPLq8mO5aEx/EKKtdXYTDnvdFEa3K7gs3jn1SKRXwQf9maOmIilmjnnx7Qy+3annPA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-6.1.0.tgz", + "integrity": "sha512-sA8gF/pUhjoGAN3s1Ya43h+F4Q0z7cv9RgqbUfhP7bJI0MbqeshLYFb6hiHgZorovGr8AXqhLi22eQ7V3pru/Q==", "license": "MIT", "peer": true, "dependencies": { @@ -40288,16 +40215,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/react-native/node_modules/promise": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", - "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", - "license": "MIT", - "peer": true, - "dependencies": { - "asap": "~2.0.6" - } - }, "node_modules/react-native/node_modules/react-is": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", @@ -40305,16 +40222,6 @@ "license": "MIT", "peer": true }, - "node_modules/react-native/node_modules/react-refresh": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", - "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/react-native/node_modules/regenerator-runtime": { "version": "0.13.11", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", @@ -40333,9 +40240,9 @@ } }, "node_modules/react-native/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.0.tgz", + "integrity": "sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ==", "license": "ISC", "peer": true, "bin": { @@ -40389,6 +40296,16 @@ "node": ">=12" } }, + "node_modules/react-refresh": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/react-remove-scroll": { "version": "2.5.5", "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz", @@ -43556,57 +43473,6 @@ "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "dev": true }, - "node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/through2/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "license": "MIT", - "peer": true - }, - "node_modules/through2/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "license": "MIT", - "peer": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/through2/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "license": "MIT", - "peer": true - }, - "node_modules/through2/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "license": "MIT", - "peer": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", @@ -46256,7 +46122,7 @@ }, "packages/armory-sdk": { "name": "@narval-xyz/armory-sdk", - "version": "0.18.0", + "version": "0.19.0", "license": "MPL-2.0", "dependencies": { "@noble/curves": "1.6.0", diff --git a/packages/armory-e2e-testing/src/__test__/e2e/scenario/bind-access-token.spec.ts b/packages/armory-e2e-testing/src/__test__/e2e/scenario/bind-access-token.spec.ts new file mode 100644 index 000000000..5076d92c6 --- /dev/null +++ b/packages/armory-e2e-testing/src/__test__/e2e/scenario/bind-access-token.spec.ts @@ -0,0 +1,394 @@ +/* eslint-disable no-console */ +import { + Action, + AuthAdminClient, + AuthClient, + Criterion, + Entities, + EntityStoreClient, + EntityUtil, + Permission, + Policy, + PolicyStoreClient, + Then, + UserEntity, + UserRole, + VaultAdminClient, + VaultClient, + createHttpDataStore, + credential, + resourceId +} from '@narval/armory-sdk' +import { + AccountEntity, + AccountType, + ConfirmationClaimProofMethod, + SignTransactionAction +} from '@narval/policy-engine-shared' +import { Ed25519PrivateKey, buildSignerForAlg, getPublicKey, hash, signJwt } from '@narval/signature' +import { AxiosError } from 'axios' +import { randomUUID } from 'crypto' +import { format } from 'date-fns' +import { v4 as uuid } from 'uuid' +import { Hex } from 'viem' +import { privateKeyToAccount } from 'viem/accounts' + +const ACCOUNT_PRIVATE_KEY: Hex = '0x7cfef3303797cbc7515d9ce22ffe849c701b0f2812f999b0847229c47951fca5' + +const TEST_TIMEOUT_MS = 30_000 + +jest.setTimeout(TEST_TIMEOUT_MS) + +const getAuthHost = () => 'http://localhost:3005' + +const getAuthAdminApiKey = () => 'armory-admin-api-key' + +const getVaultHost = () => 'http://localhost:3011' + +const getVaultAdminApiKey = () => 'vault-admin-api-key' + +// IMPORTANT: The order of tests matters. +// These tests are meant to be run in series, not in parallel, because they +// represent an end-to-end user journey. +describe('User Journeys', () => { + let ephemeralPrivateKey: Ed25519PrivateKey + let dataStorePrivateKey: Ed25519PrivateKey + let appPrivateKey: Ed25519PrivateKey + let authClient: AuthClient + let vaultClient: VaultClient + + const clientId = uuid() + + const setup = async () => { + try { + const authAdminClient = new AuthAdminClient({ + host: getAuthHost(), + adminApiKey: getAuthAdminApiKey() + }) + + const vaultAdminClient = new VaultAdminClient({ + host: getVaultHost(), + adminApiKey: getVaultAdminApiKey() + }) + + const vaultClient = new VaultClient({ + host: getVaultHost(), + clientId, + signer: { + jwk: getPublicKey(ephemeralPrivateKey), + alg: ephemeralPrivateKey.alg, + sign: await buildSignerForAlg(ephemeralPrivateKey) + } + }) + + const authClient = new AuthClient({ + host: getAuthHost(), + clientId, + signer: { + jwk: getPublicKey(appPrivateKey), + alg: appPrivateKey.alg, + sign: await buildSignerForAlg(appPrivateKey) + }, + pollingTimeoutMs: TEST_TIMEOUT_MS - 10_000, + // In a local AS and PE, 250 ms is equivalent to ~3 requests until + // the job is processed. + pollingIntervalMs: 250 + }) + + const clientAuth = await authAdminClient.createClient({ + id: clientId, + name: `Bind Access Token E2E Test ${format(new Date(), 'dd/MM/yyyy HH:mm:ss')}`, + dataStore: createHttpDataStore({ + host: getAuthHost(), + clientId, + keys: [getPublicKey(dataStorePrivateKey)] + }), + useManagedDataStore: true + }) + + await vaultAdminClient.createClient({ + clientId, + name: `provider-e2e-testing-${clientId}`, + baseUrl: getVaultHost(), + auth: { + local: { + jwsd: { + maxAge: 300, + requiredComponents: ['htm', 'uri', 'created', 'ath'] + } + }, + tokenValidation: { + disabled: false, + url: null, + // IMPORTANT: Pin the policy engine's public key in the token + // validation. + pinnedPublicKey: clientAuth.policyEngine.nodes[0].publicKey, + verification: { + audience: null, + issuer: 'https://armory.narval.xyz', + maxTokenAge: 300, + // IMPORTANT: It must be set to true + requireBoundTokens: true, + // IMPORTANT: It does not need bearer token + allowBearerTokens: false + } + } + } + }) + + const viemAccount = privateKeyToAccount(ACCOUNT_PRIVATE_KEY) + + const account: AccountEntity = { + id: resourceId(viemAccount.address), + address: viemAccount.address, + accountType: AccountType.EOA + } + + const appUser: UserEntity = { + id: uuid(), + role: UserRole.ADMIN + } + + const entities: Entities = { + ...EntityUtil.empty(), + users: [appUser], + credentials: [credential(appUser, getPublicKey(appPrivateKey))], + accounts: [account] + } + + const policies: Policy[] = [ + { + id: uuid(), + description: 'Allows admin to do anything', + when: [ + { + criterion: Criterion.CHECK_PRINCIPAL_ROLE, + args: [UserRole.ADMIN] + } + ], + then: Then.PERMIT + } + ] + + const entityStoreClient = new EntityStoreClient({ + host: getAuthHost(), + clientId: clientAuth.id, + clientSecret: clientAuth.clientSecret, + signer: { + jwk: dataStorePrivateKey, + alg: dataStorePrivateKey.alg, + sign: await buildSignerForAlg(dataStorePrivateKey) + } + }) + + await entityStoreClient.signAndPush(entities) + + const policyStoreClient = new PolicyStoreClient({ + host: getAuthHost(), + clientId: clientAuth.id, + clientSecret: clientAuth.clientSecret, + signer: { + jwk: dataStorePrivateKey, + alg: dataStorePrivateKey.alg, + sign: await buildSignerForAlg(dataStorePrivateKey) + } + }) + + await policyStoreClient.signAndPush(policies) + + return { + vaultClient, + authClient + } + } catch (error) { + if (error instanceof AxiosError) { + console.dir( + { + url: error.config?.url, + status: error.response?.status, + body: error.response?.data + }, + { depth: null } + ) + } + + throw error + } + } + + beforeAll(async () => { + // Pin the keys because it's easier to debug a known value. + ephemeralPrivateKey = { + kty: 'OKP', + crv: 'Ed25519', + alg: 'EDDSA', + kid: '0x65a3f312d1fc34e937ca9c1b7fbe5b9f98fb15e2cb15594ec6cd5167e36a58e3', + x: 'n0AX7pAzBhCr6R7dRhPqeGDVIKRaatVjdmL3KX58HGw', + d: 'tl8nZiFTRa5C_yJvL73KFnxDbuUi8h6bUvh28jvXmII' + } + + dataStorePrivateKey = { + kty: 'OKP', + crv: 'Ed25519', + alg: 'EDDSA', + kid: '0xb97232aabc42dbf69f19379a66417f9488520a3d3062bd14932ffc61e6958755', + x: '1e9Qy9e12g_HNNad-BxcgMWl7W7htIZ-M50Xr-RSFSM', + d: 'XxsSP2a3notOyIBr4qWwQl-uNsUqrG8cCXDwLRVR08w' + } + + appPrivateKey = { + kty: 'OKP', + crv: 'Ed25519', + alg: 'EDDSA', + kid: '0xffe1b0b211c314237b26cc5fc346445496a4b0ab65e5c007de46dfcdbf917ced', + x: 'bqV752BughPmE8QWcHc3EQdfrzomMcr_1k2kaj6v3mY', + d: '0ZIIuPFtY6iOuqlp7CcX4yyAIokJtLRqu43voyfyjZg' + } + + const context = await setup() + + authClient = context.authClient + vaultClient = context.vaultClient + }) + + it('I can issue a grant permission bound access token and use it', async () => { + try { + const request = { + action: Action.GRANT_PERMISSION, + resourceId: 'vault', + nonce: randomUUID(), + permissions: ['connection:write', 'connection:read'] + } + + const accessToken = await authClient.requestAccessToken(request, { + metadata: { + confirmation: { + key: { + jwk: getPublicKey(ephemeralPrivateKey), + proof: ConfirmationClaimProofMethod.JWS, + jws: await signJwt( + { + requestHash: hash(request) + }, + ephemeralPrivateKey + ) + } + } + } + }) + + await expect(vaultClient.listConnections({ accessToken })).resolves.not.toThrow() + } catch (error) { + if (error instanceof AxiosError) { + console.dir( + { + url: error.config?.url, + status: error.response?.status, + body: error.response?.data + }, + { depth: null } + ) + } + + throw error + } + }) + + it('I can issue a bound access token and use it to sign transaction', async () => { + try { + // + // SETUP + // + + const grantPermissionRequest = { + action: Action.GRANT_PERMISSION, + resourceId: 'vault', + nonce: randomUUID(), + permissions: [Permission.WALLET_IMPORT, Permission.WALLET_CREATE] + } + + const importAccountAccessToken = await authClient.requestAccessToken(grantPermissionRequest, { + metadata: { + confirmation: { + key: { + jwk: getPublicKey(ephemeralPrivateKey), + proof: ConfirmationClaimProofMethod.JWS, + jws: await signJwt( + { + requestHash: hash(grantPermissionRequest) + }, + ephemeralPrivateKey + ) + } + } + } + }) + + const encryptionKey = await vaultClient.generateEncryptionKey({ accessToken: importAccountAccessToken }) + + const account = await vaultClient.importAccount({ + data: { + privateKey: ACCOUNT_PRIVATE_KEY + }, + accessToken: importAccountAccessToken, + encryptionKey + }) + + // + // SIGN TRANSACTION + // + + const signTxRequest: SignTransactionAction = { + action: Action.SIGN_TRANSACTION, + nonce: uuid(), + resourceId: account.id, + transactionRequest: { + chainId: 1, + data: '0x', + from: account.address, + gas: 5000n, + nonce: 0, + to: '0xbbb7be636c3ad8cf9d08ba8bdba4abd2ef29bd23', + type: '2' + } + } + + const signTxAccessToken = await authClient.requestAccessToken(signTxRequest, { + metadata: { + confirmation: { + key: { + jwk: getPublicKey(ephemeralPrivateKey), + proof: ConfirmationClaimProofMethod.JWS, + jws: await signJwt( + { + requestHash: hash(signTxRequest) + }, + ephemeralPrivateKey + ) + } + } + } + }) + + const { signature } = await vaultClient.sign({ + data: signTxRequest, + accessToken: signTxAccessToken + }) + + expect(signature).toEqual(expect.any(String)) + } catch (error) { + if (error instanceof AxiosError) { + console.dir( + { + url: error.config?.url, + status: error.response?.status, + body: error.response?.data + }, + { depth: null } + ) + } + + throw error + } + }) +}) diff --git a/packages/armory-sdk/package.json b/packages/armory-sdk/package.json index 67f5b8c35..57e933265 100644 --- a/packages/armory-sdk/package.json +++ b/packages/armory-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@narval-xyz/armory-sdk", - "version": "0.18.0", + "version": "0.19.0", "license": "MPL-2.0", "publishConfig": { "access": "public" diff --git a/packages/armory-sdk/src/lib/auth/client.ts b/packages/armory-sdk/src/lib/auth/client.ts index f4f9311bf..bc8b985a7 100644 --- a/packages/armory-sdk/src/lib/auth/client.ts +++ b/packages/armory-sdk/src/lib/auth/client.ts @@ -14,10 +14,10 @@ import { v4 as uuid } from 'uuid' import { ArmorySdkException } from '../exceptions' import { ApplicationApi, - AuthorizationApiFactory, + AuthorizationApi, AuthorizationResponseDto, AuthorizationResponseDtoStatusEnum, - ClientApiFactory, + ClientApi, Configuration, CreateClientRequestDto, CreateClientResponseDto, @@ -26,20 +26,12 @@ import { import { polling } from '../shared/promise' import { SignOptions } from '../shared/type' import { AuthorizationResponse } from '../types' -import { - AuthAdminConfig, - AuthClientHttp, - AuthConfig, - AuthorizationHttp, - AuthorizationResult, - Evaluate, - RequestAccessTokenOptions -} from './type' +import { AuthAdminConfig, AuthConfig, AuthorizationResult, Evaluate, RequestAccessTokenOptions } from './type' export class AuthAdminClient { private config: AuthAdminConfig - private clientHttp: AuthClientHttp + private clientHttp: ClientApi constructor(config: AuthAdminConfig) { const httpConfig = new Configuration({ @@ -49,7 +41,8 @@ export class AuthAdminClient { const axiosInstance = axios.create() this.config = config - this.clientHttp = ClientApiFactory(httpConfig, config.host, axiosInstance) + + this.clientHttp = new ClientApi(httpConfig, config.host, axiosInstance) } /** @@ -62,7 +55,10 @@ export class AuthAdminClient { async createClient(input: CreateClientRequestDto): Promise { assert(this.config.adminApiKey !== undefined, 'Missing admin API key') - const { data } = await this.clientHttp.create(this.config.adminApiKey, input) + const { data } = await this.clientHttp.create({ + xApiKey: this.config.adminApiKey, + createClientRequestDto: input + }) return data } @@ -71,7 +67,7 @@ export class AuthAdminClient { export class AuthClient { private config: AuthConfig - private authorizationHttp: AuthorizationHttp + private authorizationHttp: AuthorizationApi private applicationApi: ApplicationApi @@ -84,7 +80,7 @@ export class AuthClient { this.config = AuthConfig.parse(config) - this.authorizationHttp = AuthorizationApiFactory(httpConfig, config.host, axiosInstance) + this.authorizationHttp = new AuthorizationApi(httpConfig, config.host, axiosInstance) this.applicationApi = new ApplicationApi(httpConfig, config.host, axiosInstance) } @@ -116,7 +112,10 @@ export class AuthClient { authentication }) - const { data } = await this.authorizationHttp.evaluate(this.config.clientId, request) + const { data } = await this.authorizationHttp.evaluate({ + xClientId: this.config.clientId, + authorizationRequestDto: request + }) return polling({ fn: async () => AuthorizationRequest.parse(await this.getAuthorizationById(data.id)), @@ -135,7 +134,10 @@ export class AuthClient { * @returns A Promise that resolves to the retrieved AuthorizationResponseDto. */ async getAuthorizationById(id: string): Promise { - const { data } = await this.authorizationHttp.getById(id, this.config.clientId) + const { data } = await this.authorizationHttp.getById({ + xClientId: this.config.clientId, + id + }) return data } @@ -170,10 +172,17 @@ export class AuthClient { * @returns A promise that resolves to the authorization response. */ async approve(requestId: string): Promise { - const res = await this.authorizationHttp.getById(requestId, this.config.clientId) + const res = await this.authorizationHttp.getById({ + xClientId: this.config.clientId, + id: requestId + }) const { request } = AuthorizationResponse.parse(res.data) const signature = await this.signJwtPayload(this.buildJwtPayload(request)) - const { data } = await this.authorizationHttp.approve(requestId, this.config.clientId, { signature }) + const { data } = await this.authorizationHttp.approve({ + xClientId: this.config.clientId, + id: requestId, + approvalDto: { signature } + }) return data } @@ -188,7 +197,10 @@ export class AuthClient { * @returns */ async getAccessToken(requestId: string): Promise { - const res = await this.authorizationHttp.getById(requestId, this.config.clientId) + const res = await this.authorizationHttp.getById({ + xClientId: this.config.clientId, + id: requestId + }) const lastSignature = reverse(res.data.evaluations).find((e) => e.signature !== null)?.signature if (lastSignature) { @@ -266,6 +278,7 @@ export class AuthClient { ): Promise { const authorization = await this.evaluate( { + ...(opts?.metadata && { metadata: opts.metadata }), id: opts?.id || uuid(), approvals: opts?.approvals || [], request: { diff --git a/packages/armory-sdk/src/lib/auth/type.ts b/packages/armory-sdk/src/lib/auth/type.ts index 09105df97..eaa27a361 100644 --- a/packages/armory-sdk/src/lib/auth/type.ts +++ b/packages/armory-sdk/src/lib/auth/type.ts @@ -89,7 +89,7 @@ export type AuthClientHttp = { } export type RequestAccessTokenOptions = SignOptions & - SetOptional, 'id' | 'approvals'> + SetOptional, 'id' | 'approvals' | 'metadata'> export type Evaluate = Omit diff --git a/packages/armory-sdk/src/lib/data-store/client.ts b/packages/armory-sdk/src/lib/data-store/client.ts index bccfc3d1c..b7abf7f5f 100644 --- a/packages/armory-sdk/src/lib/data-store/client.ts +++ b/packages/armory-sdk/src/lib/data-store/client.ts @@ -4,9 +4,9 @@ import assert from 'assert' import axios, { InternalAxiosRequestConfig } from 'axios' import { promisify } from 'util' import * as zlib from 'zlib' -import { Configuration, ManagedDataStoreApiFactory } from '../http/client/auth' +import { Configuration, ManagedDataStoreApi } from '../http/client/auth' import { REQUEST_HEADER_CLIENT_ID, REQUEST_HEADER_CLIENT_SECRET } from '../shared/constant' -import { DataStoreConfig, DataStoreHttp, SetEntityStoreResponse, SetPolicyStoreResponse, SignOptions } from './type' +import { DataStoreConfig, SetEntityStoreResponse, SetPolicyStoreResponse, SignOptions } from './type' const gzip = promisify(zlib.gzip) @@ -47,7 +47,7 @@ export const addCompressionInterceptor = (axiosInstance: any) => { export class EntityStoreClient { private config: DataStoreConfig - private dataStoreHttp: DataStoreHttp + private dataStoreHttp: ManagedDataStoreApi constructor(config: DataStoreConfig) { this.config = config @@ -60,7 +60,7 @@ export class EntityStoreClient { addCompressionInterceptor(axiosInstance) - this.dataStoreHttp = ManagedDataStoreApiFactory(httpConfig, config.host, axiosInstance) + this.dataStoreHttp = new ManagedDataStoreApi(httpConfig, config.host, axiosInstance) } /** @@ -88,9 +88,12 @@ export class EntityStoreClient { * @returns A promise that resolves to the response. */ async push(store: { data: Partial; signature: string }): Promise { - const { data } = await this.dataStoreHttp.setEntities(this.config.clientId, { - data: this.populate(store.data), - signature: store.signature + const { data } = await this.dataStoreHttp.setEntities({ + clientId: this.config.clientId, + setEntityStoreDto: { + data: this.populate(store.data), + signature: store.signature + } }) return data @@ -120,11 +123,16 @@ export class EntityStoreClient { async fetch(): Promise { assert(this.config.clientSecret !== undefined, 'Missing clientSecret') - const { data } = await this.dataStoreHttp.getEntities(this.config.clientId, { - headers: { - [REQUEST_HEADER_CLIENT_SECRET]: this.config.clientSecret + const { data } = await this.dataStoreHttp.getEntities( + { + clientId: this.config.clientId + }, + { + headers: { + [REQUEST_HEADER_CLIENT_SECRET]: this.config.clientSecret + } } - }) + ) return EntityStore.parse(data.entity) } @@ -137,12 +145,17 @@ export class EntityStoreClient { async sync(): Promise { assert(this.config.clientSecret !== undefined, 'Missing clientSecret') - const { data } = await this.dataStoreHttp.sync(this.config.clientSecret, { - headers: { - [REQUEST_HEADER_CLIENT_ID]: this.config.clientId, - [REQUEST_HEADER_CLIENT_SECRET]: this.config.clientSecret + const { data } = await this.dataStoreHttp.sync( + { + xClientSecret: this.config.clientSecret + }, + { + headers: { + [REQUEST_HEADER_CLIENT_ID]: this.config.clientId, + [REQUEST_HEADER_CLIENT_SECRET]: this.config.clientSecret + } } - }) + ) return data.latestSync.success } @@ -151,7 +164,7 @@ export class EntityStoreClient { export class PolicyStoreClient { private config: DataStoreConfig - private dataStoreHttp: DataStoreHttp + private dataStoreHttp: ManagedDataStoreApi constructor(config: DataStoreConfig) { this.config = config @@ -164,7 +177,7 @@ export class PolicyStoreClient { addCompressionInterceptor(axiosInstance) - this.dataStoreHttp = ManagedDataStoreApiFactory(httpConfig, config.host, axiosInstance) + this.dataStoreHttp = new ManagedDataStoreApi(httpConfig, config.host, axiosInstance) } /** @@ -185,7 +198,10 @@ export class PolicyStoreClient { * @returns A promise that resolves to the response. */ async push(store: PolicyStore): Promise { - const { data } = await this.dataStoreHttp.setPolicies(this.config.clientId, store) + const { data } = await this.dataStoreHttp.setPolicies({ + clientId: this.config.clientId, + setPolicyStoreDto: store + }) return data } @@ -211,11 +227,16 @@ export class PolicyStoreClient { async fetch(): Promise { assert(this.config.clientSecret !== undefined, 'Missing clientSecret') - const { data } = await this.dataStoreHttp.getPolicies(this.config.clientId, { - headers: { - [REQUEST_HEADER_CLIENT_SECRET]: this.config.clientSecret + const { data } = await this.dataStoreHttp.getPolicies( + { + clientId: this.config.clientId + }, + { + headers: { + [REQUEST_HEADER_CLIENT_SECRET]: this.config.clientSecret + } } - }) + ) return PolicyStore.parse(data.policy) } @@ -228,12 +249,17 @@ export class PolicyStoreClient { async sync(): Promise { assert(this.config.clientSecret !== undefined, 'Missing clientSecret') - const { data } = await this.dataStoreHttp.sync(this.config.clientSecret, { - headers: { - [REQUEST_HEADER_CLIENT_ID]: this.config.clientId, - [REQUEST_HEADER_CLIENT_SECRET]: this.config.clientSecret + const { data } = await this.dataStoreHttp.sync( + { + xClientSecret: this.config.clientSecret + }, + { + headers: { + [REQUEST_HEADER_CLIENT_ID]: this.config.clientId, + [REQUEST_HEADER_CLIENT_SECRET]: this.config.clientSecret + } } - }) + ) return data.latestSync.success } diff --git a/packages/armory-sdk/src/lib/http/client/auth/api.ts b/packages/armory-sdk/src/lib/http/client/auth/api.ts index e034663ce..29d20d399 100644 --- a/packages/armory-sdk/src/lib/http/client/auth/api.ts +++ b/packages/armory-sdk/src/lib/http/client/auth/api.ts @@ -85,6 +85,12 @@ export interface AuthorizationRequestDtoMetadata { * @memberof AuthorizationRequestDtoMetadata */ 'expiresIn'?: number; + /** + * + * @type {AuthorizationRequestDtoMetadataConfirmation} + * @memberof AuthorizationRequestDtoMetadata + */ + 'confirmation'?: AuthorizationRequestDtoMetadataConfirmation; } /** * @type AuthorizationRequestDtoMetadataAudience @@ -93,1597 +99,1649 @@ export interface AuthorizationRequestDtoMetadata { export type AuthorizationRequestDtoMetadataAudience = Array | string; /** - * @type AuthorizationRequestDtoRequest + * Option to bind the access token to a given public key. * @export + * @interface AuthorizationRequestDtoMetadataConfirmation */ -export type AuthorizationRequestDtoRequest = AuthorizationRequestDtoRequestOneOf | AuthorizationRequestDtoRequestOneOf1 | AuthorizationRequestDtoRequestOneOf2 | AuthorizationRequestDtoRequestOneOf3 | AuthorizationRequestDtoRequestOneOf4 | AuthorizationRequestDtoRequestOneOf5; - +export interface AuthorizationRequestDtoMetadataConfirmation { + /** + * + * @type {AuthorizationRequestDtoMetadataConfirmationKey} + * @memberof AuthorizationRequestDtoMetadataConfirmation + */ + 'key': AuthorizationRequestDtoMetadataConfirmationKey; +} /** * * @export - * @interface AuthorizationRequestDtoRequestOneOf + * @interface AuthorizationRequestDtoMetadataConfirmationKey */ -export interface AuthorizationRequestDtoRequestOneOf { +export interface AuthorizationRequestDtoMetadataConfirmationKey { /** * - * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOf + * @type {AuthorizationRequestDtoMetadataConfirmationKeyJwk} + * @memberof AuthorizationRequestDtoMetadataConfirmationKey */ - 'action': AuthorizationRequestDtoRequestOneOfActionEnum; + 'jwk': AuthorizationRequestDtoMetadataConfirmationKeyJwk; /** - * + * Specifies the proof method for demonstrating possession of the private key corresponding to the jwk * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOf + * @memberof AuthorizationRequestDtoMetadataConfirmationKey */ - 'nonce': string; + 'proof'?: AuthorizationRequestDtoMetadataConfirmationKeyProofEnum; /** - * + * The actual JSON Web Signature value that proves the client possesses the private key. * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOf - */ - 'resourceId': string; - /** - * - * @type {AuthorizationRequestDtoRequestOneOfTransactionRequest} - * @memberof AuthorizationRequestDtoRequestOneOf + * @memberof AuthorizationRequestDtoMetadataConfirmationKey */ - 'transactionRequest': AuthorizationRequestDtoRequestOneOfTransactionRequest; + 'jws'?: string; } -export const AuthorizationRequestDtoRequestOneOfActionEnum = { - SignTransaction: 'signTransaction' +export const AuthorizationRequestDtoMetadataConfirmationKeyProofEnum = { + Jws: 'jws' } as const; -export type AuthorizationRequestDtoRequestOneOfActionEnum = typeof AuthorizationRequestDtoRequestOneOfActionEnum[keyof typeof AuthorizationRequestDtoRequestOneOfActionEnum]; +export type AuthorizationRequestDtoMetadataConfirmationKeyProofEnum = typeof AuthorizationRequestDtoMetadataConfirmationKeyProofEnum[keyof typeof AuthorizationRequestDtoMetadataConfirmationKeyProofEnum]; + +/** + * @type AuthorizationRequestDtoMetadataConfirmationKeyJwk + * JSON Web Key that will be used to bind the access token. This ensures only the holder of the corresponding private key can use the token. + * @export + */ +export type AuthorizationRequestDtoMetadataConfirmationKeyJwk = AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf | AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf1 | AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf2 | AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf3 | AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf4; /** * * @export - * @interface AuthorizationRequestDtoRequestOneOf1 + * @interface AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf */ -export interface AuthorizationRequestDtoRequestOneOf1 { +export interface AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf { /** * * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOf1 + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf */ - 'action': AuthorizationRequestDtoRequestOneOf1ActionEnum; + 'kty': AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOfKtyEnum; /** * * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOf1 + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf */ - 'nonce': string; + 'alg': AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOfAlgEnum; /** * * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOf1 - */ - 'resourceId': string; - /** - * - * @type {AuthorizationRequestDtoRequestOneOf1Message} - * @memberof AuthorizationRequestDtoRequestOneOf1 + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf */ - 'message': AuthorizationRequestDtoRequestOneOf1Message; -} - -export const AuthorizationRequestDtoRequestOneOf1ActionEnum = { - SignMessage: 'signMessage' -} as const; - -export type AuthorizationRequestDtoRequestOneOf1ActionEnum = typeof AuthorizationRequestDtoRequestOneOf1ActionEnum[keyof typeof AuthorizationRequestDtoRequestOneOf1ActionEnum]; - -/** - * @type AuthorizationRequestDtoRequestOneOf1Message - * @export - */ -export type AuthorizationRequestDtoRequestOneOf1Message = AuthorizationRequestDtoRequestOneOf1MessageOneOf | string; - -/** - * - * @export - * @interface AuthorizationRequestDtoRequestOneOf1MessageOneOf - */ -export interface AuthorizationRequestDtoRequestOneOf1MessageOneOf { + 'use'?: AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOfUseEnum; /** * - * @type {any} - * @memberof AuthorizationRequestDtoRequestOneOf1MessageOneOf + * @type {string} + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf */ - 'raw': any; -} -/** - * - * @export - * @interface AuthorizationRequestDtoRequestOneOf2 - */ -export interface AuthorizationRequestDtoRequestOneOf2 { + 'kid': string; /** * * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOf2 + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf */ - 'action': AuthorizationRequestDtoRequestOneOf2ActionEnum; + 'addr'?: string; /** * * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOf2 + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf */ - 'nonce': string; + 'crv': AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOfCrvEnum; /** * * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOf2 + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf */ - 'resourceId': string; + 'x': string; /** * - * @type {AuthorizationRequestDtoRequestOneOf2TypedData} - * @memberof AuthorizationRequestDtoRequestOneOf2 + * @type {string} + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf */ - 'typedData': AuthorizationRequestDtoRequestOneOf2TypedData; + 'y': string; } -export const AuthorizationRequestDtoRequestOneOf2ActionEnum = { - SignTypedData: 'signTypedData' +export const AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOfKtyEnum = { + Ec: 'EC' } as const; -export type AuthorizationRequestDtoRequestOneOf2ActionEnum = typeof AuthorizationRequestDtoRequestOneOf2ActionEnum[keyof typeof AuthorizationRequestDtoRequestOneOf2ActionEnum]; +export type AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOfKtyEnum = typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOfKtyEnum[keyof typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOfKtyEnum]; +export const AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOfAlgEnum = { + Es256K: 'ES256K' +} as const; + +export type AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOfAlgEnum = typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOfAlgEnum[keyof typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOfAlgEnum]; +export const AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOfUseEnum = { + Sig: 'sig', + Enc: 'enc' +} as const; + +export type AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOfUseEnum = typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOfUseEnum[keyof typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOfUseEnum]; +export const AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOfCrvEnum = { + Secp256k1: 'secp256k1' +} as const; + +export type AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOfCrvEnum = typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOfCrvEnum[keyof typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOfCrvEnum]; /** * * @export - * @interface AuthorizationRequestDtoRequestOneOf2TypedData + * @interface AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf1 */ -export interface AuthorizationRequestDtoRequestOneOf2TypedData { - /** - * - * @type {AuthorizationRequestDtoRequestOneOf2TypedDataDomain} - * @memberof AuthorizationRequestDtoRequestOneOf2TypedData - */ - 'domain': AuthorizationRequestDtoRequestOneOf2TypedDataDomain; +export interface AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf1 { /** * - * @type {{ [key: string]: Array; }} - * @memberof AuthorizationRequestDtoRequestOneOf2TypedData + * @type {string} + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf1 */ - 'types': { [key: string]: Array; }; + 'kty': AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf1KtyEnum; /** * * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOf2TypedData + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf1 */ - 'primaryType': string; + 'alg': AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf1AlgEnum; /** * - * @type {{ [key: string]: any; }} - * @memberof AuthorizationRequestDtoRequestOneOf2TypedData + * @type {string} + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf1 */ - 'message': { [key: string]: any; }; -} -/** - * - * @export - * @interface AuthorizationRequestDtoRequestOneOf2TypedDataDomain - */ -export interface AuthorizationRequestDtoRequestOneOf2TypedDataDomain { + 'use'?: AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf1UseEnum; /** * * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOf2TypedDataDomain + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf1 */ - 'name'?: string; + 'kid': string; /** * * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOf2TypedDataDomain + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf1 */ - 'version'?: string; + 'addr'?: string; /** * - * @type {number} - * @memberof AuthorizationRequestDtoRequestOneOf2TypedDataDomain + * @type {string} + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf1 */ - 'chainId'?: number; + 'crv': AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf1CrvEnum; /** * - * @type {any} - * @memberof AuthorizationRequestDtoRequestOneOf2TypedDataDomain + * @type {string} + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf1 */ - 'verifyingContract'?: any; + 'x': string; /** * - * @type {any} - * @memberof AuthorizationRequestDtoRequestOneOf2TypedDataDomain + * @type {string} + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf1 */ - 'salt'?: any; + 'y': string; } + +export const AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf1KtyEnum = { + Ec: 'EC' +} as const; + +export type AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf1KtyEnum = typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf1KtyEnum[keyof typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf1KtyEnum]; +export const AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf1AlgEnum = { + Es256: 'ES256' +} as const; + +export type AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf1AlgEnum = typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf1AlgEnum[keyof typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf1AlgEnum]; +export const AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf1UseEnum = { + Sig: 'sig', + Enc: 'enc' +} as const; + +export type AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf1UseEnum = typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf1UseEnum[keyof typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf1UseEnum]; +export const AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf1CrvEnum = { + P256: 'P-256' +} as const; + +export type AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf1CrvEnum = typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf1CrvEnum[keyof typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf1CrvEnum]; + /** * * @export - * @interface AuthorizationRequestDtoRequestOneOf2TypedDataTypesValueInner + * @interface AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf2 */ -export interface AuthorizationRequestDtoRequestOneOf2TypedDataTypesValueInner { +export interface AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf2 { /** * * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOf2TypedDataTypesValueInner + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf2 */ - 'name': string; + 'kty': AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf2KtyEnum; /** * * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOf2TypedDataTypesValueInner + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf2 */ - 'type': string; -} -/** - * - * @export - * @interface AuthorizationRequestDtoRequestOneOf3 - */ -export interface AuthorizationRequestDtoRequestOneOf3 { + 'alg': AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf2AlgEnum; /** * * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOf3 + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf2 */ - 'action': AuthorizationRequestDtoRequestOneOf3ActionEnum; + 'use'?: AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf2UseEnum; /** * * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOf3 + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf2 */ - 'nonce': string; + 'kid': string; /** * * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOf3 + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf2 */ - 'resourceId': string; + 'addr'?: string; /** * - * @type {any} - * @memberof AuthorizationRequestDtoRequestOneOf3 + * @type {string} + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf2 */ - 'rawMessage': any; + 'n': string; + /** + * + * @type {string} + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf2 + */ + 'e': string; } -export const AuthorizationRequestDtoRequestOneOf3ActionEnum = { - SignRaw: 'signRaw' +export const AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf2KtyEnum = { + Rsa: 'RSA' } as const; -export type AuthorizationRequestDtoRequestOneOf3ActionEnum = typeof AuthorizationRequestDtoRequestOneOf3ActionEnum[keyof typeof AuthorizationRequestDtoRequestOneOf3ActionEnum]; +export type AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf2KtyEnum = typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf2KtyEnum[keyof typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf2KtyEnum]; +export const AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf2AlgEnum = { + Rs256: 'RS256' +} as const; + +export type AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf2AlgEnum = typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf2AlgEnum[keyof typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf2AlgEnum]; +export const AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf2UseEnum = { + Sig: 'sig', + Enc: 'enc' +} as const; + +export type AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf2UseEnum = typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf2UseEnum[keyof typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf2UseEnum]; /** * * @export - * @interface AuthorizationRequestDtoRequestOneOf4 + * @interface AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf3 */ -export interface AuthorizationRequestDtoRequestOneOf4 { +export interface AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf3 { /** * * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOf4 + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf3 */ - 'action': AuthorizationRequestDtoRequestOneOf4ActionEnum; + 'kty': AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf3KtyEnum; /** * * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOf4 + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf3 */ - 'nonce': string; + 'crv': AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf3CrvEnum; /** * * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOf4 + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf3 */ - 'resourceId': string; + 'alg': AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf3AlgEnum; /** * - * @type {AuthorizationRequestDtoRequestOneOf4UserOperation} - * @memberof AuthorizationRequestDtoRequestOneOf4 + * @type {string} + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf3 */ - 'userOperation': AuthorizationRequestDtoRequestOneOf4UserOperation; + 'use'?: AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf3UseEnum; + /** + * + * @type {string} + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf3 + */ + 'kid': string; + /** + * + * @type {any} + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf3 + */ + 'addr': any; } -export const AuthorizationRequestDtoRequestOneOf4ActionEnum = { - SignUserOperation: 'signUserOperation' +export const AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf3KtyEnum = { + Ec: 'EC' } as const; -export type AuthorizationRequestDtoRequestOneOf4ActionEnum = typeof AuthorizationRequestDtoRequestOneOf4ActionEnum[keyof typeof AuthorizationRequestDtoRequestOneOf4ActionEnum]; +export type AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf3KtyEnum = typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf3KtyEnum[keyof typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf3KtyEnum]; +export const AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf3CrvEnum = { + Secp256k1: 'secp256k1' +} as const; + +export type AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf3CrvEnum = typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf3CrvEnum[keyof typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf3CrvEnum]; +export const AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf3AlgEnum = { + Es256K: 'ES256K' +} as const; + +export type AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf3AlgEnum = typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf3AlgEnum[keyof typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf3AlgEnum]; +export const AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf3UseEnum = { + Sig: 'sig', + Enc: 'enc' +} as const; + +export type AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf3UseEnum = typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf3UseEnum[keyof typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf3UseEnum]; /** * * @export - * @interface AuthorizationRequestDtoRequestOneOf4UserOperation + * @interface AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf4 */ -export interface AuthorizationRequestDtoRequestOneOf4UserOperation { +export interface AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf4 { /** * - * @type {any} - * @memberof AuthorizationRequestDtoRequestOneOf4UserOperation + * @type {string} + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf4 */ - 'sender': any; + 'kty': AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf4KtyEnum; /** * * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOf4UserOperation + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf4 */ - 'nonce': string; - /** - * - * @type {any} - * @memberof AuthorizationRequestDtoRequestOneOf4UserOperation - */ - 'initCode': any; - /** - * - * @type {any} - * @memberof AuthorizationRequestDtoRequestOneOf4UserOperation - */ - 'callData': any; + 'alg': AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf4AlgEnum; /** * * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOf4UserOperation + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf4 */ - 'callGasLimit': string; + 'use'?: AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf4UseEnum; /** * * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOf4UserOperation + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf4 */ - 'verificationGasLimit': string; + 'kid': string; /** * * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOf4UserOperation + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf4 */ - 'preVerificationGas': string; + 'addr'?: string; /** * * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOf4UserOperation + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf4 */ - 'maxFeePerGas': string; + 'crv': AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf4CrvEnum; /** * * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOf4UserOperation - */ - 'maxPriorityFeePerGas': string; - /** - * - * @type {any} - * @memberof AuthorizationRequestDtoRequestOneOf4UserOperation + * @memberof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf4 */ - 'paymasterAndData': any; + 'x': string; +} + +export const AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf4KtyEnum = { + Okp: 'OKP' +} as const; + +export type AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf4KtyEnum = typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf4KtyEnum[keyof typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf4KtyEnum]; +export const AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf4AlgEnum = { + Eddsa: 'EDDSA' +} as const; + +export type AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf4AlgEnum = typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf4AlgEnum[keyof typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf4AlgEnum]; +export const AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf4UseEnum = { + Sig: 'sig', + Enc: 'enc' +} as const; + +export type AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf4UseEnum = typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf4UseEnum[keyof typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf4UseEnum]; +export const AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf4CrvEnum = { + Ed25519: 'Ed25519' +} as const; + +export type AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf4CrvEnum = typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf4CrvEnum[keyof typeof AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf4CrvEnum]; + +/** + * @type AuthorizationRequestDtoRequest + * @export + */ +export type AuthorizationRequestDtoRequest = AuthorizationRequestDtoRequestOneOf | AuthorizationRequestDtoRequestOneOf1 | AuthorizationRequestDtoRequestOneOf2 | AuthorizationRequestDtoRequestOneOf3 | AuthorizationRequestDtoRequestOneOf4 | AuthorizationRequestDtoRequestOneOf5; + +/** + * + * @export + * @interface AuthorizationRequestDtoRequestOneOf + */ +export interface AuthorizationRequestDtoRequestOneOf { /** * - * @type {any} - * @memberof AuthorizationRequestDtoRequestOneOf4UserOperation + * @type {string} + * @memberof AuthorizationRequestDtoRequestOneOf */ - 'entryPoint': any; + 'action': AuthorizationRequestDtoRequestOneOfActionEnum; /** * - * @type {any} - * @memberof AuthorizationRequestDtoRequestOneOf4UserOperation + * @type {string} + * @memberof AuthorizationRequestDtoRequestOneOf */ - 'signature': any; + 'nonce': string; /** * - * @type {any} - * @memberof AuthorizationRequestDtoRequestOneOf4UserOperation + * @type {string} + * @memberof AuthorizationRequestDtoRequestOneOf */ - 'factoryAddress': any; + 'resourceId': string; /** * - * @type {number} - * @memberof AuthorizationRequestDtoRequestOneOf4UserOperation + * @type {AuthorizationRequestDtoRequestOneOfTransactionRequest} + * @memberof AuthorizationRequestDtoRequestOneOf */ - 'chainId': number; + 'transactionRequest': AuthorizationRequestDtoRequestOneOfTransactionRequest; } + +export const AuthorizationRequestDtoRequestOneOfActionEnum = { + SignTransaction: 'signTransaction' +} as const; + +export type AuthorizationRequestDtoRequestOneOfActionEnum = typeof AuthorizationRequestDtoRequestOneOfActionEnum[keyof typeof AuthorizationRequestDtoRequestOneOfActionEnum]; + /** * * @export - * @interface AuthorizationRequestDtoRequestOneOf5 + * @interface AuthorizationRequestDtoRequestOneOf1 */ -export interface AuthorizationRequestDtoRequestOneOf5 { +export interface AuthorizationRequestDtoRequestOneOf1 { /** * * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOf5 + * @memberof AuthorizationRequestDtoRequestOneOf1 */ - 'action': AuthorizationRequestDtoRequestOneOf5ActionEnum; + 'action': AuthorizationRequestDtoRequestOneOf1ActionEnum; /** * * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOf5 + * @memberof AuthorizationRequestDtoRequestOneOf1 */ 'nonce': string; /** * * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOf5 + * @memberof AuthorizationRequestDtoRequestOneOf1 */ 'resourceId': string; /** * - * @type {Array} - * @memberof AuthorizationRequestDtoRequestOneOf5 + * @type {AuthorizationRequestDtoRequestOneOf1Message} + * @memberof AuthorizationRequestDtoRequestOneOf1 */ - 'permissions': Array; + 'message': AuthorizationRequestDtoRequestOneOf1Message; } -export const AuthorizationRequestDtoRequestOneOf5ActionEnum = { - GrantPermission: 'grantPermission' +export const AuthorizationRequestDtoRequestOneOf1ActionEnum = { + SignMessage: 'signMessage' } as const; -export type AuthorizationRequestDtoRequestOneOf5ActionEnum = typeof AuthorizationRequestDtoRequestOneOf5ActionEnum[keyof typeof AuthorizationRequestDtoRequestOneOf5ActionEnum]; +export type AuthorizationRequestDtoRequestOneOf1ActionEnum = typeof AuthorizationRequestDtoRequestOneOf1ActionEnum[keyof typeof AuthorizationRequestDtoRequestOneOf1ActionEnum]; /** - * @type AuthorizationRequestDtoRequestOneOfTransactionRequest + * @type AuthorizationRequestDtoRequestOneOf1Message * @export */ -export type AuthorizationRequestDtoRequestOneOfTransactionRequest = AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf | AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1; +export type AuthorizationRequestDtoRequestOneOf1Message = AuthorizationRequestDtoRequestOneOf1MessageOneOf | string; /** * * @export - * @interface AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf + * @interface AuthorizationRequestDtoRequestOneOf1MessageOneOf */ -export interface AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf { - /** - * - * @type {number} - * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf - */ - 'chainId': number; - /** - * - * @type {any} - * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf - */ - 'from': any; - /** - * - * @type {number} - * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf - */ - 'nonce'?: number; - /** - * - * @type {Array} - * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf - */ - 'accessList'?: Array; +export interface AuthorizationRequestDtoRequestOneOf1MessageOneOf { /** * * @type {any} - * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf - */ - 'data'?: any; - /** - * - * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf + * @memberof AuthorizationRequestDtoRequestOneOf1MessageOneOf */ - 'gas'?: string; + 'raw': any; +} +/** + * + * @export + * @interface AuthorizationRequestDtoRequestOneOf2 + */ +export interface AuthorizationRequestDtoRequestOneOf2 { /** * * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf + * @memberof AuthorizationRequestDtoRequestOneOf2 */ - 'maxFeePerGas'?: string; + 'action': AuthorizationRequestDtoRequestOneOf2ActionEnum; /** * * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf - */ - 'maxPriorityFeePerGas'?: string; - /** - * - * @type {any} - * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf + * @memberof AuthorizationRequestDtoRequestOneOf2 */ - 'to'?: any | null; + 'nonce': string; /** * * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf + * @memberof AuthorizationRequestDtoRequestOneOf2 */ - 'type'?: AuthorizationRequestDtoRequestOneOfTransactionRequestOneOfTypeEnum; + 'resourceId': string; /** * - * @type {any} - * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf + * @type {AuthorizationRequestDtoRequestOneOf2TypedData} + * @memberof AuthorizationRequestDtoRequestOneOf2 */ - 'value'?: any; + 'typedData': AuthorizationRequestDtoRequestOneOf2TypedData; } -export const AuthorizationRequestDtoRequestOneOfTransactionRequestOneOfTypeEnum = { - _2: '2' +export const AuthorizationRequestDtoRequestOneOf2ActionEnum = { + SignTypedData: 'signTypedData' } as const; -export type AuthorizationRequestDtoRequestOneOfTransactionRequestOneOfTypeEnum = typeof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOfTypeEnum[keyof typeof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOfTypeEnum]; +export type AuthorizationRequestDtoRequestOneOf2ActionEnum = typeof AuthorizationRequestDtoRequestOneOf2ActionEnum[keyof typeof AuthorizationRequestDtoRequestOneOf2ActionEnum]; /** * * @export - * @interface AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1 + * @interface AuthorizationRequestDtoRequestOneOf2TypedData */ -export interface AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1 { +export interface AuthorizationRequestDtoRequestOneOf2TypedData { /** * - * @type {number} - * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1 + * @type {AuthorizationRequestDtoRequestOneOf2TypedDataDomain} + * @memberof AuthorizationRequestDtoRequestOneOf2TypedData */ - 'chainId': number; + 'domain': AuthorizationRequestDtoRequestOneOf2TypedDataDomain; /** * - * @type {any} - * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1 + * @type {{ [key: string]: Array; }} + * @memberof AuthorizationRequestDtoRequestOneOf2TypedData */ - 'from': any; + 'types': { [key: string]: Array; }; /** * - * @type {number} - * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1 + * @type {string} + * @memberof AuthorizationRequestDtoRequestOneOf2TypedData */ - 'nonce'?: number; + 'primaryType': string; /** * - * @type {any} - * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1 + * @type {{ [key: string]: any; }} + * @memberof AuthorizationRequestDtoRequestOneOf2TypedData */ - 'data'?: any; + 'message': { [key: string]: any; }; +} +/** + * + * @export + * @interface AuthorizationRequestDtoRequestOneOf2TypedDataDomain + */ +export interface AuthorizationRequestDtoRequestOneOf2TypedDataDomain { /** * * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1 + * @memberof AuthorizationRequestDtoRequestOneOf2TypedDataDomain */ - 'gas'?: string; + 'name'?: string; /** * * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1 + * @memberof AuthorizationRequestDtoRequestOneOf2TypedDataDomain */ - 'gasPrice'?: string; + 'version'?: string; /** * - * @type {string} - * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1 + * @type {number} + * @memberof AuthorizationRequestDtoRequestOneOf2TypedDataDomain */ - 'type'?: AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1TypeEnum; + 'chainId'?: number; /** * * @type {any} - * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1 + * @memberof AuthorizationRequestDtoRequestOneOf2TypedDataDomain */ - 'to'?: any | null; + 'verifyingContract'?: any; /** * * @type {any} - * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1 + * @memberof AuthorizationRequestDtoRequestOneOf2TypedDataDomain */ - 'value'?: any; + 'salt'?: any; } - -export const AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1TypeEnum = { - _0: '0' -} as const; - -export type AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1TypeEnum = typeof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1TypeEnum[keyof typeof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1TypeEnum]; - /** * * @export - * @interface AuthorizationRequestDtoRequestOneOfTransactionRequestOneOfAccessListInner + * @interface AuthorizationRequestDtoRequestOneOf2TypedDataTypesValueInner */ -export interface AuthorizationRequestDtoRequestOneOfTransactionRequestOneOfAccessListInner { +export interface AuthorizationRequestDtoRequestOneOf2TypedDataTypesValueInner { /** * - * @type {any} - * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOfAccessListInner + * @type {string} + * @memberof AuthorizationRequestDtoRequestOneOf2TypedDataTypesValueInner */ - 'address': any; + 'name': string; /** * - * @type {Array} - * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOfAccessListInner + * @type {string} + * @memberof AuthorizationRequestDtoRequestOneOf2TypedDataTypesValueInner */ - 'storageKeys': Array; + 'type': string; } /** * * @export - * @interface AuthorizationResponseDto + * @interface AuthorizationRequestDtoRequestOneOf3 */ -export interface AuthorizationResponseDto { +export interface AuthorizationRequestDtoRequestOneOf3 { /** * - * @type {Array} - * @memberof AuthorizationResponseDto + * @type {string} + * @memberof AuthorizationRequestDtoRequestOneOf3 */ - 'approvals'?: Array; + 'action': AuthorizationRequestDtoRequestOneOf3ActionEnum; /** * * @type {string} - * @memberof AuthorizationResponseDto + * @memberof AuthorizationRequestDtoRequestOneOf3 */ - 'authentication': string; + 'nonce': string; /** * * @type {string} - * @memberof AuthorizationResponseDto + * @memberof AuthorizationRequestDtoRequestOneOf3 */ - 'clientId': string; + 'resourceId': string; /** * * @type {any} - * @memberof AuthorizationResponseDto - */ - 'createdAt': any; - /** - * - * @type {Array} - * @memberof AuthorizationResponseDto - */ - 'errors'?: Array; - /** - * - * @type {Array} - * @memberof AuthorizationResponseDto + * @memberof AuthorizationRequestDtoRequestOneOf3 */ - 'evaluations': Array; + 'rawMessage': any; +} + +export const AuthorizationRequestDtoRequestOneOf3ActionEnum = { + SignRaw: 'signRaw' +} as const; + +export type AuthorizationRequestDtoRequestOneOf3ActionEnum = typeof AuthorizationRequestDtoRequestOneOf3ActionEnum[keyof typeof AuthorizationRequestDtoRequestOneOf3ActionEnum]; + +/** + * + * @export + * @interface AuthorizationRequestDtoRequestOneOf4 + */ +export interface AuthorizationRequestDtoRequestOneOf4 { /** * * @type {string} - * @memberof AuthorizationResponseDto + * @memberof AuthorizationRequestDtoRequestOneOf4 */ - 'id': string; + 'action': AuthorizationRequestDtoRequestOneOf4ActionEnum; /** * * @type {string} - * @memberof AuthorizationResponseDto - */ - 'idempotencyKey'?: string | null; - /** - * - * @type {AuthorizationRequestDtoMetadata} - * @memberof AuthorizationResponseDto - */ - 'metadata'?: AuthorizationRequestDtoMetadata; - /** - * - * @type {AuthorizationRequestDtoRequest} - * @memberof AuthorizationResponseDto + * @memberof AuthorizationRequestDtoRequestOneOf4 */ - 'request': AuthorizationRequestDtoRequest; + 'nonce': string; /** * * @type {string} - * @memberof AuthorizationResponseDto + * @memberof AuthorizationRequestDtoRequestOneOf4 */ - 'status': AuthorizationResponseDtoStatusEnum; + 'resourceId': string; /** * - * @type {any} - * @memberof AuthorizationResponseDto + * @type {AuthorizationRequestDtoRequestOneOf4UserOperation} + * @memberof AuthorizationRequestDtoRequestOneOf4 */ - 'updatedAt': any; + 'userOperation': AuthorizationRequestDtoRequestOneOf4UserOperation; } -export const AuthorizationResponseDtoStatusEnum = { - Created: 'CREATED', - Canceled: 'CANCELED', - Failed: 'FAILED', - Processing: 'PROCESSING', - Approving: 'APPROVING', - Permitted: 'PERMITTED', - Forbidden: 'FORBIDDEN' +export const AuthorizationRequestDtoRequestOneOf4ActionEnum = { + SignUserOperation: 'signUserOperation' } as const; -export type AuthorizationResponseDtoStatusEnum = typeof AuthorizationResponseDtoStatusEnum[keyof typeof AuthorizationResponseDtoStatusEnum]; +export type AuthorizationRequestDtoRequestOneOf4ActionEnum = typeof AuthorizationRequestDtoRequestOneOf4ActionEnum[keyof typeof AuthorizationRequestDtoRequestOneOf4ActionEnum]; /** * * @export - * @interface AuthorizationResponseDtoErrorsInner + * @interface AuthorizationRequestDtoRequestOneOf4UserOperation */ -export interface AuthorizationResponseDtoErrorsInner { +export interface AuthorizationRequestDtoRequestOneOf4UserOperation { /** * * @type {any} - * @memberof AuthorizationResponseDtoErrorsInner + * @memberof AuthorizationRequestDtoRequestOneOf4UserOperation */ - 'context'?: any; + 'sender': any; /** * * @type {string} - * @memberof AuthorizationResponseDtoErrorsInner + * @memberof AuthorizationRequestDtoRequestOneOf4UserOperation */ - 'id': string; + 'nonce': string; /** * - * @type {string} - * @memberof AuthorizationResponseDtoErrorsInner + * @type {any} + * @memberof AuthorizationRequestDtoRequestOneOf4UserOperation */ - 'message': string; + 'initCode': any; + /** + * + * @type {any} + * @memberof AuthorizationRequestDtoRequestOneOf4UserOperation + */ + 'callData': any; /** * * @type {string} - * @memberof AuthorizationResponseDtoErrorsInner + * @memberof AuthorizationRequestDtoRequestOneOf4UserOperation */ - 'name': string; -} -/** - * - * @export - * @interface AuthorizationResponseDtoEvaluationsInner - */ -export interface AuthorizationResponseDtoEvaluationsInner { + 'callGasLimit': string; /** * * @type {string} - * @memberof AuthorizationResponseDtoEvaluationsInner + * @memberof AuthorizationRequestDtoRequestOneOf4UserOperation */ - 'id': string; + 'verificationGasLimit': string; /** * * @type {string} - * @memberof AuthorizationResponseDtoEvaluationsInner + * @memberof AuthorizationRequestDtoRequestOneOf4UserOperation */ - 'decision': string; + 'preVerificationGas': string; /** * * @type {string} - * @memberof AuthorizationResponseDtoEvaluationsInner + * @memberof AuthorizationRequestDtoRequestOneOf4UserOperation */ - 'signature': string | null; + 'maxFeePerGas': string; /** * - * @type {any} - * @memberof AuthorizationResponseDtoEvaluationsInner + * @type {string} + * @memberof AuthorizationRequestDtoRequestOneOf4UserOperation */ - 'transactionRequestIntent'?: any; + 'maxPriorityFeePerGas': string; /** * - * @type {AuthorizationResponseDtoEvaluationsInnerApprovalRequirements} - * @memberof AuthorizationResponseDtoEvaluationsInner + * @type {any} + * @memberof AuthorizationRequestDtoRequestOneOf4UserOperation */ - 'approvalRequirements'?: AuthorizationResponseDtoEvaluationsInnerApprovalRequirements; + 'paymasterAndData': any; /** * * @type {any} - * @memberof AuthorizationResponseDtoEvaluationsInner + * @memberof AuthorizationRequestDtoRequestOneOf4UserOperation */ - 'createdAt': any; -} -/** - * - * @export - * @interface AuthorizationResponseDtoEvaluationsInnerApprovalRequirements - */ -export interface AuthorizationResponseDtoEvaluationsInnerApprovalRequirements { + 'entryPoint': any; /** * - * @type {Array} - * @memberof AuthorizationResponseDtoEvaluationsInnerApprovalRequirements + * @type {any} + * @memberof AuthorizationRequestDtoRequestOneOf4UserOperation */ - 'required'?: Array; + 'signature': any; /** * - * @type {Array} - * @memberof AuthorizationResponseDtoEvaluationsInnerApprovalRequirements + * @type {any} + * @memberof AuthorizationRequestDtoRequestOneOf4UserOperation */ - 'missing'?: Array; + 'factoryAddress': any; /** * - * @type {Array} - * @memberof AuthorizationResponseDtoEvaluationsInnerApprovalRequirements + * @type {number} + * @memberof AuthorizationRequestDtoRequestOneOf4UserOperation */ - 'satisfied'?: Array; + 'chainId': number; } /** * * @export - * @interface AuthorizationResponseDtoEvaluationsInnerApprovalRequirementsRequiredInner + * @interface AuthorizationRequestDtoRequestOneOf5 */ -export interface AuthorizationResponseDtoEvaluationsInnerApprovalRequirementsRequiredInner { +export interface AuthorizationRequestDtoRequestOneOf5 { /** * - * @type {number} - * @memberof AuthorizationResponseDtoEvaluationsInnerApprovalRequirementsRequiredInner + * @type {string} + * @memberof AuthorizationRequestDtoRequestOneOf5 */ - 'approvalCount': number; + 'action': AuthorizationRequestDtoRequestOneOf5ActionEnum; /** - * The number of requried approvals + * * @type {string} - * @memberof AuthorizationResponseDtoEvaluationsInnerApprovalRequirementsRequiredInner + * @memberof AuthorizationRequestDtoRequestOneOf5 */ - 'approvalEntityType': AuthorizationResponseDtoEvaluationsInnerApprovalRequirementsRequiredInnerApprovalEntityTypeEnum; + 'nonce': string; /** - * List of entities IDs that must satisfy the requirements - * @type {Array} - * @memberof AuthorizationResponseDtoEvaluationsInnerApprovalRequirementsRequiredInner + * + * @type {string} + * @memberof AuthorizationRequestDtoRequestOneOf5 */ - 'entityIds': Array; + 'resourceId': string; /** * - * @type {boolean} - * @memberof AuthorizationResponseDtoEvaluationsInnerApprovalRequirementsRequiredInner + * @type {Array} + * @memberof AuthorizationRequestDtoRequestOneOf5 */ - 'countPrincipal': boolean; + 'permissions': Array; } -export const AuthorizationResponseDtoEvaluationsInnerApprovalRequirementsRequiredInnerApprovalEntityTypeEnum = { - User: 'Narval::User', - UserRole: 'Narval::UserRole', - UserGroup: 'Narval::UserGroup' +export const AuthorizationRequestDtoRequestOneOf5ActionEnum = { + GrantPermission: 'grantPermission' } as const; -export type AuthorizationResponseDtoEvaluationsInnerApprovalRequirementsRequiredInnerApprovalEntityTypeEnum = typeof AuthorizationResponseDtoEvaluationsInnerApprovalRequirementsRequiredInnerApprovalEntityTypeEnum[keyof typeof AuthorizationResponseDtoEvaluationsInnerApprovalRequirementsRequiredInnerApprovalEntityTypeEnum]; +export type AuthorizationRequestDtoRequestOneOf5ActionEnum = typeof AuthorizationRequestDtoRequestOneOf5ActionEnum[keyof typeof AuthorizationRequestDtoRequestOneOf5ActionEnum]; + +/** + * @type AuthorizationRequestDtoRequestOneOfTransactionRequest + * @export + */ +export type AuthorizationRequestDtoRequestOneOfTransactionRequest = AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf | AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1; /** * * @export - * @interface CreateClientRequestDto + * @interface AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf */ -export interface CreateClientRequestDto { +export interface AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf { /** * - * @type {string} - * @memberof CreateClientRequestDto + * @type {number} + * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf */ - 'id'?: string; + 'chainId': number; /** * - * @type {string} - * @memberof CreateClientRequestDto + * @type {any} + * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf */ - 'name': string; + 'from': any; /** * - * @type {boolean} - * @memberof CreateClientRequestDto - */ - 'useManagedDataStore'?: boolean; + * @type {number} + * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf + */ + 'nonce'?: number; + /** + * + * @type {Array} + * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf + */ + 'accessList'?: Array; + /** + * + * @type {any} + * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf + */ + 'data'?: any; /** * * @type {string} - * @memberof CreateClientRequestDto + * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf */ - 'clientSecret'?: string; + 'gas'?: string; /** * - * @type {CreateClientRequestDtoDataStore} - * @memberof CreateClientRequestDto + * @type {string} + * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf */ - 'dataStore': CreateClientRequestDtoDataStore; + 'maxFeePerGas'?: string; /** * - * @type {Array} - * @memberof CreateClientRequestDto + * @type {string} + * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf */ - 'policyEngineNodes'?: Array; -} -/** - * - * @export - * @interface CreateClientRequestDtoDataStore - */ -export interface CreateClientRequestDtoDataStore { + 'maxPriorityFeePerGas'?: string; /** * - * @type {CreateClientRequestDtoDataStoreEntity} - * @memberof CreateClientRequestDtoDataStore + * @type {any} + * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf */ - 'entity': CreateClientRequestDtoDataStoreEntity; + 'to'?: any | null; /** * - * @type {CreateClientRequestDtoDataStoreEntity} - * @memberof CreateClientRequestDtoDataStore + * @type {string} + * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf */ - 'policy': CreateClientRequestDtoDataStoreEntity; + 'type'?: AuthorizationRequestDtoRequestOneOfTransactionRequestOneOfTypeEnum; /** - * Whether to include the engine key in the entity and policy keys - * @type {boolean} - * @memberof CreateClientRequestDtoDataStore + * + * @type {any} + * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf */ - 'allowSelfSignedData'?: boolean; + 'value'?: any; } + +export const AuthorizationRequestDtoRequestOneOfTransactionRequestOneOfTypeEnum = { + _2: '2' +} as const; + +export type AuthorizationRequestDtoRequestOneOfTransactionRequestOneOfTypeEnum = typeof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOfTypeEnum[keyof typeof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOfTypeEnum]; + /** * * @export - * @interface CreateClientRequestDtoDataStoreEntity + * @interface AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1 */ -export interface CreateClientRequestDtoDataStoreEntity { +export interface AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1 { /** * - * @type {CreateClientRequestDtoDataStoreEntityData} - * @memberof CreateClientRequestDtoDataStoreEntity + * @type {number} + * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1 */ - 'data': CreateClientRequestDtoDataStoreEntityData; + 'chainId': number; /** * - * @type {CreateClientRequestDtoDataStoreEntityData} - * @memberof CreateClientRequestDtoDataStoreEntity + * @type {any} + * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1 */ - 'signature': CreateClientRequestDtoDataStoreEntityData; + 'from': any; /** * - * @type {Array} - * @memberof CreateClientRequestDtoDataStoreEntity + * @type {number} + * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1 */ - 'keys': Array; -} -/** - * @type CreateClientRequestDtoDataStoreEntityData - * @export - */ -export type CreateClientRequestDtoDataStoreEntityData = CreateClientRequestDtoDataStoreEntityDataOneOf | CreateClientRequestDtoDataStoreEntityDataOneOf1; - -/** - * - * @export - * @interface CreateClientRequestDtoDataStoreEntityDataOneOf - */ -export interface CreateClientRequestDtoDataStoreEntityDataOneOf { + 'nonce'?: number; + /** + * + * @type {any} + * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1 + */ + 'data'?: any; /** * * @type {string} - * @memberof CreateClientRequestDtoDataStoreEntityDataOneOf + * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1 */ - 'type': CreateClientRequestDtoDataStoreEntityDataOneOfTypeEnum; + 'gas'?: string; /** * * @type {string} - * @memberof CreateClientRequestDtoDataStoreEntityDataOneOf + * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1 */ - 'url': string; + 'gasPrice'?: string; + /** + * + * @type {string} + * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1 + */ + 'type'?: AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1TypeEnum; + /** + * + * @type {any} + * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1 + */ + 'to'?: any | null; + /** + * + * @type {any} + * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1 + */ + 'value'?: any; } -export const CreateClientRequestDtoDataStoreEntityDataOneOfTypeEnum = { - File: 'FILE' +export const AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1TypeEnum = { + _0: '0' } as const; -export type CreateClientRequestDtoDataStoreEntityDataOneOfTypeEnum = typeof CreateClientRequestDtoDataStoreEntityDataOneOfTypeEnum[keyof typeof CreateClientRequestDtoDataStoreEntityDataOneOfTypeEnum]; +export type AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1TypeEnum = typeof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1TypeEnum[keyof typeof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOf1TypeEnum]; /** * * @export - * @interface CreateClientRequestDtoDataStoreEntityDataOneOf1 + * @interface AuthorizationRequestDtoRequestOneOfTransactionRequestOneOfAccessListInner */ -export interface CreateClientRequestDtoDataStoreEntityDataOneOf1 { - /** - * - * @type {string} - * @memberof CreateClientRequestDtoDataStoreEntityDataOneOf1 - */ - 'type': CreateClientRequestDtoDataStoreEntityDataOneOf1TypeEnum; +export interface AuthorizationRequestDtoRequestOneOfTransactionRequestOneOfAccessListInner { /** * - * @type {string} - * @memberof CreateClientRequestDtoDataStoreEntityDataOneOf1 + * @type {any} + * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOfAccessListInner */ - 'url': string; + 'address': any; /** * - * @type {{ [key: string]: string; }} - * @memberof CreateClientRequestDtoDataStoreEntityDataOneOf1 + * @type {Array} + * @memberof AuthorizationRequestDtoRequestOneOfTransactionRequestOneOfAccessListInner */ - 'headers'?: { [key: string]: string; }; + 'storageKeys': Array; } - -export const CreateClientRequestDtoDataStoreEntityDataOneOf1TypeEnum = { - Http: 'HTTP', - Https: 'HTTPS' -} as const; - -export type CreateClientRequestDtoDataStoreEntityDataOneOf1TypeEnum = typeof CreateClientRequestDtoDataStoreEntityDataOneOf1TypeEnum[keyof typeof CreateClientRequestDtoDataStoreEntityDataOneOf1TypeEnum]; - /** * * @export - * @interface CreateClientRequestDtoDataStoreEntityKeysInner + * @interface AuthorizationResponseDto */ -export interface CreateClientRequestDtoDataStoreEntityKeysInner { +export interface AuthorizationResponseDto { /** - * Key Type (e.g. RSA or EC - * @type {string} - * @memberof CreateClientRequestDtoDataStoreEntityKeysInner + * + * @type {Array} + * @memberof AuthorizationResponseDto */ - 'kty'?: CreateClientRequestDtoDataStoreEntityKeysInnerKtyEnum; + 'approvals'?: Array; /** - * Curve name + * * @type {string} - * @memberof CreateClientRequestDtoDataStoreEntityKeysInner + * @memberof AuthorizationResponseDto */ - 'crv'?: CreateClientRequestDtoDataStoreEntityKeysInnerCrvEnum; + 'authentication': string; /** - * Algorithm + * * @type {string} - * @memberof CreateClientRequestDtoDataStoreEntityKeysInner + * @memberof AuthorizationResponseDto */ - 'alg'?: CreateClientRequestDtoDataStoreEntityKeysInnerAlgEnum; + 'clientId': string; /** - * Public Key Use - * @type {string} - * @memberof CreateClientRequestDtoDataStoreEntityKeysInner + * + * @type {any} + * @memberof AuthorizationResponseDto */ - 'use'?: CreateClientRequestDtoDataStoreEntityKeysInnerUseEnum; + 'createdAt': any; /** - * Unique key ID - * @type {string} - * @memberof CreateClientRequestDtoDataStoreEntityKeysInner + * + * @type {Array} + * @memberof AuthorizationResponseDto */ - 'kid'?: string; + 'errors'?: Array; /** - * (RSA) Key modulus - * @type {string} - * @memberof CreateClientRequestDtoDataStoreEntityKeysInner + * + * @type {Array} + * @memberof AuthorizationResponseDto */ - 'n'?: string; + 'evaluations': Array; /** - * (RSA) Key exponent + * * @type {string} - * @memberof CreateClientRequestDtoDataStoreEntityKeysInner + * @memberof AuthorizationResponseDto */ - 'e'?: string; + 'id': string; /** - * (EC) X Coordinate + * * @type {string} - * @memberof CreateClientRequestDtoDataStoreEntityKeysInner + * @memberof AuthorizationResponseDto */ - 'x'?: string; + 'idempotencyKey'?: string | null; /** - * (EC) Y Coordinate - * @type {string} - * @memberof CreateClientRequestDtoDataStoreEntityKeysInner + * + * @type {AuthorizationRequestDtoMetadata} + * @memberof AuthorizationResponseDto */ - 'y'?: string; + 'metadata'?: AuthorizationRequestDtoMetadata; /** - * (EC) Private Key + * + * @type {AuthorizationRequestDtoRequest} + * @memberof AuthorizationResponseDto + */ + 'request': AuthorizationRequestDtoRequest; + /** + * * @type {string} - * @memberof CreateClientRequestDtoDataStoreEntityKeysInner + * @memberof AuthorizationResponseDto */ - 'd'?: string; + 'status': AuthorizationResponseDtoStatusEnum; + /** + * + * @type {any} + * @memberof AuthorizationResponseDto + */ + 'updatedAt': any; } -export const CreateClientRequestDtoDataStoreEntityKeysInnerKtyEnum = { - Ec: 'EC', - Rsa: 'RSA', - Okp: 'OKP' -} as const; - -export type CreateClientRequestDtoDataStoreEntityKeysInnerKtyEnum = typeof CreateClientRequestDtoDataStoreEntityKeysInnerKtyEnum[keyof typeof CreateClientRequestDtoDataStoreEntityKeysInnerKtyEnum]; -export const CreateClientRequestDtoDataStoreEntityKeysInnerCrvEnum = { - Secp256k1: 'secp256k1', - P256: 'P-256', - Ed25519: 'Ed25519' -} as const; - -export type CreateClientRequestDtoDataStoreEntityKeysInnerCrvEnum = typeof CreateClientRequestDtoDataStoreEntityKeysInnerCrvEnum[keyof typeof CreateClientRequestDtoDataStoreEntityKeysInnerCrvEnum]; -export const CreateClientRequestDtoDataStoreEntityKeysInnerAlgEnum = { - Es256K: 'ES256K', - Es256: 'ES256', - Rs256: 'RS256', - Eddsa: 'EDDSA' -} as const; - -export type CreateClientRequestDtoDataStoreEntityKeysInnerAlgEnum = typeof CreateClientRequestDtoDataStoreEntityKeysInnerAlgEnum[keyof typeof CreateClientRequestDtoDataStoreEntityKeysInnerAlgEnum]; -export const CreateClientRequestDtoDataStoreEntityKeysInnerUseEnum = { - Sig: 'sig', - Enc: 'enc' +export const AuthorizationResponseDtoStatusEnum = { + Created: 'CREATED', + Canceled: 'CANCELED', + Failed: 'FAILED', + Processing: 'PROCESSING', + Approving: 'APPROVING', + Permitted: 'PERMITTED', + Forbidden: 'FORBIDDEN' } as const; -export type CreateClientRequestDtoDataStoreEntityKeysInnerUseEnum = typeof CreateClientRequestDtoDataStoreEntityKeysInnerUseEnum[keyof typeof CreateClientRequestDtoDataStoreEntityKeysInnerUseEnum]; +export type AuthorizationResponseDtoStatusEnum = typeof AuthorizationResponseDtoStatusEnum[keyof typeof AuthorizationResponseDtoStatusEnum]; /** * * @export - * @interface CreateClientResponseDto + * @interface AuthorizationResponseDtoErrorsInner */ -export interface CreateClientResponseDto { +export interface AuthorizationResponseDtoErrorsInner { + /** + * + * @type {any} + * @memberof AuthorizationResponseDtoErrorsInner + */ + 'context'?: any; /** * * @type {string} - * @memberof CreateClientResponseDto + * @memberof AuthorizationResponseDtoErrorsInner */ 'id': string; /** * * @type {string} - * @memberof CreateClientResponseDto + * @memberof AuthorizationResponseDtoErrorsInner + */ + 'message': string; + /** + * + * @type {string} + * @memberof AuthorizationResponseDtoErrorsInner */ 'name': string; +} +/** + * + * @export + * @interface AuthorizationResponseDtoEvaluationsInner + */ +export interface AuthorizationResponseDtoEvaluationsInner { /** - * plaintext secret for authenticating to armory + * * @type {string} - * @memberof CreateClientResponseDto + * @memberof AuthorizationResponseDtoEvaluationsInner */ - 'clientSecret': string; + 'id': string; /** - * plaintext secret for authenticating to data store + * * @type {string} - * @memberof CreateClientResponseDto + * @memberof AuthorizationResponseDtoEvaluationsInner */ - 'dataSecret': string | null; + 'decision': string; /** * - * @type {any} - * @memberof CreateClientResponseDto + * @type {string} + * @memberof AuthorizationResponseDtoEvaluationsInner */ - 'createdAt': any; + 'signature': string | null; /** * * @type {any} - * @memberof CreateClientResponseDto + * @memberof AuthorizationResponseDtoEvaluationsInner */ - 'updatedAt': any; + 'transactionRequestIntent'?: any; /** * - * @type {CreateClientResponseDtoDataStore} - * @memberof CreateClientResponseDto + * @type {AuthorizationResponseDtoEvaluationsInnerApprovalRequirements} + * @memberof AuthorizationResponseDtoEvaluationsInner */ - 'dataStore': CreateClientResponseDtoDataStore; + 'approvalRequirements'?: AuthorizationResponseDtoEvaluationsInnerApprovalRequirements; /** * - * @type {CreateClientResponseDtoPolicyEngine} - * @memberof CreateClientResponseDto + * @type {any} + * @memberof AuthorizationResponseDtoEvaluationsInner */ - 'policyEngine': CreateClientResponseDtoPolicyEngine; + 'createdAt': any; } /** * * @export - * @interface CreateClientResponseDtoDataStore + * @interface AuthorizationResponseDtoEvaluationsInnerApprovalRequirements */ -export interface CreateClientResponseDtoDataStore { - /** - * - * @type {Array} - * @memberof CreateClientResponseDtoDataStore - */ - 'entityPublicKeys': Array; - /** - * - * @type {Array} - * @memberof CreateClientResponseDtoDataStore - */ - 'policyPublicKeys': Array; +export interface AuthorizationResponseDtoEvaluationsInnerApprovalRequirements { /** * - * @type {string} - * @memberof CreateClientResponseDtoDataStore + * @type {Array} + * @memberof AuthorizationResponseDtoEvaluationsInnerApprovalRequirements */ - 'entityDataUrl'?: string; + 'required'?: Array; /** - * - * @type {string} - * @memberof CreateClientResponseDtoDataStore - */ - 'policyDataUrl'?: string; -} -/** - * - * @export - * @interface CreateClientResponseDtoPolicyEngine - */ -export interface CreateClientResponseDtoPolicyEngine { + * + * @type {Array} + * @memberof AuthorizationResponseDtoEvaluationsInnerApprovalRequirements + */ + 'missing'?: Array; /** * - * @type {Array} - * @memberof CreateClientResponseDtoPolicyEngine + * @type {Array} + * @memberof AuthorizationResponseDtoEvaluationsInnerApprovalRequirements */ - 'nodes': Array; + 'satisfied'?: Array; } /** * * @export - * @interface CreateClientResponseDtoPolicyEngineNodesInner + * @interface AuthorizationResponseDtoEvaluationsInnerApprovalRequirementsRequiredInner */ -export interface CreateClientResponseDtoPolicyEngineNodesInner { - /** - * - * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInner - */ - 'id': string; +export interface AuthorizationResponseDtoEvaluationsInnerApprovalRequirementsRequiredInner { /** * - * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInner + * @type {number} + * @memberof AuthorizationResponseDtoEvaluationsInnerApprovalRequirementsRequiredInner */ - 'clientId': string; + 'approvalCount': number; /** - * + * The number of requried approvals * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInner + * @memberof AuthorizationResponseDtoEvaluationsInnerApprovalRequirementsRequiredInner */ - 'clientSecret'?: string; + 'approvalEntityType': AuthorizationResponseDtoEvaluationsInnerApprovalRequirementsRequiredInnerApprovalEntityTypeEnum; /** - * - * @type {CreateClientResponseDtoPolicyEngineNodesInnerPublicKey} - * @memberof CreateClientResponseDtoPolicyEngineNodesInner + * List of entities IDs that must satisfy the requirements + * @type {Array} + * @memberof AuthorizationResponseDtoEvaluationsInnerApprovalRequirementsRequiredInner */ - 'publicKey': CreateClientResponseDtoPolicyEngineNodesInnerPublicKey; + 'entityIds': Array; /** * - * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInner + * @type {boolean} + * @memberof AuthorizationResponseDtoEvaluationsInnerApprovalRequirementsRequiredInner */ - 'url': string; + 'countPrincipal': boolean; } -/** - * @type CreateClientResponseDtoPolicyEngineNodesInnerPublicKey - * @export - */ -export type CreateClientResponseDtoPolicyEngineNodesInnerPublicKey = CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf | CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf1 | CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf2 | CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf3 | CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf4; + +export const AuthorizationResponseDtoEvaluationsInnerApprovalRequirementsRequiredInnerApprovalEntityTypeEnum = { + User: 'Narval::User', + UserRole: 'Narval::UserRole', + UserGroup: 'Narval::UserGroup' +} as const; + +export type AuthorizationResponseDtoEvaluationsInnerApprovalRequirementsRequiredInnerApprovalEntityTypeEnum = typeof AuthorizationResponseDtoEvaluationsInnerApprovalRequirementsRequiredInnerApprovalEntityTypeEnum[keyof typeof AuthorizationResponseDtoEvaluationsInnerApprovalRequirementsRequiredInnerApprovalEntityTypeEnum]; /** * * @export - * @interface CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf + * @interface CreateClientRequestDto */ -export interface CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf { +export interface CreateClientRequestDto { /** * * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf + * @memberof CreateClientRequestDto */ - 'kty': CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOfKtyEnum; + 'id'?: string; /** * * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf + * @memberof CreateClientRequestDto */ - 'alg': CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOfAlgEnum; + 'name': string; /** * - * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf + * @type {boolean} + * @memberof CreateClientRequestDto */ - 'use'?: CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOfUseEnum; + 'useManagedDataStore'?: boolean; /** * * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf + * @memberof CreateClientRequestDto */ - 'kid': string; + 'clientSecret'?: string; /** * - * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf + * @type {CreateClientRequestDtoDataStore} + * @memberof CreateClientRequestDto */ - 'addr'?: string; + 'dataStore': CreateClientRequestDtoDataStore; /** * - * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf + * @type {Array} + * @memberof CreateClientRequestDto */ - 'crv': CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOfCrvEnum; + 'policyEngineNodes'?: Array; +} +/** + * + * @export + * @interface CreateClientRequestDtoDataStore + */ +export interface CreateClientRequestDtoDataStore { /** * - * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf + * @type {CreateClientRequestDtoDataStoreEntity} + * @memberof CreateClientRequestDtoDataStore */ - 'x': string; + 'entity': CreateClientRequestDtoDataStoreEntity; /** * - * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf + * @type {CreateClientRequestDtoDataStoreEntity} + * @memberof CreateClientRequestDtoDataStore */ - 'y': string; + 'policy': CreateClientRequestDtoDataStoreEntity; + /** + * Whether to include the engine key in the entity and policy keys + * @type {boolean} + * @memberof CreateClientRequestDtoDataStore + */ + 'allowSelfSignedData'?: boolean; } - -export const CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOfKtyEnum = { - Ec: 'EC' -} as const; - -export type CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOfKtyEnum = typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOfKtyEnum[keyof typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOfKtyEnum]; -export const CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOfAlgEnum = { - Es256K: 'ES256K' -} as const; - -export type CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOfAlgEnum = typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOfAlgEnum[keyof typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOfAlgEnum]; -export const CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOfUseEnum = { - Sig: 'sig', - Enc: 'enc' -} as const; - -export type CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOfUseEnum = typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOfUseEnum[keyof typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOfUseEnum]; -export const CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOfCrvEnum = { - Secp256k1: 'secp256k1' -} as const; - -export type CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOfCrvEnum = typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOfCrvEnum[keyof typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOfCrvEnum]; - /** * * @export - * @interface CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf1 + * @interface CreateClientRequestDtoDataStoreEntity */ -export interface CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf1 { +export interface CreateClientRequestDtoDataStoreEntity { /** * - * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf1 + * @type {CreateClientRequestDtoDataStoreEntityData} + * @memberof CreateClientRequestDtoDataStoreEntity */ - 'kty': CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf1KtyEnum; + 'data': CreateClientRequestDtoDataStoreEntityData; /** * - * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf1 + * @type {CreateClientRequestDtoDataStoreEntityData} + * @memberof CreateClientRequestDtoDataStoreEntity */ - 'alg': CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf1AlgEnum; + 'signature': CreateClientRequestDtoDataStoreEntityData; /** * - * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf1 + * @type {Array} + * @memberof CreateClientRequestDtoDataStoreEntity */ - 'use'?: CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf1UseEnum; + 'keys': Array; +} +/** + * @type CreateClientRequestDtoDataStoreEntityData + * @export + */ +export type CreateClientRequestDtoDataStoreEntityData = CreateClientRequestDtoDataStoreEntityDataOneOf | CreateClientRequestDtoDataStoreEntityDataOneOf1; + +/** + * + * @export + * @interface CreateClientRequestDtoDataStoreEntityDataOneOf + */ +export interface CreateClientRequestDtoDataStoreEntityDataOneOf { /** * * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf1 + * @memberof CreateClientRequestDtoDataStoreEntityDataOneOf */ - 'kid': string; + 'type': CreateClientRequestDtoDataStoreEntityDataOneOfTypeEnum; /** * * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf1 + * @memberof CreateClientRequestDtoDataStoreEntityDataOneOf */ - 'addr'?: string; + 'url': string; +} + +export const CreateClientRequestDtoDataStoreEntityDataOneOfTypeEnum = { + File: 'FILE' +} as const; + +export type CreateClientRequestDtoDataStoreEntityDataOneOfTypeEnum = typeof CreateClientRequestDtoDataStoreEntityDataOneOfTypeEnum[keyof typeof CreateClientRequestDtoDataStoreEntityDataOneOfTypeEnum]; + +/** + * + * @export + * @interface CreateClientRequestDtoDataStoreEntityDataOneOf1 + */ +export interface CreateClientRequestDtoDataStoreEntityDataOneOf1 { /** * * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf1 + * @memberof CreateClientRequestDtoDataStoreEntityDataOneOf1 */ - 'crv': CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf1CrvEnum; + 'type': CreateClientRequestDtoDataStoreEntityDataOneOf1TypeEnum; /** * * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf1 + * @memberof CreateClientRequestDtoDataStoreEntityDataOneOf1 */ - 'x': string; + 'url': string; /** * - * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf1 + * @type {{ [key: string]: string; }} + * @memberof CreateClientRequestDtoDataStoreEntityDataOneOf1 */ - 'y': string; + 'headers'?: { [key: string]: string; }; } -export const CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf1KtyEnum = { - Ec: 'EC' -} as const; - -export type CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf1KtyEnum = typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf1KtyEnum[keyof typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf1KtyEnum]; -export const CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf1AlgEnum = { - Es256: 'ES256' -} as const; - -export type CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf1AlgEnum = typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf1AlgEnum[keyof typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf1AlgEnum]; -export const CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf1UseEnum = { - Sig: 'sig', - Enc: 'enc' -} as const; - -export type CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf1UseEnum = typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf1UseEnum[keyof typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf1UseEnum]; -export const CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf1CrvEnum = { - P256: 'P-256' +export const CreateClientRequestDtoDataStoreEntityDataOneOf1TypeEnum = { + Http: 'HTTP', + Https: 'HTTPS' } as const; -export type CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf1CrvEnum = typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf1CrvEnum[keyof typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf1CrvEnum]; +export type CreateClientRequestDtoDataStoreEntityDataOneOf1TypeEnum = typeof CreateClientRequestDtoDataStoreEntityDataOneOf1TypeEnum[keyof typeof CreateClientRequestDtoDataStoreEntityDataOneOf1TypeEnum]; /** * * @export - * @interface CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf2 + * @interface CreateClientRequestDtoDataStoreEntityKeysInner */ -export interface CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf2 { +export interface CreateClientRequestDtoDataStoreEntityKeysInner { /** - * + * Key Type (e.g. RSA or EC * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf2 + * @memberof CreateClientRequestDtoDataStoreEntityKeysInner */ - 'kty': CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf2KtyEnum; + 'kty'?: CreateClientRequestDtoDataStoreEntityKeysInnerKtyEnum; /** - * + * Curve name * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf2 + * @memberof CreateClientRequestDtoDataStoreEntityKeysInner */ - 'alg': CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf2AlgEnum; + 'crv'?: CreateClientRequestDtoDataStoreEntityKeysInnerCrvEnum; /** - * + * Algorithm * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf2 + * @memberof CreateClientRequestDtoDataStoreEntityKeysInner */ - 'use'?: CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf2UseEnum; + 'alg'?: CreateClientRequestDtoDataStoreEntityKeysInnerAlgEnum; /** - * + * Public Key Use * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf2 + * @memberof CreateClientRequestDtoDataStoreEntityKeysInner */ - 'kid': string; + 'use'?: CreateClientRequestDtoDataStoreEntityKeysInnerUseEnum; /** - * + * Unique key ID * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf2 + * @memberof CreateClientRequestDtoDataStoreEntityKeysInner */ - 'addr'?: string; + 'kid'?: string; /** - * + * (RSA) Key modulus * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf2 + * @memberof CreateClientRequestDtoDataStoreEntityKeysInner */ - 'n': string; + 'n'?: string; /** - * + * (RSA) Key exponent * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf2 + * @memberof CreateClientRequestDtoDataStoreEntityKeysInner */ - 'e': string; + 'e'?: string; + /** + * (EC) X Coordinate + * @type {string} + * @memberof CreateClientRequestDtoDataStoreEntityKeysInner + */ + 'x'?: string; + /** + * (EC) Y Coordinate + * @type {string} + * @memberof CreateClientRequestDtoDataStoreEntityKeysInner + */ + 'y'?: string; + /** + * (EC) Private Key + * @type {string} + * @memberof CreateClientRequestDtoDataStoreEntityKeysInner + */ + 'd'?: string; } -export const CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf2KtyEnum = { - Rsa: 'RSA' +export const CreateClientRequestDtoDataStoreEntityKeysInnerKtyEnum = { + Ec: 'EC', + Rsa: 'RSA', + Okp: 'OKP' } as const; -export type CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf2KtyEnum = typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf2KtyEnum[keyof typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf2KtyEnum]; -export const CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf2AlgEnum = { - Rs256: 'RS256' +export type CreateClientRequestDtoDataStoreEntityKeysInnerKtyEnum = typeof CreateClientRequestDtoDataStoreEntityKeysInnerKtyEnum[keyof typeof CreateClientRequestDtoDataStoreEntityKeysInnerKtyEnum]; +export const CreateClientRequestDtoDataStoreEntityKeysInnerCrvEnum = { + Secp256k1: 'secp256k1', + P256: 'P-256', + Ed25519: 'Ed25519' +} as const; + +export type CreateClientRequestDtoDataStoreEntityKeysInnerCrvEnum = typeof CreateClientRequestDtoDataStoreEntityKeysInnerCrvEnum[keyof typeof CreateClientRequestDtoDataStoreEntityKeysInnerCrvEnum]; +export const CreateClientRequestDtoDataStoreEntityKeysInnerAlgEnum = { + Es256K: 'ES256K', + Es256: 'ES256', + Rs256: 'RS256', + Eddsa: 'EDDSA' } as const; -export type CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf2AlgEnum = typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf2AlgEnum[keyof typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf2AlgEnum]; -export const CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf2UseEnum = { +export type CreateClientRequestDtoDataStoreEntityKeysInnerAlgEnum = typeof CreateClientRequestDtoDataStoreEntityKeysInnerAlgEnum[keyof typeof CreateClientRequestDtoDataStoreEntityKeysInnerAlgEnum]; +export const CreateClientRequestDtoDataStoreEntityKeysInnerUseEnum = { Sig: 'sig', Enc: 'enc' } as const; -export type CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf2UseEnum = typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf2UseEnum[keyof typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf2UseEnum]; +export type CreateClientRequestDtoDataStoreEntityKeysInnerUseEnum = typeof CreateClientRequestDtoDataStoreEntityKeysInnerUseEnum[keyof typeof CreateClientRequestDtoDataStoreEntityKeysInnerUseEnum]; /** * * @export - * @interface CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf3 + * @interface CreateClientResponseDto */ -export interface CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf3 { +export interface CreateClientResponseDto { /** * * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf3 + * @memberof CreateClientResponseDto */ - 'kty': CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf3KtyEnum; + 'id': string; /** * * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf3 + * @memberof CreateClientResponseDto */ - 'crv': CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf3CrvEnum; + 'name': string; /** - * + * plaintext secret for authenticating to armory * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf3 + * @memberof CreateClientResponseDto */ - 'alg': CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf3AlgEnum; + 'clientSecret': string; /** - * + * plaintext secret for authenticating to data store * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf3 + * @memberof CreateClientResponseDto */ - 'use'?: CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf3UseEnum; + 'dataSecret': string | null; /** * - * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf3 + * @type {any} + * @memberof CreateClientResponseDto */ - 'kid': string; + 'createdAt': any; /** * * @type {any} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf3 + * @memberof CreateClientResponseDto */ - 'addr': any; + 'updatedAt': any; + /** + * + * @type {CreateClientResponseDtoDataStore} + * @memberof CreateClientResponseDto + */ + 'dataStore': CreateClientResponseDtoDataStore; + /** + * + * @type {CreateClientResponseDtoPolicyEngine} + * @memberof CreateClientResponseDto + */ + 'policyEngine': CreateClientResponseDtoPolicyEngine; } - -export const CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf3KtyEnum = { - Ec: 'EC' -} as const; - -export type CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf3KtyEnum = typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf3KtyEnum[keyof typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf3KtyEnum]; -export const CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf3CrvEnum = { - Secp256k1: 'secp256k1' -} as const; - -export type CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf3CrvEnum = typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf3CrvEnum[keyof typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf3CrvEnum]; -export const CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf3AlgEnum = { - Es256K: 'ES256K' -} as const; - -export type CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf3AlgEnum = typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf3AlgEnum[keyof typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf3AlgEnum]; -export const CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf3UseEnum = { - Sig: 'sig', - Enc: 'enc' -} as const; - -export type CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf3UseEnum = typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf3UseEnum[keyof typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf3UseEnum]; - /** * * @export - * @interface CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf4 + * @interface CreateClientResponseDtoDataStore */ -export interface CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf4 { +export interface CreateClientResponseDtoDataStore { /** * - * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf4 + * @type {Array} + * @memberof CreateClientResponseDtoDataStore + */ + 'entityPublicKeys': Array; + /** + * + * @type {Array} + * @memberof CreateClientResponseDtoDataStore */ - 'kty': CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf4KtyEnum; + 'policyPublicKeys': Array; /** * * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf4 + * @memberof CreateClientResponseDtoDataStore */ - 'alg': CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf4AlgEnum; + 'entityDataUrl'?: string; /** * * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf4 + * @memberof CreateClientResponseDtoDataStore + */ + 'policyDataUrl'?: string; +} +/** + * + * @export + * @interface CreateClientResponseDtoPolicyEngine + */ +export interface CreateClientResponseDtoPolicyEngine { + /** + * + * @type {Array} + * @memberof CreateClientResponseDtoPolicyEngine */ - 'use'?: CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf4UseEnum; + 'nodes': Array; +} +/** + * + * @export + * @interface CreateClientResponseDtoPolicyEngineNodesInner + */ +export interface CreateClientResponseDtoPolicyEngineNodesInner { /** * * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf4 + * @memberof CreateClientResponseDtoPolicyEngineNodesInner */ - 'kid': string; + 'id': string; /** * * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf4 + * @memberof CreateClientResponseDtoPolicyEngineNodesInner */ - 'addr'?: string; + 'clientId': string; /** * * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf4 + * @memberof CreateClientResponseDtoPolicyEngineNodesInner + */ + 'clientSecret'?: string; + /** + * + * @type {CreateClientResponseDtoPolicyEngineNodesInnerPublicKey} + * @memberof CreateClientResponseDtoPolicyEngineNodesInner */ - 'crv': CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf4CrvEnum; + 'publicKey': CreateClientResponseDtoPolicyEngineNodesInnerPublicKey; /** * * @type {string} - * @memberof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf4 + * @memberof CreateClientResponseDtoPolicyEngineNodesInner */ - 'x': string; + 'url': string; } - -export const CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf4KtyEnum = { - Okp: 'OKP' -} as const; - -export type CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf4KtyEnum = typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf4KtyEnum[keyof typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf4KtyEnum]; -export const CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf4AlgEnum = { - Eddsa: 'EDDSA' -} as const; - -export type CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf4AlgEnum = typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf4AlgEnum[keyof typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf4AlgEnum]; -export const CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf4UseEnum = { - Sig: 'sig', - Enc: 'enc' -} as const; - -export type CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf4UseEnum = typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf4UseEnum[keyof typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf4UseEnum]; -export const CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf4CrvEnum = { - Ed25519: 'Ed25519' -} as const; - -export type CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf4CrvEnum = typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf4CrvEnum[keyof typeof CreateClientResponseDtoPolicyEngineNodesInnerPublicKeyOneOf4CrvEnum]; +/** + * @type CreateClientResponseDtoPolicyEngineNodesInnerPublicKey + * @export + */ +export type CreateClientResponseDtoPolicyEngineNodesInnerPublicKey = AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf | AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf1 | AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf2 | AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf3 | AuthorizationRequestDtoMetadataConfirmationKeyJwkOneOf4; /** * @@ -4382,7 +4440,7 @@ export const ApplicationApiFactory = function (configuration?: Configuration, ba * @param {*} [options] Override http request option. * @throws {RequiredError} */ - ping(options?: any): AxiosPromise { + ping(options?: RawAxiosRequestConfig): AxiosPromise { return localVarFp.ping(options).then((request) => request(axios, basePath)); }, }; @@ -4443,8 +4501,8 @@ export const AuthorizationApiAxiosParamCreator = function (configuration?: Confi const localVarHeaderParameter = {} as any; const localVarQueryParameter = {} as any; - // authentication CLIENT_ID required - await setApiKeyToObject(localVarHeaderParameter, "CLIENT_ID", configuration) + // authentication Client-ID required + await setApiKeyToObject(localVarHeaderParameter, "x-client-id", configuration) if (xClientId != null) { localVarHeaderParameter['x-client-id'] = String(xClientId); @@ -4489,8 +4547,8 @@ export const AuthorizationApiAxiosParamCreator = function (configuration?: Confi const localVarHeaderParameter = {} as any; const localVarQueryParameter = {} as any; - // authentication CLIENT_ID required - await setApiKeyToObject(localVarHeaderParameter, "CLIENT_ID", configuration) + // authentication Client-ID required + await setApiKeyToObject(localVarHeaderParameter, "x-client-id", configuration) if (xClientId != null) { localVarHeaderParameter['x-client-id'] = String(xClientId); @@ -4536,8 +4594,8 @@ export const AuthorizationApiAxiosParamCreator = function (configuration?: Confi const localVarHeaderParameter = {} as any; const localVarQueryParameter = {} as any; - // authentication CLIENT_ID required - await setApiKeyToObject(localVarHeaderParameter, "CLIENT_ID", configuration) + // authentication Client-ID required + await setApiKeyToObject(localVarHeaderParameter, "x-client-id", configuration) if (xClientId != null) { localVarHeaderParameter['x-client-id'] = String(xClientId); @@ -4620,40 +4678,106 @@ export const AuthorizationApiFactory = function (configuration?: Configuration, /** * * @summary Approves an authorization request - * @param {string} id - * @param {string} xClientId - * @param {ApprovalDto} approvalDto + * @param {AuthorizationApiApproveRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - approve(id: string, xClientId: string, approvalDto: ApprovalDto, options?: any): AxiosPromise { - return localVarFp.approve(id, xClientId, approvalDto, options).then((request) => request(axios, basePath)); + approve(requestParameters: AuthorizationApiApproveRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.approve(requestParameters.id, requestParameters.xClientId, requestParameters.approvalDto, options).then((request) => request(axios, basePath)); }, /** * * @summary Submits a new authorization request for evaluation by the policy engine - * @param {string} xClientId - * @param {AuthorizationRequestDto} authorizationRequestDto + * @param {AuthorizationApiEvaluateRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - evaluate(xClientId: string, authorizationRequestDto: AuthorizationRequestDto, options?: any): AxiosPromise { - return localVarFp.evaluate(xClientId, authorizationRequestDto, options).then((request) => request(axios, basePath)); + evaluate(requestParameters: AuthorizationApiEvaluateRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.evaluate(requestParameters.xClientId, requestParameters.authorizationRequestDto, options).then((request) => request(axios, basePath)); }, /** * * @summary Gets an authorization request by ID - * @param {string} id - * @param {string} xClientId + * @param {AuthorizationApiGetByIdRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getById(id: string, xClientId: string, options?: any): AxiosPromise { - return localVarFp.getById(id, xClientId, options).then((request) => request(axios, basePath)); + getById(requestParameters: AuthorizationApiGetByIdRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.getById(requestParameters.id, requestParameters.xClientId, options).then((request) => request(axios, basePath)); }, }; }; +/** + * Request parameters for approve operation in AuthorizationApi. + * @export + * @interface AuthorizationApiApproveRequest + */ +export interface AuthorizationApiApproveRequest { + /** + * + * @type {string} + * @memberof AuthorizationApiApprove + */ + readonly id: string + + /** + * + * @type {string} + * @memberof AuthorizationApiApprove + */ + readonly xClientId: string + + /** + * + * @type {ApprovalDto} + * @memberof AuthorizationApiApprove + */ + readonly approvalDto: ApprovalDto +} + +/** + * Request parameters for evaluate operation in AuthorizationApi. + * @export + * @interface AuthorizationApiEvaluateRequest + */ +export interface AuthorizationApiEvaluateRequest { + /** + * + * @type {string} + * @memberof AuthorizationApiEvaluate + */ + readonly xClientId: string + + /** + * + * @type {AuthorizationRequestDto} + * @memberof AuthorizationApiEvaluate + */ + readonly authorizationRequestDto: AuthorizationRequestDto +} + +/** + * Request parameters for getById operation in AuthorizationApi. + * @export + * @interface AuthorizationApiGetByIdRequest + */ +export interface AuthorizationApiGetByIdRequest { + /** + * + * @type {string} + * @memberof AuthorizationApiGetById + */ + readonly id: string + + /** + * + * @type {string} + * @memberof AuthorizationApiGetById + */ + readonly xClientId: string +} + /** * AuthorizationApi - object-oriented interface * @export @@ -4664,41 +4788,37 @@ export class AuthorizationApi extends BaseAPI { /** * * @summary Approves an authorization request - * @param {string} id - * @param {string} xClientId - * @param {ApprovalDto} approvalDto + * @param {AuthorizationApiApproveRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof AuthorizationApi */ - public approve(id: string, xClientId: string, approvalDto: ApprovalDto, options?: RawAxiosRequestConfig) { - return AuthorizationApiFp(this.configuration).approve(id, xClientId, approvalDto, options).then((request) => request(this.axios, this.basePath)); + public approve(requestParameters: AuthorizationApiApproveRequest, options?: RawAxiosRequestConfig) { + return AuthorizationApiFp(this.configuration).approve(requestParameters.id, requestParameters.xClientId, requestParameters.approvalDto, options).then((request) => request(this.axios, this.basePath)); } /** * * @summary Submits a new authorization request for evaluation by the policy engine - * @param {string} xClientId - * @param {AuthorizationRequestDto} authorizationRequestDto + * @param {AuthorizationApiEvaluateRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof AuthorizationApi */ - public evaluate(xClientId: string, authorizationRequestDto: AuthorizationRequestDto, options?: RawAxiosRequestConfig) { - return AuthorizationApiFp(this.configuration).evaluate(xClientId, authorizationRequestDto, options).then((request) => request(this.axios, this.basePath)); + public evaluate(requestParameters: AuthorizationApiEvaluateRequest, options?: RawAxiosRequestConfig) { + return AuthorizationApiFp(this.configuration).evaluate(requestParameters.xClientId, requestParameters.authorizationRequestDto, options).then((request) => request(this.axios, this.basePath)); } /** * * @summary Gets an authorization request by ID - * @param {string} id - * @param {string} xClientId + * @param {AuthorizationApiGetByIdRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof AuthorizationApi */ - public getById(id: string, xClientId: string, options?: RawAxiosRequestConfig) { - return AuthorizationApiFp(this.configuration).getById(id, xClientId, options).then((request) => request(this.axios, this.basePath)); + public getById(requestParameters: AuthorizationApiGetByIdRequest, options?: RawAxiosRequestConfig) { + return AuthorizationApiFp(this.configuration).getById(requestParameters.id, requestParameters.xClientId, options).then((request) => request(this.axios, this.basePath)); } } @@ -4735,8 +4855,8 @@ export const ClientApiAxiosParamCreator = function (configuration?: Configuratio const localVarHeaderParameter = {} as any; const localVarQueryParameter = {} as any; - // authentication ADMIN_API_KEY required - await setApiKeyToObject(localVarHeaderParameter, "ADMIN_API_KEY", configuration) + // authentication Admin-API-Key required + await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration) if (xApiKey != null) { localVarHeaderParameter['x-api-key'] = String(xApiKey); @@ -4793,17 +4913,37 @@ export const ClientApiFactory = function (configuration?: Configuration, basePat /** * * @summary Creates a new client - * @param {string} xApiKey - * @param {CreateClientRequestDto} createClientRequestDto + * @param {ClientApiCreateRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - create(xApiKey: string, createClientRequestDto: CreateClientRequestDto, options?: any): AxiosPromise { - return localVarFp.create(xApiKey, createClientRequestDto, options).then((request) => request(axios, basePath)); + create(requestParameters: ClientApiCreateRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.create(requestParameters.xApiKey, requestParameters.createClientRequestDto, options).then((request) => request(axios, basePath)); }, }; }; +/** + * Request parameters for create operation in ClientApi. + * @export + * @interface ClientApiCreateRequest + */ +export interface ClientApiCreateRequest { + /** + * + * @type {string} + * @memberof ClientApiCreate + */ + readonly xApiKey: string + + /** + * + * @type {CreateClientRequestDto} + * @memberof ClientApiCreate + */ + readonly createClientRequestDto: CreateClientRequestDto +} + /** * ClientApi - object-oriented interface * @export @@ -4814,14 +4954,13 @@ export class ClientApi extends BaseAPI { /** * * @summary Creates a new client - * @param {string} xApiKey - * @param {CreateClientRequestDto} createClientRequestDto + * @param {ClientApiCreateRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof ClientApi */ - public create(xApiKey: string, createClientRequestDto: CreateClientRequestDto, options?: RawAxiosRequestConfig) { - return ClientApiFp(this.configuration).create(xApiKey, createClientRequestDto, options).then((request) => request(this.axios, this.basePath)); + public create(requestParameters: ClientApiCreateRequest, options?: RawAxiosRequestConfig) { + return ClientApiFp(this.configuration).create(requestParameters.xApiKey, requestParameters.createClientRequestDto, options).then((request) => request(this.axios, this.basePath)); } } @@ -5015,8 +5154,8 @@ export const ManagedDataStoreApiAxiosParamCreator = function (configuration?: Co const localVarHeaderParameter = {} as any; const localVarQueryParameter = {} as any; - // authentication CLIENT_SECRET required - await setApiKeyToObject(localVarHeaderParameter, "CLIENT_SECRET", configuration) + // authentication Client-Secret required + await setApiKeyToObject(localVarHeaderParameter, "x-client-secret", configuration) if (xClientSecret != null) { localVarHeaderParameter['x-client-secret'] = String(xClientSecret); @@ -5123,58 +5262,140 @@ export const ManagedDataStoreApiFactory = function (configuration?: Configuratio /** * * @summary Gets the client entities - * @param {string} clientId + * @param {ManagedDataStoreApiGetEntitiesRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getEntities(clientId: string, options?: any): AxiosPromise { - return localVarFp.getEntities(clientId, options).then((request) => request(axios, basePath)); + getEntities(requestParameters: ManagedDataStoreApiGetEntitiesRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.getEntities(requestParameters.clientId, options).then((request) => request(axios, basePath)); }, /** * * @summary Gets the client policies - * @param {string} clientId + * @param {ManagedDataStoreApiGetPoliciesRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getPolicies(clientId: string, options?: any): AxiosPromise { - return localVarFp.getPolicies(clientId, options).then((request) => request(axios, basePath)); + getPolicies(requestParameters: ManagedDataStoreApiGetPoliciesRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.getPolicies(requestParameters.clientId, options).then((request) => request(axios, basePath)); }, /** * * @summary Sets the client entities - * @param {string} clientId - * @param {SetEntityStoreDto} setEntityStoreDto + * @param {ManagedDataStoreApiSetEntitiesRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - setEntities(clientId: string, setEntityStoreDto: SetEntityStoreDto, options?: any): AxiosPromise { - return localVarFp.setEntities(clientId, setEntityStoreDto, options).then((request) => request(axios, basePath)); + setEntities(requestParameters: ManagedDataStoreApiSetEntitiesRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.setEntities(requestParameters.clientId, requestParameters.setEntityStoreDto, options).then((request) => request(axios, basePath)); }, /** * * @summary Sets the client policies - * @param {string} clientId - * @param {SetPolicyStoreDto} setPolicyStoreDto + * @param {ManagedDataStoreApiSetPoliciesRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - setPolicies(clientId: string, setPolicyStoreDto: SetPolicyStoreDto, options?: any): AxiosPromise { - return localVarFp.setPolicies(clientId, setPolicyStoreDto, options).then((request) => request(axios, basePath)); + setPolicies(requestParameters: ManagedDataStoreApiSetPoliciesRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.setPolicies(requestParameters.clientId, requestParameters.setPolicyStoreDto, options).then((request) => request(axios, basePath)); }, /** * * @summary Sync the client data store with the engine cluster - * @param {string} xClientSecret + * @param {ManagedDataStoreApiSyncRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - sync(xClientSecret: string, options?: any): AxiosPromise { - return localVarFp.sync(xClientSecret, options).then((request) => request(axios, basePath)); + sync(requestParameters: ManagedDataStoreApiSyncRequest, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.sync(requestParameters.xClientSecret, options).then((request) => request(axios, basePath)); }, }; }; +/** + * Request parameters for getEntities operation in ManagedDataStoreApi. + * @export + * @interface ManagedDataStoreApiGetEntitiesRequest + */ +export interface ManagedDataStoreApiGetEntitiesRequest { + /** + * + * @type {string} + * @memberof ManagedDataStoreApiGetEntities + */ + readonly clientId: string +} + +/** + * Request parameters for getPolicies operation in ManagedDataStoreApi. + * @export + * @interface ManagedDataStoreApiGetPoliciesRequest + */ +export interface ManagedDataStoreApiGetPoliciesRequest { + /** + * + * @type {string} + * @memberof ManagedDataStoreApiGetPolicies + */ + readonly clientId: string +} + +/** + * Request parameters for setEntities operation in ManagedDataStoreApi. + * @export + * @interface ManagedDataStoreApiSetEntitiesRequest + */ +export interface ManagedDataStoreApiSetEntitiesRequest { + /** + * + * @type {string} + * @memberof ManagedDataStoreApiSetEntities + */ + readonly clientId: string + + /** + * + * @type {SetEntityStoreDto} + * @memberof ManagedDataStoreApiSetEntities + */ + readonly setEntityStoreDto: SetEntityStoreDto +} + +/** + * Request parameters for setPolicies operation in ManagedDataStoreApi. + * @export + * @interface ManagedDataStoreApiSetPoliciesRequest + */ +export interface ManagedDataStoreApiSetPoliciesRequest { + /** + * + * @type {string} + * @memberof ManagedDataStoreApiSetPolicies + */ + readonly clientId: string + + /** + * + * @type {SetPolicyStoreDto} + * @memberof ManagedDataStoreApiSetPolicies + */ + readonly setPolicyStoreDto: SetPolicyStoreDto +} + +/** + * Request parameters for sync operation in ManagedDataStoreApi. + * @export + * @interface ManagedDataStoreApiSyncRequest + */ +export interface ManagedDataStoreApiSyncRequest { + /** + * + * @type {string} + * @memberof ManagedDataStoreApiSync + */ + readonly xClientSecret: string +} + /** * ManagedDataStoreApi - object-oriented interface * @export @@ -5185,63 +5406,61 @@ export class ManagedDataStoreApi extends BaseAPI { /** * * @summary Gets the client entities - * @param {string} clientId + * @param {ManagedDataStoreApiGetEntitiesRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof ManagedDataStoreApi */ - public getEntities(clientId: string, options?: RawAxiosRequestConfig) { - return ManagedDataStoreApiFp(this.configuration).getEntities(clientId, options).then((request) => request(this.axios, this.basePath)); + public getEntities(requestParameters: ManagedDataStoreApiGetEntitiesRequest, options?: RawAxiosRequestConfig) { + return ManagedDataStoreApiFp(this.configuration).getEntities(requestParameters.clientId, options).then((request) => request(this.axios, this.basePath)); } /** * * @summary Gets the client policies - * @param {string} clientId + * @param {ManagedDataStoreApiGetPoliciesRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof ManagedDataStoreApi */ - public getPolicies(clientId: string, options?: RawAxiosRequestConfig) { - return ManagedDataStoreApiFp(this.configuration).getPolicies(clientId, options).then((request) => request(this.axios, this.basePath)); + public getPolicies(requestParameters: ManagedDataStoreApiGetPoliciesRequest, options?: RawAxiosRequestConfig) { + return ManagedDataStoreApiFp(this.configuration).getPolicies(requestParameters.clientId, options).then((request) => request(this.axios, this.basePath)); } /** * * @summary Sets the client entities - * @param {string} clientId - * @param {SetEntityStoreDto} setEntityStoreDto + * @param {ManagedDataStoreApiSetEntitiesRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof ManagedDataStoreApi */ - public setEntities(clientId: string, setEntityStoreDto: SetEntityStoreDto, options?: RawAxiosRequestConfig) { - return ManagedDataStoreApiFp(this.configuration).setEntities(clientId, setEntityStoreDto, options).then((request) => request(this.axios, this.basePath)); + public setEntities(requestParameters: ManagedDataStoreApiSetEntitiesRequest, options?: RawAxiosRequestConfig) { + return ManagedDataStoreApiFp(this.configuration).setEntities(requestParameters.clientId, requestParameters.setEntityStoreDto, options).then((request) => request(this.axios, this.basePath)); } /** * * @summary Sets the client policies - * @param {string} clientId - * @param {SetPolicyStoreDto} setPolicyStoreDto + * @param {ManagedDataStoreApiSetPoliciesRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof ManagedDataStoreApi */ - public setPolicies(clientId: string, setPolicyStoreDto: SetPolicyStoreDto, options?: RawAxiosRequestConfig) { - return ManagedDataStoreApiFp(this.configuration).setPolicies(clientId, setPolicyStoreDto, options).then((request) => request(this.axios, this.basePath)); + public setPolicies(requestParameters: ManagedDataStoreApiSetPoliciesRequest, options?: RawAxiosRequestConfig) { + return ManagedDataStoreApiFp(this.configuration).setPolicies(requestParameters.clientId, requestParameters.setPolicyStoreDto, options).then((request) => request(this.axios, this.basePath)); } /** * * @summary Sync the client data store with the engine cluster - * @param {string} xClientSecret + * @param {ManagedDataStoreApiSyncRequest} requestParameters Request parameters. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof ManagedDataStoreApi */ - public sync(xClientSecret: string, options?: RawAxiosRequestConfig) { - return ManagedDataStoreApiFp(this.configuration).sync(xClientSecret, options).then((request) => request(this.axios, this.basePath)); + public sync(requestParameters: ManagedDataStoreApiSyncRequest, options?: RawAxiosRequestConfig) { + return ManagedDataStoreApiFp(this.configuration).sync(requestParameters.xClientSecret, options).then((request) => request(this.axios, this.basePath)); } } diff --git a/packages/armory-sdk/src/lib/http/client/auth/base.ts b/packages/armory-sdk/src/lib/http/client/auth/base.ts index faf10c639..2699806d4 100644 --- a/packages/armory-sdk/src/lib/http/client/auth/base.ts +++ b/packages/armory-sdk/src/lib/http/client/auth/base.ts @@ -19,7 +19,7 @@ import type { Configuration } from './configuration'; import type { AxiosPromise, AxiosInstance, RawAxiosRequestConfig } from 'axios'; import globalAxios from 'axios'; -export const BASE_PATH = "http://localhost".replace(/\/+$/, ""); +export const BASE_PATH = "http://localhost:3005".replace(/\/+$/, ""); /** * diff --git a/packages/policy-engine-shared/src/index.ts b/packages/policy-engine-shared/src/index.ts index b64777d9b..29023286d 100644 --- a/packages/policy-engine-shared/src/index.ts +++ b/packages/policy-engine-shared/src/index.ts @@ -15,6 +15,7 @@ export * from './lib/type/policy.type' export * as EntityUtil from './lib/util/entity.util' export * from './lib/util/caip.util' +export * from './lib/util/confirmation-claim.util' export * from './lib/util/encoding.util' export * from './lib/util/enum.util' export * from './lib/util/evm.util' diff --git a/packages/policy-engine-shared/src/lib/type/authorization-server.type.ts b/packages/policy-engine-shared/src/lib/type/authorization-server.type.ts index 40f629d9a..5373b50b0 100644 --- a/packages/policy-engine-shared/src/lib/type/authorization-server.type.ts +++ b/packages/policy-engine-shared/src/lib/type/authorization-server.type.ts @@ -1,6 +1,6 @@ import { z } from 'zod' import { Action, SerializedTransactionRequest, TransactionRequest } from './action.type' -import { Approvals, JwtString, Request, SerializedRequest } from './domain.type' +import { Approvals, ConfirmationClaim, JwtString, Request, SerializedRequest } from './domain.type' export const AuthorizationRequestStatus = { CREATED: 'CREATED', @@ -78,7 +78,8 @@ export type AuthorizationRequestError = z.infer diff --git a/packages/policy-engine-shared/src/lib/type/domain.type.ts b/packages/policy-engine-shared/src/lib/type/domain.type.ts index 510658deb..75e358c28 100644 --- a/packages/policy-engine-shared/src/lib/type/domain.type.ts +++ b/packages/policy-engine-shared/src/lib/type/domain.type.ts @@ -1,3 +1,4 @@ +import { publicKeySchema } from '@narval/signature' import { ZodTypeAny, z } from 'zod' import { credentialEntitySchema } from '../schema/entity.schema' import { ChainAccountId } from '../util/caip.util' @@ -143,12 +144,40 @@ export type Feed = { data?: Data } +export const ConfirmationClaimProofMethod = { + JWS: 'jws' +} as const +export type ConfirmationClaimProofMethod = + (typeof ConfirmationClaimProofMethod)[keyof typeof ConfirmationClaimProofMethod] + +export const ConfirmationClaim = z + .object({ + key: z.object({ + jwk: publicKeySchema.describe( + 'JSON Web Key that will be used to bind the access token. This ensures only the holder of the corresponding private key can use the token.' + ), + proof: z + .literal(ConfirmationClaimProofMethod.JWS) + .optional() + .describe( + 'Specifies the proof method for demonstrating possession of the private key corresponding to the jwk' + ), + jws: z + .string() + .optional() + .describe('The actual JSON Web Signature value that proves the client possesses the private key.') + }) + }) + .describe('Option to bind the access token to a given public key.') +export type ConfirmationClaim = z.infer + export const EvaluationMetadata = z .object({ audience: z.union([z.string(), z.array(z.string())]).optional(), issuer: z.string().optional(), issuedAt: z.number().optional(), - expiresIn: z.number().optional() + expiresIn: z.number().optional(), + confirmation: ConfirmationClaim.optional() }) .describe('Metadata for the grant permission access token') export type EvaluationMetadata = z.infer @@ -167,7 +196,6 @@ export const EvaluationRequest = z.object({ ), metadata: EvaluationMetadata.optional() }) - export type EvaluationRequest = z.infer export const SerializedEvaluationRequest = EvaluationRequest.extend({ diff --git a/packages/policy-engine-shared/src/lib/util/__test__/unit/confirmation-claim.util.spec.ts b/packages/policy-engine-shared/src/lib/util/__test__/unit/confirmation-claim.util.spec.ts new file mode 100644 index 000000000..3f0f41124 --- /dev/null +++ b/packages/policy-engine-shared/src/lib/util/__test__/unit/confirmation-claim.util.spec.ts @@ -0,0 +1,129 @@ +import { Alg, PrivateKey, generateJwk, getPublicKey, hash, signJwt } from '@narval/signature' +import { Action } from '../../../type/action.type' +import { ConfirmationClaimProofMethod, Request } from '../../../type/domain.type' +import { verifyConfirmationClaimProofOfPossession } from '../../confirmation-claim.util' + +const bindPrivateKey: PrivateKey = { + kty: 'OKP', + crv: 'Ed25519', + alg: 'EDDSA', + kid: '0x65a3f312d1fc34e937ca9c1b7fbe5b9f98fb15e2cb15594ec6cd5167e36a58e3', + x: 'n0AX7pAzBhCr6R7dRhPqeGDVIKRaatVjdmL3KX58HGw', + d: 'tl8nZiFTRa5C_yJvL73KFnxDbuUi8h6bUvh28jvXmII' +} + +const request: Request = { + action: Action.SIGN_MESSAGE, + nonce: '123', + message: 'sign me', + resourceId: 'test-resource-id' +} + +describe('verifyConfirmationClaimProofOfPossession', () => { + it('verifies valid proof of possession', async () => { + const result = await verifyConfirmationClaimProofOfPossession({ + authentication: '', + request, + metadata: { + confirmation: { + key: { + jwk: getPublicKey(bindPrivateKey), + proof: ConfirmationClaimProofMethod.JWS, + jws: await signJwt( + { + requestHash: hash(request) + }, + bindPrivateKey + ) + } + } + } + }) + + expect(result).toBe(true) + }) + + it('returns true when no proof method is specified', async () => { + const result = await verifyConfirmationClaimProofOfPossession({ + authentication: '', + request, + metadata: { + confirmation: { + key: { + jwk: getPublicKey(bindPrivateKey) + } + } + } + }) + + expect(result).toBe(true) + }) + + it('throws error when proof method is specified but jws is missing', async () => { + await expect( + verifyConfirmationClaimProofOfPossession({ + authentication: '', + request, + metadata: { + confirmation: { + key: { + jwk: getPublicKey(bindPrivateKey), + proof: ConfirmationClaimProofMethod.JWS + } + } + } + }) + ).rejects.toThrow('Missing confirmation claim jws') + }) + + it('throws error when hash mismatch', async () => { + await expect( + verifyConfirmationClaimProofOfPossession({ + authentication: '', + // Source request. + request, + metadata: { + confirmation: { + key: { + jwk: getPublicKey(bindPrivateKey), + proof: ConfirmationClaimProofMethod.JWS, + jws: await signJwt( + { + // Tampered request. + requestHash: hash({ + ...request, + nonce: 'modified-nonce' + }) + }, + bindPrivateKey + ) + } + } + } + }) + ).rejects.toThrow('Confirmation claim jws hash mismatch') + }) + + it('throws error when JWT verification fails', async () => { + await expect( + verifyConfirmationClaimProofOfPossession({ + authentication: '', + request, + metadata: { + confirmation: { + key: { + jwk: getPublicKey(bindPrivateKey), + proof: ConfirmationClaimProofMethod.JWS, + jws: await signJwt( + { + requestHash: hash(request) + }, + await generateJwk(Alg.EDDSA) + ) + } + } + } + }) + ).rejects.toThrow('Invalid confirmation claim jws') + }) +}) diff --git a/packages/policy-engine-shared/src/lib/util/confirmation-claim.util.ts b/packages/policy-engine-shared/src/lib/util/confirmation-claim.util.ts new file mode 100644 index 000000000..0399fd998 --- /dev/null +++ b/packages/policy-engine-shared/src/lib/util/confirmation-claim.util.ts @@ -0,0 +1,31 @@ +import { JwtError, hash, verifyJwt } from '@narval/signature' +import { EvaluationRequest } from '../type/domain.type' + +export class ConfirmationClaimError extends Error {} + +export const verifyConfirmationClaimProofOfPossession = async (evaluation: EvaluationRequest): Promise => { + if (evaluation.metadata?.confirmation && evaluation.metadata.confirmation?.key.proof) { + const { confirmation } = evaluation.metadata + + if (!confirmation.key.jws) { + throw new ConfirmationClaimError('Missing confirmation claim jws') + } + + try { + const jwt = await verifyJwt(confirmation.key.jws, confirmation.key.jwk) + const message = hash(evaluation.request) + + if (jwt.payload.requestHash !== message) { + throw new ConfirmationClaimError('Confirmation claim jws hash mismatch') + } + } catch (error: unknown) { + if (error instanceof JwtError) { + throw new ConfirmationClaimError(`Invalid confirmation claim jws: ${error.message}`) + } + + throw error + } + } + + return true +} From 37cc70faa53b35e99256fa728a1de0b1c34de5df Mon Sep 17 00:00:00 2001 From: Matt Schoch Date: Mon, 3 Feb 2025 10:16:42 +0100 Subject: [PATCH 112/120] BitGo Integration * BitGo Hookup, raw accounts, sync, transfer --- .github/workflows/vault.yml | 7 +- Makefile | 4 +- apps/vault/src/broker/broker.module.ts | 6 + .../bitgo/bitgo-scoped-sync.service.ts | 194 + .../provider/bitgo/bitgo-transfer.service.ts | 331 + .../broker/core/provider/bitgo/bitgo.util.ts | 110 + .../fireblocks/fireblocks-transfer.service.ts | 6 +- .../src/broker/core/service/asset.service.ts | 8 + .../core/service/raw-account.service.ts | 72 +- .../core/service/scoped-sync.service.ts | 4 + .../broker/core/service/transfer.service.ts | 4 + .../core/type/indexed-resources.type.ts | 2 +- .../src/broker/http/client/bitgo.client.ts | 300 + .../src/broker/shared/__test__/mock-server.ts | 3 +- .../migration.sql | 8 + examples/unified-api/.gitignore | 1 - examples/unified-api/7-bitgo-stake.ts | 62 + examples/unified-api/8-bitgo-transfer.ts | 48 + examples/unified-api/9-bitgo-connect.ts | 31 + package-lock.json | 47273 +++++++++++----- package.json | 4 + 21 files changed, 34244 insertions(+), 14234 deletions(-) create mode 100644 apps/vault/src/broker/core/provider/bitgo/bitgo-scoped-sync.service.ts create mode 100644 apps/vault/src/broker/core/provider/bitgo/bitgo-transfer.service.ts create mode 100644 apps/vault/src/broker/core/provider/bitgo/bitgo.util.ts create mode 100644 apps/vault/src/broker/http/client/bitgo.client.ts create mode 100644 apps/vault/src/shared/module/persistence/schema/migrations/20250123154218_account_wallet_id_nullable/migration.sql create mode 100644 examples/unified-api/7-bitgo-stake.ts create mode 100644 examples/unified-api/8-bitgo-transfer.ts create mode 100644 examples/unified-api/9-bitgo-connect.ts diff --git a/.github/workflows/vault.yml b/.github/workflows/vault.yml index 05493b8ab..78d61bd51 100644 --- a/.github/workflows/vault.yml +++ b/.github/workflows/vault.yml @@ -23,7 +23,8 @@ on: jobs: test: name: Test - runs-on: ubuntu-latest + runs-on: + labels: default-larger services: postgres: @@ -105,7 +106,9 @@ jobs: release: name: Release - runs-on: ubuntu-latest + runs-on: + labels: default-larger + if: github.ref == 'refs/heads/main' # Only run if the Test job succeeds diff --git a/Makefile b/Makefile index c62ba0193..2e51c46e9 100644 --- a/Makefile +++ b/Makefile @@ -19,10 +19,10 @@ TERM_GREEN := \033[0;32m # === Install === install: - npm install --engine-strict + npm install install/ci: - npm ci --engine-strict + npm ci # === Setup === diff --git a/apps/vault/src/broker/broker.module.ts b/apps/vault/src/broker/broker.module.ts index 80629a778..fddf2be63 100644 --- a/apps/vault/src/broker/broker.module.ts +++ b/apps/vault/src/broker/broker.module.ts @@ -16,6 +16,8 @@ import { AnchorageProxyService } from './core/provider/anchorage/anchorage-proxy import { AnchorageScopedSyncService } from './core/provider/anchorage/anchorage-scoped-sync.service' import { AnchorageTransferService } from './core/provider/anchorage/anchorage-transfer.service' import { BitgoCredentialService } from './core/provider/bitgo/bitgo-credential.service' +import { BitgoScopedSyncService } from './core/provider/bitgo/bitgo-scoped-sync.service' +import { BitgoTransferService } from './core/provider/bitgo/bitgo-transfer.service' import { FireblocksCredentialService } from './core/provider/fireblocks/fireblocks-credential.service' import { FireblocksKnownDestinationService } from './core/provider/fireblocks/fireblocks-known-destination.service' import { FireblocksProxyService } from './core/provider/fireblocks/fireblocks-proxy.service' @@ -36,6 +38,7 @@ import { TransferService } from './core/service/transfer.service' import { WalletService } from './core/service/wallet.service' import { ConnectionScopedSyncEventHandler } from './event/handler/connection-scoped-sync.event-handler' import { AnchorageClient } from './http/client/anchorage.client' +import { BitgoClient } from './http/client/bitgo.client' import { FireblocksClient } from './http/client/fireblocks.client' import { ProviderAccountController } from './http/rest/controller/account.controller' import { ProviderAddressController } from './http/rest/controller/address.controller' @@ -102,10 +105,13 @@ import { NetworkSeed } from './persistence/seed/network.seed' AnchorageKnownDestinationService, AnchorageProxyService, AnchorageScopedSyncService, + BitgoScopedSyncService, AnchorageTransferService, AssetRepository, AssetService, BitgoCredentialService, + BitgoClient, + BitgoTransferService, ConnectionRepository, ConnectionService, ConnectionScopedSyncEventHandler, diff --git a/apps/vault/src/broker/core/provider/bitgo/bitgo-scoped-sync.service.ts b/apps/vault/src/broker/core/provider/bitgo/bitgo-scoped-sync.service.ts new file mode 100644 index 000000000..8e0c8fa8e --- /dev/null +++ b/apps/vault/src/broker/core/provider/bitgo/bitgo-scoped-sync.service.ts @@ -0,0 +1,194 @@ +import { LoggerService } from '@narval/nestjs-shared' +import { Injectable } from '@nestjs/common' +import { randomUUID } from 'crypto' +import { chunk, uniqBy } from 'lodash/fp' +import { BitGoWallet, BitgoClient } from '../../../http/client/bitgo.client' +import { ConnectionWithCredentials } from '../../type/connection.type' +import { Account, Address } from '../../type/indexed-resources.type' +import { NetworkMap } from '../../type/network.type' +import { Provider, ProviderScopedSyncService } from '../../type/provider.type' +import { + RawAccount, + RawAccountError, + RawAccountSyncFailure, + ScopedSyncContext, + ScopedSyncResult +} from '../../type/scoped-sync.type' +import { CONCURRENT_BITGO_REQUEST, validateConnection } from './bitgo.util' + +type RawAccountSyncSuccess = { + success: true + account: Account + address: Address +} + +type RawAccountSyncFailed = { + success: false + failure: RawAccountSyncFailure +} + +type RawAccountSyncResult = RawAccountSyncSuccess | RawAccountSyncFailed + +@Injectable() +export class BitgoScopedSyncService implements ProviderScopedSyncService { + constructor( + private readonly bitgoClient: BitgoClient, + private readonly logger: LoggerService + ) {} + + private resolveFailure(failure: RawAccountSyncFailure): RawAccountSyncFailed { + this.logger.log('Failed to sync Raw Account', failure) + return { success: false, failure } + } + + private resolveSuccess({ + rawAccount, + account, + address + }: { + address: Address + rawAccount: RawAccount + account: Account + }): RawAccountSyncSuccess { + this.logger.log('Successfully fetched and map Raw Account', { + rawAccount, + account + }) + return { + success: true, + account, + address + } + } + + syncRawAccount({ + rawAccount, + networks, + bitgoWallet, + connection, + now, + existingAccounts + }: { + rawAccount: RawAccount + networks: NetworkMap + bitgoWallet: BitGoWallet + connection: ConnectionWithCredentials + now: Date + existingAccounts: Account[] + }): RawAccountSyncResult { + const network = networks.get(bitgoWallet.coin.toUpperCase()) + + if (!network) { + return this.resolveFailure({ + rawAccount, + message: 'Network not found', + code: RawAccountError.UNLISTED_NETWORK, + networkId: bitgoWallet.coin + }) + } + + const addressObj = bitgoWallet.receiveAddress + const existingAcc = existingAccounts.find((a) => a.externalId === bitgoWallet.id) + const accountId = existingAcc?.accountId || randomUUID() + + const account: Account = { + externalId: bitgoWallet.id, + accountId, + addresses: [], + clientId: connection.clientId, + connectionId: connection.connectionId, + createdAt: now, + label: bitgoWallet.label, + networkId: network.networkId, + provider: Provider.BITGO, + updatedAt: now, + walletId: null // BitGo doesn't have a concept that maps to our "wallet" + } + + const address: Address = { + accountId, + address: addressObj.address, + addressId: randomUUID(), + clientId: connection.clientId, + connectionId: connection.connectionId, + createdAt: now, + externalId: addressObj.id, + provider: Provider.BITGO, + updatedAt: now + } + + return this.resolveSuccess({ + rawAccount, + account, + address + }) + } + + async scopeSync({ + connection, + rawAccounts, + networks, + existingAccounts + }: ScopedSyncContext): Promise { + const now = new Date() + + this.logger.log('Sync BitGo accounts', { + connectionId: connection.connectionId, + clientId: connection.clientId, + url: connection.url + }) + + validateConnection(connection) + + const bitgoWallets = await this.bitgoClient.getWallets({ + url: connection.url, + apiKey: connection.credentials.apiKey, + options: { + walletIds: rawAccounts.map((account) => account.externalId) + } + }) + + const accounts: Account[] = [] + const addresses: Address[] = [] + const failures: RawAccountSyncFailure[] = [] + + const chunkedRawAccounts = chunk(CONCURRENT_BITGO_REQUEST, rawAccounts) + const results = [] + + for (const chunk of chunkedRawAccounts) { + const chunkResults = await Promise.all( + chunk.map((rawAccount) => { + const bitgoWallet = bitgoWallets.find((b) => b.id === rawAccount.externalId) + + if (!bitgoWallet) { + return this.resolveFailure({ + rawAccount, + message: 'BitGo wallet not found', + code: RawAccountError.EXTERNAL_RESOURCE_NOT_FOUND, + externalResourceId: rawAccount.externalId, + externalResourceType: 'wallet' + }) + } + return this.syncRawAccount({ connection, rawAccount, networks, bitgoWallet, now, existingAccounts }) + }) + ) + results.push(...chunkResults) + } + + for (const result of results) { + if (result.success) { + accounts.push(result.account) + addresses.push(result.address) + } else { + failures.push(result.failure) + } + } + + return { + wallets: [], + accounts: uniqBy('externalId', accounts), + addresses: uniqBy('externalId', addresses), + failures + } + } +} diff --git a/apps/vault/src/broker/core/provider/bitgo/bitgo-transfer.service.ts b/apps/vault/src/broker/core/provider/bitgo/bitgo-transfer.service.ts new file mode 100644 index 000000000..4abdfa6ab --- /dev/null +++ b/apps/vault/src/broker/core/provider/bitgo/bitgo-transfer.service.ts @@ -0,0 +1,331 @@ +import { LoggerService } from '@narval/nestjs-shared' +import { HttpStatus, Injectable } from '@nestjs/common' +import { randomUUID } from 'crypto' +import { BitGoTransferType, BitgoClient } from '../../../http/client/bitgo.client' +import { TransferRepository } from '../../../persistence/repository/transfer.repository' +import { BrokerException } from '../../exception/broker.exception' +import { AccountService } from '../../service/account.service' +import { AddressService } from '../../service/address.service' +import { AssetService } from '../../service/asset.service' +import { NetworkService } from '../../service/network.service' +import { ResolvedTransferAsset } from '../../service/transfer-asset.service' +import { ConnectionWithCredentials } from '../../type/connection.type' +import { ExternalNetwork } from '../../type/network.type' +import { Provider, ProviderTransferService } from '../../type/provider.type' +import { ConnectionScope } from '../../type/scope.type' +import { + Destination, + InternalTransfer, + NetworkFeeAttribution, + SendTransfer, + Source, + Transfer, + TransferAsset, + TransferPartyType, + isAddressDestination +} from '../../type/transfer.type' +import { ValidConnection, decideState, mapBitgoStateToInternalStatus, validateConnection } from './bitgo.util' + +type BitGoResolvedTransferAsset = Omit & { + assetId: string + decimals: number + contractAddress?: string +} + +@Injectable() +export class BitgoTransferService implements ProviderTransferService { + constructor( + private readonly bitgoClient: BitgoClient, + private readonly accountService: AccountService, + private readonly addressService: AddressService, + private readonly networkService: NetworkService, + private readonly transferRepository: TransferRepository, + private readonly assetService: AssetService, + private readonly logger: LoggerService + ) {} + + async findById(connection: ConnectionWithCredentials, id: string): Promise { + validateConnection(connection) + const transfer = await this.transferRepository.findById(connection.clientId, id) + + if (!transfer) { + throw new BrokerException({ + message: 'Transfer not found', + suggestedHttpStatusCode: HttpStatus.NOT_FOUND, + context: { connectionId: connection.connectionId, id } + }) + } + + const { source } = transfer + + let account + if (source.type === TransferPartyType.ACCOUNT) { + account = await this.accountService.findById(connection, source.id) + } else if (source.type === TransferPartyType.WALLET) { + throw new BrokerException({ + message: 'Wallet does not exist in Bitgo. This is an invalid state', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, + context: { connectionId: connection.connectionId, source } + }) + } else if (source.type === TransferPartyType.ADDRESS) { + const address = await this.addressService.findById(connection, source.id) + account = await this.accountService.findById(connection, address.accountId) + } + + if (!account) { + throw new BrokerException({ + message: 'Account not found', + suggestedHttpStatusCode: HttpStatus.NOT_FOUND, + context: { connectionId: connection.connectionId, source } + }) + } + + if (!transfer.assetExternalId) { + throw new BrokerException({ + message: 'Asset not found', + suggestedHttpStatusCode: HttpStatus.NOT_FOUND, + context: { connectionId: connection.connectionId, transfer } + }) + } + + transfer.externalId + + const events = await this.bitgoClient.getTransaction({ + url: connection.url, + apiKey: connection.credentials.apiKey, + data: { + txRequestIds: [transfer.externalId], + walletId: account.externalId + } + }) + + this.logger.error('Fees are not supported for Bitgo transfers', { transfer }) + + const states = events.map((ext) => mapBitgoStateToInternalStatus(ext.state)) + + return { + ...transfer, + status: decideState(states), + fees: [] + } + } + + private async getSource(scope: ConnectionScope, source: Source) { + if (source.type === TransferPartyType.ACCOUNT) { + const account = await this.accountService.findById(scope, source.id) + return account.externalId + } + + throw new BrokerException({ + message: 'Cannot resolve Bitgo transfer source', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, + context: { scope, source } + }) + } + + private async getDestination(connection: ValidConnection, destination: Destination) { + if (isAddressDestination(destination)) { + return destination.address + } + + if (destination.type === TransferPartyType.ACCOUNT) { + const account = await this.accountService.findById(connection, destination.id) + + if (!account) { + throw new BrokerException({ + message: 'Account not found', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, + context: { scope: connection, destination } + }) + } + + const { addresses } = account + + if (!addresses || !addresses.length) { + throw new BrokerException({ + message: 'Account does not have any addresses', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, + context: { scope: connection, destination } + }) + } + + if (addresses.length !== 1) { + const bitgoWallet = await this.bitgoClient.getWallets({ + url: connection.url, + apiKey: connection.credentials.apiKey, + options: { + walletIds: [account.externalId] + } + }) + + if (!bitgoWallet || bitgoWallet.length !== 1) { + throw new BrokerException({ + message: 'Could not resolve an address for this account', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, + context: { account } + }) + } + + return bitgoWallet[0].receiveAddress.address + } + + return addresses[0].address + } + + throw new BrokerException({ + message: 'Cannot resolve Bitgo transfer destination', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, + context: { scope: connection, destination } + }) + } + + private async findAsset(transferAsset: TransferAsset): Promise { + if (transferAsset.assetId) { + const asset = await this.assetService.findById(transferAsset.assetId) + if (asset?.decimals) { + const network = await this.networkService.findById(asset.networkId) + const bitGoAssetId = asset.externalAssets.find( + (externalAsset) => externalAsset.provider === Provider.BITGO + )?.externalId + if (bitGoAssetId && network) { + return { + assetExternalId: bitGoAssetId, + decimals: asset.decimals, + network, + assetId: asset.assetId, + contractAddress: asset.onchainId || undefined + } + } + } + } + + if (transferAsset.address && transferAsset.networkId) { + const asset = await this.assetService.findByOnchainId(transferAsset.networkId, transferAsset.address) + if (asset?.decimals) { + const network = await this.networkService.findById(asset.networkId) + const bitGoAssetId = asset.externalAssets.find( + (externalAsset) => externalAsset.provider === Provider.BITGO + )?.externalId + if (bitGoAssetId && network) { + return { + assetExternalId: bitGoAssetId, + decimals: asset.decimals, + network, + assetId: asset.assetId, + contractAddress: asset.onchainId || undefined + } + } + } + } + + if (transferAsset.externalAssetId) { + const asset = await this.assetService.findByExternalId(Provider.BITGO, transferAsset.externalAssetId) + if (asset?.decimals) { + const network = await this.networkService.findById(asset.networkId) + + if (network) { + return { + assetExternalId: transferAsset.externalAssetId, + decimals: asset.decimals, + network, + assetId: asset.assetId, + contractAddress: asset.onchainId || undefined + } + } + } + } + + throw new BrokerException({ + message: 'Cannot find transfer asset', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, + context: { transferAsset } + }) + } + + private async findTransferNetwork(transferAsset: TransferAsset): Promise { + const { network } = await this.findAsset(transferAsset) + + const bitgoNetwork = network.externalNetworks.find((externalNetwork) => externalNetwork.provider === Provider.BITGO) + if (!bitgoNetwork) { + throw new BrokerException({ + message: 'Cannot find Bitgo network', + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, + context: { transferAsset } + }) + } + + return bitgoNetwork + } + + async send(connection: ConnectionWithCredentials, sendTransfer: SendTransfer): Promise { + validateConnection(connection) + const now = new Date() + const { + amount, + source, + destination, + asset: transferAsset, + memo, + transferId, + idempotenceId, + customerRefId + } = sendTransfer + + const walletId = await this.getSource(connection, source) + const address = await this.getDestination(connection, destination) + + const asset = await this.findAsset(transferAsset) + + const native = await this.assetService.findNative(asset.network.networkId) + + const { externalId: coin } = await this.findTransferNetwork(transferAsset) + + const networkFeeAttribution = sendTransfer.networkFeeAttribution || NetworkFeeAttribution.ON_TOP + + const transferType = asset.assetId === native?.assetId ? BitGoTransferType.NATIVE : BitGoTransferType.TOKEN + + const amountInBaseUnits = this.assetService.toBaseUnit(amount, +asset.decimals) + + const res = await this.bitgoClient.createTransfer({ + url: connection.url, + apiKey: connection.credentials.apiKey, + walletPassphrase: connection.credentials.walletPassphrase, + data: { + walletId, + coin, + amount: amountInBaseUnits, + address, + asset: asset.assetExternalId, + tokenContractAddress: asset.contractAddress || undefined, + type: transferType, + networkFeeAttribution, + idempotenceId, + decimals: asset.decimals + } + }) + + const internalTransfer: InternalTransfer = { + clientId: connection.clientId, + connectionId: connection.connectionId, + provider: Provider.BITGO, + createdAt: now, + assetExternalId: asset.assetExternalId, + assetId: asset.assetId, + customerRefId: customerRefId || null, + destination, + source, + status: mapBitgoStateToInternalStatus(res.state), + grossAmount: amount, + idempotenceId, + memo: memo || null, + transferId: transferId || randomUUID(), + externalId: res.txRequestId, + externalStatus: res.state, + networkFeeAttribution + } + + await this.transferRepository.bulkCreate([internalTransfer]) + + return internalTransfer + } +} diff --git a/apps/vault/src/broker/core/provider/bitgo/bitgo.util.ts b/apps/vault/src/broker/core/provider/bitgo/bitgo.util.ts new file mode 100644 index 000000000..0c650eff0 --- /dev/null +++ b/apps/vault/src/broker/core/provider/bitgo/bitgo.util.ts @@ -0,0 +1,110 @@ +import { HttpStatus } from '@nestjs/common' +import { BrokerException } from '../../exception/broker.exception' +import { ConnectionInvalidException } from '../../exception/connection-invalid.exception' +import { ConnectionWithCredentials } from '../../type/connection.type' +import { Provider } from '../../type/provider.type' +import { TransferStatus } from '../../type/transfer.type' +import { BitgoInputCredentials } from './bitgo.type' + +export const CONCURRENT_BITGO_REQUEST = 5 + +export type ValidConnection = { + url: string + credentials: { + apiKey: string + walletPassphrase?: string + } + clientId: string + connectionId: string +} + +export function validateConnection( + connection: ConnectionWithCredentials +): asserts connection is ConnectionWithCredentials & ValidConnection { + const context = { + clientId: connection.clientId, + connectionId: connection.connectionId, + provider: connection.provider, + status: connection.status, + url: connection.url + } + + if (connection.provider !== Provider.BITGO) { + throw new ConnectionInvalidException({ + message: 'Invalid connection provider for BitGo', + context + }) + } + + if (!connection.url) { + throw new ConnectionInvalidException({ + message: 'BitGo connection missing URL', + context + }) + } + + if (!connection.credentials) { + throw new ConnectionInvalidException({ + message: 'BitGo connection missing credentials', + context + }) + } + + const credentials = BitgoInputCredentials.parse(connection.credentials) + + if (!credentials.apiKey) { + throw new ConnectionInvalidException({ + message: 'BitGo connection missing API key', + context + }) + } +} + +export function mapBitgoStateToInternalStatus(state: string): TransferStatus { + switch (state) { + case 'pendingCommitment': + return TransferStatus.PROCESSING + case 'signed': + return TransferStatus.PROCESSING + case 'pendingApproval': + return TransferStatus.PROCESSING + case 'initialized': + return TransferStatus.PROCESSING + case 'pendingDelivery': + return TransferStatus.PROCESSING + case 'pendingUserSignature': + return TransferStatus.PROCESSING + case 'canceled': + return TransferStatus.FAILED + case 'rejected': + return TransferStatus.FAILED + case 'delivered': + return TransferStatus.SUCCESS + default: + throw new BrokerException({ + message: `Unknown BitGo state: ${state}`, + context: { state }, + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY + }) + } +} + +export function decideState(states: TransferStatus[]): TransferStatus { + if (states.includes(TransferStatus.FAILED)) { + return TransferStatus.FAILED + } + + if (states.some((state) => state === TransferStatus.SUCCESS)) { + return TransferStatus.SUCCESS + } + + if (states.includes(TransferStatus.PROCESSING)) { + return TransferStatus.PROCESSING + } + + throw new BrokerException({ + message: 'Unknown or empty state list', + context: { states }, + suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY + }) +} diff --git a/apps/vault/src/broker/core/provider/fireblocks/fireblocks-transfer.service.ts b/apps/vault/src/broker/core/provider/fireblocks/fireblocks-transfer.service.ts index ae141445b..737a4de2d 100644 --- a/apps/vault/src/broker/core/provider/fireblocks/fireblocks-transfer.service.ts +++ b/apps/vault/src/broker/core/provider/fireblocks/fireblocks-transfer.service.ts @@ -244,7 +244,7 @@ export class FireblocksTransferService implements ProviderTransferService { if (sendTransfer.source.type === TransferPartyType.ACCOUNT) { const account = await this.accountService.findById(scope, sendTransfer.source.id) - if (account) { + if (account && account.walletId) { const wallet = await this.walletService.findById(scope, account.walletId) if (wallet) { @@ -280,7 +280,7 @@ export class FireblocksTransferService implements ProviderTransferService { if (address) { const account = await this.accountService.findById(scope, address.accountId) - if (account) { + if (account && account.walletId) { const wallet = await this.walletService.findById(scope, account.walletId) if (wallet) { @@ -303,7 +303,7 @@ export class FireblocksTransferService implements ProviderTransferService { if (destination.type === TransferPartyType.ACCOUNT) { const account = await this.accountService.findById(scope, destination.id) - if (account) { + if (account && account.walletId) { const wallet = await this.walletService.findById(scope, account.walletId) if (wallet) { diff --git a/apps/vault/src/broker/core/service/asset.service.ts b/apps/vault/src/broker/core/service/asset.service.ts index 8ce9ecf49..53d4b492b 100644 --- a/apps/vault/src/broker/core/service/asset.service.ts +++ b/apps/vault/src/broker/core/service/asset.service.ts @@ -22,6 +22,14 @@ export class AssetService { @Inject(CACHE_MANAGER) private cacheManager: Cache ) {} + toBaseUnit(amount: string, decimals: number): string { + const amountStr = amount.toString() + const [integerPart, decimalPart = ''] = amountStr.split('.') + const paddedDecimal = decimalPart.padEnd(decimals, '0').slice(0, decimals) + const cleanInteger = integerPart.replace(/^0+/, '') || '0' + return cleanInteger + paddedDecimal + } + async bulkCreate(assets: Asset[]): Promise { const createdAssets: Asset[] = [] diff --git a/apps/vault/src/broker/core/service/raw-account.service.ts b/apps/vault/src/broker/core/service/raw-account.service.ts index 9bdec023c..818e34cf2 100644 --- a/apps/vault/src/broker/core/service/raw-account.service.ts +++ b/apps/vault/src/broker/core/service/raw-account.service.ts @@ -1,12 +1,15 @@ import { LoggerService, PaginatedResult, PaginationOptions } from '@narval/nestjs-shared' import { HttpStatus, Injectable } from '@nestjs/common' +import { formatUnits } from 'viem' import { z } from 'zod' import { AnchorageClient } from '../../http/client/anchorage.client' +import { BitgoClient } from '../../http/client/bitgo.client' import { FireblocksClient } from '../../http/client/fireblocks.client' import { AccountRepository } from '../../persistence/repository/account.repository' import { AssetRepository } from '../../persistence/repository/asset.repository' import { BrokerException } from '../exception/broker.exception' import { validateConnection as validateAnchorageConnection } from '../provider/anchorage/anchorage.util' +import { validateConnection as validateBitgoConnection } from '../provider/bitgo/bitgo.util' import { buildFireblocksAssetWalletExternalId, validateConnection as validateFireblocksConnection @@ -56,6 +59,7 @@ export class RawAccountService { private readonly assetRepository: AssetRepository, private readonly anchorageClient: AnchorageClient, private readonly fireblocksClient: FireblocksClient, + private readonly bitgoClient: BitgoClient, private readonly loggerService: LoggerService ) {} @@ -260,8 +264,74 @@ export class RawAccountService { return { data: rawAccountsWithAddresses.map((account) => RawAccount.parse(account)) // TODO: don't re-do the parse. It's an asset typedef because the .filter isn't inferred that it's no longer nullable. } - } + } else if (connection.provider === Provider.BITGO) { + validateBitgoConnection(connection) + + let bitgoNetworkFilter: string | undefined + if (networkFilter) { + const baseAsset = await this.assetRepository.findNative(networkFilter.networkId) + bitgoNetworkFilter = baseAsset?.externalAssets.find((a) => a.provider === Provider.BITGO)?.externalId + if (!bitgoNetworkFilter) { + throw new BrokerException({ + message: 'BitGo does not support this network', + suggestedHttpStatusCode: HttpStatus.BAD_REQUEST, + context: { + networkId: networkFilter.networkId + } + }) + } + } + // BitGo "coin" filter can be a network or asset + const bitgoCoinFilter = + assetFilter?.externalAssets.find((a) => a.provider === Provider.BITGO)?.externalId || bitgoNetworkFilter + + const wallets = await this.bitgoClient.getWallets({ + url: connection.url, + apiKey: connection.credentials.apiKey, + walletPassphrase: connection.credentials.walletPassphrase, + options: { + labelContains: options?.filters?.namePrefix || options?.filters?.nameSuffix, + limit: options?.pagination?.take, + after: options?.pagination?.cursor?.id, // TODO: Our cursor has too strict of typing, it can't pass-through + coin: bitgoCoinFilter + } + }) + + const accounts = await Promise.all( + wallets.map(async (w) => ({ + provider: Provider.BITGO, + externalId: w.id, + label: w.label, + subLabel: w.coin, + defaultAddress: w.receiveAddress?.address, + network: await this.networkService.findByExternalId(Provider.BITGO, w.coin), + assets: await Promise.all( + Object.entries({ + [w.coin]: { + balanceString: w.balanceString || '0', + confirmedBalanceString: w.confirmedBalanceString || '0', + spendableBalanceString: w.spendableBalanceString || '0', + transferCount: 0 // unknown + }, + ...(w.tokens || {}) + }).map(async ([coin, balance]) => { + if (balance.balanceString === '0' && balance.transferCount === 0) return undefined // bitgo returns some other "tokens" that are defaults, so filter them out + const asset = await this.assetRepository.findByExternalId(Provider.BITGO, coin) + if (!asset) return undefined + return { + asset, + balance: asset?.decimals ? formatUnits(BigInt(balance.balanceString), asset.decimals) : undefined + } + }) + ).then((a) => [...a.filter((a) => !!a)]) + })) + ) + + return { + data: accounts.map((a) => RawAccount.parse(a)) + } + } throw new BrokerException({ message: 'Unsupported provider', suggestedHttpStatusCode: HttpStatus.NOT_IMPLEMENTED, diff --git a/apps/vault/src/broker/core/service/scoped-sync.service.ts b/apps/vault/src/broker/core/service/scoped-sync.service.ts index 6969b2ca8..026895274 100644 --- a/apps/vault/src/broker/core/service/scoped-sync.service.ts +++ b/apps/vault/src/broker/core/service/scoped-sync.service.ts @@ -10,6 +10,7 @@ import { OTEL_ATTR_CONNECTION_ID, OTEL_ATTR_CONNECTION_PROVIDER, OTEL_ATTR_SYNC_ import { ScopedSyncStartedEvent } from '../../shared/event/scoped-sync-started.event' import { ScopedSyncException } from '../exception/scoped-sync.exception' import { AnchorageScopedSyncService } from '../provider/anchorage/anchorage-scoped-sync.service' +import { BitgoScopedSyncService } from '../provider/bitgo/bitgo-scoped-sync.service' import { FireblocksScopedSyncService } from '../provider/fireblocks/fireblocks-scoped-sync.service' import { ConnectionWithCredentials } from '../type/connection.type' import { Provider, ProviderScopedSyncService } from '../type/provider.type' @@ -34,6 +35,7 @@ export class ScopedSyncService { private readonly scopedSyncRepository: ScopedSyncRepository, private readonly anchorageScopedSyncService: AnchorageScopedSyncService, private readonly fireblocksScopedSyncService: FireblocksScopedSyncService, + private readonly bitgoScopedSyncService: BitgoScopedSyncService, private readonly walletService: WalletService, private readonly accountService: AccountService, private readonly addressService: AddressService, @@ -318,6 +320,8 @@ export class ScopedSyncService { return this.anchorageScopedSyncService case Provider.FIREBLOCKS: return this.fireblocksScopedSyncService + case Provider.BITGO: + return this.bitgoScopedSyncService default: throw new NotImplementedException(`Unsupported Scoped Sync for provider ${provider}`) } diff --git a/apps/vault/src/broker/core/service/transfer.service.ts b/apps/vault/src/broker/core/service/transfer.service.ts index 180b23c67..0dac1c98a 100644 --- a/apps/vault/src/broker/core/service/transfer.service.ts +++ b/apps/vault/src/broker/core/service/transfer.service.ts @@ -5,6 +5,7 @@ import { TransferRepository } from '../../persistence/repository/transfer.reposi import { OTEL_ATTR_CONNECTION_PROVIDER } from '../../shared/constant' import { BrokerException } from '../exception/broker.exception' import { AnchorageTransferService } from '../provider/anchorage/anchorage-transfer.service' +import { BitgoTransferService } from '../provider/bitgo/bitgo-transfer.service' import { FireblocksTransferService } from '../provider/fireblocks/fireblocks-transfer.service' import { isActiveConnection } from '../type/connection.type' import { Provider, ProviderTransferService } from '../type/provider.type' @@ -19,6 +20,7 @@ export class TransferService { private readonly connectionService: ConnectionService, private readonly anchorageTransferService: AnchorageTransferService, private readonly fireblocksTransferService: FireblocksTransferService, + private readonly bitgoTransferService: BitgoTransferService, private readonly logger: LoggerService, @Inject(TraceService) private readonly traceService: TraceService ) {} @@ -82,6 +84,8 @@ export class TransferService { return this.anchorageTransferService case Provider.FIREBLOCKS: return this.fireblocksTransferService + case Provider.BITGO: + return this.bitgoTransferService default: throw new NotImplementedException(`Unsupported transfer for provider ${provider}`) } diff --git a/apps/vault/src/broker/core/type/indexed-resources.type.ts b/apps/vault/src/broker/core/type/indexed-resources.type.ts index 48632292c..0ed378b03 100644 --- a/apps/vault/src/broker/core/type/indexed-resources.type.ts +++ b/apps/vault/src/broker/core/type/indexed-resources.type.ts @@ -25,7 +25,7 @@ export const Account = z.object({ networkId: z.string(), provider: z.nativeEnum(Provider), updatedAt: z.date(), - walletId: z.string() + walletId: z.string().nullable() }) export type Account = z.infer diff --git a/apps/vault/src/broker/http/client/bitgo.client.ts b/apps/vault/src/broker/http/client/bitgo.client.ts new file mode 100644 index 000000000..7c6396f1f --- /dev/null +++ b/apps/vault/src/broker/http/client/bitgo.client.ts @@ -0,0 +1,300 @@ +import { LoggerService } from '@narval/nestjs-shared' +import { HttpStatus, Injectable } from '@nestjs/common' +import { AxiosError } from 'axios' +import { BitGo, TokenType, TxRequest } from 'bitgo' +import { randomUUID } from 'crypto' +import { Observable, OperatorFunction, catchError, from, lastValueFrom, map, switchMap, tap } from 'rxjs' +import { z } from 'zod' +import { ProviderHttpException } from '../../core/exception/provider-http.exception' +import { Provider } from '../../core/type/provider.type' +import { NetworkFeeAttribution } from '../../core/type/transfer.type' + +// +// Response Schema +// + +const BitGoCoinSpecific = z.object({ + deployedInBlock: z.boolean(), + lastChainIndex: z.unknown(), + baseAddress: z.string(), + feeAddress: z.string(), + pendingChainInitialization: z.boolean(), + pendingEcdsaTssInitialization: z.boolean(), + creationFailure: z.array(z.unknown()), + gasPriceTier: z.string(), + tokenFlushThresholds: z.record(z.unknown()), + lowPriorityFeeAddress: z.string(), + salt: z.string(), + walletVersion: z.number(), + pendingDeployment: z.boolean(), + deployForwardersManually: z.boolean(), + flushForwardersManually: z.boolean(), + enableMMI: z.boolean(), + enableNFT: z.boolean() +}) + +const BitGoReceiveAddress = z.object({ + id: z.string(), + address: z.string(), + chain: z.number(), + index: z.number(), + coin: z.string(), + lastNonce: z.number().optional(), + wallet: z.string(), + lastConsolidatedTime: z.string().optional(), + needsConsolidation: z.boolean().optional(), + coinSpecific: z.unknown() +}) + +export const BitGoWallet = z.object({ + id: z.string(), + coin: z.string(), + label: z.string(), + enterprise: z.string(), + organization: z.string(), + bitgoOrg: z.string(), + freeze: z.record(z.unknown()), + deleted: z.boolean(), + approvalsRequired: z.number(), + isCold: z.boolean(), + coinSpecific: BitGoCoinSpecific, + startDate: z.string(), + type: z.string(), + hasLargeNumberOfAddresses: z.boolean(), + receiveAddress: BitGoReceiveAddress, + balanceString: z.string().optional(), + confirmedBalanceString: z.string().optional(), + spendableBalanceString: z.string().optional(), + tokens: z + .record( + z.object({ + balanceString: z.string(), + confirmedBalanceString: z.string(), + spendableBalanceString: z.string(), + lockedBalanceString: z.string(), + transferCount: z.number() + }) + ) + .optional() +}) +export type BitGoWallet = z.infer + +const GetWalletsResponse = z.object({ + wallets: z.array(BitGoWallet) +}) +type GetWalletsResponse = z.infer + +export const MinimalTransactionObject = z.object({ + state: z.string(), + txRequestId: z.string() +}) +export type MinimalTransactionObject = z.infer + +export const GetTransactions = z.object({ + txRequests: z.array(MinimalTransactionObject) +}) +export type GetTransactions = z.infer + +// +// Request Options Types +// +interface RequestOptions { + url: string + apiKey: string + walletPassphrase?: string +} + +interface GetWalletsOptions extends RequestOptions { + options: { + labelContains?: string + limit?: number + after?: string + coin?: string + walletIds?: string[] + } +} + +interface CreateTransferOptions extends RequestOptions { + data: { + walletId: string + coin: string + amount: string + address: string + asset?: string + tokenContractAddress?: string + type: BitGoTransferType + networkFeeAttribution: NetworkFeeAttribution + idempotenceId: string + decimals: number + } +} + +interface GetTransactionOptions extends RequestOptions { + data: { + txRequestIds: string[] + walletId: string + } +} + +export const BitGoTransferType = { + NATIVE: 'transfer', + TOKEN: 'transfertoken' +} as const +export type BitGoTransferType = (typeof BitGoTransferType)[keyof typeof BitGoTransferType] + +@Injectable() +export class BitgoClient { + constructor(private readonly logger: LoggerService) {} + + private getBitGoInstance(url: string, apiKey: string): BitGo { + return new BitGo({ + env: url.includes('test') ? 'test' : 'prod', + accessToken: apiKey + }) + } + + private handleError(logMessage: string): OperatorFunction { + return catchError((error: unknown): Observable => { + this.logger.error(logMessage, { error }) + + if (error instanceof AxiosError) { + throw new ProviderHttpException({ + provider: Provider.BITGO, + origin: error, + response: { + status: HttpStatus.INTERNAL_SERVER_ERROR, + body: error.message + } + }) + } + + throw error + }) + } + async createTransfer(opts: CreateTransferOptions): Promise { + const bitgo = this.getBitGoInstance(opts.url, opts.apiKey) + + this.logger.log('Creating BitGo transfer', { + walletId: opts.data.walletId, + coin: opts.data.coin, + type: opts.data.type, + asset: opts.data.asset + }) + + const txRequestId = randomUUID() + return lastValueFrom( + from(bitgo.coin(opts.data.coin.toLowerCase()).wallets().get({ id: opts.data.walletId })).pipe( + switchMap((wallet) => { + const txData = + opts.data.type === BitGoTransferType.NATIVE + ? { + txRequestId, + recipients: [ + { + amount: opts.data.amount, + address: opts.data.address + } + ], + walletPassphrase: opts.walletPassphrase, + type: opts.data.type + } + : { + txRequestId, + recipients: [ + { + tokenData: { + tokenType: TokenType.ERC20, + tokenQuantity: opts.data.amount, + tokenContractAddress: opts.data.tokenContractAddress, + tokenName: opts.data.asset?.toLowerCase(), + decimalPlaces: opts.data.decimals + }, + amount: '0', + address: opts.data.address + } + ], + walletPassphrase: opts.walletPassphrase, + type: opts.data.type + } + + return from(wallet.prebuildAndSignTransaction(txData) as Promise) + }), + tap((tx: TxRequest) => { + this.logger.log('Successfully created BitGo transfer', { + walletId: opts.data.walletId, + txRequestId: tx.txRequestId + }) + }), + this.handleError('Failed to create BitGo transfer') + ) + ) + } + + async getWallets(opts: GetWalletsOptions): Promise { + const bitgo = this.getBitGoInstance(opts.url, opts.apiKey) + + this.logger.log('Requesting BitGo wallets', { + url: opts.url, + options: opts.options + }) + + const queryParams = new URLSearchParams() + if (opts.options.walletIds) { + opts.options.walletIds.forEach((id) => { + queryParams.append('id[]', id) + }) + } + if (opts.options.labelContains) queryParams.append('labelContains', opts.options.labelContains) + if (opts.options.limit) queryParams.append('limit', opts.options.limit.toString()) + if (opts.options.after) queryParams.append('prevId', opts.options.after) + if (opts.options.coin) queryParams.append('coin', opts.options.coin.toLowerCase()) + queryParams.append('expandBalance', 'true') + + const url = `${opts.url.replace(/\/+$/, '')}/api/v2/wallets${queryParams.toString() ? '?' + queryParams.toString() : ''}` + + return lastValueFrom( + from(bitgo.get(url)).pipe( + map((response) => GetWalletsResponse.parse(response.body)), + map((response) => response.wallets), + tap((wallets) => { + this.logger.log('Successfully fetched BitGo wallets', { + url, + walletsCount: wallets.length + }) + }), + this.handleError('Failed to get BitGo wallets') + ) + ) + } + + async getTransaction(opts: GetTransactionOptions): Promise { + const bitgo = this.getBitGoInstance(opts.url, opts.apiKey) + + this.logger.log('Requesting BitGo transaction', { + txRequestIds: opts.data.txRequestIds, + walletId: opts.data.walletId + }) + + const queryParams = new URLSearchParams() + + if (opts.data.txRequestIds) { + opts.data.txRequestIds.forEach((id) => { + queryParams.append('txRequestIds[]', id) + }) + } + + const url = `${opts.url.replace(/\/+$/, '')}/api/v2/wallet/${opts.data.walletId}/txrequests${queryParams.toString() ? '?' + queryParams.toString() : ''}` + return lastValueFrom( + from(bitgo.get(url)).pipe( + map((response) => GetTransactions.parse(response.body).txRequests), + tap((tx) => { + this.logger.log('Successfully fetched BitGo transaction', { + url, + txCount: tx.length + }) + }), + this.handleError('Failed to get BitGo transaction') + ) + ) + } +} diff --git a/apps/vault/src/broker/shared/__test__/mock-server.ts b/apps/vault/src/broker/shared/__test__/mock-server.ts index 82f1b1a80..e2b0c61f1 100644 --- a/apps/vault/src/broker/shared/__test__/mock-server.ts +++ b/apps/vault/src/broker/shared/__test__/mock-server.ts @@ -16,7 +16,8 @@ export const useRequestSpy = (server: SetupServerApi): [jest.Mock, SetupServerAp spy({ method: clone.method, url: clone.url, - headers: Object.fromEntries(request.headers), + // eslint-disable-next-line @typescript-eslint/no-explicit-any + headers: Object.fromEntries(request.headers as any), // For some reason, adding the BitGo SDK causes this to break typedefs.. body }) }) diff --git a/apps/vault/src/shared/module/persistence/schema/migrations/20250123154218_account_wallet_id_nullable/migration.sql b/apps/vault/src/shared/module/persistence/schema/migrations/20250123154218_account_wallet_id_nullable/migration.sql new file mode 100644 index 000000000..6513132d6 --- /dev/null +++ b/apps/vault/src/shared/module/persistence/schema/migrations/20250123154218_account_wallet_id_nullable/migration.sql @@ -0,0 +1,8 @@ +-- DropForeignKey +ALTER TABLE "provider_account" DROP CONSTRAINT "provider_account_wallet_id_fkey"; + +-- AlterTable +ALTER TABLE "provider_account" ALTER COLUMN "wallet_id" DROP NOT NULL; + +-- AddForeignKey +ALTER TABLE "provider_account" ADD CONSTRAINT "provider_account_wallet_id_fkey" FOREIGN KEY ("wallet_id") REFERENCES "provider_wallet"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/examples/unified-api/.gitignore b/examples/unified-api/.gitignore index 49ba8cf09..a8bfb1fed 100644 --- a/examples/unified-api/.gitignore +++ b/examples/unified-api/.gitignore @@ -1,4 +1,3 @@ .env node_modules config.yaml -config.*.yaml diff --git a/examples/unified-api/7-bitgo-stake.ts b/examples/unified-api/7-bitgo-stake.ts new file mode 100644 index 000000000..c555b62e3 --- /dev/null +++ b/examples/unified-api/7-bitgo-stake.ts @@ -0,0 +1,62 @@ +import { BitGo } from 'bitgo' +import dotenv from 'dotenv' + +dotenv.config() + +const main = async () => { + const WALLET_ID = '6784d7a77e4213f088e81b36ed7dd699' + const bitgo = new BitGo({ + env: 'prod', + accessToken: process.env.BITGO_ACCESS_TOKEN + }) + + const sui = await bitgo.coin('sui') + // const wallets = await (await sui.wallets().list()).wallets + const wallet = await sui.wallets().get({ id: WALLET_ID }) + console.log(wallet._wallet) + const stakingWallet = await wallet.toStakingWallet() + // const stakeRes = await stakingWallet.stake({ + // amount: '1000000000', // 1 SUI = 10^9 MIST, similar to 1 ETH = 10^18 WEI + // validator: '0x92c7bf9914897e8878e559c19a6cffd22e6a569a6dd4d26f8e82e0f2ad1873d6' // Kiln validator, from BitGo UI + // }) + // console.log('StakingRequest - Response', stakeRes) + let transactions + do { + // transactions = await stakingWallet.getStakingRequest(stakeRes.id) + transactions = await stakingWallet.getStakingRequest('9fd7864f-738d-40a4-a584-49f6ad4d327c') + if (!transactions.transactions.some((tx) => tx.txRequestId)) { + console.log('Waiting for transactions to be ready to sign; txRequestId not found', transactions) + await new Promise((resolve) => setTimeout(resolve, 1000)) // Wait 1 second before polling again + } + } while (!transactions.transactions.some((tx) => tx.txRequestId)) + + console.log('Transactions Ready to Sign', transactions) + // if (!transactions.allSigningComplete && transactions.transactions.length > 0) { + // for (const transaction of transactions.transactions) { + // console.log('Signing and Sending Transaction', transaction) + // // const res = await stakingWallet.buildSignAndSend( + // // { walletPassphrase: process.env.BITGO_WALLET_PASSPHRASE || '' }, + // // transaction + // // ) + // // console.log('Build and Send Response', res) + // } + // } +} + +main() + .then(() => console.log('done')) + .catch(console.error) + +const x = { + intent: { + intentType: 'payment', + recipients: [ + { + address: { address: '0x14e7e397d684856f28ad09d04cc550eab2b16e23' }, + amount: { value: '10000000000000000', symbol: 'hteth' } + } + ] + }, + apiVersion: 'full', + preview: false +} diff --git a/examples/unified-api/8-bitgo-transfer.ts b/examples/unified-api/8-bitgo-transfer.ts new file mode 100644 index 000000000..47d18f42c --- /dev/null +++ b/examples/unified-api/8-bitgo-transfer.ts @@ -0,0 +1,48 @@ +import { BitGo } from 'bitgo' +import dotenv from 'dotenv' + +dotenv.config() + +const stakingWalletId = '678a30728bda4b5d7a23a1896e031cda' +const stakingWalletAddress = '0xa9d15711933cfcd8332131eeed76ec9054e40518' +const defaultWalletId = '678a2a006bb272c9d62870f1994291ab' +const defaultWalletAddress = '0xdee7439a1f337d645df0b6804aaabc6ea4a17972' + +const main = async () => { + const bitgo = new BitGo({ + env: (process.env.BITGO_ENV as any) || 'test', + accessToken: process.env.BITGO_ACCESS_TOKEN + }) + const coin = 'hteth' + + const myCoin = await bitgo.coin(coin) + + // const wallets = await (await sui.wallets().list()).wallets + const wallet = await myCoin.wallets().get({ id: stakingWalletId }) + console.log(wallet._wallet) + + const transfer = await wallet.prebuildAndSignTransaction({ + recipients: [ + { + tokenData: { + tokenType: 'ERC20' as any, + tokenQuantity: '4100000000000000', + tokenContractAddress: '0x94373a4919b3240d86ea41593d5eba789fef3848', + tokenName: 'tweth', // This is the TokenId from https://developers.bitgo.com/coins/test-ethereum-terc20-tokens + decimalPlaces: undefined + }, + + amount: '0', // 0.0141 ETH in wei (1 ETH = 10^18 wei) + address: defaultWalletAddress + } + ], + walletPassphrase: process.env.BITGO_WALLET_PASSPHRASE, + type: 'transfertoken' + }) + console.log('transfer', transfer) + // console.log('txRequestId to Poll', transfer?.txRequest?.txRequestId) +} + +main() + .then(() => console.log('done')) + .catch(console.error) diff --git a/examples/unified-api/9-bitgo-connect.ts b/examples/unified-api/9-bitgo-connect.ts new file mode 100644 index 000000000..f3c897a7c --- /dev/null +++ b/examples/unified-api/9-bitgo-connect.ts @@ -0,0 +1,31 @@ +import { rsaPublicKeySchema } from '@narval-xyz/armory-sdk' +import { rsaEncrypt } from '@narval-xyz/armory-sdk/signature' +import dotenv from 'dotenv' +import { setConfig, vaultClient } from './vault.client' +dotenv.config() + +const main = async () => { + const url = 'https://app.bitgo-test.com' + const credentials = { + apiKey: process.env.BITGO_ACCESS_TOKEN, + walletPassphrase: process.env.BITGO_WALLET_PASSPHRASE + } + + const jwk = await vaultClient.generateEncryptionKey() + const encryptionKey = rsaPublicKeySchema.parse(jwk) + + const encryptedCredentials = await rsaEncrypt(JSON.stringify(credentials), encryptionKey) + + const connection = await vaultClient.createConnection({ + data: { url, encryptedCredentials, provider: 'bitgo' as any } + }) + + // Save the connectionId to the config file + setConfig('connectionId', connection.data.connectionId) + + console.dir(connection.data) +} + +main() + .then(() => console.log('done')) + .catch(console.error) diff --git a/package-lock.json b/package-lock.json index da253687a..a48b3a755 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,9 @@ ], "dependencies": { "@aws-crypto/client-node": "4.0.1", + "@bitgo/public-types": "4.11.2", + "@bitgo/sdk-api": "1.58.2", + "@bitgo/sdk-core": "28.20.0", "@bull-board/api": "5.20.1", "@bull-board/express": "5.20.1", "@bull-board/nestjs": "5.20.1", @@ -57,6 +60,7 @@ "@tanstack/react-query": "5.51.11", "axios": "1.7.7", "axios-retry": "4.5.0", + "bitgo": "39.23.0", "bull": "4.16.4", "cache-manager": "6.3.2", "class-transformer": "0.5.1", @@ -443,6 +447,213 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@aptos-labs/aptos-cli": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@aptos-labs/aptos-cli/-/aptos-cli-1.0.2.tgz", + "integrity": "sha512-PYPsd0Kk3ynkxNfe3S4fanI3DiUICCoh4ibQderbvjPFL5A0oK6F4lPEO2t0MDsQySTk2t4vh99Xjy6Bd9y+aQ==", + "license": "Apache-2.0", + "dependencies": { + "commander": "^12.1.0" + }, + "bin": { + "aptos": "dist/aptos.js" + } + }, + "node_modules/@aptos-labs/aptos-cli/node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@aptos-labs/aptos-client": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@aptos-labs/aptos-client/-/aptos-client-0.1.1.tgz", + "integrity": "sha512-kJsoy4fAPTOhzVr7Vwq8s/AUg6BQiJDa7WOqRzev4zsuIS3+JCuIZ6vUd7UBsjnxtmguJJulMRs9qWCzVBt2XA==", + "license": "Apache-2.0", + "dependencies": { + "axios": "1.7.4", + "got": "^11.8.6" + }, + "engines": { + "node": ">=15.10.0" + } + }, + "node_modules/@aptos-labs/aptos-client/node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "license": "MIT", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@aptos-labs/aptos-client/node_modules/axios": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", + "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/@aptos-labs/aptos-client/node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "license": "MIT", + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/@aptos-labs/aptos-client/node_modules/cacheable-request": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", + "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "license": "MIT", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@aptos-labs/aptos-client/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@aptos-labs/aptos-client/node_modules/got": { + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/@aptos-labs/aptos-client/node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "license": "MIT", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/@aptos-labs/aptos-client/node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@aptos-labs/aptos-client/node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@aptos-labs/aptos-client/node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@aptos-labs/aptos-client/node_modules/responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "license": "MIT", + "dependencies": { + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@aptos-labs/ts-sdk": { + "version": "1.33.1", + "resolved": "https://registry.npmjs.org/@aptos-labs/ts-sdk/-/ts-sdk-1.33.1.tgz", + "integrity": "sha512-d6nWtUI//fyEN8DeLjm3+ro87Ad6+IKwR9pCqfrs/Azahso1xR1Llxd/O6fj/m1DDsuDj/HAsCsy5TC/aKD6Eg==", + "license": "Apache-2.0", + "dependencies": { + "@aptos-labs/aptos-cli": "^1.0.2", + "@aptos-labs/aptos-client": "^0.1.1", + "@noble/curves": "^1.4.0", + "@noble/hashes": "^1.4.0", + "@scure/bip32": "^1.4.0", + "@scure/bip39": "^1.3.0", + "eventemitter3": "^5.0.1", + "form-data": "^4.0.0", + "js-base64": "^3.7.7", + "jwt-decode": "^4.0.0", + "poseidon-lite": "^0.2.0" + }, + "engines": { + "node": ">=11.0.0" + } + }, + "node_modules/@aptos-labs/ts-sdk/node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" + }, "node_modules/@automock/adapters.nestjs": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@automock/adapters.nestjs/-/adapters.nestjs-2.1.0.tgz", @@ -1639,6 +1850,83 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/highlight": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.9.tgz", + "integrity": "sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "license": "MIT", + "peer": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "license": "MIT", + "peer": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/parser": { "version": "7.26.7", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.7.tgz", @@ -1714,11 +2002,28 @@ "@babel/core": "^7.0.0" } }, + "node_modules/@babel/plugin-proposal-class-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", + "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-proposal-decorators": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.24.7.tgz", "integrity": "sha512-RL9GR0pUG5Kc8BUWLNDm2T5OpYwSX15r98I0IkgmRQTXuELq/OynH8xtMTMvTJFjXbMWFVTKtYkTaYQsuAwQlQ==", - "dev": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7", @@ -1747,6 +2052,82 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", + "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead.", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-object-rest-spread": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz", + "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-object-rest-spread instead.", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/compat-data": "^7.20.5", + "@babel/helper-compilation-targets": "^7.20.7", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.20.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-catch-binding": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", + "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-catch-binding instead.", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-chaining": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", + "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead.", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-proposal-private-property-in-object": { "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", @@ -1809,7 +2190,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.24.7.tgz", "integrity": "sha512-Ui4uLJJrRV1lb38zg1yYTmRKmiZLiftDEvZN2iq3kd9kUFU+PttmzTbAFC2ucRk/XJmtek6G23gPsuZbhrT8fQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -2516,6 +2896,22 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-object-assign": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.25.9.tgz", + "integrity": "sha512-I/Vl1aQnPsrrn837oLbo+VQtkNcjuuiATqwmuweg4fTauwHHQoxyjmjjOVKyO8OaTxgqYTKW3LuQsykXjDf5Ag==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-transform-object-rest-spread": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", @@ -3377,2445 +3773,3305 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, - "node_modules/@bull-board/api": { - "version": "5.20.1", - "resolved": "https://registry.npmjs.org/@bull-board/api/-/api-5.20.1.tgz", - "integrity": "sha512-45aDhnOzWRrtUUAKHxdClSnLIus5f8BK3ATzb2IwI/BRgOi1lWTe1YG266hVqDdWXsUDxKzf75DAANKfAoEsRA==", + "node_modules/@bitgo-forks/avalanchejs": { + "version": "4.1.0-alpha.1", + "resolved": "https://registry.npmjs.org/@bitgo-forks/avalanchejs/-/avalanchejs-4.1.0-alpha.1.tgz", + "integrity": "sha512-iVyxSLaNEBL1GNNYOAnvvNCuYOTz07b/8Y20WLWVtGSTjeZS/MSfoo31uUlDYTQX01CsI16WvbFDyRBKlKh1Jg==", "dependencies": { - "redis-info": "^3.0.8" + "@noble/curves": "1.3.0", + "@noble/hashes": "1.3.3", + "@noble/secp256k1": "2.0.0", + "@scure/base": "1.1.5", + "micro-eth-signer": "0.7.2" }, - "peerDependencies": { - "@bull-board/ui": "5.20.1" + "engines": { + "node": ">=18" } }, - "node_modules/@bull-board/express": { - "version": "5.20.1", - "resolved": "https://registry.npmjs.org/@bull-board/express/-/express-5.20.1.tgz", - "integrity": "sha512-980wGA8kjMyw7MrYNN25l7lJNlLz22ln3jW/H3ef98BXhTeBnPR16XhXu1Z6471X5Aor9WXZ6FRQ5pJhP4iXuA==", + "node_modules/@bitgo-forks/avalanchejs/node_modules/@noble/curves": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz", + "integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==", + "license": "MIT", "dependencies": { - "@bull-board/api": "5.20.1", - "@bull-board/ui": "5.20.1", - "ejs": "^3.1.10", - "express": "^4.19.2" + "@noble/hashes": "1.3.3" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@bull-board/nestjs": { - "version": "5.20.1", - "resolved": "https://registry.npmjs.org/@bull-board/nestjs/-/nestjs-5.20.1.tgz", - "integrity": "sha512-6WREzrJdrAuJ3LcZVETzfEpQxUSF2xxC7plPiSj11jyO30i/moKkc7gUVuP2h6YgQnhhH3ppFxECVduXWRBDLQ==", - "dependencies": { - "@nestjs/bull-shared": "^10.0.0" + "node_modules/@bitgo-forks/avalanchejs/node_modules/@noble/hashes": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", + "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", + "license": "MIT", + "engines": { + "node": ">= 16" }, - "peerDependencies": { - "@bull-board/api": "^5.20.1", - "@bull-board/express": "^5.20.1", - "@nestjs/common": "^9.0.0 || ^10.0.0", - "@nestjs/core": "^9.0.0 || ^10.0.0", - "reflect-metadata": "^0.1.13 || ^0.2.0", - "rxjs": "^7.8.1" + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@bull-board/ui": { - "version": "5.20.1", - "resolved": "https://registry.npmjs.org/@bull-board/ui/-/ui-5.20.1.tgz", - "integrity": "sha512-RzNinC4FKHNuxzkIRsCL+n9iO5RxmF5YM7byCuuv1/UeFjtCtsLHFi6TI9ZgJsXETA2Uxq9Mg7ppncojUjrINw==", - "dependencies": { - "@bull-board/api": "5.20.1" + "node_modules/@bitgo-forks/avalanchejs/node_modules/@noble/secp256k1": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-2.0.0.tgz", + "integrity": "sha512-rUGBd95e2a45rlmFTqQJYEFA4/gdIARFfuTuTqLglz0PZ6AKyzyXsEZZq7UZn8hZsvaBgpCzKKBJizT2cJERXw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT" + }, + "node_modules/@bitgo-forks/avalanchejs/node_modules/@scure/base": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.5.tgz", + "integrity": "sha512-Brj9FiG2W1MRQSTB212YVPRrcbjkv48FoZi/u4l/zds/ieRrqsh7aUf6CLwkAq61oKXr/ZlTzlY66gLIj3TFTQ==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@bundled-es-modules/cookie": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@bundled-es-modules/cookie/-/cookie-2.0.1.tgz", - "integrity": "sha512-8o+5fRPLNbjbdGRRmJj3h6Hh1AQJf2dk3qQ/5ZFb+PXkRNiSoMGGUKlsgLfrxneb72axVJyIYji64E2+nNfYyw==", - "dev": true, - "license": "ISC", + "node_modules/@bitgo/abstract-cosmos": { + "version": "11.2.16", + "resolved": "https://registry.npmjs.org/@bitgo/abstract-cosmos/-/abstract-cosmos-11.2.16.tgz", + "integrity": "sha512-G5Gnh46U3bHP3zcMe9NUNvQ5ggiIebrbvoJ+XEgMSglWz1F8XX4pKvfaFIoH8iR014EOAuivfdLKUY+pZFn4LA==", + "license": "MIT", "dependencies": { - "cookie": "^0.7.2" + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/statics": "^50.20.0", + "@bitgo/utxo-lib": "^11.2.1", + "@cosmjs/amino": "^0.29.5", + "@cosmjs/crypto": "^0.30.1", + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/proto-signing": "^0.29.5", + "@cosmjs/stargate": "^0.29.5", + "bignumber.js": "^9.1.1", + "cosmjs-types": "^0.6.1", + "lodash": "^4.17.21", + "protobufjs": "^7.4.0", + "superagent": "^9.0.1" + }, + "engines": { + "node": ">=18 <21" } }, - "node_modules/@bundled-es-modules/cookie/node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "dev": true, + "node_modules/@bitgo/abstract-eth": { + "version": "22.4.10", + "resolved": "https://registry.npmjs.org/@bitgo/abstract-eth/-/abstract-eth-22.4.10.tgz", + "integrity": "sha512-phcnbNIqrPbFm9/dThkXrNczTqZ/BaUsstMS9w6mJX96lidpi9wYn0tGB21rZhNXnieqUIMaRF7Ifo5sYhHPdg==", "license": "MIT", + "dependencies": { + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/statics": "^50.20.0", + "@bitgo/utxo-lib": "^11.2.1", + "@ethereumjs/common": "^2.6.5", + "@ethereumjs/tx": "^3.3.0", + "@metamask/eth-sig-util": "^5.0.2", + "bignumber.js": "^9.1.1", + "bn.js": "^5.2.1", + "debug": "^3.1.0", + "ethereumjs-abi": "^0.6.5", + "ethereumjs-util": "7.1.5", + "ethers": "^5.1.3", + "keccak": "^3.0.3", + "lodash": "4.17.21", + "secp256k1": "5.0.1", + "superagent": "^9.0.1" + }, "engines": { - "node": ">= 0.6" + "node": ">=18 <21" } }, - "node_modules/@bundled-es-modules/statuses": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@bundled-es-modules/statuses/-/statuses-1.0.1.tgz", - "integrity": "sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==", - "dev": true, - "license": "ISC", + "node_modules/@bitgo/abstract-eth/node_modules/@ethereumjs/common": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", + "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", + "license": "MIT", "dependencies": { - "statuses": "^2.0.1" + "crc-32": "^1.2.0", + "ethereumjs-util": "^7.1.5" } }, - "node_modules/@bundled-es-modules/tough-cookie": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@bundled-es-modules/tough-cookie/-/tough-cookie-0.1.6.tgz", - "integrity": "sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw==", - "dev": true, - "license": "ISC", + "node_modules/@bitgo/abstract-eth/node_modules/@ethereumjs/tx": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.5.2.tgz", + "integrity": "sha512-gQDNJWKrSDGu2w7w0PzVXVBNMzb7wwdDOmOqczmhNjqFxFuIbhVJDwiGEnxFNC2/b8ifcZzY7MLcluizohRzNw==", + "license": "MPL-2.0", "dependencies": { - "@types/tough-cookie": "^4.0.5", - "tough-cookie": "^4.1.4" + "@ethereumjs/common": "^2.6.4", + "ethereumjs-util": "^7.1.5" } }, - "node_modules/@coinbase/wallet-sdk": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/@coinbase/wallet-sdk/-/wallet-sdk-4.2.3.tgz", - "integrity": "sha512-BcyHZ/Ec84z0emORzqdXDv4P0oV+tV3a0OirfA8Ko1JGBIAVvB+hzLvZzCDvnuZx7MTK+Dd8Y9Tjlo446BpCIg==", + "node_modules/@bitgo/abstract-eth/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "license": "MIT", "dependencies": { - "@noble/hashes": "^1.4.0", - "clsx": "^1.2.1", - "eventemitter3": "^5.0.1", - "preact": "^10.24.2" + "ms": "^2.1.1" } }, - "node_modules/@coinbase/wallet-sdk/node_modules/clsx": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", - "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "node_modules/@bitgo/abstract-lightning": { + "version": "1.2.38", + "resolved": "https://registry.npmjs.org/@bitgo/abstract-lightning/-/abstract-lightning-1.2.38.tgz", + "integrity": "sha512-pW0LNvAHOZaeV/JtZ9aCevkwLFg6HTo7eU4LKpo4MRDcsjkJ4/7xX0cIuJK1y3G1HuequQGmimDagIwA59vW0g==", + "license": "MIT", + "dependencies": { + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/utxo-lib": "^11.2.1" + }, "engines": { - "node": ">=6" + "node": ">=18 <21" } }, - "node_modules/@coinbase/wallet-sdk/node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" - }, - "node_modules/@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "optional": true, + "node_modules/@bitgo/abstract-substrate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@bitgo/abstract-substrate/-/abstract-substrate-1.0.2.tgz", + "integrity": "sha512-lHlITYQQelNNI5qfc1PO/nVLNKGEnw4oHlofEoDK7k0KTyIjLteAmpWseQHEuJLe5+xliQ7H1QODZDZorRvIJg==", + "license": "MIT", + "dependencies": { + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/statics": "^50.20.0" + }, "engines": { - "node": ">=0.1.90" + "node": ">=18 <21" } }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, + "node_modules/@bitgo/abstract-utxo": { + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/@bitgo/abstract-utxo/-/abstract-utxo-9.12.0.tgz", + "integrity": "sha512-iB8FVbsv/7NNYizZQTZ3Wt+IFBWE82Ei9qhJy5kS2ujT1hffKSCNuVBquqXRsh2yqmz3KTygkxmY+ZNLph1/+Q==", + "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" + "@bitgo/blockapis": "^1.10.9", + "@bitgo/sdk-api": "^1.58.2", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/unspents": "^0.47.17", + "@bitgo/utxo-lib": "^11.2.1", + "@bitgo/wasm-miniscript": "^2.0.0-beta.2", + "@types/bluebird": "^3.5.25", + "@types/lodash": "^4.14.121", + "@types/superagent": "4.1.15", + "bignumber.js": "^9.0.2", + "bip174": "npm:@bitgo-forks/bip174@3.1.0-master.4", + "bitcoinjs-message": "npm:@bitgo-forks/bitcoinjs-message@1.0.0-master.3", + "bluebird": "^3.5.3", + "debug": "^3.1.0", + "io-ts": "npm:@bitgo-forks/io-ts@2.1.4", + "lodash": "^4.17.14", + "superagent": "^9.0.1" }, "engines": { - "node": ">=12" + "node": ">=18 <21" } }, - "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, + "node_modules/@bitgo/abstract-utxo/node_modules/@types/superagent": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.15.tgz", + "integrity": "sha512-mu/N4uvfDN2zVQQ5AYJI/g4qxn2bHB6521t1UuH09ShNWjebTqN0ZFuYK9uYjcgmI0dTQEs+Owi1EO6U0OkOZQ==", + "license": "MIT", "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@types/cookiejar": "*", + "@types/node": "*" } }, - "node_modules/@dabh/diagnostics": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", - "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", + "node_modules/@bitgo/abstract-utxo/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "license": "MIT", "dependencies": { - "colorspace": "1.1.x", - "enabled": "2.0.x", - "kuler": "^2.0.0" + "ms": "^2.1.1" } }, - "node_modules/@discoveryjs/json-ext": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", - "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "node_modules/@bitgo/account-lib": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@bitgo/account-lib/-/account-lib-24.2.0.tgz", + "integrity": "sha512-t0GzSCmRdQC/qt6xYV05OL5Q3qp6eZR166yvUHiko3GIiv2JVesl+DD4Yf56RbC1wBiD7TmDH8qiOw2vzyI1vg==", + "license": "ISC", + "dependencies": { + "@bitgo/sdk-coin-algo": "^2.1.58", + "@bitgo/sdk-coin-apt": "^1.4.1", + "@bitgo/sdk-coin-arbeth": "^21.0.52", + "@bitgo/sdk-coin-atom": "^13.1.16", + "@bitgo/sdk-coin-avaxc": "^5.2.10", + "@bitgo/sdk-coin-avaxp": "^5.0.59", + "@bitgo/sdk-coin-bera": "^2.3.4", + "@bitgo/sdk-coin-bld": "^3.0.29", + "@bitgo/sdk-coin-bsc": "^22.2.13", + "@bitgo/sdk-coin-celo": "^4.0.11", + "@bitgo/sdk-coin-coredao": "^1.2.12", + "@bitgo/sdk-coin-coreum": "^21.0.29", + "@bitgo/sdk-coin-cspr": "^2.0.60", + "@bitgo/sdk-coin-dot": "^4.1.38", + "@bitgo/sdk-coin-etc": "^2.2.27", + "@bitgo/sdk-coin-eth": "^24.2.49", + "@bitgo/sdk-coin-eth2": "^3.0.59", + "@bitgo/sdk-coin-hash": "^3.0.29", + "@bitgo/sdk-coin-hbar": "^2.0.60", + "@bitgo/sdk-coin-icp": "^1.1.0", + "@bitgo/sdk-coin-injective": "^3.0.29", + "@bitgo/sdk-coin-islm": "^2.1.10", + "@bitgo/sdk-coin-near": "^2.0.60", + "@bitgo/sdk-coin-oas": "^1.1.13", + "@bitgo/sdk-coin-opeth": "^18.1.45", + "@bitgo/sdk-coin-osmo": "^3.0.29", + "@bitgo/sdk-coin-polygon": "^21.0.29", + "@bitgo/sdk-coin-rbtc": "^2.0.60", + "@bitgo/sdk-coin-rune": "^1.1.17", + "@bitgo/sdk-coin-sei": "^3.0.29", + "@bitgo/sdk-coin-sol": "^4.7.17", + "@bitgo/sdk-coin-stx": "^3.3.17", + "@bitgo/sdk-coin-sui": "^5.8.19", + "@bitgo/sdk-coin-tia": "^3.0.29", + "@bitgo/sdk-coin-ton": "^3.4.17", + "@bitgo/sdk-coin-trx": "^2.0.60", + "@bitgo/sdk-coin-xrp": "^3.7.2", + "@bitgo/sdk-coin-xtz": "^2.1.58", + "@bitgo/sdk-coin-zeta": "^3.0.29", + "@bitgo/sdk-coin-zketh": "^2.0.52", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/sdk-lib-mpc": "^10.1.0", + "@bitgo/statics": "^50.20.0", + "bignumber.js": "^9.1.1", + "bs58": "^4.0.1" + }, + "engines": { + "node": ">=18 <21" + } + }, + "node_modules/@bitgo/account-lib/node_modules/@bitgo/sdk-coin-sui": { + "version": "5.8.19", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-sui/-/sdk-coin-sui-5.8.19.tgz", + "integrity": "sha512-axpv9x6bOU63F97E3W5lJ97NaEjUxJhv5xVePnw1V4DWCvKGhTS/VxabflRiONY6F1ia8wgAYEGftgWkbXy2Pg==", + "license": "MIT", + "dependencies": { + "@bitgo/blake2b": "^3.2.4", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/sdk-lib-mpc": "^10.1.0", + "@bitgo/statics": "^50.20.0", + "@mysten/bcs": "^0.7.0", + "bignumber.js": "^9.0.0", + "bs58": "^4.0.1", + "lodash": "^4.17.21", + "superagent": "3.8.2", + "superstruct": "^1.0.3", + "tweetnacl": "^1.0.3" + }, "engines": { - "node": ">=10.0.0" + "node": ">=18 <21" } }, - "node_modules/@docsearch/css": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.6.1.tgz", - "integrity": "sha512-VtVb5DS+0hRIprU2CO6ZQjK2Zg4QU5HrDM1+ix6rT0umsYvFvatMAnf97NHZlVWDaaLlx7GRfR/7FikANiM2Fg==" + "node_modules/@bitgo/account-lib/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } }, - "node_modules/@docsearch/react": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.6.1.tgz", - "integrity": "sha512-qXZkEPvybVhSXj0K7U3bXc233tk5e8PfhoZ6MhPOiik/qUQxYC+Dn9DnoS7CxHQQhHfCvTiN0eY9M12oRghEXw==", + "node_modules/@bitgo/account-lib/node_modules/form-data": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.2.tgz", + "integrity": "sha512-GgwY0PS7DbXqajuGf4OYlsrIu3zgxD6Vvql43IBhm6MahqA5SK/7mwhtNj2AdH2z35YR34ujJ7BN+3fFC3jP5Q==", + "license": "MIT", "dependencies": { - "@algolia/autocomplete-core": "1.9.3", - "@algolia/autocomplete-preset-algolia": "1.9.3", - "@docsearch/css": "3.6.1", - "algoliasearch": "^4.19.1" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12", + "safe-buffer": "^5.2.1" }, - "peerDependencies": { - "@types/react": ">= 16.8.0 < 19.0.0", - "react": ">= 16.8.0 < 19.0.0", - "react-dom": ">= 16.8.0 < 19.0.0", - "search-insights": ">= 1 < 3" + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/@bitgo/account-lib/node_modules/formidable": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", + "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==", + "deprecated": "Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau", + "license": "MIT", + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, + "node_modules/@bitgo/account-lib/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/@bitgo/account-lib/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/@bitgo/account-lib/node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/@bitgo/account-lib/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/@bitgo/account-lib/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/@bitgo/account-lib/node_modules/superagent": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.2.tgz", + "integrity": "sha512-gVH4QfYHcY3P0f/BZzavLreHW3T1v7hG9B+hpMQotGQqurOvhv87GcMCd6LWySmBuf+BDR44TQd0aISjVHLeNQ==", + "deprecated": "Please upgrade to v9.0.0+ as we have fixed a public vulnerability with formidable dependency. Note that v9.0.0+ requires Node.js v14.18.0+. See https://github.com/ladjs/superagent/pull/1800 for insight. This project is supported and maintained by the team at Forward Email @ https://forwardemail.net", + "license": "MIT", + "dependencies": { + "component-emitter": "^1.2.0", + "cookiejar": "^2.1.0", + "debug": "^3.1.0", + "extend": "^3.0.0", + "form-data": "^2.3.1", + "formidable": "^1.1.1", + "methods": "^1.1.1", + "mime": "^1.4.1", + "qs": "^6.5.1", + "readable-stream": "^2.0.5" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "react": { - "optional": true - }, - "react-dom": { - "optional": true - }, - "search-insights": { - "optional": true - } + "engines": { + "node": ">= 4.0" } }, - "node_modules/@docusaurus/core": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.4.0.tgz", - "integrity": "sha512-g+0wwmN2UJsBqy2fQRQ6fhXruoEa62JDeEa5d8IdTJlMoaDaEDfHh7WjwGRn4opuTQWpjAwP/fbcgyHKlE+64w==", + "node_modules/@bitgo/blake2b": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@bitgo/blake2b/-/blake2b-3.2.4.tgz", + "integrity": "sha512-46PEgEVPxecNJ/xczggIllSxIkFIvvbVM0OfIDdNJ5qpFHUeBCkNIiGdzC3fYZlsv7bVTdUZOj79GcFBLMYBqA==", + "license": "ISC", "dependencies": { - "@babel/core": "^7.23.3", - "@babel/generator": "^7.23.3", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-runtime": "^7.22.9", - "@babel/preset-env": "^7.22.9", - "@babel/preset-react": "^7.22.5", - "@babel/preset-typescript": "^7.22.5", - "@babel/runtime": "^7.22.6", - "@babel/runtime-corejs3": "^7.22.6", - "@babel/traverse": "^7.22.8", - "@docusaurus/cssnano-preset": "3.4.0", - "@docusaurus/logger": "3.4.0", - "@docusaurus/mdx-loader": "3.4.0", - "@docusaurus/utils": "3.4.0", - "@docusaurus/utils-common": "3.4.0", - "@docusaurus/utils-validation": "3.4.0", - "autoprefixer": "^10.4.14", - "babel-loader": "^9.1.3", - "babel-plugin-dynamic-import-node": "^2.3.3", - "boxen": "^6.2.1", - "chalk": "^4.1.2", - "chokidar": "^3.5.3", - "clean-css": "^5.3.2", - "cli-table3": "^0.6.3", - "combine-promises": "^1.1.0", - "commander": "^5.1.0", - "copy-webpack-plugin": "^11.0.0", - "core-js": "^3.31.1", - "css-loader": "^6.8.1", - "css-minimizer-webpack-plugin": "^5.0.1", - "cssnano": "^6.1.2", - "del": "^6.1.1", - "detect-port": "^1.5.1", - "escape-html": "^1.0.3", - "eta": "^2.2.0", - "eval": "^0.1.8", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "html-minifier-terser": "^7.2.0", - "html-tags": "^3.3.1", - "html-webpack-plugin": "^5.5.3", - "leven": "^3.1.0", + "@bitgo/blake2b-wasm": "^3.2.3", + "nanoassert": "^2.0.0" + } + }, + "node_modules/@bitgo/blake2b-wasm": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@bitgo/blake2b-wasm/-/blake2b-wasm-3.2.3.tgz", + "integrity": "sha512-NaurBrMaEpjfg7EdUJgW/c6byt27O6q1ZaxB5Ita10MjjYjUu0SyYF4q7JPNxpHF/lMxb0YZakOxigbDBu9Jjw==", + "license": "MIT", + "dependencies": { + "nanoassert": "^1.0.0" + } + }, + "node_modules/@bitgo/blake2b-wasm/node_modules/nanoassert": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/nanoassert/-/nanoassert-1.1.0.tgz", + "integrity": "sha512-C40jQ3NzfkP53NsO8kEOFd79p4b9kDXQMwgiY1z8ZwrDZgUyom0AHwGegF4Dm99L+YoYhuaB0ceerUcXmqr1rQ==", + "license": "ISC" + }, + "node_modules/@bitgo/blockapis": { + "version": "1.10.9", + "resolved": "https://registry.npmjs.org/@bitgo/blockapis/-/blockapis-1.10.9.tgz", + "integrity": "sha512-8GWR1oruh9WrfxWq9RCKDvMrB3WXcCJ7Gb3uyk5OXt0/bMdpa0QCrLv4e1dG/QeBipCBnLiOkb6NSzS4cbocFA==", + "license": "MIT", + "dependencies": { + "@bitgo/utxo-lib": "^11.2.1", + "@types/superagent": "4.1.16", + "bluebird": "^3.7.2", + "superagent": "^9.0.1" + } + }, + "node_modules/@bitgo/blockapis/node_modules/@types/superagent": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.16.tgz", + "integrity": "sha512-tLfnlJf6A5mB6ddqF159GqcDizfzbMUB1/DeT59/wBNqzRTNNKsaw79A/1TZ84X+f/EwWH8FeuSkjlCLyqS/zQ==", + "license": "MIT", + "dependencies": { + "@types/cookiejar": "*", + "@types/node": "*" + } + }, + "node_modules/@bitgo/bls-dkg": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@bitgo/bls-dkg/-/bls-dkg-1.3.1.tgz", + "integrity": "sha512-pD5f3LQVoCUOczQxGJcEAq3DfchVbdojJ5azikJE64WjV/zR5HkPQDgYcznbM+ou2xX3sbweN893brtYTCNtRw==", + "license": "ISC", + "dependencies": { + "noble-bls12-381": "^0.7.2" + } + }, + "node_modules/@bitgo/public-types": { + "version": "4.11.2", + "resolved": "https://registry.npmjs.org/@bitgo/public-types/-/public-types-4.11.2.tgz", + "integrity": "sha512-McGUcJrvDMHMcCrdnLdgv++k+NasMZliFQARGV2i4czGjSVwK/DHzyNLAiFy0keNoT66nIZ3bV0CTc1uMjlH4g==", + "license": "UNLICENSED", + "dependencies": { + "fp-ts": "^2.0.0", + "io-ts": "npm:@bitgo-forks/io-ts@2.1.4", + "io-ts-types": "^0.5.16", + "monocle-ts": "^2.3.13", + "newtype-ts": "^0.3.5" + } + }, + "node_modules/@bitgo/sdk-api": { + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-api/-/sdk-api-1.58.2.tgz", + "integrity": "sha512-egMomQ6n0u4x8y1J1oHsHjEcGX3CbXt+1I6SoXQwSaSWChWY6pN1i2npUJTmuDUCYH9wqazW0yTIhMCUPdQb7A==", + "license": "MIT", + "dependencies": { + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/sdk-hmac": "^1.1.0", + "@bitgo/sjcl": "^1.0.1", + "@bitgo/unspents": "^0.47.17", + "@bitgo/utxo-lib": "^11.2.1", + "@types/superagent": "4.1.15", + "bitcoinjs-message": "npm:@bitgo-forks/bitcoinjs-message@1.0.0-master.3", + "bluebird": "^3.5.3", + "debug": "3.1.0", + "eol": "^0.5.0", + "lodash": "^4.17.15", + "proxy-agent": "6.4.0", + "sanitize-html": "^2.11", + "secp256k1": "5.0.1", + "secrets.js-grempe": "^1.1.0", + "superagent": "^9.0.1" + } + }, + "node_modules/@bitgo/sdk-api/node_modules/@types/superagent": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.15.tgz", + "integrity": "sha512-mu/N4uvfDN2zVQQ5AYJI/g4qxn2bHB6521t1UuH09ShNWjebTqN0ZFuYK9uYjcgmI0dTQEs+Owi1EO6U0OkOZQ==", + "license": "MIT", + "dependencies": { + "@types/cookiejar": "*", + "@types/node": "*" + } + }, + "node_modules/@bitgo/sdk-api/node_modules/debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/@bitgo/sdk-api/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/@bitgo/sdk-coin-ada": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-ada/-/sdk-coin-ada-4.6.0.tgz", + "integrity": "sha512-VJEvh0ahtgmfQa1oYplzJU7evnLHSNTQY1rASwE4eqbD+Iwr6tIefBC2c0eNdaaMib5LMrqZ//dobEwh5XRn1g==", + "license": "MIT", + "dependencies": { + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/sdk-lib-mpc": "^10.1.0", + "@bitgo/statics": "^50.20.0", + "@emurgo/cardano-serialization-lib-browser": "^12.0.1", + "@emurgo/cardano-serialization-lib-nodejs": "^12.0.1", + "bech32": "^2.0.0", + "bignumber.js": "^9.0.2", "lodash": "^4.17.21", - "mini-css-extract-plugin": "^2.7.6", - "p-map": "^4.0.0", - "postcss": "^8.4.26", - "postcss-loader": "^7.3.3", - "prompts": "^2.4.2", - "react-dev-utils": "^12.0.1", - "react-helmet-async": "^1.3.0", - "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", - "react-loadable-ssr-addon-v5-slorber": "^1.0.1", - "react-router": "^5.3.4", - "react-router-config": "^5.1.1", - "react-router-dom": "^5.3.4", - "rtl-detect": "^1.0.4", - "semver": "^7.5.4", - "serve-handler": "^6.1.5", - "shelljs": "^0.8.5", - "terser-webpack-plugin": "^5.3.9", - "tslib": "^2.6.0", - "update-notifier": "^6.0.2", - "url-loader": "^4.1.1", - "webpack": "^5.88.1", - "webpack-bundle-analyzer": "^4.9.0", - "webpack-dev-server": "^4.15.1", - "webpack-merge": "^5.9.0", - "webpackbar": "^5.0.2" - }, - "bin": { - "docusaurus": "bin/docusaurus.mjs" + "superagent": "^9.0.1", + "tweetnacl": "^1.0.3" }, "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "node": ">=18 <21" } }, - "node_modules/@docusaurus/core/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "bin": { - "semver": "bin/semver.js" + "node_modules/@bitgo/sdk-coin-algo": { + "version": "2.1.58", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-algo/-/sdk-coin-algo-2.1.58.tgz", + "integrity": "sha512-AxdCaZ7cJ+Gj9Es+6CRxiLTSTFfDHhtr4WP6gliCNT+fRPnaSC5iGrMjJEp2HFd2NnTxv7DnvesjzOEAmqQ4sg==", + "license": "MIT", + "dependencies": { + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/statics": "^50.20.0", + "@hashgraph/cryptography": "1.1.2", + "@stablelib/hex": "^1.0.0", + "algosdk": "1.23.1", + "bignumber.js": "^9.0.0", + "hi-base32": "^0.5.1", + "joi": "^17.4.0", + "js-sha512": "0.8.0", + "lodash": "^4.17.14", + "stellar-sdk": "^10.0.1", + "tweetnacl": "^1.0.3" }, "engines": { - "node": ">=10" + "node": ">=18 <21" } }, - "node_modules/@docusaurus/cssnano-preset": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.4.0.tgz", - "integrity": "sha512-qwLFSz6v/pZHy/UP32IrprmH5ORce86BGtN0eBtG75PpzQJAzp9gefspox+s8IEOr0oZKuQ/nhzZ3xwyc3jYJQ==", + "node_modules/@bitgo/sdk-coin-apt": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-apt/-/sdk-coin-apt-1.4.1.tgz", + "integrity": "sha512-doM4SeOHwEV3XgoDZcG2Hud0hgy+xjLmGpEfVgtL/Z2iWNhC9oHMaVJCxyba/w/eArMcZIkdxXTttsULqrsT6A==", + "license": "MIT", "dependencies": { - "cssnano-preset-advanced": "^6.1.2", - "postcss": "^8.4.38", - "postcss-sort-media-queries": "^5.2.0", - "tslib": "^2.6.0" + "@aptos-labs/ts-sdk": "^1.32.0", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/statics": "^50.20.0", + "bignumber.js": "^9.1.2", + "lodash": "^4.17.21" }, "engines": { - "node": ">=18.0" + "node": ">=16 <21" } }, - "node_modules/@docusaurus/logger": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.4.0.tgz", - "integrity": "sha512-bZwkX+9SJ8lB9kVRkXw+xvHYSMGG4bpYHKGXeXFvyVc79NMeeBSGgzd4TQLHH+DYeOJoCdl8flrFJVxlZ0wo/Q==", + "node_modules/@bitgo/sdk-coin-arbeth": { + "version": "21.0.52", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-arbeth/-/sdk-coin-arbeth-21.0.52.tgz", + "integrity": "sha512-2zz0jw30uh9TwwmIZQ+EufYKdsgHlMgNzofq7fsl2e9V8rR/8DJxw75I1iPFHJN3AQ7hdFYzs+/avpCJmtItfQ==", + "license": "MIT", "dependencies": { - "chalk": "^4.1.2", - "tslib": "^2.6.0" + "@bitgo/abstract-eth": "^22.4.10", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/statics": "^50.20.0", + "@bitgo/utxo-lib": "^11.2.1", + "@ethereumjs/common": "^2.6.5", + "ethereumjs-abi": "^0.6.5", + "ethereumjs-util": "7.1.5" }, "engines": { - "node": ">=18.0" + "node": ">=18 <21" } }, - "node_modules/@docusaurus/mdx-loader": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.4.0.tgz", - "integrity": "sha512-kSSbrrk4nTjf4d+wtBA9H+FGauf2gCax89kV8SUSJu3qaTdSIKdWERlngsiHaCFgZ7laTJ8a67UFf+xlFPtuTw==", + "node_modules/@bitgo/sdk-coin-arbeth/node_modules/@ethereumjs/common": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", + "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", + "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.4.0", - "@docusaurus/utils": "3.4.0", - "@docusaurus/utils-validation": "3.4.0", - "@mdx-js/mdx": "^3.0.0", - "@slorber/remark-comment": "^1.0.0", - "escape-html": "^1.0.3", - "estree-util-value-to-estree": "^3.0.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "image-size": "^1.0.2", - "mdast-util-mdx": "^3.0.0", - "mdast-util-to-string": "^4.0.0", - "rehype-raw": "^7.0.0", - "remark-directive": "^3.0.0", - "remark-emoji": "^4.0.0", - "remark-frontmatter": "^5.0.0", - "remark-gfm": "^4.0.0", - "stringify-object": "^3.3.0", - "tslib": "^2.6.0", - "unified": "^11.0.3", - "unist-util-visit": "^5.0.0", - "url-loader": "^4.1.1", - "vfile": "^6.0.1", - "webpack": "^5.88.1" + "crc-32": "^1.2.0", + "ethereumjs-util": "^7.1.5" + } + }, + "node_modules/@bitgo/sdk-coin-atom": { + "version": "13.1.16", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-atom/-/sdk-coin-atom-13.1.16.tgz", + "integrity": "sha512-TbJ9QEkavJKhIeBs3hg2HBIESgSJcvDleDuUnipDGKFI33O5f/WgKVozVUyjE+5/kIZTzLS9rHxkTgbhEWmDug==", + "license": "MIT", + "dependencies": { + "@bitgo/abstract-cosmos": "^11.2.16", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/sdk-lib-mpc": "^10.1.0", + "@bitgo/statics": "^50.20.0", + "@cosmjs/amino": "^0.29.5", + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/stargate": "^0.29.5", + "bignumber.js": "^9.1.1" }, "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "node": ">=18 <21" } }, - "node_modules/@docusaurus/module-type-aliases": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.4.0.tgz", - "integrity": "sha512-A1AyS8WF5Bkjnb8s+guTDuYmUiwJzNrtchebBHpc0gz0PyHJNMaybUlSrmJjHVcGrya0LKI4YcR3lBDQfXRYLw==", + "node_modules/@bitgo/sdk-coin-avaxc": { + "version": "5.2.10", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-avaxc/-/sdk-coin-avaxc-5.2.10.tgz", + "integrity": "sha512-FymTUNo0Isb0uzLrxBLqscf4bu9FUsvbMHXfGd/1RbIjKH/BR6sZPYhJo+ESxYhbrNcEhjDjdg21EuFHYXw2ZA==", + "license": "MIT", "dependencies": { - "@docusaurus/types": "3.4.0", - "@types/history": "^4.7.11", - "@types/react": "*", - "@types/react-router-config": "*", - "@types/react-router-dom": "*", - "react-helmet-async": "*", - "react-loadable": "npm:@docusaurus/react-loadable@6.0.0" + "@bitgo/abstract-eth": "^22.4.10", + "@bitgo/sdk-coin-avaxp": "^5.0.59", + "@bitgo/sdk-coin-eth": "^24.2.49", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/statics": "^50.20.0", + "@bitgo/utxo-lib": "^11.2.1", + "@ethereumjs/common": "^2.6.5", + "bignumber.js": "^9.1.1", + "ethereumjs-abi": "^0.6.5", + "ethereumjs-util": "7.1.5", + "keccak": "^3.0.3", + "lodash": "^4.17.14", + "secp256k1": "5.0.1", + "superagent": "^9.0.1" }, - "peerDependencies": { - "react": "*", - "react-dom": "*" + "engines": { + "node": ">=18 <21" } }, - "node_modules/@docusaurus/module-type-aliases/node_modules/@docusaurus/types": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", - "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", + "node_modules/@bitgo/sdk-coin-avaxc/node_modules/@ethereumjs/common": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", + "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", + "license": "MIT", "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "^1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "crc-32": "^1.2.0", + "ethereumjs-util": "^7.1.5" } }, - "node_modules/@docusaurus/plugin-content-blog": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.4.0.tgz", - "integrity": "sha512-vv6ZAj78ibR5Jh7XBUT4ndIjmlAxkijM3Sx5MAAzC1gyv0vupDQNhzuFg1USQmQVj3P5I6bquk12etPV3LJ+Xw==", + "node_modules/@bitgo/sdk-coin-avaxp": { + "version": "5.0.59", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-avaxp/-/sdk-coin-avaxp-5.0.59.tgz", + "integrity": "sha512-m7NJhRKJ2YHJuK5OLNw6mmZxkW8yR25jw+XJ7mCNarJDcIa8ocDsWwt3NkZ7GMmdo9Hz9kgSmVm9Ob8yDQY9fQ==", + "license": "MIT", "dependencies": { - "@docusaurus/core": "3.4.0", - "@docusaurus/logger": "3.4.0", - "@docusaurus/mdx-loader": "3.4.0", - "@docusaurus/types": "3.4.0", - "@docusaurus/utils": "3.4.0", - "@docusaurus/utils-common": "3.4.0", - "@docusaurus/utils-validation": "3.4.0", - "cheerio": "^1.0.0-rc.12", - "feed": "^4.2.2", - "fs-extra": "^11.1.1", - "lodash": "^4.17.21", - "reading-time": "^1.5.0", - "srcset": "^4.0.0", - "tslib": "^2.6.0", - "unist-util-visit": "^5.0.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" + "@bitgo-forks/avalanchejs": "4.1.0-alpha.1", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/statics": "^50.20.0", + "@bitgo/utxo-lib": "^11.2.1", + "avalanche": "3.15.3", + "bignumber.js": "^9.0.0", + "create-hash": "^1.2.0", + "elliptic": "^6.5.2", + "ethereumjs-util": "7.1.5", + "lodash": "^4.17.14", + "safe-buffer": "^5.2.1" }, "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "node": ">=18 <21" } }, - "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/types": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", - "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", + "node_modules/@bitgo/sdk-coin-bch": { + "version": "2.1.10", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-bch/-/sdk-coin-bch-2.1.10.tgz", + "integrity": "sha512-rJncGy0cLxCbiYDQFyOuy/H04nZDOBufwwPYLRKzTL1YJtdzYlEqEJKKFdSKZ9+1PCQk7ihVFho3QXX8Br3iPg==", + "license": "MIT", "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "^1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1", - "webpack-merge": "^5.9.0" + "@bitgo/abstract-utxo": "^9.12.0", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/utxo-lib": "^11.2.1" }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "engines": { + "node": ">=18 <21" } }, - "node_modules/@docusaurus/plugin-content-docs": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.4.0.tgz", - "integrity": "sha512-HkUCZffhBo7ocYheD9oZvMcDloRnGhBMOZRyVcAQRFmZPmNqSyISlXA1tQCIxW+r478fty97XXAGjNYzBjpCsg==", + "node_modules/@bitgo/sdk-coin-bcha": { + "version": "2.2.10", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-bcha/-/sdk-coin-bcha-2.2.10.tgz", + "integrity": "sha512-UZnSrnLgahWIUI5jTI0Fwm9u5Fr8l1DZdMOJhje/E7ysx/5dAhXMoKyvW9K9McbWHwqX7AO87PFzzCwYcuW+gQ==", + "license": "MIT", "dependencies": { - "@docusaurus/core": "3.4.0", - "@docusaurus/logger": "3.4.0", - "@docusaurus/mdx-loader": "3.4.0", - "@docusaurus/module-type-aliases": "3.4.0", - "@docusaurus/types": "3.4.0", - "@docusaurus/utils": "3.4.0", - "@docusaurus/utils-common": "3.4.0", - "@docusaurus/utils-validation": "3.4.0", - "@types/react-router-config": "^5.0.7", - "combine-promises": "^1.1.0", - "fs-extra": "^11.1.1", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "tslib": "^2.6.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" + "@bitgo/abstract-utxo": "^9.12.0", + "@bitgo/sdk-coin-bch": "^2.1.10", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/utxo-lib": "^11.2.1" }, "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "node": ">=18 <21" } }, - "node_modules/@docusaurus/plugin-content-docs/node_modules/@docusaurus/types": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", - "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", + "node_modules/@bitgo/sdk-coin-bera": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-bera/-/sdk-coin-bera-2.3.4.tgz", + "integrity": "sha512-mBsyYT1YAWhyD2zYAF/Ta+xgmecanx6GLx/OT14W4V0uZOmtxQMtc4kh3qFi7ZpxMu+A7zsBJe7V/rnI0OWgEw==", + "license": "MIT", "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "^1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1", - "webpack-merge": "^5.9.0" + "@bitgo/abstract-eth": "^22.4.10", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/statics": "^50.20.0", + "@bitgo/utxo-lib": "^11.2.1", + "@ethereumjs/common": "^2.6.5" }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "engines": { + "node": ">=18 <21" } }, - "node_modules/@docusaurus/plugin-content-pages": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.4.0.tgz", - "integrity": "sha512-h2+VN/0JjpR8fIkDEAoadNjfR3oLzB+v1qSXbIAKjQ46JAHx3X22n9nqS+BWSQnTnp1AjkjSvZyJMekmcwxzxg==", + "node_modules/@bitgo/sdk-coin-bera/node_modules/@ethereumjs/common": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", + "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", + "license": "MIT", "dependencies": { - "@docusaurus/core": "3.4.0", - "@docusaurus/mdx-loader": "3.4.0", - "@docusaurus/types": "3.4.0", - "@docusaurus/utils": "3.4.0", - "@docusaurus/utils-validation": "3.4.0", - "fs-extra": "^11.1.1", - "tslib": "^2.6.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "crc-32": "^1.2.0", + "ethereumjs-util": "^7.1.5" } }, - "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/types": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", - "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", + "node_modules/@bitgo/sdk-coin-bld": { + "version": "3.0.29", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-bld/-/sdk-coin-bld-3.0.29.tgz", + "integrity": "sha512-ZJsw2beH5FWc8XuCFM818R7AnnctJlyCTE/6GUIavL4TR0o4uDTguPCfiRz5cF2RCxtW7zE0EJoOjPPlCloI+Q==", + "license": "MIT", "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "^1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1", - "webpack-merge": "^5.9.0" + "@bitgo/abstract-cosmos": "^11.2.16", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/sdk-lib-mpc": "^10.1.0", + "@bitgo/statics": "^50.20.0", + "@cosmjs/amino": "^0.29.5", + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/stargate": "^0.29.5", + "bignumber.js": "^9.1.1" }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "engines": { + "node": ">=18 <21" } }, - "node_modules/@docusaurus/plugin-debug": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.4.0.tgz", - "integrity": "sha512-uV7FDUNXGyDSD3PwUaf5YijX91T5/H9SX4ErEcshzwgzWwBtK37nUWPU3ZLJfeTavX3fycTOqk9TglpOLaWkCg==", + "node_modules/@bitgo/sdk-coin-bsc": { + "version": "22.2.13", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-bsc/-/sdk-coin-bsc-22.2.13.tgz", + "integrity": "sha512-+w/AnrROqBXR4ip9xsPLttAkYxcuA2cHb4dVBo/WOSumA/FkizhCzPn3EZ3ryNZU5PEfz0xJ6HnoECz5QocMyQ==", + "license": "MIT", "dependencies": { - "@docusaurus/core": "3.4.0", - "@docusaurus/types": "3.4.0", - "@docusaurus/utils": "3.4.0", - "fs-extra": "^11.1.1", - "react-json-view-lite": "^1.2.0", - "tslib": "^2.6.0" + "@bitgo/abstract-eth": "^22.4.10", + "@bitgo/sdk-coin-eth": "^24.2.49", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/statics": "^50.20.0", + "@ethereumjs/common": "^2.6.5" }, "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "node": ">=18 <21" } }, - "node_modules/@docusaurus/plugin-debug/node_modules/@docusaurus/types": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", - "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", + "node_modules/@bitgo/sdk-coin-bsc/node_modules/@ethereumjs/common": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", + "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", + "license": "MIT", "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "^1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "crc-32": "^1.2.0", + "ethereumjs-util": "^7.1.5" } }, - "node_modules/@docusaurus/plugin-google-analytics": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.4.0.tgz", - "integrity": "sha512-mCArluxEGi3cmYHqsgpGGt3IyLCrFBxPsxNZ56Mpur0xSlInnIHoeLDH7FvVVcPJRPSQ9/MfRqLsainRw+BojA==", + "node_modules/@bitgo/sdk-coin-bsv": { + "version": "2.1.10", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-bsv/-/sdk-coin-bsv-2.1.10.tgz", + "integrity": "sha512-Jo4II1N7IJsn2RnA6QE1lPLyVDIu7M/ev+0Tge4VAFoOOJGnz0VRomP06Bjn82WW6oaGridFAy+/7oJQNfSw2A==", + "license": "MIT", "dependencies": { - "@docusaurus/core": "3.4.0", - "@docusaurus/types": "3.4.0", - "@docusaurus/utils-validation": "3.4.0", - "tslib": "^2.6.0" + "@bitgo/abstract-utxo": "^9.12.0", + "@bitgo/sdk-coin-bch": "^2.1.10", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/utxo-lib": "^11.2.1" }, "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "node": ">=18 <21" } }, - "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/types": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", - "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", + "node_modules/@bitgo/sdk-coin-btc": { + "version": "2.4.10", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-btc/-/sdk-coin-btc-2.4.10.tgz", + "integrity": "sha512-trO8txafVN2CUXrMP9qHjAgX5BDxcJXTDg4gknyD8mucK9y2Bbqd7hTZZEEATTl9jdwFTNKNQZ1k7QQhxmSpFQ==", + "license": "MIT", "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "^1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1", - "webpack-merge": "^5.9.0" + "@bitgo/abstract-utxo": "^9.12.0", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/utxo-lib": "^11.2.1", + "@bitgo/utxo-ord": "^1.20.65" }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "engines": { + "node": ">=18 <21" } }, - "node_modules/@docusaurus/plugin-google-gtag": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.4.0.tgz", - "integrity": "sha512-Dsgg6PLAqzZw5wZ4QjUYc8Z2KqJqXxHxq3vIoyoBWiLEEfigIs7wHR+oiWUQy3Zk9MIk6JTYj7tMoQU0Jm3nqA==", + "node_modules/@bitgo/sdk-coin-btg": { + "version": "2.1.10", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-btg/-/sdk-coin-btg-2.1.10.tgz", + "integrity": "sha512-TWDberjOACQCopSGklaIuqfBGaznOl13ZQgCvMtPdb2zXvLSplrPBrJDjjqneVPSfvbH81dNqIcV3fM7ExBMEQ==", + "license": "MIT", "dependencies": { - "@docusaurus/core": "3.4.0", - "@docusaurus/types": "3.4.0", - "@docusaurus/utils-validation": "3.4.0", - "@types/gtag.js": "^0.0.12", - "tslib": "^2.6.0" + "@bitgo/abstract-utxo": "^9.12.0", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/utxo-lib": "^11.2.1" }, "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "node": ">=18 <21" } }, - "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/types": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", - "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", + "node_modules/@bitgo/sdk-coin-celo": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-celo/-/sdk-coin-celo-4.0.11.tgz", + "integrity": "sha512-nh3TfQpM1kCcm7RF24+kXjCzSOKSZrqpazeybrwjQCG3Mnuc8wypx0MXpVibqkWf6B30qJxsMya7IIsI+f1t2g==", + "license": "MIT", "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "^1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1", - "webpack-merge": "^5.9.0" + "@bitgo/abstract-eth": "^22.4.10", + "@bitgo/sdk-coin-eth": "^24.2.49", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/statics": "^50.20.0", + "@celo/connect": "^2.0.0", + "@celo/contractkit": "^2.0.0", + "@celo/wallet-base": "^2.0.0", + "@celo/wallet-local": "^2.0.0", + "@ethereumjs/common": "^2.6.5", + "bignumber.js": "^9.0.0", + "ethereumjs-abi": "^0.6.5", + "ethereumjs-util": "7.1.5", + "ethers": "^5.1.3" }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "engines": { + "node": ">=18 <21" } }, - "node_modules/@docusaurus/plugin-google-tag-manager": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.4.0.tgz", - "integrity": "sha512-O9tX1BTwxIhgXpOLpFDueYA9DWk69WCbDRrjYoMQtFHSkTyE7RhNgyjSPREUWJb9i+YUg3OrsvrBYRl64FCPCQ==", + "node_modules/@bitgo/sdk-coin-celo/node_modules/@ethereumjs/common": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", + "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", + "license": "MIT", "dependencies": { - "@docusaurus/core": "3.4.0", - "@docusaurus/types": "3.4.0", - "@docusaurus/utils-validation": "3.4.0", - "tslib": "^2.6.0" + "crc-32": "^1.2.0", + "ethereumjs-util": "^7.1.5" + } + }, + "node_modules/@bitgo/sdk-coin-coredao": { + "version": "1.2.12", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-coredao/-/sdk-coin-coredao-1.2.12.tgz", + "integrity": "sha512-hGON3B/2Xkadq8DpOgMXUbPGe2yslWeAxX3ZtyKpSHa/zHywL11vgA5bblq2AFBYeaGoP9woJvdlrSoyRGypHQ==", + "license": "MIT", + "dependencies": { + "@bitgo/abstract-eth": "^22.4.10", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/statics": "^50.20.0", + "@ethereumjs/common": "^2.6.5" }, "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "node": ">=18 <21" } }, - "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/types": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", - "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", + "node_modules/@bitgo/sdk-coin-coredao/node_modules/@ethereumjs/common": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", + "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", + "license": "MIT", "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "^1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "crc-32": "^1.2.0", + "ethereumjs-util": "^7.1.5" } }, - "node_modules/@docusaurus/plugin-sitemap": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.4.0.tgz", - "integrity": "sha512-+0VDvx9SmNrFNgwPoeoCha+tRoAjopwT0+pYO1xAbyLcewXSemq+eLxEa46Q1/aoOaJQ0qqHELuQM7iS2gp33Q==", + "node_modules/@bitgo/sdk-coin-coreum": { + "version": "21.0.29", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-coreum/-/sdk-coin-coreum-21.0.29.tgz", + "integrity": "sha512-8l4peds9CcFzuhD5WjKxIU/0niFLPTQUq5G2izRRLZuCD1Kh1TlJslROp1GnfzR+U3EgSdr5JIpKmO8WIuDrQw==", + "license": "MIT", "dependencies": { - "@docusaurus/core": "3.4.0", - "@docusaurus/logger": "3.4.0", - "@docusaurus/types": "3.4.0", - "@docusaurus/utils": "3.4.0", - "@docusaurus/utils-common": "3.4.0", - "@docusaurus/utils-validation": "3.4.0", - "fs-extra": "^11.1.1", - "sitemap": "^7.1.1", - "tslib": "^2.6.0" + "@bitgo/abstract-cosmos": "^11.2.16", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/sdk-lib-mpc": "^10.1.0", + "@bitgo/statics": "^50.20.0", + "@cosmjs/amino": "^0.29.5", + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/stargate": "^0.29.5", + "bignumber.js": "^9.1.1" }, "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "node": ">=18 <21" } }, - "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/types": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", - "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", + "node_modules/@bitgo/sdk-coin-cspr": { + "version": "2.0.60", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-cspr/-/sdk-coin-cspr-2.0.60.tgz", + "integrity": "sha512-v9xWUgdWGdlEIcLwCjWy3ovKWYHnmgpSyebeaeAsUYjomWSoYM97r2DSByZt37fUs1WUnnmFNeffZNF+/H6olA==", + "license": "MIT", "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "^1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1", - "webpack-merge": "^5.9.0" + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/statics": "^50.20.0", + "@bitgo/utxo-lib": "^11.2.1", + "@ethersproject/bignumber": "^5.6.0", + "@stablelib/hex": "^1.0.0", + "bignumber.js": "^9.0.0", + "casper-js-sdk": "2.7.6", + "lodash": "^4.17.15", + "secp256k1": "5.0.1" }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "engines": { + "node": ">=18 <21" } }, - "node_modules/@docusaurus/preset-classic": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.4.0.tgz", - "integrity": "sha512-Ohj6KB7siKqZaQhNJVMBBUzT3Nnp6eTKqO+FXO3qu/n1hJl3YLwVKTWBg28LF7MWrKu46UuYavwMRxud0VyqHg==", + "node_modules/@bitgo/sdk-coin-dash": { + "version": "2.1.10", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-dash/-/sdk-coin-dash-2.1.10.tgz", + "integrity": "sha512-Tnub50BNpLU1dja3iYr8YEYx5bRKHjRykiumoRTI2vXsk39kXJFWJhBbUeMuViCwlt+b7jDgT9uzaQu4ihrVOQ==", + "license": "MIT", "dependencies": { - "@docusaurus/core": "3.4.0", - "@docusaurus/plugin-content-blog": "3.4.0", - "@docusaurus/plugin-content-docs": "3.4.0", - "@docusaurus/plugin-content-pages": "3.4.0", - "@docusaurus/plugin-debug": "3.4.0", - "@docusaurus/plugin-google-analytics": "3.4.0", - "@docusaurus/plugin-google-gtag": "3.4.0", - "@docusaurus/plugin-google-tag-manager": "3.4.0", - "@docusaurus/plugin-sitemap": "3.4.0", - "@docusaurus/theme-classic": "3.4.0", - "@docusaurus/theme-common": "3.4.0", - "@docusaurus/theme-search-algolia": "3.4.0", - "@docusaurus/types": "3.4.0" + "@bitgo/abstract-utxo": "^9.12.0", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/utxo-lib": "^11.2.1" }, "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "node": ">=18 <21" } }, - "node_modules/@docusaurus/preset-classic/node_modules/@docusaurus/types": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", - "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", + "node_modules/@bitgo/sdk-coin-doge": { + "version": "2.1.10", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-doge/-/sdk-coin-doge-2.1.10.tgz", + "integrity": "sha512-xwizHhFd9hPu2BiOTHj8n9pvmaUMgE8moIxV61BGjXvQrNni0ALfxefp+Iikmw1wjfzLnEfpgyjOOnCMqYVfYA==", + "license": "MIT", "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "^1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1", - "webpack-merge": "^5.9.0" + "@bitgo/abstract-utxo": "^9.12.0", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/utxo-lib": "^11.2.1" }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "engines": { + "node": ">=18 <21" } }, - "node_modules/@docusaurus/theme-classic": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.4.0.tgz", - "integrity": "sha512-0IPtmxsBYv2adr1GnZRdMkEQt1YW6tpzrUPj02YxNpvJ5+ju4E13J5tB4nfdaen/tfR1hmpSPlTFPvTf4kwy8Q==", + "node_modules/@bitgo/sdk-coin-dot": { + "version": "4.1.38", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-dot/-/sdk-coin-dot-4.1.38.tgz", + "integrity": "sha512-2/HY3dMDrCffLpFRmEdItY3/a9uPNXA/MghpGr25Lzkk2ooQVAP3yLAiTJM9Kj7JnxukY62FFFDiYAKZ72IVhg==", + "license": "MIT", "dependencies": { - "@docusaurus/core": "3.4.0", - "@docusaurus/mdx-loader": "3.4.0", - "@docusaurus/module-type-aliases": "3.4.0", - "@docusaurus/plugin-content-blog": "3.4.0", - "@docusaurus/plugin-content-docs": "3.4.0", - "@docusaurus/plugin-content-pages": "3.4.0", - "@docusaurus/theme-common": "3.4.0", - "@docusaurus/theme-translations": "3.4.0", - "@docusaurus/types": "3.4.0", - "@docusaurus/utils": "3.4.0", - "@docusaurus/utils-common": "3.4.0", - "@docusaurus/utils-validation": "3.4.0", - "@mdx-js/react": "^3.0.0", - "clsx": "^2.0.0", - "copy-text-to-clipboard": "^3.2.0", - "infima": "0.2.0-alpha.43", - "lodash": "^4.17.21", - "nprogress": "^0.2.0", - "postcss": "^8.4.26", - "prism-react-renderer": "^2.3.0", - "prismjs": "^1.29.0", - "react-router-dom": "^5.3.4", - "rtlcss": "^4.1.0", - "tslib": "^2.6.0", - "utility-types": "^3.10.0" + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/sdk-lib-mpc": "^10.1.0", + "@bitgo/statics": "^50.20.0", + "@polkadot/api": "14.1.1", + "@polkadot/api-augment": "14.1.1", + "@polkadot/keyring": "13.2.3", + "@polkadot/types": "14.1.1", + "@polkadot/util": "13.2.3", + "@polkadot/util-crypto": "13.2.3", + "@substrate/txwrapper-core": "7.5.2", + "@substrate/txwrapper-polkadot": "7.5.2", + "bignumber.js": "^9.0.0", + "bs58": "^4.0.1", + "hi-base32": "^0.5.1", + "joi": "^17.4.0", + "lodash": "^4.17.15", + "tweetnacl": "^1.0.3" + }, + "engines": { + "node": ">=18 <21" + } + }, + "node_modules/@bitgo/sdk-coin-eos": { + "version": "2.1.53", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-eos/-/sdk-coin-eos-2.1.53.tgz", + "integrity": "sha512-8ePzNgvE3rwNnJ/E5boXC9FwNTfkb2gJrdgCpPMas3DVqX51FwGfBS5izadAiZuG0KUSBDXDuoPjzUWCVoCHJw==", + "license": "MIT", + "dependencies": { + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/statics": "^50.20.0", + "@bitgo/utxo-lib": "^11.2.1", + "bignumber.js": "^9.0.2", + "eosjs": "^21.0.2", + "eosjs-ecc": "^4.0.4", + "lodash": "^4.17.14", + "superagent": "^9.0.1" }, "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "node": ">=18 <21" } }, - "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/types": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", - "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", + "node_modules/@bitgo/sdk-coin-etc": { + "version": "2.2.27", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-etc/-/sdk-coin-etc-2.2.27.tgz", + "integrity": "sha512-ZyHbxRQk/yHRj/s4uVsVqCImAY+AyB/t9MFZcj4gzPx4fsKlqGWZVWHbGkh3j1umD6v+AbXaOBctJTAuQWs7Jw==", + "license": "MIT", "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "^1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1", - "webpack-merge": "^5.9.0" + "@bitgo/abstract-eth": "^22.4.10", + "@bitgo/sdk-coin-eth": "^24.2.49", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/statics": "^50.20.0", + "@bitgo/utxo-lib": "^11.2.1", + "@ethereumjs/common": "^2.6.5", + "bignumber.js": "^9.1.1", + "ethereumjs-abi": "^0.6.5", + "ethereumjs-util": "7.1.5", + "lodash": "^4.17.14", + "superagent": "^9.0.1" }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "engines": { + "node": ">=18 <21" } }, - "node_modules/@docusaurus/theme-common": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.4.0.tgz", - "integrity": "sha512-0A27alXuv7ZdCg28oPE8nH/Iz73/IUejVaCazqu9elS4ypjiLhK3KfzdSQBnL/g7YfHSlymZKdiOHEo8fJ0qMA==", + "node_modules/@bitgo/sdk-coin-etc/node_modules/@ethereumjs/common": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", + "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", + "license": "MIT", "dependencies": { - "@docusaurus/mdx-loader": "3.4.0", - "@docusaurus/module-type-aliases": "3.4.0", - "@docusaurus/plugin-content-blog": "3.4.0", - "@docusaurus/plugin-content-docs": "3.4.0", - "@docusaurus/plugin-content-pages": "3.4.0", - "@docusaurus/utils": "3.4.0", - "@docusaurus/utils-common": "3.4.0", - "@types/history": "^4.7.11", - "@types/react": "*", - "@types/react-router-config": "*", - "clsx": "^2.0.0", - "parse-numeric-range": "^1.3.0", - "prism-react-renderer": "^2.3.0", - "tslib": "^2.6.0", - "utility-types": "^3.10.0" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "crc-32": "^1.2.0", + "ethereumjs-util": "^7.1.5" } }, - "node_modules/@docusaurus/theme-search-algolia": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.4.0.tgz", - "integrity": "sha512-aiHFx7OCw4Wck1z6IoShVdUWIjntC8FHCw9c5dR8r3q4Ynh+zkS8y2eFFunN/DL6RXPzpnvKCg3vhLQYJDmT9Q==", + "node_modules/@bitgo/sdk-coin-eth": { + "version": "24.2.49", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-eth/-/sdk-coin-eth-24.2.49.tgz", + "integrity": "sha512-NYKm57BZy+Y4rGh2lsrZy0373rpGYV8Sh1jVkeq4Xj9vh/hdWqmekFjoTNcY0uST/DdLD982sOtZm4u2CVlTlg==", + "license": "MIT", "dependencies": { - "@docsearch/react": "^3.5.2", - "@docusaurus/core": "3.4.0", - "@docusaurus/logger": "3.4.0", - "@docusaurus/plugin-content-docs": "3.4.0", - "@docusaurus/theme-common": "3.4.0", - "@docusaurus/theme-translations": "3.4.0", - "@docusaurus/utils": "3.4.0", - "@docusaurus/utils-validation": "3.4.0", - "algoliasearch": "^4.18.0", - "algoliasearch-helper": "^3.13.3", - "clsx": "^2.0.0", - "eta": "^2.2.0", - "fs-extra": "^11.1.1", - "lodash": "^4.17.21", - "tslib": "^2.6.0", - "utility-types": "^3.10.0" + "@bitgo/abstract-eth": "^22.4.10", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/statics": "^50.20.0", + "@bitgo/utxo-lib": "^11.2.1", + "@ethereumjs/tx": "^3.3.0", + "@ethereumjs/util": "8.0.3", + "bignumber.js": "^9.1.1", + "ethereumjs-abi": "^0.6.5", + "ethereumjs-util": "7.1.5", + "ethers": "^5.1.3", + "lodash": "^4.17.14", + "secp256k1": "5.0.1", + "superagent": "^9.0.1" }, "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "node": ">=18 <21" } }, - "node_modules/@docusaurus/theme-translations": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.4.0.tgz", - "integrity": "sha512-zSxCSpmQCCdQU5Q4CnX/ID8CSUUI3fvmq4hU/GNP/XoAWtXo9SAVnM3TzpU8Gb//H3WCsT8mJcTfyOk3d9ftNg==", + "node_modules/@bitgo/sdk-coin-eth/node_modules/@ethereumjs/common": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", + "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", + "license": "MIT", "dependencies": { - "fs-extra": "^11.1.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=18.0" + "crc-32": "^1.2.0", + "ethereumjs-util": "^7.1.5" } }, - "node_modules/@docusaurus/tsconfig": { + "node_modules/@bitgo/sdk-coin-eth/node_modules/@ethereumjs/tx": { "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docusaurus/tsconfig/-/tsconfig-3.5.2.tgz", - "integrity": "sha512-rQ7toURCFnWAIn8ubcquDs0ewhPwviMzxh6WpRjBW7sJVCXb6yzwUaY3HMNa0VXCFw+qkIbFywrMTf+Pb4uHWQ==", - "dev": true - }, - "node_modules/@docusaurus/types": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.1.0.tgz", - "integrity": "sha512-VaczOZf7+re8aFBIWnex1XENomwHdsSTkrdX43zyor7G/FY4OIsP6X28Xc3o0jiY0YdNuvIDyA5TNwOtpgkCVw==", - "devOptional": true, + "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.5.2.tgz", + "integrity": "sha512-gQDNJWKrSDGu2w7w0PzVXVBNMzb7wwdDOmOqczmhNjqFxFuIbhVJDwiGEnxFNC2/b8ifcZzY7MLcluizohRzNw==", + "license": "MPL-2.0", "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "^1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "@ethereumjs/common": "^2.6.4", + "ethereumjs-util": "^7.1.5" } }, - "node_modules/@docusaurus/utils": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.4.0.tgz", - "integrity": "sha512-fRwnu3L3nnWaXOgs88BVBmG1yGjcQqZNHG+vInhEa2Sz2oQB+ZjbEMO5Rh9ePFpZ0YDiDUhpaVjwmS+AU2F14g==", + "node_modules/@bitgo/sdk-coin-eth/node_modules/@ethereumjs/util": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/@ethereumjs/util/-/util-8.0.3.tgz", + "integrity": "sha512-0apCbwc8xAaie6W7q6QyogfyRS2BMU816a8KwpnpRw9Qrc6Bws+l7J3LfCLMt2iL6Wi8CYb0B29AeIr2N4vHnw==", + "license": "MPL-2.0", "dependencies": { - "@docusaurus/logger": "3.4.0", - "@docusaurus/utils-common": "3.4.0", - "@svgr/webpack": "^8.1.0", - "escape-string-regexp": "^4.0.0", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "github-slugger": "^1.5.0", - "globby": "^11.1.0", - "gray-matter": "^4.0.3", - "jiti": "^1.20.0", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "micromatch": "^4.0.5", - "prompts": "^2.4.2", - "resolve-pathname": "^3.0.0", - "shelljs": "^0.8.5", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" + "@ethereumjs/rlp": "^4.0.0-beta.2", + "async": "^3.2.4", + "ethereum-cryptography": "^1.1.2" }, "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "@docusaurus/types": "*" - }, - "peerDependenciesMeta": { - "@docusaurus/types": { - "optional": true - } + "node": ">=14" } }, - "node_modules/@docusaurus/utils-common": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.4.0.tgz", - "integrity": "sha512-NVx54Wr4rCEKsjOH5QEVvxIqVvm+9kh7q8aYTU5WzUU9/Hctd6aTrcZ3G0Id4zYJ+AeaG5K5qHA4CY5Kcm2iyQ==", - "dependencies": { - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "@docusaurus/types": "*" - }, - "peerDependenciesMeta": { - "@docusaurus/types": { - "optional": true + "node_modules/@bitgo/sdk-coin-eth/node_modules/@noble/hashes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz", + "integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" } - } + ], + "license": "MIT" }, - "node_modules/@docusaurus/utils-validation": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.4.0.tgz", - "integrity": "sha512-hYQ9fM+AXYVTWxJOT1EuNaRnrR2WGpRdLDQG07O8UOpsvCPWUVOeo26Rbm0JWY2sGLfzAb+tvJ62yF+8F+TV0g==", - "dependencies": { - "@docusaurus/logger": "3.4.0", - "@docusaurus/utils": "3.4.0", - "@docusaurus/utils-common": "3.4.0", - "fs-extra": "^11.2.0", - "joi": "^17.9.2", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=18.0" - } + "node_modules/@bitgo/sdk-coin-eth/node_modules/@noble/secp256k1": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz", + "integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT" }, - "node_modules/@ecies/ciphers": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@ecies/ciphers/-/ciphers-0.2.1.tgz", - "integrity": "sha512-ezMihhjW24VNK/2qQR7lH8xCQY24nk0XHF/kwJ1OuiiY5iEwQXOcKVSy47fSoHPRG8gVGXcK5SgtONDk5xMwtQ==", - "engines": { - "bun": ">=1", - "deno": ">=2", - "node": ">=16" - }, - "peerDependencies": { - "@noble/ciphers": "^1.0.0" + "node_modules/@bitgo/sdk-coin-eth/node_modules/@scure/bip32": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.1.5.tgz", + "integrity": "sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.2.0", + "@noble/secp256k1": "~1.7.0", + "@scure/base": "~1.1.0" } }, - "node_modules/@emnapi/core": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.2.0.tgz", - "integrity": "sha512-E7Vgw78I93we4ZWdYCb4DGAwRROGkMIXk7/y87UmANR+J6qsWusmC3gLt0H+O0KOt5e6O38U8oJamgbudrES/w==", - "dev": true, + "node_modules/@bitgo/sdk-coin-eth/node_modules/@scure/bip39": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.1.tgz", + "integrity": "sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT", "dependencies": { - "@emnapi/wasi-threads": "1.0.1", - "tslib": "^2.4.0" + "@noble/hashes": "~1.2.0", + "@scure/base": "~1.1.0" } }, - "node_modules/@emnapi/runtime": { + "node_modules/@bitgo/sdk-coin-eth/node_modules/ethereum-cryptography": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.2.0.tgz", - "integrity": "sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==", - "dev": true, + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz", + "integrity": "sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==", + "license": "MIT", "dependencies": { - "tslib": "^2.4.0" + "@noble/hashes": "1.2.0", + "@noble/secp256k1": "1.7.1", + "@scure/bip32": "1.1.5", + "@scure/bip39": "1.1.1" } }, - "node_modules/@emnapi/wasi-threads": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.1.tgz", - "integrity": "sha512-iIBu7mwkq4UQGeMEM8bLwNK962nXdhodeScX4slfQnRhEMMzvYivHhutCIk8uojvmASXXPC2WNEjwxFWk72Oqw==", - "dev": true, + "node_modules/@bitgo/sdk-coin-eth2": { + "version": "3.0.59", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-eth2/-/sdk-coin-eth2-3.0.59.tgz", + "integrity": "sha512-5JtW6sjb10iOE8T5JERFDOv6WH5vRgfjW126bmI8bUowPrddqPRwMco4Pcu71+3/Z6lcHPLzIy3hvTaOC7mFrg==", + "license": "MIT", "dependencies": { - "tslib": "^2.4.0" + "@bitgo/sdk-core": "^28.20.0", + "bignumber.js": "^9.1.1", + "ethereumjs-util": "7.1.5", + "lodash": "^4.17.14", + "superagent": "^9.0.1" + }, + "engines": { + "node": ">=18 <21" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "devOptional": true, + "node_modules/@bitgo/sdk-coin-ethlike": { + "version": "1.1.41", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-ethlike/-/sdk-coin-ethlike-1.1.41.tgz", + "integrity": "sha512-vEorAiVpmwi6QThcmhkoFs4dJkg81cyQUm45AP1yLT8RZ7x9ZSPVoJJUbA6lKjCo3GVyhtt7h5M6UVJ/ekahdg==", + "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "@bitgo/abstract-eth": "^22.4.10", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/statics": "^50.20.0", + "@ethereumjs/common": "2.6.5", + "ethereumjs-util": "7.1.5" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "node": ">=18 <21" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", - "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", - "devOptional": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node_modules/@bitgo/sdk-coin-ethlike/node_modules/@ethereumjs/common": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", + "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", + "license": "MIT", + "dependencies": { + "crc-32": "^1.2.0", + "ethereumjs-util": "^7.1.5" } }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "devOptional": true, + "node_modules/@bitgo/sdk-coin-ethw": { + "version": "20.0.60", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-ethw/-/sdk-coin-ethw-20.0.60.tgz", + "integrity": "sha512-RT/5rKahckwhKGsLbDXOqtQkEx/ax+lxFl5hjgN6ymqim72z+l3xFdMdndPby9CJT3byaavnuKKH9i+v5A7vKw==", + "license": "MIT", "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" + "@bitgo/sdk-coin-eth": "^24.2.49", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/statics": "^50.20.0", + "ethereumjs-util": "7.1.5", + "superagent": "^9.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=18 <21" } }, - "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "devOptional": true, + "node_modules/@bitgo/sdk-coin-hash": { + "version": "3.0.29", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-hash/-/sdk-coin-hash-3.0.29.tgz", + "integrity": "sha512-mQ6H4BS86A834RjzQ0lP7xJ84SbRstbOky7K0t9Y/KpUyJn3BPzvgryti57knhCyd0sdiJ0pI9X4osjqncMIvQ==", + "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "@bitgo/abstract-cosmos": "^11.2.16", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/sdk-lib-mpc": "^10.1.0", + "@bitgo/statics": "^50.20.0", + "@cosmjs/amino": "^0.29.5", + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/stargate": "^0.29.5", + "bignumber.js": "^9.1.1" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": ">=18 <21" } }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "devOptional": true, + "node_modules/@bitgo/sdk-coin-hbar": { + "version": "2.0.60", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-hbar/-/sdk-coin-hbar-2.0.60.tgz", + "integrity": "sha512-EpI4pEhzuFJIwTJaqSVa+WCK7Wmk9zPWw5OM0mAXW+txO8vEOS4l9ZRgkUPMemtHAphzJAi0P/5PG1t0QxeVsQ==", + "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@bitgo/sdk-coin-algo": "^2.1.58", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/statics": "^50.20.0", + "@hashgraph/proto": "2.12.0", + "@hashgraph/sdk": "2.29.0", + "@stablelib/sha384": "^1.0.0", + "bignumber.js": "^9.0.0", + "lodash": "^4.17.15", + "long": "^4.0.0", + "protobufjs": "7.2.5", + "stellar-sdk": "^10.0.1", + "tweetnacl": "^1.0.3" + }, + "engines": { + "node": ">=18 <21" } }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "devOptional": true, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "license": "MIT", + "optional": true, + "peer": true, "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "@babel/highlight": "^7.10.4" } }, - "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "devOptional": true + "node_modules/@bitgo/sdk-coin-hbar/node_modules/@expo/config": { + "version": "6.0.26", + "resolved": "https://registry.npmjs.org/@expo/config/-/config-6.0.26.tgz", + "integrity": "sha512-nMQaZl69r6CMJFhCj0xcGJN9bIi4Uws0k9K6q6rGFPFNarS0z0aexeyNLv93/J+hsTJVn0GEYtGz5Y/R8boXxw==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@babel/code-frame": "~7.10.4", + "@expo/config-plugins": "4.1.5", + "@expo/config-types": "^45.0.0", + "@expo/json-file": "8.2.36", + "getenv": "^1.0.0", + "glob": "7.1.6", + "require-from-string": "^2.0.2", + "resolve-from": "^5.0.0", + "semver": "7.3.2", + "slugify": "^1.3.4", + "sucrase": "^3.20.0" + } }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "devOptional": true, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/@expo/config-plugins": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-4.1.5.tgz", + "integrity": "sha512-RVvU40RtZt12HavuDAe+LDIq9lHj7sheOfMEHdmpJ/uTA8pgvkbc56XF6JHQD+yRr6+uhhb+JnAasGq49dsQbw==", + "license": "MIT", + "optional": true, + "peer": true, "dependencies": { - "brace-expansion": "^1.1.7" + "@expo/config-types": "^45.0.0", + "@expo/json-file": "8.2.36", + "@expo/plist": "0.0.18", + "@expo/sdk-runtime-versions": "^1.0.0", + "@react-native/normalize-color": "^2.0.0", + "chalk": "^4.1.2", + "debug": "^4.3.1", + "find-up": "~5.0.0", + "getenv": "^1.0.0", + "glob": "7.1.6", + "resolve-from": "^5.0.0", + "semver": "^7.3.5", + "slash": "^3.0.0", + "xcode": "^3.0.1", + "xml2js": "0.4.23" + } + }, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/@expo/config-plugins/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "optional": true, + "peer": true, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": "*" + "node": ">=10" } }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "devOptional": true, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/@expo/config-types": { + "version": "45.0.0", + "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-45.0.0.tgz", + "integrity": "sha512-/QGhhLWyaGautgEyU50UJr5YqKJix5t77ePTwreOVAhmZH+ff3nrrtYTTnccx+qF08ZNQmfAyYMCD3rQfzpiJA==", + "license": "MIT", + "optional": true, + "peer": true + }, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/@expo/config/node_modules/semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "license": "ISC", + "optional": true, + "peer": true, + "bin": { + "semver": "bin/semver.js" + }, "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", - "devOptional": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node_modules/@bitgo/sdk-coin-hbar/node_modules/@expo/json-file": { + "version": "8.2.36", + "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-8.2.36.tgz", + "integrity": "sha512-tOZfTiIFA5KmMpdW9KF7bc6CFiGjb0xnbieJhTGlHrLL+ps2G0OkqmuZ3pFEXBOMnJYUVpnSy++52LFxvpa5ZQ==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@babel/code-frame": "~7.10.4", + "json5": "^1.0.1", + "write-file-atomic": "^2.3.0" } }, - "node_modules/@ethereumjs/common": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-3.2.0.tgz", - "integrity": "sha512-pksvzI0VyLgmuEF2FA/JR/4/y6hcPq8OUail3/AvycBaW1d5VSauOZzqGvJ3RTmR4MU35lWE8KseKOsEhrFRBA==", + "node_modules/@bitgo/sdk-coin-hbar/node_modules/@expo/plist": { + "version": "0.0.18", + "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.0.18.tgz", + "integrity": "sha512-+48gRqUiz65R21CZ/IXa7RNBXgAI/uPSdvJqoN9x1hfL44DNbUoWHgHiEXTx7XelcATpDwNTz6sHLfy0iNqf+w==", + "license": "MIT", + "optional": true, + "peer": true, "dependencies": { - "@ethereumjs/util": "^8.1.0", - "crc-32": "^1.2.0" + "@xmldom/xmldom": "~0.7.0", + "base64-js": "^1.2.3", + "xmlbuilder": "^14.0.0" } }, - "node_modules/@ethereumjs/rlp": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-4.0.1.tgz", - "integrity": "sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==", - "bin": { - "rlp": "bin/rlp" + "node_modules/@bitgo/sdk-coin-hbar/node_modules/@expo/vector-icons": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@expo/vector-icons/-/vector-icons-13.0.0.tgz", + "integrity": "sha512-TI+l71+5aSKnShYclFa14Kum+hQMZ86b95SH6tQUG3qZEmLTarvWpKwqtTwQKqvlJSJrpFiSFu3eCuZokY6zWA==", + "license": "MIT", + "optional": true, + "peer": true + }, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/@grpc/grpc-js": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.8.2.tgz", + "integrity": "sha512-5cqCjUvDKJWHGeu1prlrFOUmjuML0NequZKJ38PsCkfwIqPnZq4Q9burPP3It7/+46wpl0KsqVN3s6Te3B9Qtw==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/proto-loader": "^0.7.0", + "@types/node": ">=12.12.47" }, "engines": { - "node": ">=14" + "node": "^8.13.0 || >=10.10.0" } }, - "node_modules/@ethereumjs/tx": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-4.2.0.tgz", - "integrity": "sha512-1nc6VO4jtFd172BbSnTnDQVr9IYBFl1y4xPzZdtkrkKIncBCkdbgfdRV+MiTkJYAtTxvV12GRZLqBFT1PNK6Yw==", + "node_modules/@bitgo/sdk-coin-hbar/node_modules/@hashgraph/cryptography": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/@hashgraph/cryptography/-/cryptography-1.4.6.tgz", + "integrity": "sha512-3HmnT1Lek71l6nHxc4GOyT/hSx/LmgusyWfE7hQda2dnE5vL2umydDw5TK2wq8gqmD9S3uRSMhz/BO55wtzxRA==", + "license": "Apache-2.0", "dependencies": { - "@ethereumjs/common": "^3.2.0", - "@ethereumjs/rlp": "^4.0.1", - "@ethereumjs/util": "^8.1.0", - "ethereum-cryptography": "^2.0.0" + "bignumber.js": "^9.1.1", + "bn.js": "^5.1.1", + "crypto-js": "^4.1.1", + "elliptic": "^6.5.4", + "js-base64": "^3.7.4", + "tweetnacl": "^1.0.3", + "utf8": "^3.0.0" }, "engines": { - "node": ">=14" + "node": ">=12.0.0" + }, + "peerDependencies": { + "expo": "^45.0.3", + "expo-crypto": "^10.1.2", + "expo-random": "^12.1.2" + }, + "peerDependenciesMeta": { + "expo": { + "optional": true + }, + "expo-crypto": { + "optional": true + }, + "expo-random": { + "optional": true + } } }, - "node_modules/@ethereumjs/util": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@ethereumjs/util/-/util-8.1.0.tgz", - "integrity": "sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==", + "node_modules/@bitgo/sdk-coin-hbar/node_modules/@hashgraph/sdk": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/@hashgraph/sdk/-/sdk-2.29.0.tgz", + "integrity": "sha512-dMv2q7OCa2Xyi0ooGjo4JJRFxHKzKBvMd8G/n30j4jHx1JiSfI2ckPTAOwfCbYZ/o+EMDZzevyD5+Juf9iph+A==", + "license": "Apache-2.0", "dependencies": { - "@ethereumjs/rlp": "^4.0.1", - "ethereum-cryptography": "^2.0.0", - "micro-ftch": "^0.3.1" + "@ethersproject/abi": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/rlp": "^5.7.0", + "@grpc/grpc-js": "1.8.2", + "@hashgraph/cryptography": "1.4.6", + "@hashgraph/proto": "2.12.0", + "axios": "^1.3.1", + "bignumber.js": "^9.1.1", + "crypto-js": "^4.1.1", + "js-base64": "^3.7.4", + "long": "^4.0.0", + "pino": "^8.14.1", + "pino-pretty": "^10.0.0", + "protobufjs": "^7.1.2", + "utf8": "^3.0.0" }, "engines": { - "node": ">=14" - } - }, - "node_modules/@faker-js/faker": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-9.0.1.tgz", - "integrity": "sha512-4mDeYIgM3By7X6t5E6eYwLAa+2h4DeZDF7thhzIg6XB76jeEvMwadYAMCFJL/R4AnEBcAUO9+gL0vhy3s+qvZA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/fakerjs" + "node": ">=10.17.0" + }, + "peerDependencies": { + "expo": "^45.0.3" + }, + "peerDependenciesMeta": { + "expo": { + "optional": true } - ], - "engines": { - "node": ">=18.0.0", - "npm": ">=9.0.0" } }, - "node_modules/@floating-ui/core": { - "version": "1.6.4", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.4.tgz", - "integrity": "sha512-a4IowK4QkXl4SCWTGUR0INAfEOX3wtsYw3rKK5InQEHMGObkR8Xk44qYQD9P4r6HHw0iIfK6GUKECmY8sTkqRA==", + "node_modules/@bitgo/sdk-coin-hbar/node_modules/@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "license": "MIT", + "optional": true, + "peer": true, "dependencies": { - "@floating-ui/utils": "^0.2.4" + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": ">= 10.14.2" } }, - "node_modules/@floating-ui/dom": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.7.tgz", - "integrity": "sha512-wmVfPG5o2xnKDU4jx/m4w5qva9FWHcnZ8BvzEe90D/RpwsJaTAVYPEPdQ8sbr/N8zZTAHlZUTQdqg8ZUbzHmng==", + "node_modules/@bitgo/sdk-coin-hbar/node_modules/@types/yargs": { + "version": "15.0.19", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.19.tgz", + "integrity": "sha512-2XUaGVmyQjgyAZldf0D0c14vvo/yv0MhQBSTJcejMMaitsn3nxCB6TmH4G0ZQf+uxROOa9mpanoSm8h6SG/1ZA==", + "license": "MIT", + "optional": true, + "peer": true, "dependencies": { - "@floating-ui/core": "^1.6.0", - "@floating-ui/utils": "^0.2.4" + "@types/yargs-parser": "*" } }, - "node_modules/@floating-ui/react-dom": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.1.tgz", - "integrity": "sha512-4h84MJt3CHrtG18mGsXuLCHMrug49d7DFkU0RMIyshRveBeyV2hmV/pDaF2Uxtu8kgq5r46llp5E5FQiR0K2Yg==", + "node_modules/@bitgo/sdk-coin-hbar/node_modules/babel-preset-expo": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-expo/-/babel-preset-expo-9.1.0.tgz", + "integrity": "sha512-dFcgT7AY5n15bLnfOM6R25f8Lh7YSALj4zeGze6aspYHfVrREYcovVG0eMGpY9V24fnwByNRv85lElc1jAj1Mw==", + "license": "MIT", + "optional": true, + "peer": true, "dependencies": { - "@floating-ui/dom": "^1.0.0" - }, - "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" + "@babel/plugin-proposal-decorators": "^7.12.9", + "@babel/plugin-transform-react-jsx": "^7.12.17", + "@babel/preset-env": "^7.12.9", + "babel-plugin-module-resolver": "^4.1.0", + "babel-plugin-react-native-web": "~0.17.1", + "metro-react-native-babel-preset": "~0.67.0" } }, - "node_modules/@floating-ui/utils": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.4.tgz", - "integrity": "sha512-dWO2pw8hhi+WrXq1YJy2yCuWoL20PddgGaqTgVe4cOS9Q6qklXCiA1tJEqX6BEwRNSCP84/afac9hd4MS+zEUA==" - }, - "node_modules/@fortawesome/fontawesome-common-types": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.2.tgz", - "integrity": "sha512-gBxPg3aVO6J0kpfHNILc+NMhXnqHumFxOmjYCFfOiLZfwhnnfhtsdA2hfJlDnj+8PjAs6kKQPenOTKj3Rf7zHw==", - "hasInstallScript": true, - "engines": { - "node": ">=6" + "node_modules/@bitgo/sdk-coin-hbar/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@fortawesome/fontawesome-svg-core": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.5.2.tgz", - "integrity": "sha512-5CdaCBGl8Rh9ohNdxeeTMxIj8oc3KNBgIeLMvJosBMdslK/UnEB8rzyDRrbKdL1kDweqBPo4GT9wvnakHWucZw==", - "hasInstallScript": true, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", "dependencies": { - "@fortawesome/fontawesome-common-types": "6.5.2" - }, - "engines": { - "node": ">=6" + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" } }, - "node_modules/@fortawesome/free-solid-svg-icons": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.5.2.tgz", - "integrity": "sha512-QWFZYXFE7O1Gr1dTIp+D6UcFUF0qElOnZptpi7PBUMylJh+vFmIedVe1Ir6RM1t2tEQLLSV1k7bR4o92M+uqlw==", - "hasInstallScript": true, - "dependencies": { - "@fortawesome/fontawesome-common-types": "6.5.2" - }, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "optional": true, + "peer": true, "engines": { - "node": ">=6" + "node": ">= 10" } }, - "node_modules/@fortawesome/react-fontawesome": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.2.tgz", - "integrity": "sha512-EnkrprPNqI6SXJl//m29hpaNzOp1bruISWaOiRtkMi/xSvHJlzc2j2JAYS7egxt/EbjSNV/k6Xy0AQI6vB2+1g==", + "node_modules/@bitgo/sdk-coin-hbar/node_modules/compare-versions": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", + "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", + "license": "MIT", + "optional": true, + "peer": true + }, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/cross-fetch": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", + "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", + "license": "MIT", + "optional": true, + "peer": true, "dependencies": { - "prop-types": "^15.8.1" - }, - "peerDependencies": { - "@fortawesome/fontawesome-svg-core": "~1 || ~6", - "react": ">=16.3" + "node-fetch": "^2.7.0" } }, - "node_modules/@grpc/grpc-js": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.12.2.tgz", - "integrity": "sha512-bgxdZmgTrJZX50OjyVwz3+mNEnCTNkh3cIqGPWVNeW9jX6bn1ZkU80uPd+67/ZpIJIjRQ9qaHCjhavyoWYxumg==", + "node_modules/@bitgo/sdk-coin-hbar/node_modules/cross-spawn": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", + "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", + "license": "MIT", + "optional": true, + "peer": true, "dependencies": { - "@grpc/proto-loader": "^0.7.13", - "@js-sdsl/ordered-map": "^4.4.2" + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" }, "engines": { - "node": ">=12.10.0" + "node": ">=4.8" } }, - "node_modules/@grpc/proto-loader": { - "version": "0.7.13", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz", - "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==", + "node_modules/@bitgo/sdk-coin-hbar/node_modules/expo": { + "version": "45.0.8", + "resolved": "https://registry.npmjs.org/expo/-/expo-45.0.8.tgz", + "integrity": "sha512-1dSMiodS7t44+1jijPL6ky1CRR/L2pPhrDoaSDo4WBS9ntEa1hEBhC+qa1Th5VkjqG9qkR73AGRgx4h8ozRvsA==", + "license": "MIT", + "optional": true, + "peer": true, "dependencies": { - "lodash.camelcase": "^4.3.0", - "long": "^5.0.0", - "protobufjs": "^7.2.5", - "yargs": "^17.7.2" + "@babel/runtime": "^7.14.0", + "@expo/cli": "0.1.7", + "@expo/vector-icons": "^13.0.0", + "babel-preset-expo": "~9.1.0", + "cross-spawn": "^6.0.5", + "expo-application": "~4.1.0", + "expo-asset": "~8.5.0", + "expo-constants": "~13.1.1", + "expo-file-system": "~14.0.0", + "expo-font": "~10.1.0", + "expo-keep-awake": "~10.1.1", + "expo-modules-autolinking": "0.9.0", + "expo-modules-core": "0.9.2", + "fbemitter": "^3.0.0", + "getenv": "^1.0.0", + "invariant": "^2.2.4", + "md5-file": "^3.2.3", + "node-fetch": "^2.6.7", + "pretty-format": "^26.5.2", + "uuid": "^3.4.0" }, "bin": { - "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + "expo": "bin/cli.js" }, - "engines": { - "node": ">=6" + "optionalDependencies": { + "expo-error-recovery": "~3.1.0" } }, - "node_modules/@grpc/proto-loader/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "node_modules/@bitgo/sdk-coin-hbar/node_modules/expo-application": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/expo-application/-/expo-application-4.1.0.tgz", + "integrity": "sha512-Z2kctgVMpYZB1Iwaxd+XcMBq7h8EEY50GGrwxXsb1OHHQKN+WEVGBWxjvtPkAroqCdujLaB5HBay46gvUHRDQg==", + "license": "MIT", + "optional": true, + "peer": true, + "peerDependencies": { + "expo": "*" + } }, - "node_modules/@grpc/proto-loader/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" + "node_modules/@bitgo/sdk-coin-hbar/node_modules/expo-asset": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/expo-asset/-/expo-asset-8.5.0.tgz", + "integrity": "sha512-k3QErZYxb6e6rPkJ1sG5yIJ7bhd4RFvnFStz0ZCO6SfktGygBAjTz5aTOLaaomiCIObRiBQ4byky/RLdli/NLw==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "blueimp-md5": "^2.10.0", + "invariant": "^2.2.4", + "md5-file": "^3.2.3", + "path-browserify": "^1.0.0", + "url-parse": "^1.5.9" } }, - "node_modules/@grpc/proto-loader/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/@bitgo/sdk-coin-hbar/node_modules/expo-constants": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-13.1.1.tgz", + "integrity": "sha512-QRVHrrMCLenBzWZ8M+EvCXM+jjdQzFMW27YQHRac3SGGoND1hWr81scOmGwlFo2wLZrYXm8HcYt1E6ry3IIwrA==", + "license": "MIT", + "optional": true, + "peer": true, "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "@expo/config": "^6.0.14", + "uuid": "^3.3.2" }, - "engines": { - "node": ">=8" + "peerDependencies": { + "expo": "*" } }, - "node_modules/@grpc/proto-loader/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "node_modules/@bitgo/sdk-coin-hbar/node_modules/expo-error-recovery": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/expo-error-recovery/-/expo-error-recovery-3.1.0.tgz", + "integrity": "sha512-qUxCW7kPB6AVX5h3ZPVnxw4LLZWsRwAPBtRDlh1UDN7GWZ+CQN1SNk0w0BPotjNtSlXEZSFDqKqtoDDAUYjNmg==", + "license": "MIT", + "optional": true, + "peer": true, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/expo-file-system": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-14.0.0.tgz", + "integrity": "sha512-Asva7ehLUq/PIem6Y+/OQvoIqhFqYDd7l4l49yDRDgLSbK2I7Fr8qGhDeDpnUXrMVamg2uwt9zRGhyrjFNRhVw==", + "license": "MIT", + "optional": true, + "peer": true, "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" + "@expo/config-plugins": "^4.0.14", + "uuid": "^3.4.0" }, - "engines": { - "node": ">=12" + "peerDependencies": { + "expo": "*" } }, - "node_modules/@hapi/hoek": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", - "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" - }, - "node_modules/@hapi/topo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", - "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "node_modules/@bitgo/sdk-coin-hbar/node_modules/expo-font": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/expo-font/-/expo-font-10.1.0.tgz", + "integrity": "sha512-vmhzpE95Ym4iOj8IELof+C/3Weert2B3LyxV5rBjGosjzBdov+o+S6b5mN7Yc9kyEGykwB6k7npL45X3hFYDQA==", + "license": "MIT", + "optional": true, + "peer": true, "dependencies": { - "@hapi/hoek": "^9.0.0" + "fontfaceobserver": "^2.1.0" + }, + "peerDependencies": { + "expo": "*" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "deprecated": "Use @eslint/config-array instead", - "devOptional": true, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/expo-keep-awake": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-10.1.1.tgz", + "integrity": "sha512-9zC0sdhQljUeMr2yQ7o4kzEZXVAy82fFOAZE1+TwPL7qR0b0sphe7OJ5T1GX1qLcwuVaJ8YewaPoLSHRk79+Rg==", + "license": "MIT", + "optional": true, + "peer": true, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/expo-modules-autolinking": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-0.9.0.tgz", + "integrity": "sha512-brczklrHpWood7H2C4MjBfUD85NAyjotEhYs7hnHRtbnVgwwzXeAveDje/19kLaK8W40hvUN0LdBVxkZN3Hw6g==", + "license": "MIT", + "optional": true, + "peer": true, "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "chalk": "^4.1.0", + "commander": "^7.2.0", + "fast-glob": "^3.2.5", + "find-up": "^5.0.0", + "fs-extra": "^9.1.0" }, - "engines": { - "node": ">=10.10.0" + "bin": { + "expo-modules-autolinking": "bin/expo-modules-autolinking.js" } }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "devOptional": true, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/expo-modules-core": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-0.9.2.tgz", + "integrity": "sha512-p/C0GJxFIIDGwmrWi70Q0ggfsgeUFS25ZkkBgoaHT7MVgiMjlKA/DCC3D6ZUkHl/JlzUm0aTftIGS8LWXsnZBw==", + "license": "MIT", + "optional": true, + "peer": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "compare-versions": "^3.4.0", + "invariant": "^2.2.4" } }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "devOptional": true, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/fbemitter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/fbemitter/-/fbemitter-3.0.0.tgz", + "integrity": "sha512-KWKaceCwKQU0+HPoop6gn4eOHk50bBv/VxjJtGMfwmJt3D29JpN4H4eisCtIPA+a8GVBam+ldMMpMjJUvpDyHw==", + "license": "BSD-3-Clause", + "optional": true, + "peer": true, "dependencies": { - "brace-expansion": "^1.1.7" + "fbjs": "^3.0.0" + } + }, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/fbjs": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-3.0.5.tgz", + "integrity": "sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "cross-fetch": "^3.1.5", + "fbjs-css-vars": "^1.0.0", + "loose-envify": "^1.0.0", + "object-assign": "^4.1.0", + "promise": "^7.1.1", + "setimmediate": "^1.0.5", + "ua-parser-js": "^1.0.35" + } + }, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": "*" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "devOptional": true, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, "engines": { - "node": ">=12.22" + "node": ">=10" + } + }, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", - "devOptional": true + "node_modules/@bitgo/sdk-coin-hbar/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } }, - "node_modules/@inquirer/confirm": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.0.tgz", - "integrity": "sha512-osaBbIMEqVFjTX5exoqPXs6PilWQdjaLhGtMDXMXg/yxkHXNq43GlxGyTA35lK2HpzUgDN+Cjh/2AmqCN0QJpw==", - "dev": true, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { - "@inquirer/core": "^10.1.1", - "@inquirer/type": "^3.0.1" + "p-locate": "^5.0.0" }, "engines": { - "node": ">=18" + "node": ">=10" }, - "peerDependencies": { - "@types/node": ">=18" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@inquirer/core": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.1.tgz", - "integrity": "sha512-rmZVXy9iZvO3ZStEe/ayuuwIJ23LSF13aPMlLMTQARX6lGUBDHGV8UB5i9MRrfy0+mZwt5/9bdy8llszSD3NQA==", - "dev": true, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", + "license": "Apache-2.0" + }, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/metro-react-native-babel-preset": { + "version": "0.67.0", + "resolved": "https://registry.npmjs.org/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.67.0.tgz", + "integrity": "sha512-tgTG4j0SKwLHbLRELMmgkgkjV1biYkWlGGKOmM484/fJC6bpDikdaFhfjsyE+W+qt7I5szbCPCickMTNQ+zwig==", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { - "@inquirer/figures": "^1.0.8", - "@inquirer/type": "^3.0.1", - "ansi-escapes": "^4.3.2", - "cli-width": "^4.1.0", - "mute-stream": "^2.0.0", - "signal-exit": "^4.1.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^6.2.0", - "yoctocolors-cjs": "^2.1.2" + "@babel/core": "^7.14.0", + "@babel/plugin-proposal-class-properties": "^7.0.0", + "@babel/plugin-proposal-export-default-from": "^7.0.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0", + "@babel/plugin-proposal-object-rest-spread": "^7.0.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.0.0", + "@babel/plugin-proposal-optional-chaining": "^7.0.0", + "@babel/plugin-syntax-dynamic-import": "^7.0.0", + "@babel/plugin-syntax-export-default-from": "^7.0.0", + "@babel/plugin-syntax-flow": "^7.2.0", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.0.0", + "@babel/plugin-syntax-optional-chaining": "^7.0.0", + "@babel/plugin-transform-arrow-functions": "^7.0.0", + "@babel/plugin-transform-async-to-generator": "^7.0.0", + "@babel/plugin-transform-block-scoping": "^7.0.0", + "@babel/plugin-transform-classes": "^7.0.0", + "@babel/plugin-transform-computed-properties": "^7.0.0", + "@babel/plugin-transform-destructuring": "^7.0.0", + "@babel/plugin-transform-exponentiation-operator": "^7.0.0", + "@babel/plugin-transform-flow-strip-types": "^7.0.0", + "@babel/plugin-transform-for-of": "^7.0.0", + "@babel/plugin-transform-function-name": "^7.0.0", + "@babel/plugin-transform-literals": "^7.0.0", + "@babel/plugin-transform-modules-commonjs": "^7.0.0", + "@babel/plugin-transform-object-assign": "^7.0.0", + "@babel/plugin-transform-parameters": "^7.0.0", + "@babel/plugin-transform-react-display-name": "^7.0.0", + "@babel/plugin-transform-react-jsx": "^7.0.0", + "@babel/plugin-transform-react-jsx-self": "^7.0.0", + "@babel/plugin-transform-react-jsx-source": "^7.0.0", + "@babel/plugin-transform-regenerator": "^7.0.0", + "@babel/plugin-transform-runtime": "^7.0.0", + "@babel/plugin-transform-shorthand-properties": "^7.0.0", + "@babel/plugin-transform-spread": "^7.0.0", + "@babel/plugin-transform-sticky-regex": "^7.0.0", + "@babel/plugin-transform-template-literals": "^7.0.0", + "@babel/plugin-transform-typescript": "^7.5.0", + "@babel/plugin-transform-unicode-regex": "^7.0.0", + "@babel/template": "^7.0.0", + "react-refresh": "^0.4.0" }, - "engines": { - "node": ">=18" + "peerDependencies": { + "@babel/core": "*" } }, - "node_modules/@inquirer/core/node_modules/cli-width": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", - "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", - "dev": true, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">= 12" + "node": "*" } }, - "node_modules/@inquirer/core/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/@inquirer/core/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", "license": "MIT", "engines": { - "node": ">=8" + "node": ">=14.0.0" } }, - "node_modules/@inquirer/core/node_modules/mute-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", - "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", - "dev": true, - "license": "ISC", + "node_modules/@bitgo/sdk-coin-hbar/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "p-limit": "^3.0.2" + }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@inquirer/core/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", + "node_modules/@bitgo/sdk-coin-hbar/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "license": "MIT", + "optional": true, + "peer": true, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=4" } }, - "node_modules/@inquirer/core/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/pino": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-8.21.0.tgz", + "integrity": "sha512-ip4qdzjkAyDDZklUaZkcRFb2iA118H9SgRh8yzTkSQK8HilsOJF7rSY8HoW5+I0M46AZgX/pxbprf2vvzQCE0Q==", "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.1.1", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^1.2.0", + "pino-std-serializers": "^6.0.0", + "process-warning": "^3.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^3.7.0", + "thread-stream": "^2.6.0" }, - "engines": { - "node": ">=8" + "bin": { + "pino": "bin.js" } }, - "node_modules/@inquirer/core/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/pino-abstract-transport": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz", + "integrity": "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==", + "license": "MIT", + "dependencies": { + "readable-stream": "^4.0.0", + "split2": "^4.0.0" + } + }, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/pino-std-serializers": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz", + "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==", + "license": "MIT" + }, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "react-is": "^17.0.1" }, "engines": { - "node": ">=8" + "node": ">= 10" } }, - "node_modules/@inquirer/figures": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.8.tgz", - "integrity": "sha512-tKd+jsmhq21AP1LhexC0pPwsCxEhGgAkg28byjJAd+xhmIs8LUX8JbUc3vBf3PhLxWiB5EvyBE5X7JSPAqMAqg==", - "dev": true, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/process-warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", + "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==", + "license": "MIT" + }, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "asap": "~2.0.3" + } + }, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/protobufjs": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.5.tgz", + "integrity": "sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "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": ">=18" + "node": ">=12.0.0" } }, - "node_modules/@inquirer/type": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.1.tgz", - "integrity": "sha512-+ksJMIy92sOAiAccGpcKZUc3bYO07cADnscIxHBknEm3uNts3movSmBofc1908BNy5edKscxYeAdaX1NXkHS6A==", - "dev": true, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/protobufjs/node_modules/long": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.4.tgz", + "integrity": "sha512-qtzLbJE8hq7VabR3mISmVGtoXP8KGc2Z/AT8OuqlYD7JTR3oqrgwdjnk07wpj1twXxYmgDXgoKVWUG/fReSzHg==", + "license": "Apache-2.0" + }, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/react-refresh": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.4.3.tgz", + "integrity": "sha512-Hwln1VNuGl/6bVwnd0Xdn1e84gT/8T9aYNL+HAKDArLCS7LWjwr7StE30IEYbIkx0Vi3vs+coQxe+SQDbGbbpA==", "license": "MIT", + "optional": true, + "peer": true, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" + "node": ">=0.10.0" } }, - "node_modules/@ioredis/commands": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", - "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==" - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "license": "MIT", "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" }, "engines": { - "node": ">=12" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "node": ">= 12.13.0" } }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", + "optional": true, + "peer": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "license": "MIT", + "optional": true, + "peer": true, "dependencies": { - "ansi-regex": "^6.0.1" + "shebang-regex": "^1.0.0" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/@isaacs/ttlcache": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz", - "integrity": "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==", - "license": "ISC", + "node_modules/@bitgo/sdk-coin-hbar/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "license": "MIT", + "optional": true, "peer": true, "engines": { - "node": ">=12" + "node": ">=0.10.0" } }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "node_modules/@bitgo/sdk-coin-hbar/node_modules/sonic-boom": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.1.tgz", + "integrity": "sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg==", + "license": "MIT", "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" + "atomic-sleep": "^1.0.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/@bitgo/sdk-coin-hbar/node_modules/thread-stream": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.7.0.tgz", + "integrity": "sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw==", + "license": "MIT", "dependencies": { - "sprintf-js": "~1.0.2" + "real-require": "^0.2.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "node_modules/@bitgo/sdk-coin-hbar/node_modules/ua-parser-js": { + "version": "1.0.40", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.40.tgz", + "integrity": "sha512-z6PJ8Lml+v3ichVojCiB8toQJBuwR42ySM4ezjXIqXK3M0HczmKQ3LF4rhU55PfD99KEEXQG6yb7iOMyvYuHew==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + }, + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + } + ], + "license": "MIT", + "optional": true, + "peer": true, + "bin": { + "ua-parser-js": "script/cli.js" + }, "engines": { - "node": ">=6" + "node": "*" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "node_modules/@bitgo/sdk-coin-hbar/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "license": "MIT", + "optional": true, + "peer": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/@bitgo/sdk-coin-hbar/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "license": "ISC", + "optional": true, + "peer": true, "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "isexe": "^2.0.0" }, "bin": { - "js-yaml": "bin/js-yaml.js" + "which": "bin/which" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + "node_modules/@bitgo/sdk-coin-hbar/node_modules/write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "node_modules/@bitgo/sdk-coin-icp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-icp/-/sdk-coin-icp-1.1.0.tgz", + "integrity": "sha512-koLlZomvG92dC4Zn9BWMafj+H3TeUVxJSXsD00CNQOl9GBVp01Yt11cyIGDYHhqks2blK5QeYTMRuhaQD0vwRw==", + "license": "MIT", + "dependencies": { + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/statics": "^50.20.0" + }, "engines": { - "node": ">=8" + "node": ">=18 <21" } }, - "node_modules/@jest/console": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", - "dev": true, + "node_modules/@bitgo/sdk-coin-injective": { + "version": "3.0.29", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-injective/-/sdk-coin-injective-3.0.29.tgz", + "integrity": "sha512-hmmkuU/cVaa/GxTygMTUJwXtbdccTydNSnVjq+zXFrk3gd/MpmcYDJECDzYO79D7Hl5QBv6Xaow2S+Vy7qmbmQ==", + "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" + "@bitgo/abstract-cosmos": "^11.2.16", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/sdk-lib-mpc": "^10.1.0", + "@bitgo/statics": "^50.20.0", + "@cosmjs/amino": "^0.29.5", + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/stargate": "^0.29.5", + "bignumber.js": "^9.1.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18 <21" } }, - "node_modules/@jest/core": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", - "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", - "dev": true, + "node_modules/@bitgo/sdk-coin-islm": { + "version": "2.1.10", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-islm/-/sdk-coin-islm-2.1.10.tgz", + "integrity": "sha512-1qXAIwT18KSkUFIJqfTHm6bUlL48DaMCWjE/wJlH3Iptct8tzQc0EyHHJ38lqnH7B2ll5JM+4mKdDNOBJAT3Vg==", + "license": "MIT", "dependencies": { - "@jest/console": "^29.7.0", - "@jest/reporters": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.7.0", - "jest-config": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-resolve-dependencies": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "jest-watcher": "^29.7.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" + "@bitgo/abstract-cosmos": "^11.2.16", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/statics": "^50.20.0", + "@cosmjs/amino": "^0.29.5", + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/proto-signing": "^0.29.5", + "@cosmjs/stargate": "^0.29.5", + "bignumber.js": "^9.1.1", + "cosmjs-types": "^0.6.1", + "ethers": "^5.7.2", + "keccak": "3.0.3", + "protobufjs": "7.2.5" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "node": ">=18 <21" } }, - "node_modules/@jest/core/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, + "node_modules/@bitgo/sdk-coin-islm/node_modules/keccak": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.3.tgz", + "integrity": "sha512-JZrLIAJWuZxKbCilMpNz5Vj7Vtb4scDG3dMXLOsbzBmQGyjwE61BbW7bJkfKKCShXiQZt3T6sBgALRtmd+nZaQ==", + "hasInstallScript": true, + "license": "MIT", "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0", + "readable-stream": "^3.6.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10.0.0" } }, - "node_modules/@jest/core/node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" + "node_modules/@bitgo/sdk-coin-islm/node_modules/protobufjs": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.5.tgz", + "integrity": "sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "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" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "engines": { + "node": ">=12.0.0" } }, - "node_modules/@jest/core/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true - }, - "node_modules/@jest/create-cache-key-function": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz", - "integrity": "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==", + "node_modules/@bitgo/sdk-coin-lnbtc": { + "version": "1.1.38", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-lnbtc/-/sdk-coin-lnbtc-1.1.38.tgz", + "integrity": "sha512-pYou1qXEuuCuXX2vtZ7c1SKKtv5Glo1zdzmcFVSY38nA6hucbzko6lDt4Q1nVa1wgZZa7AAGXA+htxND7UweSA==", "license": "MIT", - "peer": true, "dependencies": { - "@jest/types": "^29.6.3" + "@bitgo/abstract-lightning": "^1.2.38", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/utxo-lib": "^11.2.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18 <21" } }, - "node_modules/@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "node_modules/@bitgo/sdk-coin-ltc": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-ltc/-/sdk-coin-ltc-3.1.10.tgz", + "integrity": "sha512-QVeBsxDYoGB7hRmAhEjkiChaVxuOp87TRwB0fhbVQoziT9yhNZiVZIhjQMwvHjY1fOp47TQ5M9AKgnwz6eiD8A==", + "license": "MIT", "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" + "@bitgo/abstract-utxo": "^9.12.0", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/utxo-lib": "^11.2.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18 <21" } }, - "node_modules/@jest/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", - "dev": true, + "node_modules/@bitgo/sdk-coin-near": { + "version": "2.0.60", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-near/-/sdk-coin-near-2.0.60.tgz", + "integrity": "sha512-DC7YofT5dzbiuTukeIlqMTXtvFPuUvuM6A4XRZF+GTVw1OCFItxXyomdHyO7kEDkbFxPrhg2FRFMh3rWEK2yDQ==", + "license": "MIT", "dependencies": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/statics": "^50.20.0", + "@stablelib/hex": "^1.0.0", + "bignumber.js": "^9.0.0", + "bn.js": "^5.2.1", + "bs58": "^4.0.1", + "js-sha256": "^0.9.0", + "lodash": "^4.17.14", + "near-api-js": "^0.44.2", + "superagent": "^9.0.1", + "tweetnacl": "^1.0.3" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18 <21" } }, - "node_modules/@jest/expect-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", - "dev": true, + "node_modules/@bitgo/sdk-coin-oas": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-oas/-/sdk-coin-oas-1.1.13.tgz", + "integrity": "sha512-sEmz0yF1Dd/9w7wLY9KhXEejWq61GILQ1qrT9dAIdKiDYH9uuJanIenGXifi64UprN1D0bNokUg4l4XJvmFlSQ==", + "license": "MIT", "dependencies": { - "jest-get-type": "^29.6.3" + "@bitgo/abstract-eth": "^22.4.10", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/statics": "^50.20.0", + "@ethereumjs/common": "^2.6.5" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18 <21" } }, - "node_modules/@jest/fake-timers": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "node_modules/@bitgo/sdk-coin-oas/node_modules/@ethereumjs/common": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", + "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", + "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" + "crc-32": "^1.2.0", + "ethereumjs-util": "^7.1.5" + } + }, + "node_modules/@bitgo/sdk-coin-opeth": { + "version": "18.1.45", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-opeth/-/sdk-coin-opeth-18.1.45.tgz", + "integrity": "sha512-a7ltFrapsb3O5YubCT+m2xuU2/FjKsqZ42RddTgONmybKth/YAoZaBjaMQfCge/RU9fUhIdrb+Ux1ACx6mdvTA==", + "license": "MIT", + "dependencies": { + "@bitgo/abstract-eth": "^22.4.10", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/statics": "^50.20.0", + "@bitgo/utxo-lib": "^11.2.1", + "@ethereumjs/common": "^2.6.5", + "ethereumjs-abi": "^0.6.5", + "ethereumjs-util": "7.1.5" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18 <21" } }, - "node_modules/@jest/globals": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", - "dev": true, + "node_modules/@bitgo/sdk-coin-opeth/node_modules/@ethereumjs/common": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", + "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", + "license": "MIT", "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" + "crc-32": "^1.2.0", + "ethereumjs-util": "^7.1.5" + } + }, + "node_modules/@bitgo/sdk-coin-osmo": { + "version": "3.0.29", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-osmo/-/sdk-coin-osmo-3.0.29.tgz", + "integrity": "sha512-FDDZuHUzYt0mI9ctuzEdWu7g0kB5jeJWzXHMuV2DwyqQEADRTuiJvbpF7wTusTuv3ClcMtmw5aqWPCI0SX4OVA==", + "license": "MIT", + "dependencies": { + "@bitgo/abstract-cosmos": "^11.2.16", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/sdk-lib-mpc": "^10.1.0", + "@bitgo/statics": "^50.20.0", + "@cosmjs/amino": "^0.29.5", + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/stargate": "^0.29.5", + "bignumber.js": "^9.1.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18 <21" } }, - "node_modules/@jest/reporters": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", - "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", - "dev": true, + "node_modules/@bitgo/sdk-coin-polygon": { + "version": "21.0.29", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-polygon/-/sdk-coin-polygon-21.0.29.tgz", + "integrity": "sha512-TfImxztWi82OXObvR0N+BUsP/M3GpegvN+mgYSy93JKjlPdNL1CtnQOoSUHn+qN4hpm4RIA1nGUQ8pVUb6HvCA==", + "license": "MIT", "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" + "@bitgo/abstract-eth": "^22.4.10", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/sjcl": "^1.0.1", + "@bitgo/statics": "^50.20.0", + "@bitgo/utxo-lib": "^11.2.1", + "@ethereumjs/common": "^2.6.5", + "ethereumjs-util": "7.1.5", + "ethers": "^5.1.3" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "node": ">=18 <21" } }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/@bitgo/sdk-coin-polygon/node_modules/@ethereumjs/common": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", + "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", + "license": "MIT", "dependencies": { - "@sinclair/typebox": "^0.27.8" + "crc-32": "^1.2.0", + "ethereumjs-util": "^7.1.5" + } + }, + "node_modules/@bitgo/sdk-coin-rbtc": { + "version": "2.0.60", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-rbtc/-/sdk-coin-rbtc-2.0.60.tgz", + "integrity": "sha512-HHmyV9ThmbWzH1Cm3UTKDqWSL7sQHl+q202qBHia4L4d9cpFrVGAkZGmeSbIytLke+QJKXetfV0/A5WecbXFvQ==", + "license": "MIT", + "dependencies": { + "@bitgo/abstract-eth": "^22.4.10", + "@bitgo/sdk-coin-eth": "^24.2.49", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/statics": "^50.20.0", + "@ethereumjs/common": "^2.6.5", + "ethereumjs-abi": "^0.6.5" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18 <21" } }, - "node_modules/@jest/source-map": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", - "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", - "dev": true, + "node_modules/@bitgo/sdk-coin-rbtc/node_modules/@ethereumjs/common": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", + "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", + "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" + "crc-32": "^1.2.0", + "ethereumjs-util": "^7.1.5" + } + }, + "node_modules/@bitgo/sdk-coin-rune": { + "version": "1.1.17", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-rune/-/sdk-coin-rune-1.1.17.tgz", + "integrity": "sha512-4WJ1EU+XH6ySSVEXXpKnmofQDwl9ug5rnBcQuiz/U9QBbCpkapLt052GY4YJ5UoRQTg0sZUq9Bqdauaj0o27rg==", + "license": "MIT", + "dependencies": { + "@bitgo/abstract-cosmos": "^11.2.16", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/statics": "^50.20.0", + "@cosmjs/amino": "^0.29.5", + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/proto-signing": "^0.29.5", + "@cosmjs/stargate": "^0.29.5", + "bech32-buffer": "^0.2.1", + "bignumber.js": "^9.1.1", + "lodash": "^4.17.21" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18 <21" } }, - "node_modules/@jest/test-result": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", - "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", - "dev": true, + "node_modules/@bitgo/sdk-coin-sei": { + "version": "3.0.29", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-sei/-/sdk-coin-sei-3.0.29.tgz", + "integrity": "sha512-9LYZtNMfk0VsmmT5YDnX+hr4Z7v9hJwll177ZoFmAFRlQZMV4vt/bmLb353nLGXX7Eg1OcUqkTI+bWhxut8OaQ==", + "license": "MIT", "dependencies": { - "@jest/console": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" + "@bitgo/abstract-cosmos": "^11.2.16", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/sdk-lib-mpc": "^10.1.0", + "@bitgo/statics": "^50.20.0", + "@cosmjs/amino": "^0.29.5", + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/stargate": "^0.29.5", + "bignumber.js": "^9.1.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18 <21" } }, - "node_modules/@jest/test-sequencer": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", - "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", - "dev": true, + "node_modules/@bitgo/sdk-coin-sol": { + "version": "4.7.17", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-sol/-/sdk-coin-sol-4.7.17.tgz", + "integrity": "sha512-uoQ40f23NrzitmwjVgJwWeFUDVLlgRnn0/sjfmzXOOIA1e++RBCIAAWyvVwtZEHdSilDt5iT/T/1Wc357x0m2g==", + "license": "MIT", "dependencies": { - "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/sdk-lib-mpc": "^10.1.0", + "@bitgo/statics": "^50.20.0", + "@solana/spl-token": "0.3.1", + "@solana/web3.js": "1.92.1", + "bignumber.js": "^9.0.0", + "bs58": "^4.0.1", + "lodash": "^4.17.14", + "superagent": "^9.0.1", + "tweetnacl": "^1.0.3" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18 <21" } }, - "node_modules/@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "node_modules/@bitgo/sdk-coin-stx": { + "version": "3.3.17", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-stx/-/sdk-coin-stx-3.3.17.tgz", + "integrity": "sha512-cWVGjjYID6mSthQwqrLkw8RHeozFElfTy9xBfiYmp+T19RJGt0l57BZuOCVkbPWqFNH/uplTmN+vb+2f1CF8Dg==", + "license": "MIT", "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/statics": "^50.20.0", + "@bitgo/utxo-lib": "^11.2.1", + "@stacks/network": "^4.3.0", + "@stacks/transactions": "2.0.1", + "bignumber.js": "^9.0.0", + "bn.js": "^5.2.1", + "elliptic": "^6.5.2", + "ethereumjs-util": "7.1.5", + "lodash": "^4.17.15" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18 <21" } }, - "node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/@bitgo/sdk-coin-tao": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-tao/-/sdk-coin-tao-1.0.2.tgz", + "integrity": "sha512-8O0ysGnQBJGobBRfwb2SerQ8NXjlkuXw9JeZghnoCg5JB4EkhfhJ5hVBdNwqo4z2aYEFGUI544Qvec9P5KYhpQ==", + "license": "MIT", "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "@bitgo/abstract-substrate": "^1.0.2", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/statics": "^50.20.0", + "bignumber.js": "^9.1.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=16 <21" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "node_modules/@bitgo/sdk-coin-tia": { + "version": "3.0.29", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-tia/-/sdk-coin-tia-3.0.29.tgz", + "integrity": "sha512-s2pGn/cQ8s7dEEpf/FqjprocGtKknYKoy91WKWWFXikThLpcmV1/CDmTPVUk7MDn6caQIl+pYoCtlRWHwcmvVA==", + "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" + "@bitgo/abstract-cosmos": "^11.2.16", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/sdk-lib-mpc": "^10.1.0", + "@bitgo/statics": "^50.20.0", + "@cosmjs/amino": "^0.29.5", + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/stargate": "^0.29.5", + "bignumber.js": "^9.1.1" }, "engines": { - "node": ">=6.0.0" + "node": ">=18 <21" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "node_modules/@bitgo/sdk-coin-ton": { + "version": "3.4.17", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-ton/-/sdk-coin-ton-3.4.17.tgz", + "integrity": "sha512-mKwymowr/DTTyplkptQWWp0Tt/JaNdeP9YL8wwFjk/e2uJDIUBPc1U4/7Cq8E2QRlNC0rD+oTiTU9E4h17oV+Q==", + "license": "MIT", + "dependencies": { + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/sdk-lib-mpc": "^10.1.0", + "@bitgo/statics": "^50.20.0", + "bignumber.js": "^9.0.0", + "bn.js": "^5.2.1", + "lodash": "^4.17.21", + "tonweb": "^0.0.62", + "tweetnacl": "^1.0.3" + }, "engines": { - "node": ">=6.0.0" + "node": ">=18 <21" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "node_modules/@bitgo/sdk-coin-trx": { + "version": "2.0.60", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-trx/-/sdk-coin-trx-2.0.60.tgz", + "integrity": "sha512-OziYDAi4hAJ1hX+u6O2K6C0nvbyb+zhlgoSAto2L+ZQSeaUlqBKSh2utu6MnJwX9R7qVn7EOtVXVlOV7OEbVTQ==", + "license": "MIT", + "dependencies": { + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/statics": "^50.20.0", + "@bitgo/utxo-lib": "^11.2.1", + "@stablelib/hex": "^1.0.0", + "bignumber.js": "^9.0.0", + "ethers": "^5.7.2", + "lodash": "^4.17.14", + "protobufjs": "7.2.5", + "secp256k1": "5.0.1", + "superagent": "^9.0.1", + "tronweb": "5.1.0" + }, "engines": { - "node": ">=6.0.0" + "node": ">=18 <21" } }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", - "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "node_modules/@bitgo/sdk-coin-trx/node_modules/protobufjs": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.5.tgz", + "integrity": "sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==", + "hasInstallScript": true, + "license": "BSD-3-Clause", "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" + "@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/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "node_modules/@bitgo/sdk-coin-xlm": { + "version": "3.2.34", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-xlm/-/sdk-coin-xlm-3.2.34.tgz", + "integrity": "sha512-9PiLJlo8gXDJ7SvanX4mnjUY17egVh/6LtsEoZGB5kJpkLugZXVxOZnTjJXMDJLxRud0unthZU52zA0gQFgCzw==", + "license": "MIT", "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/statics": "^50.20.0", + "bignumber.js": "^9.1.1", + "lodash": "^4.17.14", + "stellar-sdk": "^10.0.1", + "superagent": "^9.0.1" + }, + "engines": { + "node": ">=18 <21" } }, - "node_modules/@js-sdsl/ordered-map": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", - "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/js-sdsl" + "node_modules/@bitgo/sdk-coin-xrp": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-xrp/-/sdk-coin-xrp-3.7.2.tgz", + "integrity": "sha512-ketTWWs7qhkSCdDDEOfCL2uLRSHcqqNtICuk1U0+BHItKCAotjfMpA6rPmSxXZ8lCb78IdGycWKUeUQuWXbEzg==", + "license": "MIT", + "dependencies": { + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/statics": "^50.20.0", + "@bitgo/utxo-lib": "^11.2.1", + "bignumber.js": "^9.0.0", + "lodash": "^4.17.14", + "ripple-binary-codec": "2.1.0", + "ripple-keypairs": "2.0.0", + "xrpl": "4.0.0" + }, + "engines": { + "node": ">=18 <21" } }, - "node_modules/@jsonjoy.com/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", - "dev": true, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" + "node_modules/@bitgo/sdk-coin-xtz": { + "version": "2.1.58", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-xtz/-/sdk-coin-xtz-2.1.58.tgz", + "integrity": "sha512-hWRw4jl5kQ8G1S52L6Gfj2uZBQWmxnNzKwZDXzvPOKdVqjXFlAhvYwsXSLzI85LLliEaQQpLzFxdCJ97gzgKDw==", + "license": "MIT", + "dependencies": { + "@bitgo/blake2b": "^3.2.4", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/statics": "^50.20.0", + "@bitgo/utxo-lib": "^11.2.1", + "@taquito/local-forging": "6.3.5-beta.0", + "@taquito/signer": "6.3.5-beta.0", + "bignumber.js": "^9.0.0", + "bs58check": "^2.1.2", + "elliptic": "^6.5.2", + "libsodium-wrappers": "^0.7.6", + "lodash": "^4.17.15" }, - "peerDependencies": { - "tslib": "2" + "engines": { + "node": ">=18 <21" } }, - "node_modules/@jsonjoy.com/json-pack": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.1.0.tgz", - "integrity": "sha512-zlQONA+msXPPwHWZMKFVS78ewFczIll5lXiVPwFPCZUsrOKdxc2AvxU1HoNBmMRhqDZUR9HkC3UOm+6pME6Xsg==", - "dev": true, + "node_modules/@bitgo/sdk-coin-zec": { + "version": "2.1.10", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-zec/-/sdk-coin-zec-2.1.10.tgz", + "integrity": "sha512-UTPMWv1okkj6ehbhDK9DRZyVJ22JrgFKkiRD/VF4movjhnEsV8uCtl2SOhIkbIRKXm2/5JiUu7sLuESfEXQLqQ==", + "license": "MIT", "dependencies": { - "@jsonjoy.com/base64": "^1.1.1", - "@jsonjoy.com/util": "^1.1.2", - "hyperdyperid": "^1.2.0", - "thingies": "^1.20.0" + "@bitgo/abstract-utxo": "^9.12.0", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/utxo-lib": "^11.2.1" }, "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" + "node": ">=18 <21" } }, - "node_modules/@jsonjoy.com/util": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.3.0.tgz", - "integrity": "sha512-Cebt4Vk7k1xHy87kHY7KSPLT77A7Ev7IfOblyLZhtYEhrdQ6fX4EoLq3xOQ3O/DRMEh2ok5nyC180E+ABS8Wmw==", - "dev": true, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" + "node_modules/@bitgo/sdk-coin-zeta": { + "version": "3.0.29", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-zeta/-/sdk-coin-zeta-3.0.29.tgz", + "integrity": "sha512-PKL2e3jH6PhbjmD02Elp8OYh62tvyLqYXJtZo8EUmdBJxZ/9SIBatzNU9WG8B3Yen9nPlzhiHI1BCujPpPmVOw==", + "license": "MIT", + "dependencies": { + "@bitgo/abstract-cosmos": "^11.2.16", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/sdk-lib-mpc": "^10.1.0", + "@bitgo/statics": "^50.20.0", + "@cosmjs/amino": "^0.29.5", + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/stargate": "^0.29.5", + "bignumber.js": "^9.1.1" }, - "peerDependencies": { - "tslib": "2" + "engines": { + "node": ">=18 <21" } }, - "node_modules/@keyv/serialize": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.0.2.tgz", - "integrity": "sha512-+E/LyaAeuABniD/RvUezWVXKpeuvwLEA9//nE9952zBaOdBd2mQ3pPoM8cUe2X6IcMByfuSLzmYqnYshG60+HQ==", + "node_modules/@bitgo/sdk-coin-zketh": { + "version": "2.0.52", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-zketh/-/sdk-coin-zketh-2.0.52.tgz", + "integrity": "sha512-PE1RQ8peAyqrsJXnlwxe8jdMwlTB/QGseAeJtKG1VDD1ayYaZoov8bTZvJWY9NSVL1H6p0o8Jqnsj6gahet83w==", "license": "MIT", "dependencies": { - "buffer": "^6.0.3" + "@bitgo/abstract-eth": "^22.4.10", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/statics": "^50.20.0", + "@bitgo/utxo-lib": "^11.2.1", + "@ethereumjs/common": "^2.6.5" + }, + "engines": { + "node": ">=16 <21" } }, - "node_modules/@keyv/serialize/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/@bitgo/sdk-coin-zketh/node_modules/@ethereumjs/common": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", + "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", "license": "MIT", "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" + "crc-32": "^1.2.0", + "ethereumjs-util": "^7.1.5" } }, - "node_modules/@leichtgewicht/ip-codec": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", - "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==" + "node_modules/@bitgo/sdk-core": { + "version": "28.20.0", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-core/-/sdk-core-28.20.0.tgz", + "integrity": "sha512-ieOAVMR1aOpYcpuG3sM4NBuFUeTMMO2TIKdbGQ1BHS4A3mgl+youFytYbbMRJsHE4NDyzyKD2+G+q2e4aWBJ0w==", + "license": "MIT", + "dependencies": { + "@bitgo/bls-dkg": "^1.3.1", + "@bitgo/public-types": "4.9.2", + "@bitgo/sdk-lib-mpc": "^10.1.0", + "@bitgo/sjcl": "^1.0.1", + "@bitgo/statics": "^50.20.0", + "@bitgo/utxo-lib": "^11.2.1", + "@noble/secp256k1": "1.6.3", + "@stablelib/hex": "^1.0.0", + "@types/elliptic": "^6.4.12", + "@types/superagent": "4.1.15", + "bech32": "^2.0.0", + "big.js": "^3.1.3", + "bigint-crypto-utils": "3.1.4", + "bignumber.js": "^9.1.1", + "bitcoinjs-message": "npm:@bitgo-forks/bitcoinjs-message@1.0.0-master.3", + "bolt11": "^1.4.0", + "bs58": "^4.0.1", + "bs58check": "^2.1.2", + "create-hmac": "^1.1.7", + "debug": "^3.1.0", + "elliptic": "^6.5.2", + "ethereumjs-util": "7.1.5", + "fp-ts": "^2.12.2", + "io-ts": "npm:@bitgo-forks/io-ts@2.1.4", + "io-ts-types": "^0.5.16", + "keccak": "3.0.3", + "libsodium-wrappers-sumo": "^0.7.9", + "lodash": "^4.17.15", + "macaroon": "^3.0.4", + "noble-bls12-381": "0.7.2", + "openpgp": "5.10.1", + "paillier-bigint": "3.3.0", + "secp256k1": "5.0.1", + "strip-hex-prefix": "^1.0.0", + "superagent": "^9.0.1", + "tweetnacl": "^1.0.3", + "uuid": "^8.3.2" + } }, - "node_modules/@lit-labs/ssr-dom-shim": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.2.1.tgz", - "integrity": "sha512-wx4aBmgeGvFmOKucFKY+8VFJSYZxs9poN3SDNQFF6lT6NrQUnHiPB2PWz2sc4ieEcAaYYzN+1uWahEeTq2aRIQ==" + "node_modules/@bitgo/sdk-core/node_modules/@bitgo/public-types": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/@bitgo/public-types/-/public-types-4.9.2.tgz", + "integrity": "sha512-yVP/duh0ION0pfSVMJt24qCQ66Vxjlg7eP9iewlaDpod1q1aGX4m0sP9GNcAWSVBHo1S0+r9YgWZIdcB/DHxTg==", + "license": "UNLICENSED", + "dependencies": { + "fp-ts": "^2.0.0", + "io-ts": "npm:@bitgo-forks/io-ts@2.1.4", + "io-ts-types": "^0.5.16", + "monocle-ts": "^2.3.13", + "newtype-ts": "^0.3.5" + } }, - "node_modules/@lit/reactive-element": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.6.3.tgz", - "integrity": "sha512-QuTgnG52Poic7uM1AN5yJ09QMe0O28e10XzSvWDz02TJiiKee4stsiownEIadWm8nYzyDAyT+gKzUoZmiWQtsQ==", + "node_modules/@bitgo/sdk-core/node_modules/@types/superagent": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.15.tgz", + "integrity": "sha512-mu/N4uvfDN2zVQQ5AYJI/g4qxn2bHB6521t1UuH09ShNWjebTqN0ZFuYK9uYjcgmI0dTQEs+Owi1EO6U0OkOZQ==", + "license": "MIT", "dependencies": { - "@lit-labs/ssr-dom-shim": "^1.0.0" + "@types/cookiejar": "*", + "@types/node": "*" } }, - "node_modules/@lukeed/csprng": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz", - "integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==", + "node_modules/@bitgo/sdk-core/node_modules/big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", + "license": "MIT", "engines": { - "node": ">=8" + "node": "*" } }, - "node_modules/@mdx-js/mdx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.0.1.tgz", - "integrity": "sha512-eIQ4QTrOWyL3LWEe/bu6Taqzq2HQvHcyTMaOrI95P2/LmJE7AsfPfgJGuFLPVqBUE1BC1rik3VIhU+s9u72arA==", + "node_modules/@bitgo/sdk-core/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "license": "MIT", "dependencies": { - "@types/estree": "^1.0.0", - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdx": "^2.0.0", - "collapse-white-space": "^2.0.0", - "devlop": "^1.0.0", - "estree-util-build-jsx": "^3.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "estree-util-to-js": "^2.0.0", - "estree-walker": "^3.0.0", - "hast-util-to-estree": "^3.0.0", - "hast-util-to-jsx-runtime": "^2.0.0", - "markdown-extensions": "^2.0.0", - "periscopic": "^3.0.0", - "remark-mdx": "^3.0.0", - "remark-parse": "^11.0.0", - "remark-rehype": "^11.0.0", - "source-map": "^0.7.0", - "unified": "^11.0.0", - "unist-util-position-from-estree": "^2.0.0", - "unist-util-stringify-position": "^4.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "ms": "^2.1.1" } }, - "node_modules/@mdx-js/react": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.1.tgz", - "integrity": "sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A==", + "node_modules/@bitgo/sdk-core/node_modules/keccak": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.3.tgz", + "integrity": "sha512-JZrLIAJWuZxKbCilMpNz5Vj7Vtb4scDG3dMXLOsbzBmQGyjwE61BbW7bJkfKKCShXiQZt3T6sBgALRtmd+nZaQ==", + "hasInstallScript": true, + "license": "MIT", "dependencies": { - "@types/mdx": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0", + "readable-stream": "^3.6.0" }, - "peerDependencies": { - "@types/react": ">=16", - "react": ">=16" + "engines": { + "node": ">=10.0.0" } }, - "node_modules/@metamask/eth-json-rpc-provider": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@metamask/eth-json-rpc-provider/-/eth-json-rpc-provider-1.0.1.tgz", - "integrity": "sha512-whiUMPlAOrVGmX8aKYVPvlKyG4CpQXiNNyt74vE1xb5sPvmx5oA7B/kOi/JdBvhGQq97U1/AVdXEdk2zkP8qyA==", + "node_modules/@bitgo/sdk-core/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@bitgo/sdk-hmac": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-hmac/-/sdk-hmac-1.1.0.tgz", + "integrity": "sha512-l6eq/ZQxahuWjESPQM/7JfoYJVeMFN8seKu9KTdzhajkVlHkoMSNAuulrFECtyySzGC5SHnoyubEceZANyZbXg==", + "license": "MIT", "dependencies": { - "@metamask/json-rpc-engine": "^7.0.0", - "@metamask/safe-event-emitter": "^3.0.0", - "@metamask/utils": "^5.0.1" - }, - "engines": { - "node": ">=14.0.0" + "@bitgo/sjcl": "^1.0.1" } }, - "node_modules/@metamask/eth-json-rpc-provider/node_modules/@metamask/json-rpc-engine": { - "version": "7.3.3", - "resolved": "https://registry.npmjs.org/@metamask/json-rpc-engine/-/json-rpc-engine-7.3.3.tgz", - "integrity": "sha512-dwZPq8wx9yV3IX2caLi9q9xZBw2XeIoYqdyihDDDpuHVCEiqadJLwqM3zy+uwf6F1QYQ65A8aOMQg1Uw7LMLNg==", + "node_modules/@bitgo/sdk-lib-mpc": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-lib-mpc/-/sdk-lib-mpc-10.1.0.tgz", + "integrity": "sha512-0OtkLE01YLMoCl2nQvXygXx5Y5v0d3/F4Pl7DSN5tafMhZEuwXjID48mzQT2ukEbCLrBjg1bZc74zNsb0EDVdA==", + "license": "MIT", "dependencies": { - "@metamask/rpc-errors": "^6.2.1", - "@metamask/safe-event-emitter": "^3.0.0", - "@metamask/utils": "^8.3.0" + "@noble/curves": "1.4.0", + "@silencelaboratories/dkls-wasm-ll-node": "1.1.2", + "@silencelaboratories/dkls-wasm-ll-web": "1.1.2", + "@types/superagent": "4.1.15", + "@wasmer/wasi": "^1.2.2", + "bigint-crypto-utils": "3.1.4", + "bigint-mod-arith": "3.1.2", + "cbor-x": "1.5.9", + "fp-ts": "2.16.2", + "io-ts": "npm:@bitgo-forks/io-ts@2.1.4", + "libsodium-wrappers-sumo": "^0.7.9", + "openpgp": "5.10.1", + "paillier-bigint": "3.3.0", + "secp256k1": "5.0.1" + }, + "peerDependencies": { + "@silencelaboratories/dkls-wasm-ll-bundler": "1.1.2" }, - "engines": { - "node": ">=16.0.0" + "peerDependenciesMeta": { + "@silencelaboratories/dkls-wasm-ll-bundler": { + "optional": true + } } }, - "node_modules/@metamask/eth-json-rpc-provider/node_modules/@metamask/json-rpc-engine/node_modules/@metamask/utils": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-8.5.0.tgz", - "integrity": "sha512-I6bkduevXb72TIM9q2LRO63JSsF9EXduh3sBr9oybNX2hNNpr/j1tEjXrsG0Uabm4MJ1xkGAQEMwifvKZIkyxQ==", + "node_modules/@bitgo/sdk-lib-mpc/node_modules/@noble/curves": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.0.tgz", + "integrity": "sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg==", + "license": "MIT", "dependencies": { - "@ethereumjs/tx": "^4.2.0", - "@metamask/superstruct": "^3.0.0", - "@noble/hashes": "^1.3.1", - "@scure/base": "^1.1.3", - "@types/debug": "^4.1.7", - "debug": "^4.3.4", - "pony-cause": "^2.1.10", - "semver": "^7.5.4", - "uuid": "^9.0.1" + "@noble/hashes": "1.4.0" }, - "engines": { - "node": ">=16.0.0" + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@metamask/eth-json-rpc-provider/node_modules/@metamask/utils": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-5.0.2.tgz", - "integrity": "sha512-yfmE79bRQtnMzarnKfX7AEJBwFTxvTyw3nBQlu/5rmGXrjAeAMltoGxO62TFurxrQAFMNa/fEjIHNvungZp0+g==", + "node_modules/@bitgo/sdk-lib-mpc/node_modules/@types/superagent": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.15.tgz", + "integrity": "sha512-mu/N4uvfDN2zVQQ5AYJI/g4qxn2bHB6521t1UuH09ShNWjebTqN0ZFuYK9uYjcgmI0dTQEs+Owi1EO6U0OkOZQ==", + "license": "MIT", "dependencies": { - "@ethereumjs/tx": "^4.1.2", - "@types/debug": "^4.1.7", - "debug": "^4.3.4", - "semver": "^7.3.8", - "superstruct": "^1.0.3" - }, - "engines": { - "node": ">=14.0.0" + "@types/cookiejar": "*", + "@types/node": "*" } }, - "node_modules/@metamask/eth-json-rpc-provider/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "node_modules/@bitgo/sdk-lib-mpc/node_modules/fp-ts": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-2.16.2.tgz", + "integrity": "sha512-CkqAjnIKFqvo3sCyoBTqgJvF+bHrSik584S9nhTjtBESLx26cbtVMR/T9a6ApChOcSDAaM3JydDmWDUn4EEXng==", + "license": "MIT" + }, + "node_modules/@bitgo/sjcl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@bitgo/sjcl/-/sjcl-1.0.1.tgz", + "integrity": "sha512-dBICMzShC8gXdpSj9cvl4wl9Jkt4h14wt4XQ+/6V6qcC2IObyKRJfaG5TYUU6RvVknhPBPyBx9v84vNKODM5fQ==", + "license": "(BSD-2-Clause OR GPL-2.0-only)" + }, + "node_modules/@bitgo/statics": { + "version": "50.20.0", + "resolved": "https://registry.npmjs.org/@bitgo/statics/-/statics-50.20.0.tgz", + "integrity": "sha512-smbJsJ7fFDMY2qdqikjKuMsuIKbUqRzlh04lIyMQFBs4KvQK/PpDzHnJqVdiTobvbjEf12aW8NgAO/FbP3ai/w==", + "license": "Apache-2.0" + }, + "node_modules/@bitgo/unspents": { + "version": "0.47.17", + "resolved": "https://registry.npmjs.org/@bitgo/unspents/-/unspents-0.47.17.tgz", + "integrity": "sha512-mWic5w/ATgfsg5AR+BPGNkSm8XPYha4z37GE4SeVAKzsKm2LiryAQBcP+Z+aIYUHXB9pK5++WtGY+AXNAUOU6A==", + "license": "Apache-2.0", + "dependencies": { + "@bitgo/utxo-lib": "^11.2.1", + "lodash": "~4.17.21", + "tcomb": "~3.2.29", + "varuint-bitcoin": "^1.0.4" } }, - "node_modules/@metamask/json-rpc-engine": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@metamask/json-rpc-engine/-/json-rpc-engine-8.0.2.tgz", - "integrity": "sha512-IoQPmql8q7ABLruW7i4EYVHWUbF74yrp63bRuXV5Zf9BQwcn5H9Ww1eLtROYvI1bUXwOiHZ6qT5CWTrDc/t/AA==", + "node_modules/@bitgo/utxo-lib": { + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/@bitgo/utxo-lib/-/utxo-lib-11.2.1.tgz", + "integrity": "sha512-ko9twLjxurdcJHEtWXa2fDv3qBQEmVVq8zfzXvktt46R5Dc/jXGVE6puxbDduFvwlYgHRGj92JCqLWNKQvMpiw==", + "license": "MIT", "dependencies": { - "@metamask/rpc-errors": "^6.2.1", - "@metamask/safe-event-emitter": "^3.0.0", - "@metamask/utils": "^8.3.0" + "@bitgo/blake2b": "^3.2.4", + "@brandonblack/musig": "^0.0.1-alpha.0", + "@noble/secp256k1": "1.6.3", + "bech32": "^2.0.0", + "bip174": "npm:@bitgo-forks/bip174@3.1.0-master.4", + "bip32": "^3.0.1", + "bitcoin-ops": "^1.3.0", + "bitcoinjs-lib": "npm:@bitgo-forks/bitcoinjs-lib@7.1.0-master.9", + "bn.js": "^5.2.1", + "bs58check": "^2.1.2", + "cashaddress": "^1.1.0", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "ecpair": "npm:@bitgo/ecpair@2.1.0-rc.0", + "elliptic": "^6.5.2", + "fastpriorityqueue": "^0.7.1", + "typeforce": "^1.11.3", + "varuint-bitcoin": "^1.1.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=10.22.0 <21", + "npm": ">=3.10.10" } }, - "node_modules/@metamask/json-rpc-middleware-stream": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@metamask/json-rpc-middleware-stream/-/json-rpc-middleware-stream-7.0.2.tgz", - "integrity": "sha512-yUdzsJK04Ev98Ck4D7lmRNQ8FPioXYhEUZOMS01LXW8qTvPGiRVXmVltj2p4wrLkh0vW7u6nv0mNl5xzC5Qmfg==", + "node_modules/@bitgo/utxo-ord": { + "version": "1.20.65", + "resolved": "https://registry.npmjs.org/@bitgo/utxo-ord/-/utxo-ord-1.20.65.tgz", + "integrity": "sha512-Ja82Ars/MJIzS18OG9gt46gqJfrgrewHa18bJCBA3Ha5zByawRlF2x6h2eyjMO6eOl4ChCIij40vjvOUiOJ7Mg==", + "license": "MIT", "dependencies": { - "@metamask/json-rpc-engine": "^8.0.2", - "@metamask/safe-event-emitter": "^3.0.0", - "@metamask/utils": "^8.3.0", - "readable-stream": "^3.6.2" + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/unspents": "^0.47.17", + "@bitgo/utxo-lib": "^11.2.1" + } + }, + "node_modules/@bitgo/wasm-miniscript": { + "version": "2.0.0-beta.2", + "resolved": "https://registry.npmjs.org/@bitgo/wasm-miniscript/-/wasm-miniscript-2.0.0-beta.2.tgz", + "integrity": "sha512-hh6R8NYTS6N1VdlgljkXAMRFNAsr2SGm1QcFjChHZ2bTotnNiCLlOlVR6EYhwtGr5eWLItye3iZG10m/li0xKA==" + }, + "node_modules/@brandonblack/musig": { + "version": "0.0.1-alpha.1", + "resolved": "https://registry.npmjs.org/@brandonblack/musig/-/musig-0.0.1-alpha.1.tgz", + "integrity": "sha512-00RbByQG85lSzrkDjCblzrUc2n1LJAPPrEMHS4oMg+QckE0kzjd26JytT6yx6tNU2+aOXfK7O4kGW/sKVL67cw==", + "license": "MIT" + }, + "node_modules/@bull-board/api": { + "version": "5.20.1", + "resolved": "https://registry.npmjs.org/@bull-board/api/-/api-5.20.1.tgz", + "integrity": "sha512-45aDhnOzWRrtUUAKHxdClSnLIus5f8BK3ATzb2IwI/BRgOi1lWTe1YG266hVqDdWXsUDxKzf75DAANKfAoEsRA==", + "dependencies": { + "redis-info": "^3.0.8" }, - "engines": { - "node": ">=16.0.0" + "peerDependencies": { + "@bull-board/ui": "5.20.1" } }, - "node_modules/@metamask/object-multiplex": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@metamask/object-multiplex/-/object-multiplex-2.1.0.tgz", - "integrity": "sha512-4vKIiv0DQxljcXwfpnbsXcfa5glMj5Zg9mqn4xpIWqkv6uJ2ma5/GtUfLFSxhlxnR8asRMv8dDmWya1Tc1sDFA==", + "node_modules/@bull-board/express": { + "version": "5.20.1", + "resolved": "https://registry.npmjs.org/@bull-board/express/-/express-5.20.1.tgz", + "integrity": "sha512-980wGA8kjMyw7MrYNN25l7lJNlLz22ln3jW/H3ef98BXhTeBnPR16XhXu1Z6471X5Aor9WXZ6FRQ5pJhP4iXuA==", "dependencies": { - "once": "^1.4.0", - "readable-stream": "^3.6.2" + "@bull-board/api": "5.20.1", + "@bull-board/ui": "5.20.1", + "ejs": "^3.1.10", + "express": "^4.19.2" + } + }, + "node_modules/@bull-board/nestjs": { + "version": "5.20.1", + "resolved": "https://registry.npmjs.org/@bull-board/nestjs/-/nestjs-5.20.1.tgz", + "integrity": "sha512-6WREzrJdrAuJ3LcZVETzfEpQxUSF2xxC7plPiSj11jyO30i/moKkc7gUVuP2h6YgQnhhH3ppFxECVduXWRBDLQ==", + "dependencies": { + "@nestjs/bull-shared": "^10.0.0" }, + "peerDependencies": { + "@bull-board/api": "^5.20.1", + "@bull-board/express": "^5.20.1", + "@nestjs/common": "^9.0.0 || ^10.0.0", + "@nestjs/core": "^9.0.0 || ^10.0.0", + "reflect-metadata": "^0.1.13 || ^0.2.0", + "rxjs": "^7.8.1" + } + }, + "node_modules/@bull-board/ui": { + "version": "5.20.1", + "resolved": "https://registry.npmjs.org/@bull-board/ui/-/ui-5.20.1.tgz", + "integrity": "sha512-RzNinC4FKHNuxzkIRsCL+n9iO5RxmF5YM7byCuuv1/UeFjtCtsLHFi6TI9ZgJsXETA2Uxq9Mg7ppncojUjrINw==", + "dependencies": { + "@bull-board/api": "5.20.1" + } + }, + "node_modules/@bundled-es-modules/cookie": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/cookie/-/cookie-2.0.1.tgz", + "integrity": "sha512-8o+5fRPLNbjbdGRRmJj3h6Hh1AQJf2dk3qQ/5ZFb+PXkRNiSoMGGUKlsgLfrxneb72axVJyIYji64E2+nNfYyw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cookie": "^0.7.2" + } + }, + "node_modules/@bundled-es-modules/cookie/node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "dev": true, + "license": "MIT", "engines": { - "node": "^16.20 || ^18.16 || >=20" + "node": ">= 0.6" } }, - "node_modules/@metamask/onboarding": { + "node_modules/@bundled-es-modules/statuses": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@metamask/onboarding/-/onboarding-1.0.1.tgz", - "integrity": "sha512-FqHhAsCI+Vacx2qa5mAFcWNSrTcVGMNjzxVgaX8ECSny/BJ9/vgXP9V7WF/8vb9DltPeQkxr+Fnfmm6GHfmdTQ==", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/statuses/-/statuses-1.0.1.tgz", + "integrity": "sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==", + "dev": true, + "license": "ISC", "dependencies": { - "bowser": "^2.9.0" + "statuses": "^2.0.1" } }, - "node_modules/@metamask/providers": { - "version": "16.1.0", - "resolved": "https://registry.npmjs.org/@metamask/providers/-/providers-16.1.0.tgz", - "integrity": "sha512-znVCvux30+3SaUwcUGaSf+pUckzT5ukPRpcBmy+muBLC0yaWnBcvDqGfcsw6CBIenUdFrVoAFa8B6jsuCY/a+g==", + "node_modules/@bundled-es-modules/tough-cookie": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/tough-cookie/-/tough-cookie-0.1.6.tgz", + "integrity": "sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw==", + "dev": true, + "license": "ISC", "dependencies": { - "@metamask/json-rpc-engine": "^8.0.1", - "@metamask/json-rpc-middleware-stream": "^7.0.1", - "@metamask/object-multiplex": "^2.0.0", - "@metamask/rpc-errors": "^6.2.1", - "@metamask/safe-event-emitter": "^3.1.1", - "@metamask/utils": "^8.3.0", - "detect-browser": "^5.2.0", - "extension-port-stream": "^3.0.0", - "fast-deep-equal": "^3.1.3", - "is-stream": "^2.0.0", - "readable-stream": "^3.6.2", - "webextension-polyfill": "^0.10.0" - }, - "engines": { - "node": "^18.18 || >=20" + "@types/tough-cookie": "^4.0.5", + "tough-cookie": "^4.1.4" } }, - "node_modules/@metamask/rpc-errors": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/@metamask/rpc-errors/-/rpc-errors-6.4.0.tgz", - "integrity": "sha512-1ugFO1UoirU2esS3juZanS/Fo8C8XYocCuBpfZI5N7ECtoG+zu0wF+uWZASik6CkO6w9n/Iebt4iI4pT0vptpg==", + "node_modules/@cbor-extract/cbor-extract-darwin-arm64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-darwin-arm64/-/cbor-extract-darwin-arm64-2.2.0.tgz", + "integrity": "sha512-P7swiOAdF7aSi0H+tHtHtr6zrpF3aAq/W9FXx5HektRvLTM2O89xCyXF3pk7pLc7QpaY7AoaE8UowVf9QBdh3w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@cbor-extract/cbor-extract-darwin-x64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-darwin-x64/-/cbor-extract-darwin-x64-2.2.0.tgz", + "integrity": "sha512-1liF6fgowph0JxBbYnAS7ZlqNYLf000Qnj4KjqPNW4GViKrEql2MgZnAsExhY9LSy8dnvA4C0qHEBgPrll0z0w==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@cbor-extract/cbor-extract-linux-arm": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-linux-arm/-/cbor-extract-linux-arm-2.2.0.tgz", + "integrity": "sha512-QeBcBXk964zOytiedMPQNZr7sg0TNavZeuUCD6ON4vEOU/25+pLhNN6EDIKJ9VLTKaZ7K7EaAriyYQ1NQ05s/Q==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@cbor-extract/cbor-extract-linux-arm64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-linux-arm64/-/cbor-extract-linux-arm64-2.2.0.tgz", + "integrity": "sha512-rQvhNmDuhjTVXSPFLolmQ47/ydGOFXtbR7+wgkSY0bdOxCFept1hvg59uiLPT2fVDuJFuEy16EImo5tE2x3RsQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@cbor-extract/cbor-extract-linux-x64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-linux-x64/-/cbor-extract-linux-x64-2.2.0.tgz", + "integrity": "sha512-cWLAWtT3kNLHSvP4RKDzSTX9o0wvQEEAj4SKvhWuOVZxiDAeQazr9A+PSiRILK1VYMLeDml89ohxCnUNQNQNCw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@cbor-extract/cbor-extract-win32-x64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-win32-x64/-/cbor-extract-win32-x64-2.2.0.tgz", + "integrity": "sha512-l2M+Z8DO2vbvADOBNLbbh9y5ST1RY5sqkWOg/58GkUPBYou/cuNZ68SGQ644f1CvZ8kcOxyZtw06+dxWHIoN/w==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@celo/base": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@celo/base/-/base-2.3.0.tgz", + "integrity": "sha512-Jo81eVGCPcKpUw9G4/uFE2x2TeYpS6BhEpmzmrkL86AU+EC93ES9UUlCcCpFSVRfoiHldIGp2QzyU+kAYap//Q==", + "license": "Apache-2.0" + }, + "node_modules/@celo/connect": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@celo/connect/-/connect-2.3.0.tgz", + "integrity": "sha512-p4oPU7ZafhaBXlX189I2jDTC9t5O9ayUywTsJMkSbsfz/q3RalTl+/YWM1m8twF2VdilAjOR1GiObbVVkYQLNQ==", + "deprecated": "Versions less than 5.1 are deprecated and will no longer be able to submit transactions to celo in a future hardfork", + "license": "Apache-2.0", "dependencies": { - "@metamask/utils": "^9.0.0", - "fast-safe-stringify": "^2.0.6" + "@celo/base": "2.3.0", + "@celo/utils": "2.3.0", + "@types/debug": "^4.1.5", + "@types/utf8": "^2.1.6", + "bignumber.js": "^9.0.0", + "debug": "^4.1.1", + "utf8": "3.0.0" }, "engines": { - "node": ">=16.0.0" + "node": ">=8.13.0" + }, + "peerDependencies": { + "web3": "1.3.6" } }, - "node_modules/@metamask/rpc-errors/node_modules/@metamask/utils": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-9.3.0.tgz", - "integrity": "sha512-w8CVbdkDrVXFJbfBSlDfafDR6BAkpDmv1bC1UJVCoVny5tW2RKAdn9i68Xf7asYT4TnUhl/hN4zfUiKQq9II4g==", + "node_modules/@celo/contractkit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@celo/contractkit/-/contractkit-2.3.0.tgz", + "integrity": "sha512-mctnQBp7GZAsuV4I47kTK3fBtjoL4uqd0LZ8wUmck+COJT9yW3DuQjPQwQvBxN6InKET9IeUmTuoTW4oAbW/FQ==", + "deprecated": "Versions less than 5.1 are deprecated and will no longer be able to submit transactions to celo in a future hardfork", + "license": "Apache-2.0", "dependencies": { - "@ethereumjs/tx": "^4.2.0", - "@metamask/superstruct": "^3.1.0", - "@noble/hashes": "^1.3.1", - "@scure/base": "^1.1.3", - "@types/debug": "^4.1.7", - "debug": "^4.3.4", - "pony-cause": "^2.1.10", - "semver": "^7.5.4", - "uuid": "^9.0.1" + "@celo/base": "2.3.0", + "@celo/connect": "2.3.0", + "@celo/utils": "2.3.0", + "@celo/wallet-local": "2.3.0", + "@types/bn.js": "^5.1.0", + "@types/debug": "^4.1.5", + "bignumber.js": "^9.0.0", + "cross-fetch": "^3.0.6", + "debug": "^4.1.1", + "fp-ts": "2.1.1", + "io-ts": "2.0.1", + "semver": "^7.3.5", + "web3": "1.3.6" }, "engines": { - "node": ">=16.0.0" + "node": ">=8.13.0" } }, - "node_modules/@metamask/rpc-errors/node_modules/semver": { + "node_modules/@celo/contractkit/node_modules/cross-fetch": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", + "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", + "license": "MIT", + "dependencies": { + "node-fetch": "^2.7.0" + } + }, + "node_modules/@celo/contractkit/node_modules/fp-ts": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-2.1.1.tgz", + "integrity": "sha512-YcWhMdDCFCja0MmaDroTgNu+NWWrrnUEn92nvDgrtVy9Z71YFnhNVIghoHPt8gs82ijoMzFGeWKvArbyICiJgw==", + "license": "MIT" + }, + "node_modules/@celo/contractkit/node_modules/io-ts": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/io-ts/-/io-ts-2.0.1.tgz", + "integrity": "sha512-RezD+WcCfW4VkMkEcQWL/Nmy/nqsWTvTYg7oUmTGzglvSSV2P9h2z1PVeREPFf0GWNzruYleAt1XCMQZSg1xxQ==", + "license": "MIT", + "peerDependencies": { + "fp-ts": "^2.0.0" + } + }, + "node_modules/@celo/contractkit/node_modules/semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -5823,1401 +7079,11709 @@ "node": ">=10" } }, - "node_modules/@metamask/safe-event-emitter": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@metamask/safe-event-emitter/-/safe-event-emitter-3.1.2.tgz", - "integrity": "sha512-5yb2gMI1BDm0JybZezeoX/3XhPDOtTbcFvpTXM9kxsoZjPZFh4XciqRbpD6N86HYZqWDhEaKUDuOyR0sQHEjMA==", - "engines": { - "node": ">=12.0.0" + "node_modules/@celo/utils": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@celo/utils/-/utils-2.3.0.tgz", + "integrity": "sha512-K4Ga1rpYyFTTyhopHUHdeNehJN4qYT+cdf2BPgc6wS4AsI/G8vq91tmXOBJNL1oPVIbnW7MOp51IKJP51/zdhA==", + "license": "Apache-2.0", + "dependencies": { + "@celo/base": "2.3.0", + "@types/bn.js": "^5.1.0", + "@types/elliptic": "^6.4.9", + "@types/ethereumjs-util": "^5.2.0", + "@types/node": "^10.12.18", + "bignumber.js": "^9.0.0", + "elliptic": "^6.5.4", + "ethereumjs-util": "^5.2.0", + "io-ts": "2.0.1", + "web3-eth-abi": "1.3.6", + "web3-utils": "1.3.6" } }, - "node_modules/@metamask/sdk": { - "version": "0.30.1", - "resolved": "https://registry.npmjs.org/@metamask/sdk/-/sdk-0.30.1.tgz", - "integrity": "sha512-NelEjJZsF5wVpSQELpmvXtnS9+C6HdxGQ4GB9jMRzeejphmPyKqmrIGM6XtaPrJtlpX+40AcJ2dtBQcjJVzpbQ==", + "node_modules/@celo/utils/node_modules/@types/node": { + "version": "10.17.60", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", + "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==", + "license": "MIT" + }, + "node_modules/@celo/utils/node_modules/bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "license": "MIT" + }, + "node_modules/@celo/utils/node_modules/ethereum-cryptography": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", + "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "license": "MIT", "dependencies": { - "@metamask/onboarding": "^1.0.1", - "@metamask/providers": "16.1.0", - "@metamask/sdk-communication-layer": "0.30.0", - "@metamask/sdk-install-modal-web": "0.30.0", - "bowser": "^2.9.0", - "cross-fetch": "^4.0.0", - "debug": "^4.3.4", - "eciesjs": "^0.4.8", - "eth-rpc-errors": "^4.0.3", - "eventemitter2": "^6.4.7", - "i18next": "23.11.5", - "i18next-browser-languagedetector": "7.1.0", - "obj-multiplex": "^1.0.0", - "pump": "^3.0.0", - "qrcode-terminal-nooctal": "^0.12.1", - "react-native-webview": "^11.26.0", - "readable-stream": "^3.6.2", - "socket.io-client": "^4.5.1", - "util": "^0.12.4", - "uuid": "^8.3.2" - }, + "@types/pbkdf2": "^3.0.0", + "@types/secp256k1": "^4.0.1", + "blakejs": "^1.1.0", + "browserify-aes": "^1.2.0", + "bs58check": "^2.1.2", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "hash.js": "^1.1.7", + "keccak": "^3.0.0", + "pbkdf2": "^3.0.17", + "randombytes": "^2.1.0", + "safe-buffer": "^5.1.2", + "scrypt-js": "^3.0.0", + "secp256k1": "^4.0.1", + "setimmediate": "^1.0.5" + } + }, + "node_modules/@celo/utils/node_modules/ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "license": "MPL-2.0", + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/@celo/utils/node_modules/io-ts": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/io-ts/-/io-ts-2.0.1.tgz", + "integrity": "sha512-RezD+WcCfW4VkMkEcQWL/Nmy/nqsWTvTYg7oUmTGzglvSSV2P9h2z1PVeREPFf0GWNzruYleAt1XCMQZSg1xxQ==", + "license": "MIT", "peerDependencies": { - "react": "^18.2.0", - "react-dom": "^18.2.0" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } + "fp-ts": "^2.0.0" } }, - "node_modules/@metamask/sdk-communication-layer": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/@metamask/sdk-communication-layer/-/sdk-communication-layer-0.30.0.tgz", - "integrity": "sha512-q5nbdYkAf76MsZxi1l5MJEAyd8sY9jLRapC8a7x1Q1BNV4rzQeFeux/d0mJ/jTR2LAwbnLZs2rL226AM75oK4w==", + "node_modules/@celo/utils/node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", + "license": "MIT" + }, + "node_modules/@celo/utils/node_modules/secp256k1": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.4.tgz", + "integrity": "sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==", + "hasInstallScript": true, + "license": "MIT", "dependencies": { - "bufferutil": "^4.0.8", - "date-fns": "^2.29.3", - "debug": "^4.3.4", - "utf-8-validate": "^5.0.2", - "uuid": "^8.3.2" + "elliptic": "^6.5.7", + "node-addon-api": "^5.0.0", + "node-gyp-build": "^4.2.0" }, - "peerDependencies": { - "cross-fetch": "^4.0.0", - "eciesjs": "^0.3.16", - "eventemitter2": "^6.4.7", - "readable-stream": "^3.6.2", - "socket.io-client": "^4.5.1" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@metamask/sdk-communication-layer/node_modules/date-fns": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", - "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "node_modules/@celo/wallet-base": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@celo/wallet-base/-/wallet-base-2.3.0.tgz", + "integrity": "sha512-C5+t5Sx39Riul1EATPMq0bqWyHCAqoIRW4fU/5FrML+OYvpH+3SAIjJuxoD4vdj3gZZBWockg32PFp0TNb6e4g==", + "deprecated": "Versions less than 5.1 are deprecated and will no longer be able to submit transactions to celo in a future hardfork", + "license": "Apache-2.0", "dependencies": { - "@babel/runtime": "^7.21.0" + "@celo/base": "2.3.0", + "@celo/connect": "2.3.0", + "@celo/utils": "2.3.0", + "@types/debug": "^4.1.5", + "@types/ethereumjs-util": "^5.2.0", + "bignumber.js": "^9.0.0", + "debug": "^4.1.1", + "eth-lib": "^0.2.8", + "ethereumjs-util": "^5.2.0" }, "engines": { - "node": ">=0.11" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/date-fns" + "node": ">=8.13.0" } }, - "node_modules/@metamask/sdk-communication-layer/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" - } + "node_modules/@celo/wallet-base/node_modules/bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "license": "MIT" }, - "node_modules/@metamask/sdk-install-modal-web": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/@metamask/sdk-install-modal-web/-/sdk-install-modal-web-0.30.0.tgz", - "integrity": "sha512-1gT533Huja9tK3cmttvcpZirRAtWJ7vnYH+lnNRKEj2xIP335Df2cOwS+zqNC4GlRCZw7A3IsTjIzlKoxBY1uQ==", + "node_modules/@celo/wallet-base/node_modules/ethereum-cryptography": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", + "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "license": "MIT", "dependencies": { - "qr-code-styling": "^1.6.0-rc.1" - }, - "peerDependencies": { - "i18next": "23.11.5", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-native": "*" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-dom": { - "optional": true - }, - "react-native": { - "optional": true - } + "@types/pbkdf2": "^3.0.0", + "@types/secp256k1": "^4.0.1", + "blakejs": "^1.1.0", + "browserify-aes": "^1.2.0", + "bs58check": "^2.1.2", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "hash.js": "^1.1.7", + "keccak": "^3.0.0", + "pbkdf2": "^3.0.17", + "randombytes": "^2.1.0", + "safe-buffer": "^5.1.2", + "scrypt-js": "^3.0.0", + "secp256k1": "^4.0.1", + "setimmediate": "^1.0.5" + } + }, + "node_modules/@celo/wallet-base/node_modules/ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "license": "MPL-2.0", + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" } }, - "node_modules/@metamask/sdk/node_modules/@noble/hashes": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.5.0.tgz", - "integrity": "sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==", - "engines": { - "node": "^14.21.3 || >=16" + "node_modules/@celo/wallet-base/node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", + "license": "MIT" + }, + "node_modules/@celo/wallet-base/node_modules/secp256k1": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.4.tgz", + "integrity": "sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "elliptic": "^6.5.7", + "node-addon-api": "^5.0.0", + "node-gyp-build": "^4.2.0" }, - "funding": { - "url": "https://paulmillr.com/funding/" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@metamask/sdk/node_modules/eciesjs": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/eciesjs/-/eciesjs-0.4.11.tgz", - "integrity": "sha512-SmUG449n1w1YGvJD9R30tBGvpxTxA0cnn0rfvpFIBvmezfIhagLjsH2JG8HBHOLS8slXsPh48II7IDUTH/J3Mg==", + "node_modules/@celo/wallet-local": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@celo/wallet-local/-/wallet-local-2.3.0.tgz", + "integrity": "sha512-B2rg6DmKnHP98ixkIRH7I4aNFZVcj4e7wmB9z2LB08wAiuBFS4qsGp4ciplLb+AQuwbUSe8SpRSuKYxKUTQmFA==", + "license": "Apache-2.0", "dependencies": { - "@ecies/ciphers": "^0.2.1", - "@noble/ciphers": "^1.0.0", - "@noble/curves": "^1.6.0", - "@noble/hashes": "^1.5.0" + "@celo/connect": "2.3.0", + "@celo/utils": "2.3.0", + "@celo/wallet-base": "2.3.0", + "@types/ethereumjs-util": "^5.2.0", + "eth-lib": "^0.2.8", + "ethereumjs-util": "^5.2.0" }, "engines": { - "bun": ">=1", - "deno": ">=2", - "node": ">=16" + "node": ">=8.13.0" } }, - "node_modules/@metamask/sdk/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" - } + "node_modules/@celo/wallet-local/node_modules/bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "license": "MIT" }, - "node_modules/@metamask/superstruct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@metamask/superstruct/-/superstruct-3.1.0.tgz", - "integrity": "sha512-N08M56HdOgBfRKkrgCMZvQppkZGcArEop3kixNEtVbJKm6P9Cfg0YkI6X0s1g78sNrj2fWUwvJADdZuzJgFttA==", - "engines": { - "node": ">=16.0.0" + "node_modules/@celo/wallet-local/node_modules/ethereum-cryptography": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", + "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "license": "MIT", + "dependencies": { + "@types/pbkdf2": "^3.0.0", + "@types/secp256k1": "^4.0.1", + "blakejs": "^1.1.0", + "browserify-aes": "^1.2.0", + "bs58check": "^2.1.2", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "hash.js": "^1.1.7", + "keccak": "^3.0.0", + "pbkdf2": "^3.0.17", + "randombytes": "^2.1.0", + "safe-buffer": "^5.1.2", + "scrypt-js": "^3.0.0", + "secp256k1": "^4.0.1", + "setimmediate": "^1.0.5" + } + }, + "node_modules/@celo/wallet-local/node_modules/ethereumjs-util": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", + "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", + "license": "MPL-2.0", + "dependencies": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "^0.1.3", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1" } }, - "node_modules/@metamask/utils": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-8.5.0.tgz", - "integrity": "sha512-I6bkduevXb72TIM9q2LRO63JSsF9EXduh3sBr9oybNX2hNNpr/j1tEjXrsG0Uabm4MJ1xkGAQEMwifvKZIkyxQ==", + "node_modules/@celo/wallet-local/node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", + "license": "MIT" + }, + "node_modules/@celo/wallet-local/node_modules/secp256k1": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.4.tgz", + "integrity": "sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==", + "hasInstallScript": true, + "license": "MIT", "dependencies": { - "@ethereumjs/tx": "^4.2.0", - "@metamask/superstruct": "^3.0.0", - "@noble/hashes": "^1.3.1", - "@scure/base": "^1.1.3", - "@types/debug": "^4.1.7", - "debug": "^4.3.4", - "pony-cause": "^2.1.10", - "semver": "^7.5.4", - "uuid": "^9.0.1" + "elliptic": "^6.5.7", + "node-addon-api": "^5.0.0", + "node-gyp-build": "^4.2.0" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, - "node_modules/@metamask/utils/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "bin": { - "semver": "bin/semver.js" - }, + "node_modules/@coinbase/wallet-sdk": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@coinbase/wallet-sdk/-/wallet-sdk-4.2.3.tgz", + "integrity": "sha512-BcyHZ/Ec84z0emORzqdXDv4P0oV+tV3a0OirfA8Ko1JGBIAVvB+hzLvZzCDvnuZx7MTK+Dd8Y9Tjlo446BpCIg==", + "dependencies": { + "@noble/hashes": "^1.4.0", + "clsx": "^1.2.1", + "eventemitter3": "^5.0.1", + "preact": "^10.24.2" + } + }, + "node_modules/@coinbase/wallet-sdk/node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", "engines": { - "node": ">=10" + "node": ">=6" } }, - "node_modules/@microsoft/tsdoc": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.15.0.tgz", - "integrity": "sha512-HZpPoABogPvjeJOdzCOSJsXeL/SMCBgBZMVC3X3d7YYp2gf31MfxhUoYUNwf1ERPJOnQc0wkFn9trqI6ZEdZuA==" + "node_modules/@coinbase/wallet-sdk/node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" }, - "node_modules/@module-federation/bridge-react-webpack-plugin": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@module-federation/bridge-react-webpack-plugin/-/bridge-react-webpack-plugin-0.2.8.tgz", - "integrity": "sha512-6G1qTo1HWvRcN5fzE+SZgvgzSPoq5YqNx8hFL8BttJmnd3wj4SUOFiikAsXhdVrzSK+Zuzg6pipkiLH1m+pbtw==", - "dev": true, - "dependencies": { - "@module-federation/sdk": "0.2.8" + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "optional": true, + "engines": { + "node": ">=0.1.90" } }, - "node_modules/@module-federation/dts-plugin": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@module-federation/dts-plugin/-/dts-plugin-0.2.8.tgz", - "integrity": "sha512-qY1Wbqo0yu9nh6KR8K19t5T4tYtlUbmcNdcaCweISCyAbH99TrhpQkJ89NY0TLtnxQ6uayIYayqAWS7vzyDXVw==", - "dev": true, + "node_modules/@confio/ics23": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@confio/ics23/-/ics23-0.6.8.tgz", + "integrity": "sha512-wB6uo+3A50m0sW/EWcU64xpV/8wShZ6bMTa7pF8eYsTrSkQA7oLUIJcs/wb8g4y2Oyq701BaGiO6n/ak5WXO1w==", + "deprecated": "Unmaintained. The codebase for this package was moved to https://github.com/cosmos/ics23 but then the JS implementation was removed in https://github.com/cosmos/ics23/pull/353. Please consult the maintainers of https://github.com/cosmos for further assistance.", + "license": "Apache-2.0", "dependencies": { - "@module-federation/managers": "0.2.8", - "@module-federation/sdk": "0.2.8", - "@module-federation/third-party-dts-extractor": "0.2.8", - "adm-zip": "^0.5.10", - "ansi-colors": "^4.1.3", - "axios": "^1.6.7", - "chalk": "3.0.0", - "fs-extra": "9.1.0", - "isomorphic-ws": "5.0.0", - "koa": "2.11.0", - "lodash.clonedeepwith": "4.5.0", - "log4js": "6.9.1", - "node-schedule": "2.1.1", - "rambda": "^9.1.0", - "ws": "8.17.1" - }, - "peerDependencies": { - "typescript": "^4.9.0 || ^5.0.0", - "vue-tsc": ">=1.0.24" - }, - "peerDependenciesMeta": { - "vue-tsc": { - "optional": true - } + "@noble/hashes": "^1.0.0", + "protobufjs": "^6.8.8" } }, - "node_modules/@module-federation/dts-plugin/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, + "node_modules/@confio/ics23/node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", + "license": "Apache-2.0" + }, + "node_modules/@confio/ics23/node_modules/protobufjs": { + "version": "6.11.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.4.tgz", + "integrity": "sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw==", + "hasInstallScript": true, + "license": "BSD-3-Clause", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "@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/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" }, - "engines": { - "node": ">=8" + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" } }, - "node_modules/@module-federation/dts-plugin/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, + "node_modules/@cosmjs/amino": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/amino/-/amino-0.29.5.tgz", + "integrity": "sha512-Qo8jpC0BiziTSUqpkNatBcwtKNhCovUnFul9SlT/74JUCdLYaeG5hxr3q1cssQt++l4LvlcpF+OUXL48XjNjLw==", + "license": "Apache-2.0", "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" + "@cosmjs/crypto": "^0.29.5", + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/math": "^0.29.5", + "@cosmjs/utils": "^0.29.5" } }, - "node_modules/@module-federation/dts-plugin/node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "node_modules/@cosmjs/amino/node_modules/@cosmjs/crypto": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.29.5.tgz", + "integrity": "sha512-2bKkaLGictaNL0UipQCL6C1afaisv6k8Wr/GCLx9FqiyFkh9ZgRHDyetD64ZsjnWV/N/D44s/esI+k6oPREaiQ==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/math": "^0.29.5", + "@cosmjs/utils": "^0.29.5", + "@noble/hashes": "^1", + "bn.js": "^5.2.0", + "elliptic": "^6.5.4", + "libsodium-wrappers": "^0.7.6" } }, - "node_modules/@module-federation/enhanced": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@module-federation/enhanced/-/enhanced-0.2.8.tgz", - "integrity": "sha512-6fGM/GiKw6LZiBe6DF8Petz6ih/Yyf3q2htLrx+hrWoDWfWEoWlLvoCUsVkY2UgMCLKid7Fm3Auc4w8A4aRjvQ==", - "dev": true, + "node_modules/@cosmjs/crypto": { + "version": "0.30.1", + "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.30.1.tgz", + "integrity": "sha512-rAljUlake3MSXs9xAm87mu34GfBLN0h/1uPPV6jEwClWjNkAMotzjC0ab9MARy5FFAvYHL3lWb57bhkbt2GtzQ==", + "license": "Apache-2.0", "dependencies": { - "@module-federation/bridge-react-webpack-plugin": "0.2.8", - "@module-federation/dts-plugin": "0.2.8", - "@module-federation/managers": "0.2.8", - "@module-federation/manifest": "0.2.8", - "@module-federation/rspack": "0.2.8", - "@module-federation/runtime-tools": "0.2.8", - "@module-federation/sdk": "0.2.8", - "btoa": "^1.2.1", - "upath": "2.0.1" - }, - "peerDependencies": { - "typescript": "^4.9.0 || ^5.0.0", - "vue-tsc": ">=1.0.24", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - }, - "vue-tsc": { - "optional": true - }, - "webpack": { - "optional": true - } + "@cosmjs/encoding": "^0.30.1", + "@cosmjs/math": "^0.30.1", + "@cosmjs/utils": "^0.30.1", + "@noble/hashes": "^1", + "bn.js": "^5.2.0", + "elliptic": "^6.5.4", + "libsodium-wrappers": "^0.7.6" } }, - "node_modules/@module-federation/managers": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@module-federation/managers/-/managers-0.2.8.tgz", - "integrity": "sha512-S5GXqt2Vrs1+uNXHw7UzZ7m3fs8H3nxNsNGQ0j5+HiT5yA7uRTY1AZJZCGAHzG6XImJ1DzL/SW1acM2Hwj0aAw==", - "dev": true, + "node_modules/@cosmjs/crypto/node_modules/@cosmjs/encoding": { + "version": "0.30.1", + "resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.30.1.tgz", + "integrity": "sha512-rXmrTbgqwihORwJ3xYhIgQFfMSrwLu1s43RIK9I8EBudPx3KmnmyAKzMOVsRDo9edLFNuZ9GIvysUCwQfq3WlQ==", + "license": "Apache-2.0", "dependencies": { - "@module-federation/sdk": "0.2.8", - "find-pkg": "2.0.0", - "fs-extra": "9.1.0" + "base64-js": "^1.3.0", + "bech32": "^1.1.4", + "readonly-date": "^1.0.0" } }, - "node_modules/@module-federation/managers/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, + "node_modules/@cosmjs/crypto/node_modules/@cosmjs/math": { + "version": "0.30.1", + "resolved": "https://registry.npmjs.org/@cosmjs/math/-/math-0.30.1.tgz", + "integrity": "sha512-yaoeI23pin9ZiPHIisa6qqLngfnBR/25tSaWpkTm8Cy10MX70UF5oN4+/t1heLaM6SSmRrhk3psRkV4+7mH51Q==", + "license": "Apache-2.0", "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" + "bn.js": "^5.2.0" } }, - "node_modules/@module-federation/manifest": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@module-federation/manifest/-/manifest-0.2.8.tgz", - "integrity": "sha512-kw4PeAldkOuGCWfCnDzZwPHUx5qv9+WztY5+TEbsgXc5E+/e2NDA6Gg3eT8zUGeexeGdab3f+DuN9ZClZJYVGA==", - "dev": true, + "node_modules/@cosmjs/crypto/node_modules/@cosmjs/utils": { + "version": "0.30.1", + "resolved": "https://registry.npmjs.org/@cosmjs/utils/-/utils-0.30.1.tgz", + "integrity": "sha512-KvvX58MGMWh7xA+N+deCfunkA/ZNDvFLw4YbOmX3f/XBIkqrVY7qlotfy2aNb1kgp6h4B6Yc8YawJPDTfvWX7g==", + "license": "Apache-2.0" + }, + "node_modules/@cosmjs/crypto/node_modules/bech32": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", + "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", + "license": "MIT" + }, + "node_modules/@cosmjs/encoding": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.29.5.tgz", + "integrity": "sha512-G4rGl/Jg4dMCw5u6PEZHZcoHnUBlukZODHbm/wcL4Uu91fkn5jVo5cXXZcvs4VCkArVGrEj/52eUgTZCmOBGWQ==", + "license": "Apache-2.0", "dependencies": { - "@module-federation/dts-plugin": "0.2.8", - "@module-federation/managers": "0.2.8", - "@module-federation/sdk": "0.2.8", - "chalk": "3.0.0", - "find-pkg": "2.0.0" + "base64-js": "^1.3.0", + "bech32": "^1.1.4", + "readonly-date": "^1.0.0" } }, - "node_modules/@module-federation/manifest/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, + "node_modules/@cosmjs/encoding/node_modules/bech32": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", + "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", + "license": "MIT" + }, + "node_modules/@cosmjs/json-rpc": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/json-rpc/-/json-rpc-0.29.5.tgz", + "integrity": "sha512-C78+X06l+r9xwdM1yFWIpGl03LhB9NdM1xvZpQHwgCOl0Ir/WV8pw48y3Ez2awAoUBRfTeejPe4KvrE6NoIi/w==", + "license": "Apache-2.0", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" + "@cosmjs/stream": "^0.29.5", + "xstream": "^11.14.0" } }, - "node_modules/@module-federation/rspack": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@module-federation/rspack/-/rspack-0.2.8.tgz", - "integrity": "sha512-5Bofm3cY7OOwO2DT5TevITd+HAA03zsY1wwsMb1BP6NkS/ukUtsjuRo2Anua0RkHBEIx+Dv5rpqOn7qSlOm1Fg==", - "dev": true, + "node_modules/@cosmjs/math": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/math/-/math-0.29.5.tgz", + "integrity": "sha512-2GjKcv+A9f86MAWYLUkjhw1/WpRl2R1BTb3m9qPG7lzMA7ioYff9jY5SPCfafKdxM4TIQGxXQlYGewQL16O68Q==", + "license": "Apache-2.0", "dependencies": { - "@module-federation/bridge-react-webpack-plugin": "0.2.8", - "@module-federation/dts-plugin": "0.2.8", - "@module-federation/managers": "0.2.8", - "@module-federation/manifest": "0.2.8", - "@module-federation/runtime-tools": "0.2.8", - "@module-federation/sdk": "0.2.8" - }, - "peerDependencies": { - "typescript": "^4.9.0 || ^5.0.0", - "vue-tsc": ">=1.0.24" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - }, - "vue-tsc": { - "optional": true - } + "bn.js": "^5.2.0" } }, - "node_modules/@module-federation/runtime": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@module-federation/runtime/-/runtime-0.2.8.tgz", - "integrity": "sha512-8xmA/+z1zD09F5qU8VnSWLExqTCVWoHOguXsCX79kkqp7i0c+D2YaebWzlQ2kku+DU+0VIzXpQ3BBcumZ3v3wQ==", - "dev": true, + "node_modules/@cosmjs/proto-signing": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/proto-signing/-/proto-signing-0.29.5.tgz", + "integrity": "sha512-QRrS7CiKaoETdgIqvi/7JC2qCwCR7lnWaUsTzh/XfRy3McLkEd+cXbKAW3cygykv7IN0VAEIhZd2lyIfT8KwNA==", + "license": "Apache-2.0", "dependencies": { - "@module-federation/sdk": "0.2.8" + "@cosmjs/amino": "^0.29.5", + "@cosmjs/crypto": "^0.29.5", + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/math": "^0.29.5", + "@cosmjs/utils": "^0.29.5", + "cosmjs-types": "^0.5.2", + "long": "^4.0.0" } }, - "node_modules/@module-federation/runtime-tools": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@module-federation/runtime-tools/-/runtime-tools-0.2.8.tgz", - "integrity": "sha512-RSNtyhcNvnTQIdzRUIOGue6WQA/9mL9cY/n0dEd357L/lmLCvfHiZbowlkacckDzyApariUHxzkHrU2Q6kzoew==", - "dev": true, + "node_modules/@cosmjs/proto-signing/node_modules/@cosmjs/crypto": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.29.5.tgz", + "integrity": "sha512-2bKkaLGictaNL0UipQCL6C1afaisv6k8Wr/GCLx9FqiyFkh9ZgRHDyetD64ZsjnWV/N/D44s/esI+k6oPREaiQ==", + "license": "Apache-2.0", "dependencies": { - "@module-federation/runtime": "0.2.8", - "@module-federation/webpack-bundler-runtime": "0.2.8" + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/math": "^0.29.5", + "@cosmjs/utils": "^0.29.5", + "@noble/hashes": "^1", + "bn.js": "^5.2.0", + "elliptic": "^6.5.4", + "libsodium-wrappers": "^0.7.6" } }, - "node_modules/@module-federation/sdk": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@module-federation/sdk/-/sdk-0.2.8.tgz", - "integrity": "sha512-eGMnJxdRDgt6dtMv8gkAlzEbTPWVHb3AHUNUG0w56wcbIF0RHC6kmvpHpSQyq4DVGWv3U4g/ZiH5BvBlqEelDQ==", - "dev": true - }, - "node_modules/@module-federation/third-party-dts-extractor": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@module-federation/third-party-dts-extractor/-/third-party-dts-extractor-0.2.8.tgz", - "integrity": "sha512-VGXvdsRlljbFUfGeA448CxR7i6fLWJN07ViRuNXYYXc19e4bQVhBHzrf7eCv9ahcf/tA/8YYCS2h11ixbD691A==", - "dev": true, + "node_modules/@cosmjs/proto-signing/node_modules/cosmjs-types": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/cosmjs-types/-/cosmjs-types-0.5.2.tgz", + "integrity": "sha512-zxCtIJj8v3Di7s39uN4LNcN3HIE1z0B9Z0SPE8ZNQR0oSzsuSe1ACgxoFkvhkS7WBasCAFcglS11G2hyfd5tPg==", + "license": "Apache-2.0", "dependencies": { - "find-pkg": "2.0.0", - "fs-extra": "9.1.0", - "resolve": "1.22.8" + "long": "^4.0.0", + "protobufjs": "~6.11.2" } }, - "node_modules/@module-federation/third-party-dts-extractor/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, + "node_modules/@cosmjs/proto-signing/node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", + "license": "Apache-2.0" + }, + "node_modules/@cosmjs/proto-signing/node_modules/protobufjs": { + "version": "6.11.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.4.tgz", + "integrity": "sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw==", + "hasInstallScript": true, + "license": "BSD-3-Clause", "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "@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/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" }, - "engines": { - "node": ">=10" + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" } }, - "node_modules/@module-federation/webpack-bundler-runtime": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@module-federation/webpack-bundler-runtime/-/webpack-bundler-runtime-0.2.8.tgz", - "integrity": "sha512-tiW1kD/V3QNul1/O3Y3lwQv/r4sUU4jvWZykrLvHYt2vuoGe1d4tHnSIFEVEAi9FSpuDwdRK2+NaWBr92gIS7Q==", - "dev": true, + "node_modules/@cosmjs/socket": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/socket/-/socket-0.29.5.tgz", + "integrity": "sha512-5VYDupIWbIXq3ftPV1LkS5Ya/T7Ol/AzWVhNxZ79hPe/mBfv1bGau/LqIYOm2zxGlgm9hBHOTmWGqNYDwr9LNQ==", + "license": "Apache-2.0", "dependencies": { - "@module-federation/runtime": "0.2.8", - "@module-federation/sdk": "0.2.8" + "@cosmjs/stream": "^0.29.5", + "isomorphic-ws": "^4.0.1", + "ws": "^7", + "xstream": "^11.14.0" } }, - "node_modules/@monaco-editor/loader": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.4.0.tgz", - "integrity": "sha512-00ioBig0x642hytVspPl7DbQyaSWRaolYie/UFNjoTdvoKPzo6xrXLhTk9ixgIKcLH5b5vDOjVNiGyY+uDCUlg==", - "dependencies": { - "state-local": "^1.0.6" - }, + "node_modules/@cosmjs/socket/node_modules/isomorphic-ws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", + "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", + "license": "MIT", "peerDependencies": { - "monaco-editor": ">= 0.21.0 < 1" + "ws": "*" } }, - "node_modules/@monaco-editor/react": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.6.0.tgz", - "integrity": "sha512-RFkU9/i7cN2bsq/iTkurMWOEErmYcY6JiQI3Jn+WeR/FGISH8JbHERjpS9oRuSOPvDMJI0Z8nJeKkbOs9sBYQw==", - "dependencies": { - "@monaco-editor/loader": "^1.4.0" + "node_modules/@cosmjs/socket/node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" }, "peerDependencies": { - "monaco-editor": ">= 0.25.0 < 1", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, - "node_modules/@motionone/animation": { - "version": "10.18.0", - "resolved": "https://registry.npmjs.org/@motionone/animation/-/animation-10.18.0.tgz", - "integrity": "sha512-9z2p5GFGCm0gBsZbi8rVMOAJCtw1WqBTIPw3ozk06gDvZInBPIsQcHgYogEJ4yuHJ+akuW8g1SEIOpTOvYs8hw==", + "node_modules/@cosmjs/stargate": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/stargate/-/stargate-0.29.5.tgz", + "integrity": "sha512-hjEv8UUlJruLrYGJcUZXM/CziaINOKwfVm2BoSdUnNTMxGvY/jC1ABHKeZUYt9oXHxEJ1n9+pDqzbKc8pT0nBw==", + "license": "Apache-2.0", "dependencies": { - "@motionone/easing": "^10.18.0", - "@motionone/types": "^10.17.1", - "@motionone/utils": "^10.18.0", - "tslib": "^2.3.1" + "@confio/ics23": "^0.6.8", + "@cosmjs/amino": "^0.29.5", + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/math": "^0.29.5", + "@cosmjs/proto-signing": "^0.29.5", + "@cosmjs/stream": "^0.29.5", + "@cosmjs/tendermint-rpc": "^0.29.5", + "@cosmjs/utils": "^0.29.5", + "cosmjs-types": "^0.5.2", + "long": "^4.0.0", + "protobufjs": "~6.11.3", + "xstream": "^11.14.0" + } + }, + "node_modules/@cosmjs/stargate/node_modules/cosmjs-types": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/cosmjs-types/-/cosmjs-types-0.5.2.tgz", + "integrity": "sha512-zxCtIJj8v3Di7s39uN4LNcN3HIE1z0B9Z0SPE8ZNQR0oSzsuSe1ACgxoFkvhkS7WBasCAFcglS11G2hyfd5tPg==", + "license": "Apache-2.0", + "dependencies": { + "long": "^4.0.0", + "protobufjs": "~6.11.2" } }, - "node_modules/@motionone/dom": { - "version": "10.18.0", - "resolved": "https://registry.npmjs.org/@motionone/dom/-/dom-10.18.0.tgz", - "integrity": "sha512-bKLP7E0eyO4B2UaHBBN55tnppwRnaE3KFfh3Ps9HhnAkar3Cb69kUCJY9as8LrccVYKgHA+JY5dOQqJLOPhF5A==", + "node_modules/@cosmjs/stargate/node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", + "license": "Apache-2.0" + }, + "node_modules/@cosmjs/stargate/node_modules/protobufjs": { + "version": "6.11.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.4.tgz", + "integrity": "sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw==", + "hasInstallScript": true, + "license": "BSD-3-Clause", "dependencies": { - "@motionone/animation": "^10.18.0", - "@motionone/generators": "^10.18.0", - "@motionone/types": "^10.17.1", - "@motionone/utils": "^10.18.0", - "hey-listen": "^1.0.8", - "tslib": "^2.3.1" + "@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/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + }, + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" } }, - "node_modules/@motionone/easing": { - "version": "10.18.0", - "resolved": "https://registry.npmjs.org/@motionone/easing/-/easing-10.18.0.tgz", - "integrity": "sha512-VcjByo7XpdLS4o9T8t99JtgxkdMcNWD3yHU/n6CLEz3bkmKDRZyYQ/wmSf6daum8ZXqfUAgFeCZSpJZIMxaCzg==", + "node_modules/@cosmjs/stream": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/stream/-/stream-0.29.5.tgz", + "integrity": "sha512-TToTDWyH1p05GBtF0Y8jFw2C+4783ueDCmDyxOMM6EU82IqpmIbfwcdMOCAm0JhnyMh+ocdebbFvnX/sGKzRAA==", + "license": "Apache-2.0", "dependencies": { - "@motionone/utils": "^10.18.0", - "tslib": "^2.3.1" + "xstream": "^11.14.0" } }, - "node_modules/@motionone/generators": { - "version": "10.18.0", - "resolved": "https://registry.npmjs.org/@motionone/generators/-/generators-10.18.0.tgz", - "integrity": "sha512-+qfkC2DtkDj4tHPu+AFKVfR/C30O1vYdvsGYaR13W/1cczPrrcjdvYCj0VLFuRMN+lP1xvpNZHCRNM4fBzn1jg==", + "node_modules/@cosmjs/tendermint-rpc": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/tendermint-rpc/-/tendermint-rpc-0.29.5.tgz", + "integrity": "sha512-ar80twieuAxsy0x2za/aO3kBr2DFPAXDmk2ikDbmkda+qqfXgl35l9CVAAjKRqd9d+cRvbQyb5M4wy6XQpEV6w==", + "license": "Apache-2.0", "dependencies": { - "@motionone/types": "^10.17.1", - "@motionone/utils": "^10.18.0", - "tslib": "^2.3.1" + "@cosmjs/crypto": "^0.29.5", + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/json-rpc": "^0.29.5", + "@cosmjs/math": "^0.29.5", + "@cosmjs/socket": "^0.29.5", + "@cosmjs/stream": "^0.29.5", + "@cosmjs/utils": "^0.29.5", + "axios": "^0.21.2", + "readonly-date": "^1.0.0", + "xstream": "^11.14.0" + } + }, + "node_modules/@cosmjs/tendermint-rpc/node_modules/@cosmjs/crypto": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.29.5.tgz", + "integrity": "sha512-2bKkaLGictaNL0UipQCL6C1afaisv6k8Wr/GCLx9FqiyFkh9ZgRHDyetD64ZsjnWV/N/D44s/esI+k6oPREaiQ==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/math": "^0.29.5", + "@cosmjs/utils": "^0.29.5", + "@noble/hashes": "^1", + "bn.js": "^5.2.0", + "elliptic": "^6.5.4", + "libsodium-wrappers": "^0.7.6" } }, - "node_modules/@motionone/svelte": { - "version": "10.16.4", - "resolved": "https://registry.npmjs.org/@motionone/svelte/-/svelte-10.16.4.tgz", - "integrity": "sha512-zRVqk20lD1xqe+yEDZhMYgftsuHc25+9JSo+r0a0OWUJFocjSV9D/+UGhX4xgJsuwB9acPzXLr20w40VnY2PQA==", + "node_modules/@cosmjs/tendermint-rpc/node_modules/axios": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "license": "MIT", "dependencies": { - "@motionone/dom": "^10.16.4", - "tslib": "^2.3.1" + "follow-redirects": "^1.14.0" } }, - "node_modules/@motionone/types": { - "version": "10.17.1", - "resolved": "https://registry.npmjs.org/@motionone/types/-/types-10.17.1.tgz", - "integrity": "sha512-KaC4kgiODDz8hswCrS0btrVrzyU2CSQKO7Ps90ibBVSQmjkrt2teqta6/sOG59v7+dPnKMAg13jyqtMKV2yJ7A==" + "node_modules/@cosmjs/utils": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/utils/-/utils-0.29.5.tgz", + "integrity": "sha512-m7h+RXDUxOzEOGt4P+3OVPX7PuakZT3GBmaM/Y2u+abN3xZkziykD/NvedYFvvCCdQo714XcGl33bwifS9FZPQ==", + "license": "Apache-2.0" }, - "node_modules/@motionone/utils": { - "version": "10.18.0", - "resolved": "https://registry.npmjs.org/@motionone/utils/-/utils-10.18.0.tgz", - "integrity": "sha512-3XVF7sgyTSI2KWvTf6uLlBJ5iAgRgmvp3bpuOiQJvInd4nZ19ET8lX5unn30SlmRH7hXbBbH+Gxd0m0klJ3Xtw==", + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, "dependencies": { - "@motionone/types": "^10.17.1", - "hey-listen": "^1.0.8", - "tslib": "^2.3.1" + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" } }, - "node_modules/@motionone/vue": { - "version": "10.16.4", - "resolved": "https://registry.npmjs.org/@motionone/vue/-/vue-10.16.4.tgz", - "integrity": "sha512-z10PF9JV6SbjFq+/rYabM+8CVlMokgl8RFGvieSGNTmrkQanfHn+15XBrhG3BgUfvmTeSeyShfOHpG0i9zEdcg==", - "deprecated": "Motion One for Vue is deprecated. Use Oku Motion instead https://oku-ui.com/motion", + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, "dependencies": { - "@motionone/dom": "^10.16.4", - "tslib": "^2.3.1" + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz", - "integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz", - "integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ] + "node_modules/@dabh/diagnostics": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", + "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", + "dependencies": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@docsearch/css": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.6.1.tgz", + "integrity": "sha512-VtVb5DS+0hRIprU2CO6ZQjK2Zg4QU5HrDM1+ix6rT0umsYvFvatMAnf97NHZlVWDaaLlx7GRfR/7FikANiM2Fg==" + }, + "node_modules/@docsearch/react": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.6.1.tgz", + "integrity": "sha512-qXZkEPvybVhSXj0K7U3bXc233tk5e8PfhoZ6MhPOiik/qUQxYC+Dn9DnoS7CxHQQhHfCvTiN0eY9M12oRghEXw==", + "dependencies": { + "@algolia/autocomplete-core": "1.9.3", + "@algolia/autocomplete-preset-algolia": "1.9.3", + "@docsearch/css": "3.6.1", + "algoliasearch": "^4.19.1" + }, + "peerDependencies": { + "@types/react": ">= 16.8.0 < 19.0.0", + "react": ">= 16.8.0 < 19.0.0", + "react-dom": ">= 16.8.0 < 19.0.0", + "search-insights": ">= 1 < 3" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "search-insights": { + "optional": true + } + } + }, + "node_modules/@docusaurus/core": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.4.0.tgz", + "integrity": "sha512-g+0wwmN2UJsBqy2fQRQ6fhXruoEa62JDeEa5d8IdTJlMoaDaEDfHh7WjwGRn4opuTQWpjAwP/fbcgyHKlE+64w==", + "dependencies": { + "@babel/core": "^7.23.3", + "@babel/generator": "^7.23.3", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-runtime": "^7.22.9", + "@babel/preset-env": "^7.22.9", + "@babel/preset-react": "^7.22.5", + "@babel/preset-typescript": "^7.22.5", + "@babel/runtime": "^7.22.6", + "@babel/runtime-corejs3": "^7.22.6", + "@babel/traverse": "^7.22.8", + "@docusaurus/cssnano-preset": "3.4.0", + "@docusaurus/logger": "3.4.0", + "@docusaurus/mdx-loader": "3.4.0", + "@docusaurus/utils": "3.4.0", + "@docusaurus/utils-common": "3.4.0", + "@docusaurus/utils-validation": "3.4.0", + "autoprefixer": "^10.4.14", + "babel-loader": "^9.1.3", + "babel-plugin-dynamic-import-node": "^2.3.3", + "boxen": "^6.2.1", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "clean-css": "^5.3.2", + "cli-table3": "^0.6.3", + "combine-promises": "^1.1.0", + "commander": "^5.1.0", + "copy-webpack-plugin": "^11.0.0", + "core-js": "^3.31.1", + "css-loader": "^6.8.1", + "css-minimizer-webpack-plugin": "^5.0.1", + "cssnano": "^6.1.2", + "del": "^6.1.1", + "detect-port": "^1.5.1", + "escape-html": "^1.0.3", + "eta": "^2.2.0", + "eval": "^0.1.8", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "html-minifier-terser": "^7.2.0", + "html-tags": "^3.3.1", + "html-webpack-plugin": "^5.5.3", + "leven": "^3.1.0", + "lodash": "^4.17.21", + "mini-css-extract-plugin": "^2.7.6", + "p-map": "^4.0.0", + "postcss": "^8.4.26", + "postcss-loader": "^7.3.3", + "prompts": "^2.4.2", + "react-dev-utils": "^12.0.1", + "react-helmet-async": "^1.3.0", + "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", + "react-loadable-ssr-addon-v5-slorber": "^1.0.1", + "react-router": "^5.3.4", + "react-router-config": "^5.1.1", + "react-router-dom": "^5.3.4", + "rtl-detect": "^1.0.4", + "semver": "^7.5.4", + "serve-handler": "^6.1.5", + "shelljs": "^0.8.5", + "terser-webpack-plugin": "^5.3.9", + "tslib": "^2.6.0", + "update-notifier": "^6.0.2", + "url-loader": "^4.1.1", + "webpack": "^5.88.1", + "webpack-bundle-analyzer": "^4.9.0", + "webpack-dev-server": "^4.15.1", + "webpack-merge": "^5.9.0", + "webpackbar": "^5.0.2" + }, + "bin": { + "docusaurus": "bin/docusaurus.mjs" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/core/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@docusaurus/cssnano-preset": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.4.0.tgz", + "integrity": "sha512-qwLFSz6v/pZHy/UP32IrprmH5ORce86BGtN0eBtG75PpzQJAzp9gefspox+s8IEOr0oZKuQ/nhzZ3xwyc3jYJQ==", + "dependencies": { + "cssnano-preset-advanced": "^6.1.2", + "postcss": "^8.4.38", + "postcss-sort-media-queries": "^5.2.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@docusaurus/logger": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.4.0.tgz", + "integrity": "sha512-bZwkX+9SJ8lB9kVRkXw+xvHYSMGG4bpYHKGXeXFvyVc79NMeeBSGgzd4TQLHH+DYeOJoCdl8flrFJVxlZ0wo/Q==", + "dependencies": { + "chalk": "^4.1.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@docusaurus/mdx-loader": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.4.0.tgz", + "integrity": "sha512-kSSbrrk4nTjf4d+wtBA9H+FGauf2gCax89kV8SUSJu3qaTdSIKdWERlngsiHaCFgZ7laTJ8a67UFf+xlFPtuTw==", + "dependencies": { + "@docusaurus/logger": "3.4.0", + "@docusaurus/utils": "3.4.0", + "@docusaurus/utils-validation": "3.4.0", + "@mdx-js/mdx": "^3.0.0", + "@slorber/remark-comment": "^1.0.0", + "escape-html": "^1.0.3", + "estree-util-value-to-estree": "^3.0.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "image-size": "^1.0.2", + "mdast-util-mdx": "^3.0.0", + "mdast-util-to-string": "^4.0.0", + "rehype-raw": "^7.0.0", + "remark-directive": "^3.0.0", + "remark-emoji": "^4.0.0", + "remark-frontmatter": "^5.0.0", + "remark-gfm": "^4.0.0", + "stringify-object": "^3.3.0", + "tslib": "^2.6.0", + "unified": "^11.0.3", + "unist-util-visit": "^5.0.0", + "url-loader": "^4.1.1", + "vfile": "^6.0.1", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/module-type-aliases": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.4.0.tgz", + "integrity": "sha512-A1AyS8WF5Bkjnb8s+guTDuYmUiwJzNrtchebBHpc0gz0PyHJNMaybUlSrmJjHVcGrya0LKI4YcR3lBDQfXRYLw==", + "dependencies": { + "@docusaurus/types": "3.4.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router-config": "*", + "@types/react-router-dom": "*", + "react-helmet-async": "*", + "react-loadable": "npm:@docusaurus/react-loadable@6.0.0" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/@docusaurus/module-type-aliases/node_modules/@docusaurus/types": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", + "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "^1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-content-blog": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.4.0.tgz", + "integrity": "sha512-vv6ZAj78ibR5Jh7XBUT4ndIjmlAxkijM3Sx5MAAzC1gyv0vupDQNhzuFg1USQmQVj3P5I6bquk12etPV3LJ+Xw==", + "dependencies": { + "@docusaurus/core": "3.4.0", + "@docusaurus/logger": "3.4.0", + "@docusaurus/mdx-loader": "3.4.0", + "@docusaurus/types": "3.4.0", + "@docusaurus/utils": "3.4.0", + "@docusaurus/utils-common": "3.4.0", + "@docusaurus/utils-validation": "3.4.0", + "cheerio": "^1.0.0-rc.12", + "feed": "^4.2.2", + "fs-extra": "^11.1.1", + "lodash": "^4.17.21", + "reading-time": "^1.5.0", + "srcset": "^4.0.0", + "tslib": "^2.6.0", + "unist-util-visit": "^5.0.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/types": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", + "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "^1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-content-docs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.4.0.tgz", + "integrity": "sha512-HkUCZffhBo7ocYheD9oZvMcDloRnGhBMOZRyVcAQRFmZPmNqSyISlXA1tQCIxW+r478fty97XXAGjNYzBjpCsg==", + "dependencies": { + "@docusaurus/core": "3.4.0", + "@docusaurus/logger": "3.4.0", + "@docusaurus/mdx-loader": "3.4.0", + "@docusaurus/module-type-aliases": "3.4.0", + "@docusaurus/types": "3.4.0", + "@docusaurus/utils": "3.4.0", + "@docusaurus/utils-common": "3.4.0", + "@docusaurus/utils-validation": "3.4.0", + "@types/react-router-config": "^5.0.7", + "combine-promises": "^1.1.0", + "fs-extra": "^11.1.1", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "tslib": "^2.6.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-content-docs/node_modules/@docusaurus/types": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", + "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "^1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-content-pages": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.4.0.tgz", + "integrity": "sha512-h2+VN/0JjpR8fIkDEAoadNjfR3oLzB+v1qSXbIAKjQ46JAHx3X22n9nqS+BWSQnTnp1AjkjSvZyJMekmcwxzxg==", + "dependencies": { + "@docusaurus/core": "3.4.0", + "@docusaurus/mdx-loader": "3.4.0", + "@docusaurus/types": "3.4.0", + "@docusaurus/utils": "3.4.0", + "@docusaurus/utils-validation": "3.4.0", + "fs-extra": "^11.1.1", + "tslib": "^2.6.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/types": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", + "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "^1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-debug": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.4.0.tgz", + "integrity": "sha512-uV7FDUNXGyDSD3PwUaf5YijX91T5/H9SX4ErEcshzwgzWwBtK37nUWPU3ZLJfeTavX3fycTOqk9TglpOLaWkCg==", + "dependencies": { + "@docusaurus/core": "3.4.0", + "@docusaurus/types": "3.4.0", + "@docusaurus/utils": "3.4.0", + "fs-extra": "^11.1.1", + "react-json-view-lite": "^1.2.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-debug/node_modules/@docusaurus/types": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", + "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "^1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-analytics": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.4.0.tgz", + "integrity": "sha512-mCArluxEGi3cmYHqsgpGGt3IyLCrFBxPsxNZ56Mpur0xSlInnIHoeLDH7FvVVcPJRPSQ9/MfRqLsainRw+BojA==", + "dependencies": { + "@docusaurus/core": "3.4.0", + "@docusaurus/types": "3.4.0", + "@docusaurus/utils-validation": "3.4.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/types": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", + "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "^1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-gtag": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.4.0.tgz", + "integrity": "sha512-Dsgg6PLAqzZw5wZ4QjUYc8Z2KqJqXxHxq3vIoyoBWiLEEfigIs7wHR+oiWUQy3Zk9MIk6JTYj7tMoQU0Jm3nqA==", + "dependencies": { + "@docusaurus/core": "3.4.0", + "@docusaurus/types": "3.4.0", + "@docusaurus/utils-validation": "3.4.0", + "@types/gtag.js": "^0.0.12", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/types": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", + "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "^1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-tag-manager": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.4.0.tgz", + "integrity": "sha512-O9tX1BTwxIhgXpOLpFDueYA9DWk69WCbDRrjYoMQtFHSkTyE7RhNgyjSPREUWJb9i+YUg3OrsvrBYRl64FCPCQ==", + "dependencies": { + "@docusaurus/core": "3.4.0", + "@docusaurus/types": "3.4.0", + "@docusaurus/utils-validation": "3.4.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/types": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", + "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "^1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-sitemap": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.4.0.tgz", + "integrity": "sha512-+0VDvx9SmNrFNgwPoeoCha+tRoAjopwT0+pYO1xAbyLcewXSemq+eLxEa46Q1/aoOaJQ0qqHELuQM7iS2gp33Q==", + "dependencies": { + "@docusaurus/core": "3.4.0", + "@docusaurus/logger": "3.4.0", + "@docusaurus/types": "3.4.0", + "@docusaurus/utils": "3.4.0", + "@docusaurus/utils-common": "3.4.0", + "@docusaurus/utils-validation": "3.4.0", + "fs-extra": "^11.1.1", + "sitemap": "^7.1.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/types": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", + "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "^1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/preset-classic": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.4.0.tgz", + "integrity": "sha512-Ohj6KB7siKqZaQhNJVMBBUzT3Nnp6eTKqO+FXO3qu/n1hJl3YLwVKTWBg28LF7MWrKu46UuYavwMRxud0VyqHg==", + "dependencies": { + "@docusaurus/core": "3.4.0", + "@docusaurus/plugin-content-blog": "3.4.0", + "@docusaurus/plugin-content-docs": "3.4.0", + "@docusaurus/plugin-content-pages": "3.4.0", + "@docusaurus/plugin-debug": "3.4.0", + "@docusaurus/plugin-google-analytics": "3.4.0", + "@docusaurus/plugin-google-gtag": "3.4.0", + "@docusaurus/plugin-google-tag-manager": "3.4.0", + "@docusaurus/plugin-sitemap": "3.4.0", + "@docusaurus/theme-classic": "3.4.0", + "@docusaurus/theme-common": "3.4.0", + "@docusaurus/theme-search-algolia": "3.4.0", + "@docusaurus/types": "3.4.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/preset-classic/node_modules/@docusaurus/types": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", + "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "^1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/theme-classic": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.4.0.tgz", + "integrity": "sha512-0IPtmxsBYv2adr1GnZRdMkEQt1YW6tpzrUPj02YxNpvJ5+ju4E13J5tB4nfdaen/tfR1hmpSPlTFPvTf4kwy8Q==", + "dependencies": { + "@docusaurus/core": "3.4.0", + "@docusaurus/mdx-loader": "3.4.0", + "@docusaurus/module-type-aliases": "3.4.0", + "@docusaurus/plugin-content-blog": "3.4.0", + "@docusaurus/plugin-content-docs": "3.4.0", + "@docusaurus/plugin-content-pages": "3.4.0", + "@docusaurus/theme-common": "3.4.0", + "@docusaurus/theme-translations": "3.4.0", + "@docusaurus/types": "3.4.0", + "@docusaurus/utils": "3.4.0", + "@docusaurus/utils-common": "3.4.0", + "@docusaurus/utils-validation": "3.4.0", + "@mdx-js/react": "^3.0.0", + "clsx": "^2.0.0", + "copy-text-to-clipboard": "^3.2.0", + "infima": "0.2.0-alpha.43", + "lodash": "^4.17.21", + "nprogress": "^0.2.0", + "postcss": "^8.4.26", + "prism-react-renderer": "^2.3.0", + "prismjs": "^1.29.0", + "react-router-dom": "^5.3.4", + "rtlcss": "^4.1.0", + "tslib": "^2.6.0", + "utility-types": "^3.10.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/types": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", + "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "^1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/theme-common": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.4.0.tgz", + "integrity": "sha512-0A27alXuv7ZdCg28oPE8nH/Iz73/IUejVaCazqu9elS4ypjiLhK3KfzdSQBnL/g7YfHSlymZKdiOHEo8fJ0qMA==", + "dependencies": { + "@docusaurus/mdx-loader": "3.4.0", + "@docusaurus/module-type-aliases": "3.4.0", + "@docusaurus/plugin-content-blog": "3.4.0", + "@docusaurus/plugin-content-docs": "3.4.0", + "@docusaurus/plugin-content-pages": "3.4.0", + "@docusaurus/utils": "3.4.0", + "@docusaurus/utils-common": "3.4.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router-config": "*", + "clsx": "^2.0.0", + "parse-numeric-range": "^1.3.0", + "prism-react-renderer": "^2.3.0", + "tslib": "^2.6.0", + "utility-types": "^3.10.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/theme-search-algolia": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.4.0.tgz", + "integrity": "sha512-aiHFx7OCw4Wck1z6IoShVdUWIjntC8FHCw9c5dR8r3q4Ynh+zkS8y2eFFunN/DL6RXPzpnvKCg3vhLQYJDmT9Q==", + "dependencies": { + "@docsearch/react": "^3.5.2", + "@docusaurus/core": "3.4.0", + "@docusaurus/logger": "3.4.0", + "@docusaurus/plugin-content-docs": "3.4.0", + "@docusaurus/theme-common": "3.4.0", + "@docusaurus/theme-translations": "3.4.0", + "@docusaurus/utils": "3.4.0", + "@docusaurus/utils-validation": "3.4.0", + "algoliasearch": "^4.18.0", + "algoliasearch-helper": "^3.13.3", + "clsx": "^2.0.0", + "eta": "^2.2.0", + "fs-extra": "^11.1.1", + "lodash": "^4.17.21", + "tslib": "^2.6.0", + "utility-types": "^3.10.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/theme-translations": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.4.0.tgz", + "integrity": "sha512-zSxCSpmQCCdQU5Q4CnX/ID8CSUUI3fvmq4hU/GNP/XoAWtXo9SAVnM3TzpU8Gb//H3WCsT8mJcTfyOk3d9ftNg==", + "dependencies": { + "fs-extra": "^11.1.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@docusaurus/tsconfig": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/tsconfig/-/tsconfig-3.5.2.tgz", + "integrity": "sha512-rQ7toURCFnWAIn8ubcquDs0ewhPwviMzxh6WpRjBW7sJVCXb6yzwUaY3HMNa0VXCFw+qkIbFywrMTf+Pb4uHWQ==", + "dev": true + }, + "node_modules/@docusaurus/types": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.1.0.tgz", + "integrity": "sha512-VaczOZf7+re8aFBIWnex1XENomwHdsSTkrdX43zyor7G/FY4OIsP6X28Xc3o0jiY0YdNuvIDyA5TNwOtpgkCVw==", + "devOptional": true, + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "^1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/utils": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.4.0.tgz", + "integrity": "sha512-fRwnu3L3nnWaXOgs88BVBmG1yGjcQqZNHG+vInhEa2Sz2oQB+ZjbEMO5Rh9ePFpZ0YDiDUhpaVjwmS+AU2F14g==", + "dependencies": { + "@docusaurus/logger": "3.4.0", + "@docusaurus/utils-common": "3.4.0", + "@svgr/webpack": "^8.1.0", + "escape-string-regexp": "^4.0.0", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "github-slugger": "^1.5.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "jiti": "^1.20.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "micromatch": "^4.0.5", + "prompts": "^2.4.2", + "resolve-pathname": "^3.0.0", + "shelljs": "^0.8.5", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "@docusaurus/types": "*" + }, + "peerDependenciesMeta": { + "@docusaurus/types": { + "optional": true + } + } + }, + "node_modules/@docusaurus/utils-common": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.4.0.tgz", + "integrity": "sha512-NVx54Wr4rCEKsjOH5QEVvxIqVvm+9kh7q8aYTU5WzUU9/Hctd6aTrcZ3G0Id4zYJ+AeaG5K5qHA4CY5Kcm2iyQ==", + "dependencies": { + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "@docusaurus/types": "*" + }, + "peerDependenciesMeta": { + "@docusaurus/types": { + "optional": true + } + } + }, + "node_modules/@docusaurus/utils-validation": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.4.0.tgz", + "integrity": "sha512-hYQ9fM+AXYVTWxJOT1EuNaRnrR2WGpRdLDQG07O8UOpsvCPWUVOeo26Rbm0JWY2sGLfzAb+tvJ62yF+8F+TV0g==", + "dependencies": { + "@docusaurus/logger": "3.4.0", + "@docusaurus/utils": "3.4.0", + "@docusaurus/utils-common": "3.4.0", + "fs-extra": "^11.2.0", + "joi": "^17.9.2", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@ecies/ciphers": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@ecies/ciphers/-/ciphers-0.2.1.tgz", + "integrity": "sha512-ezMihhjW24VNK/2qQR7lH8xCQY24nk0XHF/kwJ1OuiiY5iEwQXOcKVSy47fSoHPRG8gVGXcK5SgtONDk5xMwtQ==", + "engines": { + "bun": ">=1", + "deno": ">=2", + "node": ">=16" + }, + "peerDependencies": { + "@noble/ciphers": "^1.0.0" + } + }, + "node_modules/@emnapi/core": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.2.0.tgz", + "integrity": "sha512-E7Vgw78I93we4ZWdYCb4DGAwRROGkMIXk7/y87UmANR+J6qsWusmC3gLt0H+O0KOt5e6O38U8oJamgbudrES/w==", + "dev": true, + "dependencies": { + "@emnapi/wasi-threads": "1.0.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.2.0.tgz", + "integrity": "sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==", + "dev": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.1.tgz", + "integrity": "sha512-iIBu7mwkq4UQGeMEM8bLwNK962nXdhodeScX4slfQnRhEMMzvYivHhutCIk8uojvmASXXPC2WNEjwxFWk72Oqw==", + "dev": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emurgo/cardano-serialization-lib-browser": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-browser/-/cardano-serialization-lib-browser-12.1.1.tgz", + "integrity": "sha512-DANl1Jr3LdmA0aDW/meEgnF6JLGjIZ3rgo4KLFNGtch0cuG53uzj3LXzslHLofYTEuNBRaBJFPMmG2xnd1uQAg==", + "license": "MIT" + }, + "node_modules/@emurgo/cardano-serialization-lib-nodejs": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-nodejs/-/cardano-serialization-lib-nodejs-12.1.1.tgz", + "integrity": "sha512-zXJNbtCrurlQtNvGaXjEjqCzVeCQ92mQgxwPziKZAxqd5w+Lb7iJ+48Brl58BQS9KTrtennlVIZ/R90aP2WFqw==", + "license": "MIT" + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@ethereumjs/common": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-3.2.0.tgz", + "integrity": "sha512-pksvzI0VyLgmuEF2FA/JR/4/y6hcPq8OUail3/AvycBaW1d5VSauOZzqGvJ3RTmR4MU35lWE8KseKOsEhrFRBA==", + "dependencies": { + "@ethereumjs/util": "^8.1.0", + "crc-32": "^1.2.0" + } + }, + "node_modules/@ethereumjs/rlp": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-4.0.1.tgz", + "integrity": "sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==", + "bin": { + "rlp": "bin/rlp" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@ethereumjs/tx": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-4.2.0.tgz", + "integrity": "sha512-1nc6VO4jtFd172BbSnTnDQVr9IYBFl1y4xPzZdtkrkKIncBCkdbgfdRV+MiTkJYAtTxvV12GRZLqBFT1PNK6Yw==", + "dependencies": { + "@ethereumjs/common": "^3.2.0", + "@ethereumjs/rlp": "^4.0.1", + "@ethereumjs/util": "^8.1.0", + "ethereum-cryptography": "^2.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@ethereumjs/util": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@ethereumjs/util/-/util-8.1.0.tgz", + "integrity": "sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==", + "dependencies": { + "@ethereumjs/rlp": "^4.0.1", + "ethereum-cryptography": "^2.0.0", + "micro-ftch": "^0.3.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@ethersproject/abi": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz", + "integrity": "sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "node_modules/@ethersproject/abstract-provider": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz", + "integrity": "sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/networks": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/web": "^5.7.0" + } + }, + "node_modules/@ethersproject/abstract-signer": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz", + "integrity": "sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0" + } + }, + "node_modules/@ethersproject/address": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz", + "integrity": "sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/rlp": "^5.7.0" + } + }, + "node_modules/@ethersproject/base64": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz", + "integrity": "sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0" + } + }, + "node_modules/@ethersproject/basex": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.7.0.tgz", + "integrity": "sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/properties": "^5.7.0" + } + }, + "node_modules/@ethersproject/bignumber": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz", + "integrity": "sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "bn.js": "^5.2.1" + } + }, + "node_modules/@ethersproject/bytes": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz", + "integrity": "sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/constants": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz", + "integrity": "sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bignumber": "^5.7.0" + } + }, + "node_modules/@ethersproject/contracts": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.7.0.tgz", + "integrity": "sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/abi": "^5.7.0", + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/transactions": "^5.7.0" + } + }, + "node_modules/@ethersproject/hash": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz", + "integrity": "sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/base64": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "node_modules/@ethersproject/hdnode": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.7.0.tgz", + "integrity": "sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/basex": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/pbkdf2": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/sha2": "^5.7.0", + "@ethersproject/signing-key": "^5.7.0", + "@ethersproject/strings": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/wordlists": "^5.7.0" + } + }, + "node_modules/@ethersproject/json-wallets": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz", + "integrity": "sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/hdnode": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/pbkdf2": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/random": "^5.7.0", + "@ethersproject/strings": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "aes-js": "3.0.0", + "scrypt-js": "3.0.1" + } + }, + "node_modules/@ethersproject/keccak256": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz", + "integrity": "sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "js-sha3": "0.8.0" + } + }, + "node_modules/@ethersproject/logger": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz", + "integrity": "sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT" + }, + "node_modules/@ethersproject/networks": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz", + "integrity": "sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/pbkdf2": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz", + "integrity": "sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/sha2": "^5.7.0" + } + }, + "node_modules/@ethersproject/properties": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz", + "integrity": "sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/providers": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.7.2.tgz", + "integrity": "sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/base64": "^5.7.0", + "@ethersproject/basex": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/networks": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/random": "^5.7.0", + "@ethersproject/rlp": "^5.7.0", + "@ethersproject/sha2": "^5.7.0", + "@ethersproject/strings": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/web": "^5.7.0", + "bech32": "1.1.4", + "ws": "7.4.6" + } + }, + "node_modules/@ethersproject/providers/node_modules/bech32": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", + "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", + "license": "MIT" + }, + "node_modules/@ethersproject/providers/node_modules/ws": { + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", + "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/@ethersproject/random": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.7.0.tgz", + "integrity": "sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/rlp": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz", + "integrity": "sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/sha2": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.7.0.tgz", + "integrity": "sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "hash.js": "1.1.7" + } + }, + "node_modules/@ethersproject/signing-key": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz", + "integrity": "sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "bn.js": "^5.2.1", + "elliptic": "6.5.4", + "hash.js": "1.1.7" + } + }, + "node_modules/@ethersproject/signing-key/node_modules/elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/@ethersproject/signing-key/node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "license": "MIT" + }, + "node_modules/@ethersproject/solidity": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.7.0.tgz", + "integrity": "sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/sha2": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "node_modules/@ethersproject/strings": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz", + "integrity": "sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/transactions": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz", + "integrity": "sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/rlp": "^5.7.0", + "@ethersproject/signing-key": "^5.7.0" + } + }, + "node_modules/@ethersproject/units": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.7.0.tgz", + "integrity": "sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/wallet": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.7.0.tgz", + "integrity": "sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/hdnode": "^5.7.0", + "@ethersproject/json-wallets": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/random": "^5.7.0", + "@ethersproject/signing-key": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/wordlists": "^5.7.0" + } + }, + "node_modules/@ethersproject/web": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz", + "integrity": "sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/base64": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "node_modules/@ethersproject/wordlists": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.7.0.tgz", + "integrity": "sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "node_modules/@expo/bunyan": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@expo/bunyan/-/bunyan-4.0.0.tgz", + "integrity": "sha512-Ydf4LidRB/EBI+YrB+cVLqIseiRfjUI/AeHBgjGMtq3GroraDu81OV7zqophRgupngoL3iS3JUMDMnxO7g39qA==", + "engines": [ + "node >=0.10.0" + ], + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "uuid": "^8.0.0" + }, + "optionalDependencies": { + "mv": "~2", + "safe-json-stringify": "~1" + } + }, + "node_modules/@expo/bunyan/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "optional": true, + "peer": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@expo/cli": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@expo/cli/-/cli-0.1.7.tgz", + "integrity": "sha512-F81fPthpT7QtVu1P7QeZMezGn0tCcalCh3ANIzWBaQZNG4vly7mo2dp3PMGzNdmXq6yt93bJ4HbfS+0/NpKl7g==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@babel/runtime": "^7.14.0", + "@expo/code-signing-certificates": "^0.0.2", + "@expo/config": "~6.0.23", + "@expo/config-plugins": "~4.1.4", + "@expo/dev-server": "0.1.116", + "@expo/devcert": "^1.0.0", + "@expo/json-file": "^8.2.35", + "@expo/metro-config": "0.3.19", + "@expo/osascript": "^2.0.31", + "@expo/package-manager": "~0.0.52", + "@expo/plist": "^0.0.18", + "@expo/prebuild-config": "~4.0.0", + "@expo/rudder-sdk-node": "1.1.1", + "@expo/spawn-async": "1.5.0", + "@expo/xcpretty": "^4.1.1", + "@urql/core": "2.3.6", + "@urql/exchange-retry": "0.3.0", + "accepts": "^1.3.8", + "arg": "4.1.0", + "better-opn": "~3.0.2", + "bplist-parser": "^0.3.1", + "cacache": "^15.3.0", + "chalk": "^4.0.0", + "ci-info": "^3.3.0", + "env-editor": "^0.4.1", + "form-data": "^3.0.1", + "freeport-async": "2.0.0", + "fs-extra": "~8.1.0", + "getenv": "^1.0.0", + "graphql": "15.8.0", + "graphql-tag": "^2.10.1", + "internal-ip": "4.3.0", + "is-root": "^2.1.0", + "js-yaml": "^3.13.1", + "json-schema-deref-sync": "^0.13.0", + "md5-file": "^3.2.3", + "md5hex": "^1.0.0", + "minipass": "3.1.6", + "node-fetch": "^2.6.7", + "node-forge": "^1.3.1", + "npm-package-arg": "^7.0.0", + "ora": "3.4.0", + "pretty-bytes": "5.6.0", + "progress": "2.0.3", + "prompts": "^2.3.2", + "qrcode-terminal": "0.11.0", + "requireg": "^0.2.2", + "resolve-from": "^5.0.0", + "semver": "^6.3.0", + "slugify": "^1.3.4", + "structured-headers": "^0.4.1", + "tar": "^6.0.5", + "tempy": "^0.7.1", + "terminal-link": "^2.1.1", + "text-table": "^0.2.0", + "url-join": "4.0.0", + "uuid": "^3.4.0", + "wrap-ansi": "^7.0.0" + }, + "bin": { + "expo-internal": "build/bin/cli" + } + }, + "node_modules/@expo/cli/node_modules/@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "node_modules/@expo/cli/node_modules/@expo/config": { + "version": "6.0.26", + "resolved": "https://registry.npmjs.org/@expo/config/-/config-6.0.26.tgz", + "integrity": "sha512-nMQaZl69r6CMJFhCj0xcGJN9bIi4Uws0k9K6q6rGFPFNarS0z0aexeyNLv93/J+hsTJVn0GEYtGz5Y/R8boXxw==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@babel/code-frame": "~7.10.4", + "@expo/config-plugins": "4.1.5", + "@expo/config-types": "^45.0.0", + "@expo/json-file": "8.2.36", + "getenv": "^1.0.0", + "glob": "7.1.6", + "require-from-string": "^2.0.2", + "resolve-from": "^5.0.0", + "semver": "7.3.2", + "slugify": "^1.3.4", + "sucrase": "^3.20.0" + } + }, + "node_modules/@expo/cli/node_modules/@expo/config-plugins": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-4.1.5.tgz", + "integrity": "sha512-RVvU40RtZt12HavuDAe+LDIq9lHj7sheOfMEHdmpJ/uTA8pgvkbc56XF6JHQD+yRr6+uhhb+JnAasGq49dsQbw==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@expo/config-types": "^45.0.0", + "@expo/json-file": "8.2.36", + "@expo/plist": "0.0.18", + "@expo/sdk-runtime-versions": "^1.0.0", + "@react-native/normalize-color": "^2.0.0", + "chalk": "^4.1.2", + "debug": "^4.3.1", + "find-up": "~5.0.0", + "getenv": "^1.0.0", + "glob": "7.1.6", + "resolve-from": "^5.0.0", + "semver": "^7.3.5", + "slash": "^3.0.0", + "xcode": "^3.0.1", + "xml2js": "0.4.23" + } + }, + "node_modules/@expo/cli/node_modules/@expo/config-plugins/node_modules/@expo/json-file": { + "version": "8.2.36", + "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-8.2.36.tgz", + "integrity": "sha512-tOZfTiIFA5KmMpdW9KF7bc6CFiGjb0xnbieJhTGlHrLL+ps2G0OkqmuZ3pFEXBOMnJYUVpnSy++52LFxvpa5ZQ==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@babel/code-frame": "~7.10.4", + "json5": "^1.0.1", + "write-file-atomic": "^2.3.0" + } + }, + "node_modules/@expo/cli/node_modules/@expo/config-plugins/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/@expo/cli/node_modules/@expo/config-plugins/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "optional": true, + "peer": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/cli/node_modules/@expo/config-types": { + "version": "45.0.0", + "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-45.0.0.tgz", + "integrity": "sha512-/QGhhLWyaGautgEyU50UJr5YqKJix5t77ePTwreOVAhmZH+ff3nrrtYTTnccx+qF08ZNQmfAyYMCD3rQfzpiJA==", + "license": "MIT", + "optional": true, + "peer": true + }, + "node_modules/@expo/cli/node_modules/@expo/config/node_modules/@expo/json-file": { + "version": "8.2.36", + "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-8.2.36.tgz", + "integrity": "sha512-tOZfTiIFA5KmMpdW9KF7bc6CFiGjb0xnbieJhTGlHrLL+ps2G0OkqmuZ3pFEXBOMnJYUVpnSy++52LFxvpa5ZQ==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@babel/code-frame": "~7.10.4", + "json5": "^1.0.1", + "write-file-atomic": "^2.3.0" + } + }, + "node_modules/@expo/cli/node_modules/@expo/config/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/@expo/cli/node_modules/@expo/config/node_modules/semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "license": "ISC", + "optional": true, + "peer": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/cli/node_modules/@expo/json-file": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-8.3.3.tgz", + "integrity": "sha512-eZ5dld9AD0PrVRiIWpRkm5aIoWBw3kAyd8VkuWEy92sEthBKDDDHAnK2a0dw0Eil6j7rK7lS/Qaq/Zzngv2h5A==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@babel/code-frame": "~7.10.4", + "json5": "^2.2.2", + "write-file-atomic": "^2.3.0" + } + }, + "node_modules/@expo/cli/node_modules/@expo/metro-config": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@expo/metro-config/-/metro-config-0.3.19.tgz", + "integrity": "sha512-UZlwnD0g/7uAx/AZ5ulC7Y4unfJFJywXy3Ozu40dhQnSciOU/nkzK94XpKbxHuRZJ3crZxvL2EDwQ8jguDjASw==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@expo/config": "6.0.26", + "@expo/json-file": "8.2.36", + "chalk": "^4.1.0", + "debug": "^4.3.2", + "find-yarn-workspace-root": "~2.0.0", + "getenv": "^1.0.0", + "resolve-from": "^5.0.0", + "sucrase": "^3.20.0" + } + }, + "node_modules/@expo/cli/node_modules/@expo/metro-config/node_modules/@expo/json-file": { + "version": "8.2.36", + "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-8.2.36.tgz", + "integrity": "sha512-tOZfTiIFA5KmMpdW9KF7bc6CFiGjb0xnbieJhTGlHrLL+ps2G0OkqmuZ3pFEXBOMnJYUVpnSy++52LFxvpa5ZQ==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@babel/code-frame": "~7.10.4", + "json5": "^1.0.1", + "write-file-atomic": "^2.3.0" + } + }, + "node_modules/@expo/cli/node_modules/@expo/metro-config/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/@expo/cli/node_modules/@expo/plist": { + "version": "0.0.18", + "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.0.18.tgz", + "integrity": "sha512-+48gRqUiz65R21CZ/IXa7RNBXgAI/uPSdvJqoN9x1hfL44DNbUoWHgHiEXTx7XelcATpDwNTz6sHLfy0iNqf+w==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@xmldom/xmldom": "~0.7.0", + "base64-js": "^1.2.3", + "xmlbuilder": "^14.0.0" + } + }, + "node_modules/@expo/cli/node_modules/@urql/exchange-retry": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@urql/exchange-retry/-/exchange-retry-0.3.0.tgz", + "integrity": "sha512-hHqer2mcdVC0eYnVNbWyi28AlGOPb2vjH3lP3/Bc8Lc8BjhMsDwFMm7WhoP5C1+cfbr/QJ6Er3H/L08wznXxfg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@urql/core": ">=2.3.1", + "wonka": "^4.0.14" + }, + "peerDependencies": { + "graphql": "^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0" + } + }, + "node_modules/@expo/cli/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@expo/cli/node_modules/arg": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.0.tgz", + "integrity": "sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg==", + "license": "MIT", + "optional": true, + "peer": true + }, + "node_modules/@expo/cli/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@expo/cli/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@expo/cli/node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "license": "ISC", + "optional": true, + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/cli/node_modules/cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "restore-cursor": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@expo/cli/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT", + "optional": true, + "peer": true + }, + "node_modules/@expo/cli/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@expo/cli/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@expo/cli/node_modules/form-data": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.2.tgz", + "integrity": "sha512-sJe+TQb2vIaIyO783qN6BlMYWMw3WBOHA1Ay2qxsnjuafEOQFJ2JakedOQirT6D5XPRxDvS7AHYyem9fTpb4LQ==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@expo/cli/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/@expo/cli/node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@expo/cli/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@expo/cli/node_modules/graphql": { + "version": "15.8.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.8.0.tgz", + "integrity": "sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/@expo/cli/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@expo/cli/node_modules/hosted-git-info": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz", + "integrity": "sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/cli/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@expo/cli/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@expo/cli/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "license": "MIT", + "optional": true, + "peer": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@expo/cli/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@expo/cli/node_modules/log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "chalk": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@expo/cli/node_modules/log-symbols/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@expo/cli/node_modules/log-symbols/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@expo/cli/node_modules/mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@expo/cli/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@expo/cli/node_modules/minipass": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz", + "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@expo/cli/node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@expo/cli/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "optional": true, + "peer": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/cli/node_modules/npm-package-arg": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-7.0.0.tgz", + "integrity": "sha512-xXxr8y5U0kl8dVkz2oK7yZjPBvqM2fwaO5l3Yg13p03v8+E3qQcD0JNhHzjL1vyGgxcKkD0cco+NLR72iuPk3g==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "hosted-git-info": "^3.0.2", + "osenv": "^0.1.5", + "semver": "^5.6.0", + "validate-npm-package-name": "^3.0.0" + } + }, + "node_modules/@expo/cli/node_modules/npm-package-arg/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", + "optional": true, + "peer": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@expo/cli/node_modules/onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "mimic-fn": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@expo/cli/node_modules/ora": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-3.4.0.tgz", + "integrity": "sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-spinners": "^2.0.0", + "log-symbols": "^2.2.0", + "strip-ansi": "^5.2.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@expo/cli/node_modules/ora/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@expo/cli/node_modules/ora/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@expo/cli/node_modules/ora/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@expo/cli/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@expo/cli/node_modules/restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@expo/cli/node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "license": "BSD-3-Clause", + "optional": true, + "peer": true + }, + "node_modules/@expo/cli/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@expo/cli/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@expo/cli/node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/cli/node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "license": "ISC", + "optional": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@expo/cli/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/@expo/cli/node_modules/url-join": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.0.tgz", + "integrity": "sha512-EGXjXJZhIHiQMK2pQukuFcL303nskqIRzWvPvV5O8miOfwoUb9G+a/Cld60kUyeaybEI94wvVClT10DtfeAExA==", + "license": "MIT", + "optional": true, + "peer": true + }, + "node_modules/@expo/cli/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "license": "MIT", + "optional": true, + "peer": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/@expo/cli/node_modules/validate-npm-package-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", + "integrity": "sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "builtins": "^1.0.3" + } + }, + "node_modules/@expo/cli/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@expo/cli/node_modules/write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "node_modules/@expo/code-signing-certificates": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@expo/code-signing-certificates/-/code-signing-certificates-0.0.2.tgz", + "integrity": "sha512-vnPHFjwOqxQ1VLztktY+fYCfwvLzjqpzKn09rchcQE7Sdf0wtW5fFtIZBEFOOY5wasp8tXSnp627zrAwazPHzg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "node-forge": "^1.2.1", + "nullthrows": "^1.1.1" + } + }, + "node_modules/@expo/config": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/@expo/config/-/config-6.0.6.tgz", + "integrity": "sha512-GPI8EIdMAtZ5VaB4p5GcfuX50xyfGFdpEqLi0QmcfrCfTsGry1/j/Qy28hovHM1oJYHlaZylTcbGy+1ET+AO2w==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "~7.10.4", + "@expo/config-plugins": "4.0.6", + "@expo/config-types": "^43.0.1", + "@expo/json-file": "8.2.33", + "getenv": "^1.0.0", + "glob": "7.1.6", + "require-from-string": "^2.0.2", + "resolve-from": "^5.0.0", + "semver": "7.3.2", + "slugify": "^1.3.4", + "sucrase": "^3.20.0" + } + }, + "node_modules/@expo/config-plugins": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-4.0.6.tgz", + "integrity": "sha512-K/KQaw/CU8uLQgk7sFnZC54YGHoGucKFfdjYeZx5ds2eyzbuMAiKzGFcxZ/S+1dVBZ8QHzwowsVBW3kuYhnQ3Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "@expo/config-types": "^43.0.1", + "@expo/json-file": "8.2.33", + "@expo/plist": "0.0.15", + "@react-native/normalize-color": "^2.0.0", + "chalk": "^4.1.2", + "debug": "^4.3.1", + "find-up": "~5.0.0", + "fs-extra": "9.0.0", + "getenv": "^1.0.0", + "glob": "7.1.6", + "resolve-from": "^5.0.0", + "semver": "^7.3.5", + "slash": "^3.0.0", + "xcode": "^3.0.1", + "xml2js": "0.4.23" + } + }, + "node_modules/@expo/config-plugins/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "license": "MIT", + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@expo/config-plugins/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "license": "MIT", + "peer": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@expo/config-plugins/node_modules/fs-extra": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.0.tgz", + "integrity": "sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==", + "license": "MIT", + "peer": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^1.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/config-plugins/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "peer": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@expo/config-plugins/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "license": "MIT", + "peer": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@expo/config-plugins/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@expo/config-plugins/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "license": "MIT", + "peer": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@expo/config-plugins/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/config-plugins/node_modules/universalify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", + "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@expo/config-types": { + "version": "43.0.1", + "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-43.0.1.tgz", + "integrity": "sha512-EtllpCGDdB/UdwAIs5YXJwBLpbFQNdlLLrxIvoILA9cXrpQMWkeDCT9lQPJzFRMFcLUaMuGvkzX2tR4tx5EQFQ==", + "license": "MIT", + "peer": true + }, + "node_modules/@expo/config/node_modules/@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "node_modules/@expo/config/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "license": "MIT", + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@expo/config/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "peer": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@expo/config/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@expo/config/node_modules/semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/dev-server": { + "version": "0.1.116", + "resolved": "https://registry.npmjs.org/@expo/dev-server/-/dev-server-0.1.116.tgz", + "integrity": "sha512-jUyOv3S55wBsYiFhiYVz35Ui8QTnUGVKlsPRgQHnKU70Ey4jxJqObtGkNnrgazzDfy9S7qFJKiyJQro7621ipA==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@expo/bunyan": "4.0.0", + "@expo/metro-config": "0.3.19", + "@expo/osascript": "2.0.33", + "body-parser": "1.19.0", + "chalk": "^4.0.0", + "connect": "^3.7.0", + "fs-extra": "9.0.0", + "node-fetch": "^2.6.0", + "open": "^8.3.0", + "resolve-from": "^5.0.0", + "semver": "7.3.2", + "serialize-error": "6.0.0", + "temp-dir": "^2.0.0" + } + }, + "node_modules/@expo/dev-server/node_modules/@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "node_modules/@expo/dev-server/node_modules/@expo/config": { + "version": "6.0.26", + "resolved": "https://registry.npmjs.org/@expo/config/-/config-6.0.26.tgz", + "integrity": "sha512-nMQaZl69r6CMJFhCj0xcGJN9bIi4Uws0k9K6q6rGFPFNarS0z0aexeyNLv93/J+hsTJVn0GEYtGz5Y/R8boXxw==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@babel/code-frame": "~7.10.4", + "@expo/config-plugins": "4.1.5", + "@expo/config-types": "^45.0.0", + "@expo/json-file": "8.2.36", + "getenv": "^1.0.0", + "glob": "7.1.6", + "require-from-string": "^2.0.2", + "resolve-from": "^5.0.0", + "semver": "7.3.2", + "slugify": "^1.3.4", + "sucrase": "^3.20.0" + } + }, + "node_modules/@expo/dev-server/node_modules/@expo/config-plugins": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-4.1.5.tgz", + "integrity": "sha512-RVvU40RtZt12HavuDAe+LDIq9lHj7sheOfMEHdmpJ/uTA8pgvkbc56XF6JHQD+yRr6+uhhb+JnAasGq49dsQbw==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@expo/config-types": "^45.0.0", + "@expo/json-file": "8.2.36", + "@expo/plist": "0.0.18", + "@expo/sdk-runtime-versions": "^1.0.0", + "@react-native/normalize-color": "^2.0.0", + "chalk": "^4.1.2", + "debug": "^4.3.1", + "find-up": "~5.0.0", + "getenv": "^1.0.0", + "glob": "7.1.6", + "resolve-from": "^5.0.0", + "semver": "^7.3.5", + "slash": "^3.0.0", + "xcode": "^3.0.1", + "xml2js": "0.4.23" + } + }, + "node_modules/@expo/dev-server/node_modules/@expo/config-plugins/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "optional": true, + "peer": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/dev-server/node_modules/@expo/config-types": { + "version": "45.0.0", + "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-45.0.0.tgz", + "integrity": "sha512-/QGhhLWyaGautgEyU50UJr5YqKJix5t77ePTwreOVAhmZH+ff3nrrtYTTnccx+qF08ZNQmfAyYMCD3rQfzpiJA==", + "license": "MIT", + "optional": true, + "peer": true + }, + "node_modules/@expo/dev-server/node_modules/@expo/json-file": { + "version": "8.2.36", + "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-8.2.36.tgz", + "integrity": "sha512-tOZfTiIFA5KmMpdW9KF7bc6CFiGjb0xnbieJhTGlHrLL+ps2G0OkqmuZ3pFEXBOMnJYUVpnSy++52LFxvpa5ZQ==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@babel/code-frame": "~7.10.4", + "json5": "^1.0.1", + "write-file-atomic": "^2.3.0" + } + }, + "node_modules/@expo/dev-server/node_modules/@expo/metro-config": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@expo/metro-config/-/metro-config-0.3.19.tgz", + "integrity": "sha512-UZlwnD0g/7uAx/AZ5ulC7Y4unfJFJywXy3Ozu40dhQnSciOU/nkzK94XpKbxHuRZJ3crZxvL2EDwQ8jguDjASw==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@expo/config": "6.0.26", + "@expo/json-file": "8.2.36", + "chalk": "^4.1.0", + "debug": "^4.3.2", + "find-yarn-workspace-root": "~2.0.0", + "getenv": "^1.0.0", + "resolve-from": "^5.0.0", + "sucrase": "^3.20.0" + } + }, + "node_modules/@expo/dev-server/node_modules/@expo/osascript": { + "version": "2.0.33", + "resolved": "https://registry.npmjs.org/@expo/osascript/-/osascript-2.0.33.tgz", + "integrity": "sha512-FQinlwHrTlJbntp8a7NAlCKedVXe06Va/0DSLXRO8lZVtgbEMrYYSUZWQNcOlNtc58c2elNph6z9dMOYwSo3JQ==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@expo/spawn-async": "^1.5.0", + "exec-async": "^2.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@expo/dev-server/node_modules/@expo/plist": { + "version": "0.0.18", + "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.0.18.tgz", + "integrity": "sha512-+48gRqUiz65R21CZ/IXa7RNBXgAI/uPSdvJqoN9x1hfL44DNbUoWHgHiEXTx7XelcATpDwNTz6sHLfy0iNqf+w==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@xmldom/xmldom": "~0.7.0", + "base64-js": "^1.2.3", + "xmlbuilder": "^14.0.0" + } + }, + "node_modules/@expo/dev-server/node_modules/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/@expo/dev-server/node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/@expo/dev-server/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@expo/dev-server/node_modules/bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/@expo/dev-server/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@expo/dev-server/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@expo/dev-server/node_modules/fs-extra": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.0.tgz", + "integrity": "sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^1.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/dev-server/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@expo/dev-server/node_modules/http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@expo/dev-server/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "license": "ISC", + "optional": true, + "peer": true + }, + "node_modules/@expo/dev-server/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/@expo/dev-server/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@expo/dev-server/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@expo/dev-server/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT", + "optional": true, + "peer": true + }, + "node_modules/@expo/dev-server/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/@expo/dev-server/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@expo/dev-server/node_modules/qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "license": "BSD-3-Clause", + "optional": true, + "peer": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/@expo/dev-server/node_modules/raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/@expo/dev-server/node_modules/semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "license": "ISC", + "optional": true, + "peer": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/dev-server/node_modules/serialize-error": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-6.0.0.tgz", + "integrity": "sha512-3vmBkMZLQO+BR4RPHcyRGdE09XCF6cvxzk2N2qn8Er3F91cy8Qt7VvEbZBOpaL53qsBbe2cFOefU6tRY6WDelA==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "type-fest": "^0.12.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@expo/dev-server/node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "license": "ISC", + "optional": true, + "peer": true + }, + "node_modules/@expo/dev-server/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@expo/dev-server/node_modules/toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/@expo/dev-server/node_modules/type-fest": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.12.0.tgz", + "integrity": "sha512-53RyidyjvkGpnWPMF9bQgFtWp+Sl8O2Rp13VavmJgfAP9WWG6q6TkrKU8iyJdnwnfgHI6k2hTlgqH4aSdjoTbg==", + "license": "(MIT OR CC0-1.0)", + "optional": true, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@expo/dev-server/node_modules/universalify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", + "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@expo/dev-server/node_modules/write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "node_modules/@expo/devcert": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@expo/devcert/-/devcert-1.1.4.tgz", + "integrity": "sha512-fqBODr8c72+gBSX5Ty3SIzaY4bXainlpab78+vEYEKL3fXmsOswMLf0+KE36mUEAa36BYabX7K3EiXOXX5OPMw==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "application-config-path": "^0.1.0", + "command-exists": "^1.2.4", + "debug": "^3.1.0", + "eol": "^0.9.1", + "get-port": "^3.2.0", + "glob": "^10.4.2", + "lodash": "^4.17.21", + "mkdirp": "^0.5.1", + "password-prompt": "^1.0.4", + "sudo-prompt": "^8.2.0", + "tmp": "^0.0.33", + "tslib": "^2.4.0" + } + }, + "node_modules/@expo/devcert/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/@expo/devcert/node_modules/eol": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/eol/-/eol-0.9.1.tgz", + "integrity": "sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg==", + "license": "MIT", + "optional": true, + "peer": true + }, + "node_modules/@expo/devcert/node_modules/get-port": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", + "integrity": "sha512-x5UJKlgeUiNT8nyo/AcnwLnZuZNcSjSw0kogRB+Whd1fjjFq4B1hySFxSFWWSn4mIBzg3sRNUDFYc4g5gjPoLg==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@expo/devcert/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@expo/devcert/node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "license": "BlueOak-1.0.0", + "optional": true, + "peer": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/@expo/devcert/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@expo/devcert/node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/@expo/image-utils": { + "version": "0.3.21", + "resolved": "https://registry.npmjs.org/@expo/image-utils/-/image-utils-0.3.21.tgz", + "integrity": "sha512-Ha7pNcpl52RJIeYz3gR1ajOgPPl7WLZWiLqtLi94s9J0a7FvmNBMqd/VKrfHNj8QmtZxXcmXr7y7tPhZbVFg7w==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@expo/spawn-async": "1.5.0", + "chalk": "^4.0.0", + "fs-extra": "9.0.0", + "getenv": "^1.0.0", + "jimp-compact": "0.16.1", + "mime": "^2.4.4", + "node-fetch": "^2.6.0", + "parse-png": "^2.1.0", + "resolve-from": "^5.0.0", + "semver": "7.3.2", + "tempy": "0.3.0" + } + }, + "node_modules/@expo/image-utils/node_modules/crypto-random-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", + "integrity": "sha512-GsVpkFPlycH7/fRR7Dhcmnoii54gV1nz7y4CWyeFS14N+JVBBhY+r8amRHE4BwSYal7BPTDp8isvAlCxyFt3Hg==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@expo/image-utils/node_modules/fs-extra": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.0.tgz", + "integrity": "sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^1.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/image-utils/node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "license": "MIT", + "optional": true, + "peer": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/@expo/image-utils/node_modules/semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "license": "ISC", + "optional": true, + "peer": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/image-utils/node_modules/temp-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", + "integrity": "sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@expo/image-utils/node_modules/tempy": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.3.0.tgz", + "integrity": "sha512-WrH/pui8YCwmeiAoxV+lpRH9HpRtgBhSR2ViBPgpGb/wnYDzp21R4MN45fsCGvLROvY67o3byhJRYRONJyImVQ==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "temp-dir": "^1.0.0", + "type-fest": "^0.3.1", + "unique-string": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@expo/image-utils/node_modules/type-fest": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", + "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", + "license": "(MIT OR CC0-1.0)", + "optional": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@expo/image-utils/node_modules/unique-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", + "integrity": "sha512-ODgiYu03y5g76A1I9Gt0/chLCzQjvzDy7DsZGsLOE/1MrF6wriEskSncj1+/C58Xk/kPZDppSctDybCwOSaGAg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "crypto-random-string": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@expo/image-utils/node_modules/universalify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", + "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@expo/json-file": { + "version": "8.2.33", + "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-8.2.33.tgz", + "integrity": "sha512-CDnhjdirUs6OdN5hOSTJ2y3i9EiJMk7Z5iDljC5xyCHCrUex7oyI8vbRsZEojAahxZccgL/PrO+CjakiFFWurg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "~7.10.4", + "json5": "^1.0.1", + "write-file-atomic": "^2.3.0" + } + }, + "node_modules/@expo/json-file/node_modules/@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "node_modules/@expo/json-file/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "license": "MIT", + "peer": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/@expo/json-file/node_modules/write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "license": "ISC", + "peer": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "node_modules/@expo/metro-config": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@expo/metro-config/-/metro-config-0.2.8.tgz", + "integrity": "sha512-8g0QrHfvSgTLzryuE4JXRwFwBZ7EmqE55zR39Yy7jEVR3epYL0JbBK0/IDFmf6auwsDFtMjAZjFL4WEhRN5bEQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@expo/config": "6.0.6", + "chalk": "^4.1.0", + "debug": "^4.3.2", + "getenv": "^1.0.0", + "sucrase": "^3.20.0" + } + }, + "node_modules/@expo/osascript": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@expo/osascript/-/osascript-2.1.5.tgz", + "integrity": "sha512-Cp7YF7msGiTAIbFdzNovwHBfecdMLVL5XzSqq4xQz72ALFCQ3uSIUXRph1QV2r61ugH7Yem0gY8yi7RcDlI4qg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@expo/spawn-async": "^1.7.2", + "exec-async": "^2.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@expo/osascript/node_modules/@expo/spawn-async": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@expo/spawn-async/-/spawn-async-1.7.2.tgz", + "integrity": "sha512-QdWi16+CHB9JYP7gma19OVVg0BFkvU8zNj9GjWorYI8Iv8FUxjOCcYRuAmX4s/h91e4e7BPsskc8cSrZYho9Ew==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "cross-spawn": "^7.0.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@expo/package-manager": { + "version": "0.0.60", + "resolved": "https://registry.npmjs.org/@expo/package-manager/-/package-manager-0.0.60.tgz", + "integrity": "sha512-MdV7dpFA4aI8HIW0xsW2DBUem5aFKL8+/v5LXKPZuXmYW02/EXPSp7DBJAwow8ULpa3Q2VlYfb46hWPre3hw4A==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@expo/json-file": "^8.2.37", + "@expo/spawn-async": "^1.5.0", + "ansi-regex": "^5.0.0", + "chalk": "^4.0.0", + "find-up": "^5.0.0", + "find-yarn-workspace-root": "~2.0.0", + "npm-package-arg": "^7.0.0", + "rimraf": "^3.0.2", + "split": "^1.0.1", + "sudo-prompt": "9.1.1" + } + }, + "node_modules/@expo/package-manager/node_modules/@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "node_modules/@expo/package-manager/node_modules/@expo/json-file": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-8.3.3.tgz", + "integrity": "sha512-eZ5dld9AD0PrVRiIWpRkm5aIoWBw3kAyd8VkuWEy92sEthBKDDDHAnK2a0dw0Eil6j7rK7lS/Qaq/Zzngv2h5A==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@babel/code-frame": "~7.10.4", + "json5": "^2.2.2", + "write-file-atomic": "^2.3.0" + } + }, + "node_modules/@expo/package-manager/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@expo/package-manager/node_modules/hosted-git-info": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz", + "integrity": "sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/package-manager/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@expo/package-manager/node_modules/npm-package-arg": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-7.0.0.tgz", + "integrity": "sha512-xXxr8y5U0kl8dVkz2oK7yZjPBvqM2fwaO5l3Yg13p03v8+E3qQcD0JNhHzjL1vyGgxcKkD0cco+NLR72iuPk3g==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "hosted-git-info": "^3.0.2", + "osenv": "^0.1.5", + "semver": "^5.6.0", + "validate-npm-package-name": "^3.0.0" + } + }, + "node_modules/@expo/package-manager/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@expo/package-manager/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", + "optional": true, + "peer": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@expo/package-manager/node_modules/sudo-prompt": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/sudo-prompt/-/sudo-prompt-9.1.1.tgz", + "integrity": "sha512-es33J1g2HjMpyAhz8lOR+ICmXXAqTuKbuXuUWLhOLew20oN9oUCgCJx615U/v7aioZg7IX5lIh9x34vwneu4pA==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "license": "MIT", + "optional": true, + "peer": true + }, + "node_modules/@expo/package-manager/node_modules/validate-npm-package-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", + "integrity": "sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "builtins": "^1.0.3" + } + }, + "node_modules/@expo/package-manager/node_modules/write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "node_modules/@expo/plist": { + "version": "0.0.15", + "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.0.15.tgz", + "integrity": "sha512-LDxiS0KNZAGJu4fIJhbEKczmb+zeftl1NU0LE0tj0mozoMI5HSKdMUchgvnBm35bwBl8ekKkAfJJ0ONxljWQjQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@xmldom/xmldom": "~0.7.0", + "base64-js": "^1.2.3", + "xmlbuilder": "^14.0.0" + } + }, + "node_modules/@expo/prebuild-config": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@expo/prebuild-config/-/prebuild-config-4.0.4.tgz", + "integrity": "sha512-yvoc2w4zwiq1wko8FE8/N3e1HSrXQP8XUvX8nIJtQ2mrSLGktbg9SzNM8+s8aBVTd4j1Zp3bcMzTsYnG9ygYbA==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@expo/config": "6.0.26", + "@expo/config-plugins": "4.1.5", + "@expo/config-types": "^45.0.0", + "@expo/image-utils": "0.3.21", + "@expo/json-file": "8.2.36", + "debug": "^4.3.1", + "expo-modules-autolinking": "0.8.1", + "fs-extra": "^9.0.0", + "resolve-from": "^5.0.0", + "semver": "7.3.2", + "xml2js": "0.4.23" + } + }, + "node_modules/@expo/prebuild-config/node_modules/@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "node_modules/@expo/prebuild-config/node_modules/@expo/config": { + "version": "6.0.26", + "resolved": "https://registry.npmjs.org/@expo/config/-/config-6.0.26.tgz", + "integrity": "sha512-nMQaZl69r6CMJFhCj0xcGJN9bIi4Uws0k9K6q6rGFPFNarS0z0aexeyNLv93/J+hsTJVn0GEYtGz5Y/R8boXxw==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@babel/code-frame": "~7.10.4", + "@expo/config-plugins": "4.1.5", + "@expo/config-types": "^45.0.0", + "@expo/json-file": "8.2.36", + "getenv": "^1.0.0", + "glob": "7.1.6", + "require-from-string": "^2.0.2", + "resolve-from": "^5.0.0", + "semver": "7.3.2", + "slugify": "^1.3.4", + "sucrase": "^3.20.0" + } + }, + "node_modules/@expo/prebuild-config/node_modules/@expo/config-plugins": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-4.1.5.tgz", + "integrity": "sha512-RVvU40RtZt12HavuDAe+LDIq9lHj7sheOfMEHdmpJ/uTA8pgvkbc56XF6JHQD+yRr6+uhhb+JnAasGq49dsQbw==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@expo/config-types": "^45.0.0", + "@expo/json-file": "8.2.36", + "@expo/plist": "0.0.18", + "@expo/sdk-runtime-versions": "^1.0.0", + "@react-native/normalize-color": "^2.0.0", + "chalk": "^4.1.2", + "debug": "^4.3.1", + "find-up": "~5.0.0", + "getenv": "^1.0.0", + "glob": "7.1.6", + "resolve-from": "^5.0.0", + "semver": "^7.3.5", + "slash": "^3.0.0", + "xcode": "^3.0.1", + "xml2js": "0.4.23" + } + }, + "node_modules/@expo/prebuild-config/node_modules/@expo/config-plugins/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "optional": true, + "peer": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/prebuild-config/node_modules/@expo/config-types": { + "version": "45.0.0", + "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-45.0.0.tgz", + "integrity": "sha512-/QGhhLWyaGautgEyU50UJr5YqKJix5t77ePTwreOVAhmZH+ff3nrrtYTTnccx+qF08ZNQmfAyYMCD3rQfzpiJA==", + "license": "MIT", + "optional": true, + "peer": true + }, + "node_modules/@expo/prebuild-config/node_modules/@expo/json-file": { + "version": "8.2.36", + "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-8.2.36.tgz", + "integrity": "sha512-tOZfTiIFA5KmMpdW9KF7bc6CFiGjb0xnbieJhTGlHrLL+ps2G0OkqmuZ3pFEXBOMnJYUVpnSy++52LFxvpa5ZQ==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@babel/code-frame": "~7.10.4", + "json5": "^1.0.1", + "write-file-atomic": "^2.3.0" + } + }, + "node_modules/@expo/prebuild-config/node_modules/@expo/plist": { + "version": "0.0.18", + "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.0.18.tgz", + "integrity": "sha512-+48gRqUiz65R21CZ/IXa7RNBXgAI/uPSdvJqoN9x1hfL44DNbUoWHgHiEXTx7XelcATpDwNTz6sHLfy0iNqf+w==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@xmldom/xmldom": "~0.7.0", + "base64-js": "^1.2.3", + "xmlbuilder": "^14.0.0" + } + }, + "node_modules/@expo/prebuild-config/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@expo/prebuild-config/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@expo/prebuild-config/node_modules/expo-modules-autolinking": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-0.8.1.tgz", + "integrity": "sha512-S8qfaXCv//7tQWV9M+JKx3CF7ypYhDdSUbkUQdaVO/r8D76/aRTArY/aRw1yEfaAOzyK8C8diDToV1itl51DfQ==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "chalk": "^4.1.0", + "commander": "^7.2.0", + "fast-glob": "^3.2.5", + "find-up": "^5.0.0", + "fs-extra": "^9.1.0" + }, + "bin": { + "expo-modules-autolinking": "bin/expo-modules-autolinking.js" + } + }, + "node_modules/@expo/prebuild-config/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@expo/prebuild-config/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/prebuild-config/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@expo/prebuild-config/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/@expo/prebuild-config/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@expo/prebuild-config/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@expo/prebuild-config/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@expo/prebuild-config/node_modules/semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "license": "ISC", + "optional": true, + "peer": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/prebuild-config/node_modules/write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "node_modules/@expo/rudder-sdk-node": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@expo/rudder-sdk-node/-/rudder-sdk-node-1.1.1.tgz", + "integrity": "sha512-uy/hS/awclDJ1S88w9UGpc6Nm9XnNUjzOAAib1A3PVAnGQIwebg8DpFqOthFBTlZxeuV/BKbZ5jmTbtNZkp1WQ==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@expo/bunyan": "^4.0.0", + "@segment/loosely-validate-event": "^2.0.0", + "fetch-retry": "^4.1.1", + "md5": "^2.2.1", + "node-fetch": "^2.6.1", + "remove-trailing-slash": "^0.1.0", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@expo/rudder-sdk-node/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "optional": true, + "peer": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@expo/sdk-runtime-versions": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@expo/sdk-runtime-versions/-/sdk-runtime-versions-1.0.0.tgz", + "integrity": "sha512-Doz2bfiPndXYFPMRwPyGa1k5QaKDVpY806UJj570epIiMzWaYyCtobasyfC++qfIXVb5Ocy7r3tP9d62hAQ7IQ==", + "license": "MIT", + "optional": true, + "peer": true + }, + "node_modules/@expo/spawn-async": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@expo/spawn-async/-/spawn-async-1.5.0.tgz", + "integrity": "sha512-LB7jWkqrHo+5fJHNrLAFdimuSXQ2MQ4lA7SQW5bf/HbsXuV2VrT/jN/M8f/KoWt0uJMGN4k/j7Opx4AvOOxSew==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "cross-spawn": "^6.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@expo/spawn-async/node_modules/cross-spawn": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", + "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/@expo/spawn-async/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@expo/spawn-async/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", + "optional": true, + "peer": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@expo/spawn-async/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@expo/spawn-async/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@expo/spawn-async/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/@expo/vector-icons": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/@expo/vector-icons/-/vector-icons-12.0.5.tgz", + "integrity": "sha512-zWvHBmkpbi1KrPma6Y+r/bsGI6MjbM1MBSe6W9A4uYMLhNI5NR4JtTnqxhf7g1XdpaDtBdv5aOWKEx4d5rxnhg==", + "license": "MIT", + "peer": true, + "dependencies": { + "lodash.frompairs": "^4.0.1", + "lodash.isequal": "^4.5.0", + "lodash.isstring": "^4.0.1", + "lodash.omit": "^4.5.0", + "lodash.pick": "^4.4.0", + "lodash.template": "^4.5.0" + } + }, + "node_modules/@expo/xcpretty": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@expo/xcpretty/-/xcpretty-4.3.2.tgz", + "integrity": "sha512-ReZxZ8pdnoI3tP/dNnJdnmAk7uLT4FjsKDGW7YeDdvdOMz2XCQSmSCM9IWlrXuWtMF9zeSB6WJtEhCQ41gQOfw==", + "license": "BSD-3-Clause", + "optional": true, + "peer": true, + "dependencies": { + "@babel/code-frame": "7.10.4", + "chalk": "^4.1.0", + "find-up": "^5.0.0", + "js-yaml": "^4.1.0" + }, + "bin": { + "excpretty": "build/cli.js" + } + }, + "node_modules/@expo/xcpretty/node_modules/@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "node_modules/@expo/xcpretty/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@expo/xcpretty/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@expo/xcpretty/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@faker-js/faker": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-9.0.1.tgz", + "integrity": "sha512-4mDeYIgM3By7X6t5E6eYwLAa+2h4DeZDF7thhzIg6XB76jeEvMwadYAMCFJL/R4AnEBcAUO9+gL0vhy3s+qvZA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/fakerjs" + } + ], + "engines": { + "node": ">=18.0.0", + "npm": ">=9.0.0" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.4.tgz", + "integrity": "sha512-a4IowK4QkXl4SCWTGUR0INAfEOX3wtsYw3rKK5InQEHMGObkR8Xk44qYQD9P4r6HHw0iIfK6GUKECmY8sTkqRA==", + "dependencies": { + "@floating-ui/utils": "^0.2.4" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.7.tgz", + "integrity": "sha512-wmVfPG5o2xnKDU4jx/m4w5qva9FWHcnZ8BvzEe90D/RpwsJaTAVYPEPdQ8sbr/N8zZTAHlZUTQdqg8ZUbzHmng==", + "dependencies": { + "@floating-ui/core": "^1.6.0", + "@floating-ui/utils": "^0.2.4" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.1.tgz", + "integrity": "sha512-4h84MJt3CHrtG18mGsXuLCHMrug49d7DFkU0RMIyshRveBeyV2hmV/pDaF2Uxtu8kgq5r46llp5E5FQiR0K2Yg==", + "dependencies": { + "@floating-ui/dom": "^1.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.4.tgz", + "integrity": "sha512-dWO2pw8hhi+WrXq1YJy2yCuWoL20PddgGaqTgVe4cOS9Q6qklXCiA1tJEqX6BEwRNSCP84/afac9hd4MS+zEUA==" + }, + "node_modules/@fortawesome/fontawesome-common-types": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.2.tgz", + "integrity": "sha512-gBxPg3aVO6J0kpfHNILc+NMhXnqHumFxOmjYCFfOiLZfwhnnfhtsdA2hfJlDnj+8PjAs6kKQPenOTKj3Rf7zHw==", + "hasInstallScript": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/fontawesome-svg-core": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.5.2.tgz", + "integrity": "sha512-5CdaCBGl8Rh9ohNdxeeTMxIj8oc3KNBgIeLMvJosBMdslK/UnEB8rzyDRrbKdL1kDweqBPo4GT9wvnakHWucZw==", + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.5.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/free-solid-svg-icons": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.5.2.tgz", + "integrity": "sha512-QWFZYXFE7O1Gr1dTIp+D6UcFUF0qElOnZptpi7PBUMylJh+vFmIedVe1Ir6RM1t2tEQLLSV1k7bR4o92M+uqlw==", + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.5.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/react-fontawesome": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.2.tgz", + "integrity": "sha512-EnkrprPNqI6SXJl//m29hpaNzOp1bruISWaOiRtkMi/xSvHJlzc2j2JAYS7egxt/EbjSNV/k6Xy0AQI6vB2+1g==", + "dependencies": { + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "@fortawesome/fontawesome-svg-core": "~1 || ~6", + "react": ">=16.3" + } + }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "license": "MIT", + "optional": true, + "peer": true + }, + "node_modules/@graphql-typed-document-node/core": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz", + "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==", + "license": "MIT", + "optional": true, + "peer": true, + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@grpc/grpc-js": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.12.2.tgz", + "integrity": "sha512-bgxdZmgTrJZX50OjyVwz3+mNEnCTNkh3cIqGPWVNeW9jX6bn1ZkU80uPd+67/ZpIJIjRQ9qaHCjhavyoWYxumg==", + "dependencies": { + "@grpc/proto-loader": "^0.7.13", + "@js-sdsl/ordered-map": "^4.4.2" + }, + "engines": { + "node": ">=12.10.0" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.7.13", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz", + "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==", + "dependencies": { + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.2.5", + "yargs": "^17.7.2" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@grpc/proto-loader/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/@grpc/proto-loader/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@grpc/proto-loader/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@grpc/proto-loader/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@hashgraph/cryptography": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@hashgraph/cryptography/-/cryptography-1.1.2.tgz", + "integrity": "sha512-oSnDDs5foNq6Yni4kCwbA01NuVY2mewVr1jhkJG7yNDT6+xIBCztRWDeINb1JuShXe57Cuf88M1zmN5iFN7JgA==", + "license": "Apache-2.0", + "dependencies": { + "bignumber.js": "^9.0.2", + "crypto-js": "^4.1.1", + "elliptic": "^6.5.4", + "expo-crypto": "^10.1.2", + "expo-random": "^12.1.2", + "js-base64": "^3.7.2", + "tweetnacl": "^1.0.3", + "utf8": "^3.0.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "expo": "^44.0.5" + } + }, + "node_modules/@hashgraph/proto": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@hashgraph/proto/-/proto-2.12.0.tgz", + "integrity": "sha512-IIN6K3b2X8ih7V14IDH8rsVJ1DE9ud25FfKUpr+lDNnQdBfdZdG2AGlHRhc9iDAz4vCHoHc6F3Ao6yYKMceeTg==", + "license": "Apache-2.0", + "dependencies": { + "long": "^4.0.0", + "protobufjs": "^7.1.2", + "protobufjs-cli": "^1.0.2" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@hashgraph/proto/node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", + "license": "Apache-2.0" + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "deprecated": "Use @eslint/config-array instead", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead" + }, + "node_modules/@inquirer/confirm": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.0.tgz", + "integrity": "sha512-osaBbIMEqVFjTX5exoqPXs6PilWQdjaLhGtMDXMXg/yxkHXNq43GlxGyTA35lK2HpzUgDN+Cjh/2AmqCN0QJpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.1", + "@inquirer/type": "^3.0.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/core": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.1.tgz", + "integrity": "sha512-rmZVXy9iZvO3ZStEe/ayuuwIJ23LSF13aPMlLMTQARX6lGUBDHGV8UB5i9MRrfy0+mZwt5/9bdy8llszSD3NQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/figures": "^1.0.8", + "@inquirer/type": "^3.0.1", + "ansi-escapes": "^4.3.2", + "cli-width": "^4.1.0", + "mute-stream": "^2.0.0", + "signal-exit": "^4.1.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/core/node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 12" + } + }, + "node_modules/@inquirer/core/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@inquirer/core/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/core/node_modules/mute-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", + "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@inquirer/core/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@inquirer/core/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/core/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/figures": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.8.tgz", + "integrity": "sha512-tKd+jsmhq21AP1LhexC0pPwsCxEhGgAkg28byjJAd+xhmIs8LUX8JbUc3vBf3PhLxWiB5EvyBE5X7JSPAqMAqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/type": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.1.tgz", + "integrity": "sha512-+ksJMIy92sOAiAccGpcKZUc3bYO07cADnscIxHBknEm3uNts3movSmBofc1908BNy5edKscxYeAdaX1NXkHS6A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@ioredis/commands": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", + "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==" + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/ttlcache": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz", + "integrity": "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==", + "license": "ISC", + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/core/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/core/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, + "node_modules/@jest/create-cache-key-function": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz", + "integrity": "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/types": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@js-sdsl/ordered-map": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", + "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/@jsdoc/salty": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.9.tgz", + "integrity": "sha512-yYxMVH7Dqw6nO0d5NIV8OQWnitU8k6vXH8NtgqAfIa/IUqRMxRv/NUJJ08VEKbAakwxlgBl5PJdrU0dMPStsnw==", + "license": "Apache-2.0", + "dependencies": { + "lodash": "^4.17.21" + }, + "engines": { + "node": ">=v12.0.0" + } + }, + "node_modules/@jsonjoy.com/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", + "dev": true, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/json-pack": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.1.0.tgz", + "integrity": "sha512-zlQONA+msXPPwHWZMKFVS78ewFczIll5lXiVPwFPCZUsrOKdxc2AvxU1HoNBmMRhqDZUR9HkC3UOm+6pME6Xsg==", + "dev": true, + "dependencies": { + "@jsonjoy.com/base64": "^1.1.1", + "@jsonjoy.com/util": "^1.1.2", + "hyperdyperid": "^1.2.0", + "thingies": "^1.20.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/util": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.3.0.tgz", + "integrity": "sha512-Cebt4Vk7k1xHy87kHY7KSPLT77A7Ev7IfOblyLZhtYEhrdQ6fX4EoLq3xOQ3O/DRMEh2ok5nyC180E+ABS8Wmw==", + "dev": true, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@keyv/serialize": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.0.2.tgz", + "integrity": "sha512-+E/LyaAeuABniD/RvUezWVXKpeuvwLEA9//nE9952zBaOdBd2mQ3pPoM8cUe2X6IcMByfuSLzmYqnYshG60+HQ==", + "license": "MIT", + "dependencies": { + "buffer": "^6.0.3" + } + }, + "node_modules/@keyv/serialize/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/@ledgerhq/devices": { + "version": "5.51.1", + "resolved": "https://registry.npmjs.org/@ledgerhq/devices/-/devices-5.51.1.tgz", + "integrity": "sha512-4w+P0VkbjzEXC7kv8T1GJ/9AVaP9I6uasMZ/JcdwZBS3qwvKo5A5z9uGhP5c7TvItzcmPb44b5Mw2kT+WjUuAA==", + "license": "Apache-2.0", + "dependencies": { + "@ledgerhq/errors": "^5.50.0", + "@ledgerhq/logs": "^5.50.0", + "rxjs": "6", + "semver": "^7.3.5" + } + }, + "node_modules/@ledgerhq/devices/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/@ledgerhq/devices/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@ledgerhq/devices/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, + "node_modules/@ledgerhq/errors": { + "version": "5.50.0", + "resolved": "https://registry.npmjs.org/@ledgerhq/errors/-/errors-5.50.0.tgz", + "integrity": "sha512-gu6aJ/BHuRlpU7kgVpy2vcYk6atjB4iauP2ymF7Gk0ez0Y/6VSMVSJvubeEQN+IV60+OBK0JgeIZG7OiHaw8ow==", + "license": "Apache-2.0" + }, + "node_modules/@ledgerhq/hw-transport": { + "version": "5.51.1", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport/-/hw-transport-5.51.1.tgz", + "integrity": "sha512-6wDYdbWrw9VwHIcoDnqWBaDFyviyjZWv6H9vz9Vyhe4Qd7TIFmbTl/eWs6hZvtZBza9K8y7zD8ChHwRI4s9tSw==", + "license": "Apache-2.0", + "dependencies": { + "@ledgerhq/devices": "^5.51.1", + "@ledgerhq/errors": "^5.50.0", + "events": "^3.3.0" + } + }, + "node_modules/@ledgerhq/hw-transport-web-ble": { + "version": "5.48.0", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-web-ble/-/hw-transport-web-ble-5.48.0.tgz", + "integrity": "sha512-ezgssFvxc4/UbfwIxwg9jEn0/yiND8TW6bDkaE3kAqKCa8ZYYgFtms8iRqjTOJlqcbSYkudbNhP74jtY0NxfdA==", + "license": "Apache-2.0", + "dependencies": { + "@ledgerhq/devices": "^5.48.0", + "@ledgerhq/errors": "^5.48.0", + "@ledgerhq/hw-transport": "^5.48.0", + "@ledgerhq/logs": "^5.48.0", + "rxjs": "^6.6.7" + } + }, + "node_modules/@ledgerhq/hw-transport-web-ble/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/@ledgerhq/hw-transport-web-ble/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, + "node_modules/@ledgerhq/hw-transport-webhid": { + "version": "5.48.0", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-webhid/-/hw-transport-webhid-5.48.0.tgz", + "integrity": "sha512-g6TYxgPX3MqP3jQ4SJaJjlM+2SwUSk4Si/9MeKLwz5ySbiD3bSTh/Gbzv8VBCaHPO4fILujc5vW/xejJuMzR8w==", + "license": "Apache-2.0", + "dependencies": { + "@ledgerhq/devices": "^5.48.0", + "@ledgerhq/errors": "^5.48.0", + "@ledgerhq/hw-transport": "^5.48.0", + "@ledgerhq/logs": "^5.48.0" + } + }, + "node_modules/@ledgerhq/hw-transport-webusb": { + "version": "5.48.0", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-webusb/-/hw-transport-webusb-5.48.0.tgz", + "integrity": "sha512-tO+p11aRQx9q9ifmi/NCbCBKQ738lp+PROy1BWSzjCJcUEz1sKTLeRTLE2Xze25KebhuM2YR1NgkX5LN1z4upA==", + "license": "Apache-2.0", + "dependencies": { + "@ledgerhq/devices": "^5.48.0", + "@ledgerhq/errors": "^5.48.0", + "@ledgerhq/hw-transport": "^5.48.0", + "@ledgerhq/logs": "^5.48.0" + } + }, + "node_modules/@ledgerhq/logs": { + "version": "5.50.0", + "resolved": "https://registry.npmjs.org/@ledgerhq/logs/-/logs-5.50.0.tgz", + "integrity": "sha512-swKHYCOZUGyVt4ge0u8a7AwNcA//h4nx5wIi0sruGye1IJ5Cva0GyK9L2/WdX+kWVTKp92ZiEo1df31lrWGPgA==", + "license": "Apache-2.0" + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==" + }, + "node_modules/@lit-labs/ssr-dom-shim": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.2.1.tgz", + "integrity": "sha512-wx4aBmgeGvFmOKucFKY+8VFJSYZxs9poN3SDNQFF6lT6NrQUnHiPB2PWz2sc4ieEcAaYYzN+1uWahEeTq2aRIQ==" + }, + "node_modules/@lit/reactive-element": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.6.3.tgz", + "integrity": "sha512-QuTgnG52Poic7uM1AN5yJ09QMe0O28e10XzSvWDz02TJiiKee4stsiownEIadWm8nYzyDAyT+gKzUoZmiWQtsQ==", + "dependencies": { + "@lit-labs/ssr-dom-shim": "^1.0.0" + } + }, + "node_modules/@lukeed/csprng": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz", + "integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@mdx-js/mdx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.0.1.tgz", + "integrity": "sha512-eIQ4QTrOWyL3LWEe/bu6Taqzq2HQvHcyTMaOrI95P2/LmJE7AsfPfgJGuFLPVqBUE1BC1rik3VIhU+s9u72arA==", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdx": "^2.0.0", + "collapse-white-space": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-build-jsx": "^3.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-util-to-js": "^2.0.0", + "estree-walker": "^3.0.0", + "hast-util-to-estree": "^3.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "markdown-extensions": "^2.0.0", + "periscopic": "^3.0.0", + "remark-mdx": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "source-map": "^0.7.0", + "unified": "^11.0.0", + "unist-util-position-from-estree": "^2.0.0", + "unist-util-stringify-position": "^4.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mdx-js/react": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.1.tgz", + "integrity": "sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A==", + "dependencies": { + "@types/mdx": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=16", + "react": ">=16" + } + }, + "node_modules/@metamask/eth-json-rpc-provider": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@metamask/eth-json-rpc-provider/-/eth-json-rpc-provider-1.0.1.tgz", + "integrity": "sha512-whiUMPlAOrVGmX8aKYVPvlKyG4CpQXiNNyt74vE1xb5sPvmx5oA7B/kOi/JdBvhGQq97U1/AVdXEdk2zkP8qyA==", + "dependencies": { + "@metamask/json-rpc-engine": "^7.0.0", + "@metamask/safe-event-emitter": "^3.0.0", + "@metamask/utils": "^5.0.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@metamask/eth-json-rpc-provider/node_modules/@metamask/json-rpc-engine": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@metamask/json-rpc-engine/-/json-rpc-engine-7.3.3.tgz", + "integrity": "sha512-dwZPq8wx9yV3IX2caLi9q9xZBw2XeIoYqdyihDDDpuHVCEiqadJLwqM3zy+uwf6F1QYQ65A8aOMQg1Uw7LMLNg==", + "dependencies": { + "@metamask/rpc-errors": "^6.2.1", + "@metamask/safe-event-emitter": "^3.0.0", + "@metamask/utils": "^8.3.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@metamask/eth-json-rpc-provider/node_modules/@metamask/json-rpc-engine/node_modules/@metamask/utils": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-8.5.0.tgz", + "integrity": "sha512-I6bkduevXb72TIM9q2LRO63JSsF9EXduh3sBr9oybNX2hNNpr/j1tEjXrsG0Uabm4MJ1xkGAQEMwifvKZIkyxQ==", + "dependencies": { + "@ethereumjs/tx": "^4.2.0", + "@metamask/superstruct": "^3.0.0", + "@noble/hashes": "^1.3.1", + "@scure/base": "^1.1.3", + "@types/debug": "^4.1.7", + "debug": "^4.3.4", + "pony-cause": "^2.1.10", + "semver": "^7.5.4", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@metamask/eth-json-rpc-provider/node_modules/@metamask/utils": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-5.0.2.tgz", + "integrity": "sha512-yfmE79bRQtnMzarnKfX7AEJBwFTxvTyw3nBQlu/5rmGXrjAeAMltoGxO62TFurxrQAFMNa/fEjIHNvungZp0+g==", + "dependencies": { + "@ethereumjs/tx": "^4.1.2", + "@types/debug": "^4.1.7", + "debug": "^4.3.4", + "semver": "^7.3.8", + "superstruct": "^1.0.3" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@metamask/eth-json-rpc-provider/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@metamask/eth-sig-util": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@metamask/eth-sig-util/-/eth-sig-util-5.1.0.tgz", + "integrity": "sha512-mlgziIHYlA9pi/XZerChqg4NocdOgBPB9NmxgXWQO2U2hH8RGOJQrz6j/AIKkYxgCMIE2PY000+joOwXfzeTDQ==", + "license": "ISC", + "dependencies": { + "@ethereumjs/util": "^8.0.6", + "bn.js": "^4.12.0", + "ethereum-cryptography": "^2.0.0", + "ethjs-util": "^0.1.6", + "tweetnacl": "^1.0.3", + "tweetnacl-util": "^0.15.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@metamask/eth-sig-util/node_modules/bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "license": "MIT" + }, + "node_modules/@metamask/json-rpc-engine": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@metamask/json-rpc-engine/-/json-rpc-engine-8.0.2.tgz", + "integrity": "sha512-IoQPmql8q7ABLruW7i4EYVHWUbF74yrp63bRuXV5Zf9BQwcn5H9Ww1eLtROYvI1bUXwOiHZ6qT5CWTrDc/t/AA==", + "dependencies": { + "@metamask/rpc-errors": "^6.2.1", + "@metamask/safe-event-emitter": "^3.0.0", + "@metamask/utils": "^8.3.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@metamask/json-rpc-middleware-stream": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@metamask/json-rpc-middleware-stream/-/json-rpc-middleware-stream-7.0.2.tgz", + "integrity": "sha512-yUdzsJK04Ev98Ck4D7lmRNQ8FPioXYhEUZOMS01LXW8qTvPGiRVXmVltj2p4wrLkh0vW7u6nv0mNl5xzC5Qmfg==", + "dependencies": { + "@metamask/json-rpc-engine": "^8.0.2", + "@metamask/safe-event-emitter": "^3.0.0", + "@metamask/utils": "^8.3.0", + "readable-stream": "^3.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@metamask/object-multiplex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@metamask/object-multiplex/-/object-multiplex-2.1.0.tgz", + "integrity": "sha512-4vKIiv0DQxljcXwfpnbsXcfa5glMj5Zg9mqn4xpIWqkv6uJ2ma5/GtUfLFSxhlxnR8asRMv8dDmWya1Tc1sDFA==", + "dependencies": { + "once": "^1.4.0", + "readable-stream": "^3.6.2" + }, + "engines": { + "node": "^16.20 || ^18.16 || >=20" + } + }, + "node_modules/@metamask/onboarding": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@metamask/onboarding/-/onboarding-1.0.1.tgz", + "integrity": "sha512-FqHhAsCI+Vacx2qa5mAFcWNSrTcVGMNjzxVgaX8ECSny/BJ9/vgXP9V7WF/8vb9DltPeQkxr+Fnfmm6GHfmdTQ==", + "dependencies": { + "bowser": "^2.9.0" + } + }, + "node_modules/@metamask/providers": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@metamask/providers/-/providers-16.1.0.tgz", + "integrity": "sha512-znVCvux30+3SaUwcUGaSf+pUckzT5ukPRpcBmy+muBLC0yaWnBcvDqGfcsw6CBIenUdFrVoAFa8B6jsuCY/a+g==", + "dependencies": { + "@metamask/json-rpc-engine": "^8.0.1", + "@metamask/json-rpc-middleware-stream": "^7.0.1", + "@metamask/object-multiplex": "^2.0.0", + "@metamask/rpc-errors": "^6.2.1", + "@metamask/safe-event-emitter": "^3.1.1", + "@metamask/utils": "^8.3.0", + "detect-browser": "^5.2.0", + "extension-port-stream": "^3.0.0", + "fast-deep-equal": "^3.1.3", + "is-stream": "^2.0.0", + "readable-stream": "^3.6.2", + "webextension-polyfill": "^0.10.0" + }, + "engines": { + "node": "^18.18 || >=20" + } + }, + "node_modules/@metamask/rpc-errors": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@metamask/rpc-errors/-/rpc-errors-6.4.0.tgz", + "integrity": "sha512-1ugFO1UoirU2esS3juZanS/Fo8C8XYocCuBpfZI5N7ECtoG+zu0wF+uWZASik6CkO6w9n/Iebt4iI4pT0vptpg==", + "dependencies": { + "@metamask/utils": "^9.0.0", + "fast-safe-stringify": "^2.0.6" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@metamask/rpc-errors/node_modules/@metamask/utils": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-9.3.0.tgz", + "integrity": "sha512-w8CVbdkDrVXFJbfBSlDfafDR6BAkpDmv1bC1UJVCoVny5tW2RKAdn9i68Xf7asYT4TnUhl/hN4zfUiKQq9II4g==", + "dependencies": { + "@ethereumjs/tx": "^4.2.0", + "@metamask/superstruct": "^3.1.0", + "@noble/hashes": "^1.3.1", + "@scure/base": "^1.1.3", + "@types/debug": "^4.1.7", + "debug": "^4.3.4", + "pony-cause": "^2.1.10", + "semver": "^7.5.4", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@metamask/rpc-errors/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@metamask/safe-event-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@metamask/safe-event-emitter/-/safe-event-emitter-3.1.2.tgz", + "integrity": "sha512-5yb2gMI1BDm0JybZezeoX/3XhPDOtTbcFvpTXM9kxsoZjPZFh4XciqRbpD6N86HYZqWDhEaKUDuOyR0sQHEjMA==", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@metamask/sdk": { + "version": "0.30.1", + "resolved": "https://registry.npmjs.org/@metamask/sdk/-/sdk-0.30.1.tgz", + "integrity": "sha512-NelEjJZsF5wVpSQELpmvXtnS9+C6HdxGQ4GB9jMRzeejphmPyKqmrIGM6XtaPrJtlpX+40AcJ2dtBQcjJVzpbQ==", + "dependencies": { + "@metamask/onboarding": "^1.0.1", + "@metamask/providers": "16.1.0", + "@metamask/sdk-communication-layer": "0.30.0", + "@metamask/sdk-install-modal-web": "0.30.0", + "bowser": "^2.9.0", + "cross-fetch": "^4.0.0", + "debug": "^4.3.4", + "eciesjs": "^0.4.8", + "eth-rpc-errors": "^4.0.3", + "eventemitter2": "^6.4.7", + "i18next": "23.11.5", + "i18next-browser-languagedetector": "7.1.0", + "obj-multiplex": "^1.0.0", + "pump": "^3.0.0", + "qrcode-terminal-nooctal": "^0.12.1", + "react-native-webview": "^11.26.0", + "readable-stream": "^3.6.2", + "socket.io-client": "^4.5.1", + "util": "^0.12.4", + "uuid": "^8.3.2" + }, + "peerDependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/@metamask/sdk-communication-layer": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/@metamask/sdk-communication-layer/-/sdk-communication-layer-0.30.0.tgz", + "integrity": "sha512-q5nbdYkAf76MsZxi1l5MJEAyd8sY9jLRapC8a7x1Q1BNV4rzQeFeux/d0mJ/jTR2LAwbnLZs2rL226AM75oK4w==", + "dependencies": { + "bufferutil": "^4.0.8", + "date-fns": "^2.29.3", + "debug": "^4.3.4", + "utf-8-validate": "^5.0.2", + "uuid": "^8.3.2" + }, + "peerDependencies": { + "cross-fetch": "^4.0.0", + "eciesjs": "^0.3.16", + "eventemitter2": "^6.4.7", + "readable-stream": "^3.6.2", + "socket.io-client": "^4.5.1" + } + }, + "node_modules/@metamask/sdk-communication-layer/node_modules/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, + "node_modules/@metamask/sdk-communication-layer/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@metamask/sdk-install-modal-web": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/@metamask/sdk-install-modal-web/-/sdk-install-modal-web-0.30.0.tgz", + "integrity": "sha512-1gT533Huja9tK3cmttvcpZirRAtWJ7vnYH+lnNRKEj2xIP335Df2cOwS+zqNC4GlRCZw7A3IsTjIzlKoxBY1uQ==", + "dependencies": { + "qr-code-styling": "^1.6.0-rc.1" + }, + "peerDependencies": { + "i18next": "23.11.5", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-native": "*" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, + "node_modules/@metamask/sdk/node_modules/@noble/hashes": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.5.0.tgz", + "integrity": "sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@metamask/sdk/node_modules/eciesjs": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/eciesjs/-/eciesjs-0.4.11.tgz", + "integrity": "sha512-SmUG449n1w1YGvJD9R30tBGvpxTxA0cnn0rfvpFIBvmezfIhagLjsH2JG8HBHOLS8slXsPh48II7IDUTH/J3Mg==", + "dependencies": { + "@ecies/ciphers": "^0.2.1", + "@noble/ciphers": "^1.0.0", + "@noble/curves": "^1.6.0", + "@noble/hashes": "^1.5.0" + }, + "engines": { + "bun": ">=1", + "deno": ">=2", + "node": ">=16" + } + }, + "node_modules/@metamask/sdk/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@metamask/superstruct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@metamask/superstruct/-/superstruct-3.1.0.tgz", + "integrity": "sha512-N08M56HdOgBfRKkrgCMZvQppkZGcArEop3kixNEtVbJKm6P9Cfg0YkI6X0s1g78sNrj2fWUwvJADdZuzJgFttA==", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@metamask/utils": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-8.5.0.tgz", + "integrity": "sha512-I6bkduevXb72TIM9q2LRO63JSsF9EXduh3sBr9oybNX2hNNpr/j1tEjXrsG0Uabm4MJ1xkGAQEMwifvKZIkyxQ==", + "dependencies": { + "@ethereumjs/tx": "^4.2.0", + "@metamask/superstruct": "^3.0.0", + "@noble/hashes": "^1.3.1", + "@scure/base": "^1.1.3", + "@types/debug": "^4.1.7", + "debug": "^4.3.4", + "pony-cause": "^2.1.10", + "semver": "^7.5.4", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@metamask/utils/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@microsoft/tsdoc": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.15.0.tgz", + "integrity": "sha512-HZpPoABogPvjeJOdzCOSJsXeL/SMCBgBZMVC3X3d7YYp2gf31MfxhUoYUNwf1ERPJOnQc0wkFn9trqI6ZEdZuA==" + }, + "node_modules/@module-federation/bridge-react-webpack-plugin": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@module-federation/bridge-react-webpack-plugin/-/bridge-react-webpack-plugin-0.2.8.tgz", + "integrity": "sha512-6G1qTo1HWvRcN5fzE+SZgvgzSPoq5YqNx8hFL8BttJmnd3wj4SUOFiikAsXhdVrzSK+Zuzg6pipkiLH1m+pbtw==", + "dev": true, + "dependencies": { + "@module-federation/sdk": "0.2.8" + } + }, + "node_modules/@module-federation/dts-plugin": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@module-federation/dts-plugin/-/dts-plugin-0.2.8.tgz", + "integrity": "sha512-qY1Wbqo0yu9nh6KR8K19t5T4tYtlUbmcNdcaCweISCyAbH99TrhpQkJ89NY0TLtnxQ6uayIYayqAWS7vzyDXVw==", + "dev": true, + "dependencies": { + "@module-federation/managers": "0.2.8", + "@module-federation/sdk": "0.2.8", + "@module-federation/third-party-dts-extractor": "0.2.8", + "adm-zip": "^0.5.10", + "ansi-colors": "^4.1.3", + "axios": "^1.6.7", + "chalk": "3.0.0", + "fs-extra": "9.1.0", + "isomorphic-ws": "5.0.0", + "koa": "2.11.0", + "lodash.clonedeepwith": "4.5.0", + "log4js": "6.9.1", + "node-schedule": "2.1.1", + "rambda": "^9.1.0", + "ws": "8.17.1" + }, + "peerDependencies": { + "typescript": "^4.9.0 || ^5.0.0", + "vue-tsc": ">=1.0.24" + }, + "peerDependenciesMeta": { + "vue-tsc": { + "optional": true + } + } + }, + "node_modules/@module-federation/dts-plugin/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@module-federation/dts-plugin/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@module-federation/dts-plugin/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/@module-federation/enhanced": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@module-federation/enhanced/-/enhanced-0.2.8.tgz", + "integrity": "sha512-6fGM/GiKw6LZiBe6DF8Petz6ih/Yyf3q2htLrx+hrWoDWfWEoWlLvoCUsVkY2UgMCLKid7Fm3Auc4w8A4aRjvQ==", + "dev": true, + "dependencies": { + "@module-federation/bridge-react-webpack-plugin": "0.2.8", + "@module-federation/dts-plugin": "0.2.8", + "@module-federation/managers": "0.2.8", + "@module-federation/manifest": "0.2.8", + "@module-federation/rspack": "0.2.8", + "@module-federation/runtime-tools": "0.2.8", + "@module-federation/sdk": "0.2.8", + "btoa": "^1.2.1", + "upath": "2.0.1" + }, + "peerDependencies": { + "typescript": "^4.9.0 || ^5.0.0", + "vue-tsc": ">=1.0.24", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "vue-tsc": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/@module-federation/managers": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@module-federation/managers/-/managers-0.2.8.tgz", + "integrity": "sha512-S5GXqt2Vrs1+uNXHw7UzZ7m3fs8H3nxNsNGQ0j5+HiT5yA7uRTY1AZJZCGAHzG6XImJ1DzL/SW1acM2Hwj0aAw==", + "dev": true, + "dependencies": { + "@module-federation/sdk": "0.2.8", + "find-pkg": "2.0.0", + "fs-extra": "9.1.0" + } + }, + "node_modules/@module-federation/managers/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@module-federation/manifest": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@module-federation/manifest/-/manifest-0.2.8.tgz", + "integrity": "sha512-kw4PeAldkOuGCWfCnDzZwPHUx5qv9+WztY5+TEbsgXc5E+/e2NDA6Gg3eT8zUGeexeGdab3f+DuN9ZClZJYVGA==", + "dev": true, + "dependencies": { + "@module-federation/dts-plugin": "0.2.8", + "@module-federation/managers": "0.2.8", + "@module-federation/sdk": "0.2.8", + "chalk": "3.0.0", + "find-pkg": "2.0.0" + } + }, + "node_modules/@module-federation/manifest/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@module-federation/rspack": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@module-federation/rspack/-/rspack-0.2.8.tgz", + "integrity": "sha512-5Bofm3cY7OOwO2DT5TevITd+HAA03zsY1wwsMb1BP6NkS/ukUtsjuRo2Anua0RkHBEIx+Dv5rpqOn7qSlOm1Fg==", + "dev": true, + "dependencies": { + "@module-federation/bridge-react-webpack-plugin": "0.2.8", + "@module-federation/dts-plugin": "0.2.8", + "@module-federation/managers": "0.2.8", + "@module-federation/manifest": "0.2.8", + "@module-federation/runtime-tools": "0.2.8", + "@module-federation/sdk": "0.2.8" + }, + "peerDependencies": { + "typescript": "^4.9.0 || ^5.0.0", + "vue-tsc": ">=1.0.24" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "vue-tsc": { + "optional": true + } + } + }, + "node_modules/@module-federation/runtime": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@module-federation/runtime/-/runtime-0.2.8.tgz", + "integrity": "sha512-8xmA/+z1zD09F5qU8VnSWLExqTCVWoHOguXsCX79kkqp7i0c+D2YaebWzlQ2kku+DU+0VIzXpQ3BBcumZ3v3wQ==", + "dev": true, + "dependencies": { + "@module-federation/sdk": "0.2.8" + } + }, + "node_modules/@module-federation/runtime-tools": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@module-federation/runtime-tools/-/runtime-tools-0.2.8.tgz", + "integrity": "sha512-RSNtyhcNvnTQIdzRUIOGue6WQA/9mL9cY/n0dEd357L/lmLCvfHiZbowlkacckDzyApariUHxzkHrU2Q6kzoew==", + "dev": true, + "dependencies": { + "@module-federation/runtime": "0.2.8", + "@module-federation/webpack-bundler-runtime": "0.2.8" + } + }, + "node_modules/@module-federation/sdk": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@module-federation/sdk/-/sdk-0.2.8.tgz", + "integrity": "sha512-eGMnJxdRDgt6dtMv8gkAlzEbTPWVHb3AHUNUG0w56wcbIF0RHC6kmvpHpSQyq4DVGWv3U4g/ZiH5BvBlqEelDQ==", + "dev": true + }, + "node_modules/@module-federation/third-party-dts-extractor": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@module-federation/third-party-dts-extractor/-/third-party-dts-extractor-0.2.8.tgz", + "integrity": "sha512-VGXvdsRlljbFUfGeA448CxR7i6fLWJN07ViRuNXYYXc19e4bQVhBHzrf7eCv9ahcf/tA/8YYCS2h11ixbD691A==", + "dev": true, + "dependencies": { + "find-pkg": "2.0.0", + "fs-extra": "9.1.0", + "resolve": "1.22.8" + } + }, + "node_modules/@module-federation/third-party-dts-extractor/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@module-federation/webpack-bundler-runtime": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@module-federation/webpack-bundler-runtime/-/webpack-bundler-runtime-0.2.8.tgz", + "integrity": "sha512-tiW1kD/V3QNul1/O3Y3lwQv/r4sUU4jvWZykrLvHYt2vuoGe1d4tHnSIFEVEAi9FSpuDwdRK2+NaWBr92gIS7Q==", + "dev": true, + "dependencies": { + "@module-federation/runtime": "0.2.8", + "@module-federation/sdk": "0.2.8" + } + }, + "node_modules/@monaco-editor/loader": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.4.0.tgz", + "integrity": "sha512-00ioBig0x642hytVspPl7DbQyaSWRaolYie/UFNjoTdvoKPzo6xrXLhTk9ixgIKcLH5b5vDOjVNiGyY+uDCUlg==", + "dependencies": { + "state-local": "^1.0.6" + }, + "peerDependencies": { + "monaco-editor": ">= 0.21.0 < 1" + } + }, + "node_modules/@monaco-editor/react": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.6.0.tgz", + "integrity": "sha512-RFkU9/i7cN2bsq/iTkurMWOEErmYcY6JiQI3Jn+WeR/FGISH8JbHERjpS9oRuSOPvDMJI0Z8nJeKkbOs9sBYQw==", + "dependencies": { + "@monaco-editor/loader": "^1.4.0" + }, + "peerDependencies": { + "monaco-editor": ">= 0.25.0 < 1", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@motionone/animation": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/animation/-/animation-10.18.0.tgz", + "integrity": "sha512-9z2p5GFGCm0gBsZbi8rVMOAJCtw1WqBTIPw3ozk06gDvZInBPIsQcHgYogEJ4yuHJ+akuW8g1SEIOpTOvYs8hw==", + "dependencies": { + "@motionone/easing": "^10.18.0", + "@motionone/types": "^10.17.1", + "@motionone/utils": "^10.18.0", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/dom": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/dom/-/dom-10.18.0.tgz", + "integrity": "sha512-bKLP7E0eyO4B2UaHBBN55tnppwRnaE3KFfh3Ps9HhnAkar3Cb69kUCJY9as8LrccVYKgHA+JY5dOQqJLOPhF5A==", + "dependencies": { + "@motionone/animation": "^10.18.0", + "@motionone/generators": "^10.18.0", + "@motionone/types": "^10.17.1", + "@motionone/utils": "^10.18.0", + "hey-listen": "^1.0.8", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/easing": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/easing/-/easing-10.18.0.tgz", + "integrity": "sha512-VcjByo7XpdLS4o9T8t99JtgxkdMcNWD3yHU/n6CLEz3bkmKDRZyYQ/wmSf6daum8ZXqfUAgFeCZSpJZIMxaCzg==", + "dependencies": { + "@motionone/utils": "^10.18.0", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/generators": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/generators/-/generators-10.18.0.tgz", + "integrity": "sha512-+qfkC2DtkDj4tHPu+AFKVfR/C30O1vYdvsGYaR13W/1cczPrrcjdvYCj0VLFuRMN+lP1xvpNZHCRNM4fBzn1jg==", + "dependencies": { + "@motionone/types": "^10.17.1", + "@motionone/utils": "^10.18.0", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/svelte": { + "version": "10.16.4", + "resolved": "https://registry.npmjs.org/@motionone/svelte/-/svelte-10.16.4.tgz", + "integrity": "sha512-zRVqk20lD1xqe+yEDZhMYgftsuHc25+9JSo+r0a0OWUJFocjSV9D/+UGhX4xgJsuwB9acPzXLr20w40VnY2PQA==", + "dependencies": { + "@motionone/dom": "^10.16.4", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/types": { + "version": "10.17.1", + "resolved": "https://registry.npmjs.org/@motionone/types/-/types-10.17.1.tgz", + "integrity": "sha512-KaC4kgiODDz8hswCrS0btrVrzyU2CSQKO7Ps90ibBVSQmjkrt2teqta6/sOG59v7+dPnKMAg13jyqtMKV2yJ7A==" + }, + "node_modules/@motionone/utils": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/utils/-/utils-10.18.0.tgz", + "integrity": "sha512-3XVF7sgyTSI2KWvTf6uLlBJ5iAgRgmvp3bpuOiQJvInd4nZ19ET8lX5unn30SlmRH7hXbBbH+Gxd0m0klJ3Xtw==", + "dependencies": { + "@motionone/types": "^10.17.1", + "hey-listen": "^1.0.8", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/vue": { + "version": "10.16.4", + "resolved": "https://registry.npmjs.org/@motionone/vue/-/vue-10.16.4.tgz", + "integrity": "sha512-z10PF9JV6SbjFq+/rYabM+8CVlMokgl8RFGvieSGNTmrkQanfHn+15XBrhG3BgUfvmTeSeyShfOHpG0i9zEdcg==", + "deprecated": "Motion One for Vue is deprecated. Use Oku Motion instead https://oku-ui.com/motion", + "dependencies": { + "@motionone/dom": "^10.16.4", + "tslib": "^2.3.1" + } + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz", + "integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz", + "integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz", + "integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz", + "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz", - "integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz", + "integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz", + "integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@mswjs/interceptors": { + "version": "0.37.3", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.37.3.tgz", + "integrity": "sha512-USvgCL/uOGFtVa6SVyRrC8kIAedzRohxIXN5LISlg5C5vLZCn7dgMFVSNhSF9cuBEFrm/O2spDWEZeMnw4ZXYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@open-draft/deferred-promise": "^2.2.0", + "@open-draft/logger": "^0.3.0", + "@open-draft/until": "^2.0.0", + "is-node-process": "^1.2.0", + "outvariant": "^1.4.3", + "strict-event-emitter": "^0.5.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@mysten/bcs": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@mysten/bcs/-/bcs-0.7.4.tgz", + "integrity": "sha512-6DKzM4L10Au3Og5EJRBqJZmXWZ7hS/clVjbVUH4sA0aFtS3AZo2xc+r5fUFfdJbaWZUxVaDiQ8BNiEZWkAnEOw==", + "license": "Apache-2.0", + "dependencies": { + "bs58": "^5.0.0" + } + }, + "node_modules/@mysten/bcs/node_modules/base-x": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.0.tgz", + "integrity": "sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw==", + "license": "MIT" + }, + "node_modules/@mysten/bcs/node_modules/bs58": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-5.0.0.tgz", + "integrity": "sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==", + "license": "MIT", + "dependencies": { + "base-x": "^4.0.0" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.4.tgz", + "integrity": "sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==", + "dev": true, + "dependencies": { + "@emnapi/core": "^1.1.0", + "@emnapi/runtime": "^1.1.0", + "@tybys/wasm-util": "^0.9.0" + } + }, + "node_modules/@narval-xyz/armory-mpc-module": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@narval-xyz/armory-mpc-module/-/armory-mpc-module-0.0.1.tgz", + "integrity": "sha512-jAUKXB4tf5KgcNeqpcpVNzivvB4IiOMKpVufdhaRx+JHQDSxfCkFYcghtoWavZGA5csryrGMFHwPUZnA7q594g==", + "bundleDependencies": [ + "@narval-xyz/armory-sdk" + ], + "optional": true, + "dependencies": { + "@narval-xyz/armory-sdk": "^0.0.5", + "@nestjs/common": "^10.0.0", + "@nestjs/core": "^10.0.0", + "@nestjs/platform-express": "^10.0.0", + "@noble/curves": "^1.4.2", + "@sepior/tsmsdkv2": "^63.0.0", + "reflect-metadata": "^0.1.13", + "rxjs": "^7.8.1" + } + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/@adraffy/ens-normalize": { + "version": "1.10.0", + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/@narval-xyz/armory-sdk": { + "version": "0.0.5", + "inBundle": true, + "license": "MPL-2.0", + "optional": true, + "dependencies": { + "@noble/curves": "1.4.0", + "axios": "1.7.2", + "jose": "5.5.0", + "lodash": "4.17.21", + "tslib": "2.6.3", + "uuid": "9.0.1", + "viem": "2.16.2", + "zod": "3.23.8" + } + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/@narval-xyz/armory-sdk/node_modules/@noble/curves": { + "version": "1.4.0", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@noble/hashes": "1.4.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/@narval-xyz/armory-sdk/node_modules/tslib": { + "version": "2.6.3", + "inBundle": true, + "license": "0BSD", + "optional": true + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/@noble/hashes": { + "version": "1.4.0", + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/@scure/base": { + "version": "1.1.7", + "inBundle": true, + "license": "MIT", + "optional": true, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/@scure/bip32": { + "version": "1.3.2", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@noble/curves": "~1.2.0", + "@noble/hashes": "~1.3.2", + "@scure/base": "~1.1.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/@scure/bip32/node_modules/@noble/curves": { + "version": "1.2.0", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/@scure/bip32/node_modules/@noble/curves/node_modules/@noble/hashes": { + "version": "1.3.2", + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/@scure/bip32/node_modules/@noble/hashes": { + "version": "1.3.3", + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/@scure/bip39": { + "version": "1.2.1", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@noble/hashes": "~1.3.0", + "@scure/base": "~1.1.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/@scure/bip39/node_modules/@noble/hashes": { + "version": "1.3.3", + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/abitype": { + "version": "1.0.4", + "inBundle": true, + "license": "MIT", + "optional": true, + "funding": { + "url": "https://github.com/sponsors/wevm" + }, + "peerDependencies": { + "typescript": ">=5.0.4", + "zod": "^3 >=3.22.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/asynckit": { + "version": "0.4.0", + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/axios": { + "version": "1.7.2", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/combined-stream": { + "version": "1.0.8", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/delayed-stream": { + "version": "1.0.0", + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/follow-redirects": { + "version": "1.15.6", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/form-data": { + "version": "4.0.0", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/isows": { + "version": "1.0.4", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wagmi-dev" + } + ], + "inBundle": true, + "license": "MIT", + "optional": true, + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/jose": { + "version": "5.5.0", + "inBundle": true, + "license": "MIT", + "optional": true, + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/lodash": { + "version": "4.17.21", + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/mime-db": { + "version": "1.52.0", + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/mime-types": { + "version": "2.1.35", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/proxy-from-env": { + "version": "1.1.0", + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/uuid": { + "version": "9.0.1", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "inBundle": true, + "license": "MIT", + "optional": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/viem": { + "version": "2.16.2", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@adraffy/ens-normalize": "1.10.0", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.2", + "@scure/bip32": "1.3.2", + "@scure/bip39": "1.2.1", + "abitype": "1.0.4", + "isows": "1.0.4", + "ws": "8.17.1" + }, + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/viem/node_modules/@noble/curves": { + "version": "1.2.0", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/viem/node_modules/@noble/hashes": { + "version": "1.3.2", + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/ws": { + "version": "8.17.1", + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/zod": { + "version": "3.23.8", + "inBundle": true, + "license": "MIT", + "optional": true, + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@narval-xyz/armory-sdk": { + "resolved": "packages/armory-sdk", + "link": true + }, + "node_modules/@nestjs/axios": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-3.0.2.tgz", + "integrity": "sha512-Z6GuOUdNQjP7FX+OuV2Ybyamse+/e0BFdTWBX5JxpBDKA+YkdLynDgG6HTF04zy6e9zPa19UX0WA2VDoehwhXQ==", + "peerDependencies": { + "@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0", + "axios": "^1.3.1", + "rxjs": "^6.0.0 || ^7.0.0" + } + }, + "node_modules/@nestjs/bull": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/@nestjs/bull/-/bull-10.2.0.tgz", + "integrity": "sha512-byQI3cgAVP8BNa71h5g33D1pNwOaK2O9+zYmT98eU8LxxJHh53aWMwEUrCHrwgSz4P8bD+jY8ObQ5vtU4SsidA==", + "dependencies": { + "@nestjs/bull-shared": "^10.2.0", + "tslib": "2.6.3" + }, + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", + "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0", + "bull": "^3.3 || ^4.0.0" + } + }, + "node_modules/@nestjs/bull-shared": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/@nestjs/bull-shared/-/bull-shared-10.2.0.tgz", + "integrity": "sha512-cSi6CyPECHDFumnHWWfwLCnbc6hm5jXt7FqzJ0Id6EhGqdz5ja0FmgRwXoS4xoMA2RRjlxn2vGXr4YOaHBAeig==", + "dependencies": { + "tslib": "2.6.3" + }, + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", + "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0" + } + }, + "node_modules/@nestjs/cache-manager": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@nestjs/cache-manager/-/cache-manager-3.0.0.tgz", + "integrity": "sha512-csKvxHSQWfC0OiDo0bNEhLqrmYDopHEvRyC81MxV9xFj1AO+rOKocpHa4M1ZGH//6uKFIPGN9oiR0mvZY77APA==", + "license": "MIT", + "peerDependencies": { + "@nestjs/common": "^9.0.0 || ^10.0.0 || ^11.0.0", + "@nestjs/core": "^9.0.0 || ^10.0.0 || ^11.0.0", + "cache-manager": ">=6", + "rxjs": "^7.8.1" + } + }, + "node_modules/@nestjs/common": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.3.10.tgz", + "integrity": "sha512-H8k0jZtxk1IdtErGDmxFRy0PfcOAUg41Prrqpx76DQusGGJjsaovs1zjXVD1rZWaVYchfT1uczJ6L4Kio10VNg==", + "dependencies": { + "iterare": "1.2.1", + "tslib": "2.6.3", + "uid": "2.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "class-transformer": "*", + "class-validator": "*", + "reflect-metadata": "^0.1.12 || ^0.2.0", + "rxjs": "^7.1.0" + }, + "peerDependenciesMeta": { + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } + } + }, + "node_modules/@nestjs/config": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-3.1.1.tgz", + "integrity": "sha512-qu5QlNiJdqQtOsnB6lx4JCXPQ96jkKUsOGd+JXfXwqJqZcOSAq6heNFg0opW4pq4J/VZoNwoo87TNnx9wthnqQ==", + "dependencies": { + "dotenv": "16.3.1", + "dotenv-expand": "10.0.0", + "lodash": "4.17.21", + "uuid": "9.0.0" + }, + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", + "reflect-metadata": "^0.1.13" + } + }, + "node_modules/@nestjs/config/node_modules/dotenv": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" + } + }, + "node_modules/@nestjs/config/node_modules/uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@nestjs/core": { + "version": "10.4.7", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.4.7.tgz", + "integrity": "sha512-AIpQzW/vGGqSLkKvll1R7uaSNv99AxZI2EFyVJPNGDgFsfXaohfV1Ukl6f+s75Km+6Fj/7aNl80EqzNWQCS8Ig==", + "hasInstallScript": true, + "dependencies": { + "@nuxtjs/opencollective": "0.3.2", + "fast-safe-stringify": "2.1.1", + "iterare": "1.2.1", + "path-to-regexp": "3.3.0", + "tslib": "2.7.0", + "uid": "2.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^10.0.0", + "@nestjs/microservices": "^10.0.0", + "@nestjs/platform-express": "^10.0.0", + "@nestjs/websockets": "^10.0.0", + "reflect-metadata": "^0.1.12 || ^0.2.0", + "rxjs": "^7.1.0" + }, + "peerDependenciesMeta": { + "@nestjs/microservices": { + "optional": true + }, + "@nestjs/platform-express": { + "optional": true + }, + "@nestjs/websockets": { + "optional": true + } + } + }, + "node_modules/@nestjs/core/node_modules/path-to-regexp": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.3.0.tgz", + "integrity": "sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==" + }, + "node_modules/@nestjs/core/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + }, + "node_modules/@nestjs/event-emitter": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@nestjs/event-emitter/-/event-emitter-2.1.1.tgz", + "integrity": "sha512-6L6fBOZTyfFlL7Ih/JDdqlCzZeCW0RjCX28wnzGyg/ncv5F/EOeT1dfopQr1loBRQ3LTgu8OWM7n4zLN4xigsg==", + "license": "MIT", + "dependencies": { + "eventemitter2": "6.4.9" + }, + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", + "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0" + } + }, + "node_modules/@nestjs/mapped-types": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-2.0.5.tgz", + "integrity": "sha512-bSJv4pd6EY99NX9CjBIyn4TVDoSit82DUZlL4I3bqNfy5Gt+gXTa86i3I/i0iIV9P4hntcGM5GyO+FhZAhxtyg==", + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", + "class-transformer": "^0.4.0 || ^0.5.0", + "class-validator": "^0.13.0 || ^0.14.0", + "reflect-metadata": "^0.1.12 || ^0.2.0" + }, + "peerDependenciesMeta": { + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } + } + }, + "node_modules/@nestjs/platform-express": { + "version": "10.3.9", + "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.3.9.tgz", + "integrity": "sha512-si/UzobP6YUtYtCT1cSyQYHHzU3yseqYT6l7OHSMVvfG1+TqxaAqI6nmrix02LO+l1YntHRXEs3p+v9a7EfrSQ==", + "license": "MIT", + "dependencies": { + "body-parser": "1.20.2", + "cors": "2.8.5", + "express": "4.19.2", + "multer": "1.4.4-lts.1", + "tslib": "2.6.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^10.0.0", + "@nestjs/core": "^10.0.0" + } + }, + "node_modules/@nestjs/platform-express/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "license": "0BSD" + }, + "node_modules/@nestjs/schematics": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-9.2.0.tgz", + "integrity": "sha512-wHpNJDPzM6XtZUOB3gW0J6mkFCSJilzCM3XrHI1o0C8vZmFE1snbmkIXNyoi1eV0Nxh1BMymcgz5vIMJgQtTqw==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "16.0.1", + "@angular-devkit/schematics": "16.0.1", + "jsonc-parser": "3.2.0", + "pluralize": "8.0.0" + }, + "peerDependencies": { + "typescript": ">=4.3.5" + } + }, + "node_modules/@nestjs/swagger": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-7.4.0.tgz", + "integrity": "sha512-dCiwKkRxcR7dZs5jtrGspBAe/nqJd1AYzOBTzw9iCdbq3BGrLpwokelk6lFZPe4twpTsPQqzNKBwKzVbI6AR/g==", + "dependencies": { + "@microsoft/tsdoc": "^0.15.0", + "@nestjs/mapped-types": "2.0.5", + "js-yaml": "4.1.0", + "lodash": "4.17.21", + "path-to-regexp": "3.2.0", + "swagger-ui-dist": "5.17.14" + }, + "peerDependencies": { + "@fastify/static": "^6.0.0 || ^7.0.0", + "@nestjs/common": "^9.0.0 || ^10.0.0", + "@nestjs/core": "^9.0.0 || ^10.0.0", + "class-transformer": "*", + "class-validator": "*", + "reflect-metadata": "^0.1.12 || ^0.2.0" + }, + "peerDependenciesMeta": { + "@fastify/static": { + "optional": true + }, + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } + } + }, + "node_modules/@nestjs/testing": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.4.1.tgz", + "integrity": "sha512-pR+su5+YGqCLH0RhhVkPowQK7FCORU0/PWAywPK7LScAOtD67ZoviZ7hAU4vnGdwkg4HCB0D7W8Bkg19CGU8Xw==", + "dev": true, + "dependencies": { + "tslib": "2.6.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^10.0.0", + "@nestjs/core": "^10.0.0", + "@nestjs/microservices": "^10.0.0", + "@nestjs/platform-express": "^10.0.0" + }, + "peerDependenciesMeta": { + "@nestjs/microservices": { + "optional": true + }, + "@nestjs/platform-express": { + "optional": true + } + } + }, + "node_modules/@next/env": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.4.tgz", + "integrity": "sha512-3EtkY5VDkuV2+lNmKlbkibIJxcO4oIHEhBWne6PaAp+76J9KoSsGvNikp6ivzAT8dhhBMYrm6op2pS1ApG0Hzg==" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "14.2.6", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.6.tgz", + "integrity": "sha512-d3+p4AjIYmhqzYHhhmkRYYN6ZU35TwZAKX08xKRfnHkz72KhWL2kxMFsDptpZs5e8bBGdepn7vn1+9DaF8iX+A==", + "dev": true, + "dependencies": { + "glob": "10.3.10" + } + }, + "node_modules/@next/eslint-plugin-next/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.4.tgz", + "integrity": "sha512-AH3mO4JlFUqsYcwFUHb1wAKlebHU/Hv2u2kb1pAuRanDZ7pD/A/KPD98RHZmwsJpdHQwfEc/06mgpSzwrJYnNg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.4.tgz", + "integrity": "sha512-QVadW73sWIO6E2VroyUjuAxhWLZWEpiFqHdZdoQ/AMpN9YWGuHV8t2rChr0ahy+irKX5mlDU7OY68k3n4tAZTg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.4.tgz", + "integrity": "sha512-KT6GUrb3oyCfcfJ+WliXuJnD6pCpZiosx2X3k66HLR+DMoilRb76LpWPGb4tZprawTtcnyrv75ElD6VncVamUQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.4.tgz", + "integrity": "sha512-Alv8/XGSs/ytwQcbCHwze1HmiIkIVhDHYLjczSVrf0Wi2MvKn/blt7+S6FJitj3yTlMwMxII1gIJ9WepI4aZ/A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.4.tgz", + "integrity": "sha512-ze0ShQDBPCqxLImzw4sCdfnB3lRmN3qGMB2GWDRlq5Wqy4G36pxtNOo2usu/Nm9+V2Rh/QQnrRc2l94kYFXO6Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.4.tgz", + "integrity": "sha512-8dwC0UJoc6fC7PX70csdaznVMNr16hQrTDAMPvLPloazlcaWfdPogq+UpZX6Drqb1OBlwowz8iG7WR0Tzk/diQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.4.tgz", + "integrity": "sha512-jxyg67NbEWkDyvM+O8UDbPAyYRZqGLQDTPwvrBBeOSyVWW/jFQkQKQ70JDqDSYg1ZDdl+E3nkbFbq8xM8E9x8A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.4.tgz", + "integrity": "sha512-twrmN753hjXRdcrZmZttb/m5xaCBFa48Dt3FbeEItpJArxriYDunWxJn+QFXdJ3hPkm4u7CKxncVvnmgQMY1ag==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.4.tgz", + "integrity": "sha512-tkLrjBzqFTP8DVrAAQmZelEahfR9OxWpFR++vAI9FBhCiIxtwHwBHC23SBHCTURBtwB4kc/x44imVOnkKGNVGg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@noble/ciphers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.0.0.tgz", + "integrity": "sha512-wH5EHOmLi0rEazphPbecAzmjd12I6/Yv/SiHdkA9LSycsQk7RuuTp7am5/o62qYr0RScE7Pc9icXGBbsr6cesA==", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/curves": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.6.0.tgz", + "integrity": "sha512-TlaHRXDehJuRNR9TfZDNQ45mMEd5dwUwmicsafcIX4SsNiqnCHKjE/1alYPd/lDRVhxdhUAlv8uEhMCI5zjIJQ==", + "dependencies": { + "@noble/hashes": "1.5.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/curves/node_modules/@noble/hashes": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.5.0.tgz", + "integrity": "sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/ed25519": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/ed25519/-/ed25519-1.7.1.tgz", + "integrity": "sha512-Rk4SkJFaXZiznFyC/t77Q0NKS4FL7TLJJsVG2V2oiEq3kJVeTdxysEe/yRWSpnWMe808XRDJ+VFh5pt/FN5plw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ] + }, + "node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/secp256k1": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.6.3.tgz", + "integrity": "sha512-T04e4iTurVy7I8Sw4+c5OSN9/RkPlo1uKxAomtxQNLq8j1uPAqnsqG1bqvY3Jv7c13gyr6dui0zmh/I3+f/JaQ==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT" + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + } + }, + "node_modules/@npmcli/fs/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "optional": true, + "peer": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/move-file/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "optional": true, + "peer": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@nrwl/devkit": { + "version": "19.5.1", + "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.5.1.tgz", + "integrity": "sha512-ZsckDZszLTv3oshNsY5fZ86g8a/VcGvgDpdiP/z/A/krtOHL8iUjdT/72Eo5DIult5WcSFjnifyWcyWIGe1PeA==", + "dev": true, + "dependencies": { + "@nx/devkit": "19.5.1" + } + }, + "node_modules/@nrwl/eslint-plugin-nx": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nrwl/eslint-plugin-nx/-/eslint-plugin-nx-19.3.2.tgz", + "integrity": "sha512-OD9WYOpTCgMQWTwUKRUuXlVfegkbkqNqkVQ3hsftjTn1dkB8QbvMa9ajqDGU+pbQDLeMMwtjc4itVpUimvmudQ==", + "dev": true, + "dependencies": { + "@nx/eslint-plugin": "19.3.2" + } + }, + "node_modules/@nrwl/jest": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/jest/-/jest-19.2.0.tgz", + "integrity": "sha512-s3qb0AblY+wqPUJFraWP9MYVyv3EA8bbEsMRCuvDDbhoe2nnyd/7PmluyPsWgJVdgbY9Ajgs3ZjuBEfFQ3VV9A==", + "dev": true, + "dependencies": { + "@nx/jest": "19.2.0" + } + }, + "node_modules/@nrwl/jest/node_modules/@nrwl/devkit": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.2.0.tgz", + "integrity": "sha512-Ew5AJZkLXJwt15HjaIbHve8FOXmZ3HK8KPqTXqwKHX8jQW+fDUCaSXKe/lCZMNg0RvY+jMNecuC86uGdiIbLMg==", + "dev": true, + "dependencies": { + "@nx/devkit": "19.2.0" + } + }, + "node_modules/@nrwl/jest/node_modules/@nx/devkit": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.2.0.tgz", + "integrity": "sha512-fK3zRUE2SLp9BUomFiyCuAX2E1yfWYE/hKimniscsvM34/u/xLZYVmmZ0/jfpGPbyaonXKZr2KTb7RimX/hyqg==", + "dev": true, + "dependencies": { + "@nrwl/devkit": "19.2.0", + "ejs": "^3.1.7", + "enquirer": "~2.3.6", + "ignore": "^5.0.4", + "minimatch": "9.0.3", + "semver": "^7.5.3", + "tmp": "~0.2.1", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" + }, + "peerDependencies": { + "nx": ">= 17 <= 20" + } + }, + "node_modules/@nrwl/jest/node_modules/@nx/jest": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/jest/-/jest-19.2.0.tgz", + "integrity": "sha512-iJMqfwkIB4T7NRYAQe3nZWFEAQGGblMGcxWczMKEixCIZWcAz4up74eb0H6Yv+tUVOQHrFTm6J1OnrW3BqvOZA==", + "dev": true, + "dependencies": { + "@jest/reporters": "^29.4.1", + "@jest/test-result": "^29.4.1", + "@nrwl/jest": "19.2.0", + "@nx/devkit": "19.2.0", + "@nx/js": "19.2.0", + "@phenomnomnominal/tsquery": "~5.0.1", + "chalk": "^4.1.0", + "identity-obj-proxy": "3.0.0", + "jest-config": "^29.4.1", + "jest-resolve": "^29.4.1", + "jest-util": "^29.4.1", + "minimatch": "9.0.3", + "resolve.exports": "1.1.0", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" + } + }, + "node_modules/@nrwl/jest/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@nrwl/js": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/js/-/js-19.2.0.tgz", + "integrity": "sha512-i6CyQvTP1etmTxjFhUIw/HAtoZCENbhkc7UmAsyCgTX5IJeo0U3YoHsmDI0TE45yu+4x4gcKLqOHs2zqWj7WCw==", + "dev": true, + "dependencies": { + "@nx/js": "19.2.0" + } + }, + "node_modules/@nrwl/nest": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/nest/-/nest-19.2.0.tgz", + "integrity": "sha512-JjhGurz1neZHyrRtmstBHpIAfh/TE3h/untSMqiixrRg8k+qPZBi2dpcV6HZxWVoDkgKrL6ro7olmiXvWMQdqw==", + "dev": true, + "dependencies": { + "@nx/nest": "19.2.0" + } + }, + "node_modules/@nrwl/next": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/next/-/next-19.2.0.tgz", + "integrity": "sha512-+DFtnuB33w/x5A5c1EuSjnKE0i2YKJT5tltZ1bX7fyDcqukwESmTL+CNpYNlp5VuejDzV/3wp1pNdeqt+85/YA==", + "dev": true, + "dependencies": { + "@nx/next": "19.2.0" + } + }, + "node_modules/@nrwl/node": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/node/-/node-19.2.0.tgz", + "integrity": "sha512-fy4GPMGRT7/t3sUljOot2h9CVq0QWOv/nPxyK7YVk2jkwkjo9gTovVoZrjacv8DOOL4DE1tRr7yHfEQY6fnDig==", + "dev": true, + "dependencies": { + "@nx/node": "19.2.0" + } + }, + "node_modules/@nrwl/react": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/react/-/react-19.2.0.tgz", + "integrity": "sha512-Zz4lJK1S511s8F1OmbH0HiMz9xX/OCL8UQ5FJ9uViMNnkaLPx0NUGzrAbliDUq2XGYDBZ8ZtGFgC1DTlL9iK+w==", + "dev": true, + "dependencies": { + "@nx/react": "19.2.0" + } + }, + "node_modules/@nrwl/tao": { + "version": "19.4.4", + "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.4.4.tgz", + "integrity": "sha512-iwswcp7fW5GiIeAFvA/Ssr9fe2ZZHcuOS20bQx+mLEnEgBaARkgWqNdYMZ594NRqXQ1CrOEy5jncahS6K+pRbw==", + "dev": true, + "dependencies": { + "nx": "19.4.4", + "tslib": "^2.3.0" + }, + "bin": { + "tao": "index.js" + } + }, + "node_modules/@nrwl/web": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/web/-/web-19.2.0.tgz", + "integrity": "sha512-s6fEyic1cCwZAoKxZ64RMdCfG2jQGZC/FTyO4J7a8iB8oRD8mRLw0lWamXIcW10O0KPrE0zO63+kpjfKJ/ZK+w==", + "dev": true, + "dependencies": { + "@nx/web": "19.2.0" + } + }, + "node_modules/@nrwl/webpack": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nrwl/webpack/-/webpack-19.6.3.tgz", + "integrity": "sha512-e1Y493FBdNPO3TrXNAJSzbeGWAZiLUsDUfQDXjlAboQRL5n3bn1W/zc98DGMxobJWAzw2vWW7UEm2ZyYyeU/lA==", + "dev": true, + "dependencies": { + "@nx/webpack": "19.6.3" + } + }, + "node_modules/@nrwl/workspace": { + "version": "19.7.3", + "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-19.7.3.tgz", + "integrity": "sha512-2ffUbLzBYGQte6zQ6dDLefgU9X812Uh7v61yTV7z4zfYbUtjwInkWqlkTvRuK08DRhD5vWo9xyUDp7acAdZaxw==", + "dev": true, + "dependencies": { + "@nx/workspace": "19.7.3" + } + }, + "node_modules/@nuxtjs/opencollective": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz", + "integrity": "sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==", + "dependencies": { + "chalk": "^4.1.0", + "consola": "^2.15.0", + "node-fetch": "^2.6.1" + }, + "bin": { + "opencollective": "bin/opencollective.js" + }, + "engines": { + "node": ">=8.0.0", + "npm": ">=5.0.0" + } + }, + "node_modules/@nx/devkit": { + "version": "19.5.1", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.5.1.tgz", + "integrity": "sha512-Vj8wwzNIR5VIWmuLHhOi4aUVq7eVV5YTbctnEewKT+V/O4LZj+hClGyVNyT8s6b8JIjNWoIO4HXStLnH8rDOlw==", + "dev": true, + "dependencies": { + "@nrwl/devkit": "19.5.1", + "ejs": "^3.1.7", + "enquirer": "~2.3.6", + "ignore": "^5.0.4", + "minimatch": "9.0.3", + "semver": "^7.5.3", + "tmp": "~0.2.1", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" + }, + "peerDependencies": { + "nx": ">= 17 <= 20" + } + }, + "node_modules/@nx/devkit/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@nx/eslint": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/eslint/-/eslint-19.3.2.tgz", + "integrity": "sha512-ICUX8ADAIj9xA7Yc6hY9pfeC55ZxRjiAaqslsK3h4pCrFADVFDluShhrxSpUkp4doBzGUR7s1K7GIbeRrwD4qA==", + "dev": true, + "dependencies": { + "@nx/devkit": "19.3.2", + "@nx/js": "19.3.2", + "@nx/linter": "19.3.2", + "semver": "^7.5.3", + "tslib": "^2.3.0", + "typescript": "~5.4.2" + }, + "peerDependencies": { + "@zkochan/js-yaml": "0.0.7", + "eslint": "^8.0.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "@zkochan/js-yaml": { + "optional": true + } + } + }, + "node_modules/@nx/eslint-plugin": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/eslint-plugin/-/eslint-plugin-19.3.2.tgz", + "integrity": "sha512-ZhnFrnAKILA29EwiHQhUQnLfXleUH/YrDS3FUYBpwKnICAPXARsgb7Qi+3Uick0q4HlkL6xGRkkQSfA5cZ9Qtw==", + "dev": true, + "dependencies": { + "@nrwl/eslint-plugin-nx": "19.3.2", + "@nx/devkit": "19.3.2", + "@nx/js": "19.3.2", + "@typescript-eslint/type-utils": "^7.3.0", + "@typescript-eslint/utils": "^7.3.0", + "chalk": "^4.1.0", + "confusing-browser-globals": "^1.0.9", + "jsonc-eslint-parser": "^2.1.0", + "semver": "^7.5.3", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.13.2 || ^7.0.0", + "eslint-config-prettier": "^9.0.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/@nx/eslint-plugin/node_modules/@nrwl/devkit": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.3.2.tgz", + "integrity": "sha512-n3tFalVPUk1HAJ2VYNnF34yzB9j2+6swFUi4Y92PxD1vN7vrIXnNeaTx2qcee7JDjBpiJ7Zn0KLg2jwiH6hNwA==", + "dev": true, + "dependencies": { + "@nx/devkit": "19.3.2" + } + }, + "node_modules/@nx/eslint-plugin/node_modules/@nrwl/js": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nrwl/js/-/js-19.3.2.tgz", + "integrity": "sha512-ZgCoLsASIlp1xtYpWW/1ZxvKSb6BY3ZNXBmjoUW4LyN7Pk6su55gPAVt6JWIxSMm+HC+v+Cb4XFKZLdtuvE7bg==", + "dev": true, + "dependencies": { + "@nx/js": "19.3.2" + } + }, + "node_modules/@nx/eslint-plugin/node_modules/@nrwl/tao": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.3.2.tgz", + "integrity": "sha512-I1gW7woqwU6rdlgwj6XXAKcreJ5ptRKI2WpLdZErkrPmaRG/jMZx/yjZrG4PWdIEuZ4ZmYnRsoXbKN6ilCknQw==", + "dev": true, + "dependencies": { + "nx": "19.3.2", + "tslib": "^2.3.0" + }, + "bin": { + "tao": "index.js" + } + }, + "node_modules/@nx/eslint-plugin/node_modules/@nrwl/workspace": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-19.3.2.tgz", + "integrity": "sha512-6gV4qa38t3GyRKmO2PLcamDcFRD7I3wl6/R0/E1eC8Wm6K2oBzjOIV5ALpz4iC4LOln88IL+AjuQdG6kdtfXlA==", + "dev": true, + "dependencies": { + "@nx/workspace": "19.3.2" + } + }, + "node_modules/@nx/eslint-plugin/node_modules/@nx/devkit": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.3.2.tgz", + "integrity": "sha512-uD3jaJ1Jvf7B6jqH2t2GH0L6REwcCGBLXq1qs1HRQF5SZrEtuUeusn8wvCKP7dftPK3byLHAG0xHRW4+IUAz/g==", + "dev": true, + "dependencies": { + "@nrwl/devkit": "19.3.2", + "ejs": "^3.1.7", + "enquirer": "~2.3.6", + "ignore": "^5.0.4", + "minimatch": "9.0.3", + "semver": "^7.5.3", + "tmp": "~0.2.1", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" + }, + "peerDependencies": { + "nx": ">= 17 <= 20" + } + }, + "node_modules/@nx/eslint-plugin/node_modules/@nx/js": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/js/-/js-19.3.2.tgz", + "integrity": "sha512-WXULhOHYDIAvs+SyDiRaNrpn1DmBAl3u7F5Jpu2VIyrcXgllrYGqUAykUqSu6Oyc2J+asfEtiG67I7UucTHLhA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.23.2", + "@babel/plugin-proposal-decorators": "^7.22.7", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-runtime": "^7.23.2", + "@babel/preset-env": "^7.23.2", + "@babel/preset-typescript": "^7.22.5", + "@babel/runtime": "^7.22.6", + "@nrwl/js": "19.3.2", + "@nx/devkit": "19.3.2", + "@nx/workspace": "19.3.2", + "babel-plugin-const-enum": "^1.0.1", + "babel-plugin-macros": "^2.8.0", + "babel-plugin-transform-typescript-metadata": "^0.3.1", + "chalk": "^4.1.0", + "columnify": "^1.6.0", + "detect-port": "^1.5.1", + "fast-glob": "3.2.7", + "fs-extra": "^11.1.0", + "ignore": "^5.0.4", + "js-tokens": "^4.0.0", + "minimatch": "9.0.3", + "npm-package-arg": "11.0.1", + "npm-run-path": "^4.0.1", + "ora": "5.3.0", + "semver": "^7.5.3", + "source-map-support": "0.5.19", + "ts-node": "10.9.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "verdaccio": "^5.0.4" + }, + "peerDependenciesMeta": { + "verdaccio": { + "optional": true + } + } + }, + "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-darwin-arm64": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.3.2.tgz", + "integrity": "sha512-MTqPTR1FwfVfIkHKUw95dFlPBN6mbqfJ+KzLHvUSPcqLKelhi82tsisjMoB5sNK0YWcNNVqYW72ojCnHVB0TUg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-darwin-x64": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.3.2.tgz", + "integrity": "sha512-C8s9X5AlVgl3V5PycLdX+75lpAWq0qQs6QUEAnyxrLM9l+/HRecgoW6uZ7tX6Fnd8WGfMIwyahBw4LyZgk6zTw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-freebsd-x64": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.3.2.tgz", + "integrity": "sha512-XeEpEU0iqJ/5cAPMmjqJ0Sdz89ZtDRj4NdksioyhAHri94X5/3lm3lDs4tB3nObT7p3QL7r/HP1itq5DHYmMSQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-linux-arm-gnueabihf": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.3.2.tgz", + "integrity": "sha512-r4Wl0P94QRBUyiexUcfwKxqFXp48avMG3L0no/ZuNWGODbw1w8ppA4vhnkXtXbIaMdaTGx9eIYO7kFJ2SwMCng==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-linux-arm64-gnu": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.3.2.tgz", + "integrity": "sha512-oaTC4iS1fXnc61ZgSxwCQ2GGIqY64G22udRqNsX9TOtgrT7UA/mjE3Si01r+0xODimOiB525ueyxdIh1MAu6Vg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-linux-arm64-musl": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.3.2.tgz", + "integrity": "sha512-yyO9bTM7FW7HTYsSQlL4lgbAexUBpzfhdK+RkgsCiW+U/5bi+jFRxo/SbqGUL+IVliFavWyRXahMqOOM6nBq/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-linux-x64-gnu": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.3.2.tgz", + "integrity": "sha512-DC+llVdL4toLjQkDGBgzoCe26FWIOT+SzRdVcKePoNliZ4jDhkOh3+p75NEIOEcDUgoE9M2iCWEBUjkV978ogw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-linux-x64-musl": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.3.2.tgz", + "integrity": "sha512-Wun4v+kuuqv20tJiCENkHGisDqfx029bFufqxx2IOe9TvD6vK4rMMkFVPUoK3FP8EBdaMW4nrR0ZucTFnStl6w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-win32-arm64-msvc": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.3.2.tgz", + "integrity": "sha512-bNVf6eu5rWFjHvn0rKHeZYlHUcs3naXvvbduW1g0DPkHG6mt8FYffQmyboN+CSeBd/uWDPNyTUekVWwU7PjtLA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-win32-x64-msvc": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.3.2.tgz", + "integrity": "sha512-8DD5BPa5YrxTOKL3HTAgEd+IXNqRtJfwvbrn2MbOMNMyoMG9Zi5yhFvTH/HTT9Tz6VUHvXP16QWYA3R7eFi7Gg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/eslint-plugin/node_modules/@nx/workspace": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-19.3.2.tgz", + "integrity": "sha512-gam41l0hFftYIYTt8eTvZjh+ZWo62HO2p/efqZuFIa/1ZsXF1XG8MDRkCSh5Wfjh1f0jS2ma8HwPV3e8TJm2lw==", + "dev": true, + "dependencies": { + "@nrwl/workspace": "19.3.2", + "@nx/devkit": "19.3.2", + "chalk": "^4.1.0", + "enquirer": "~2.3.6", + "nx": "19.3.2", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" + } + }, + "node_modules/@nx/eslint-plugin/node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/@nx/eslint-plugin/node_modules/dotenv-expand": { + "version": "11.0.6", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.6.tgz", + "integrity": "sha512-8NHi73otpWsZGBSZwwknTXS5pqMOrk9+Ssrna8xCaxkzEpU9OTf9R5ArQGVw03//Zmk9MOwLPng9WwndvpAJ5g==", + "dev": true, + "dependencies": { + "dotenv": "^16.4.4" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/@nx/eslint-plugin/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/@nx/eslint-plugin/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@nx/eslint-plugin/node_modules/nx": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/nx/-/nx-19.3.2.tgz", + "integrity": "sha512-eKWs+ahkTKnq9EeWJCE4u8JLeq1cOHnq5DKoiisy2nwUg4KGy1odReegxUMLeEgNBcMI40EUtEJFiTMJSXZQeg==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@nrwl/tao": "19.3.2", + "@yarnpkg/lockfile": "^1.1.0", + "@yarnpkg/parsers": "3.0.0-rc.46", + "@zkochan/js-yaml": "0.0.7", + "axios": "^1.6.0", + "chalk": "^4.1.0", + "cli-cursor": "3.1.0", + "cli-spinners": "2.6.1", + "cliui": "^8.0.1", + "dotenv": "~16.4.5", + "dotenv-expand": "~11.0.6", + "enquirer": "~2.3.6", + "figures": "3.2.0", + "flat": "^5.0.2", + "front-matter": "^4.0.2", + "fs-extra": "^11.1.0", + "ignore": "^5.0.4", + "jest-diff": "^29.4.1", + "jsonc-parser": "3.2.0", + "lines-and-columns": "~2.0.3", + "minimatch": "9.0.3", + "node-machine-id": "1.1.12", + "npm-run-path": "^4.0.1", + "open": "^8.4.0", + "ora": "5.3.0", + "semver": "^7.5.3", + "string-width": "^4.2.3", + "strong-log-transformer": "^2.1.0", + "tar-stream": "~2.2.0", + "tmp": "~0.2.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0", + "yargs": "^17.6.2", + "yargs-parser": "21.1.1" + }, + "bin": { + "nx": "bin/nx.js", + "nx-cloud": "bin/nx-cloud.js" + }, + "optionalDependencies": { + "@nx/nx-darwin-arm64": "19.3.2", + "@nx/nx-darwin-x64": "19.3.2", + "@nx/nx-freebsd-x64": "19.3.2", + "@nx/nx-linux-arm-gnueabihf": "19.3.2", + "@nx/nx-linux-arm64-gnu": "19.3.2", + "@nx/nx-linux-arm64-musl": "19.3.2", + "@nx/nx-linux-x64-gnu": "19.3.2", + "@nx/nx-linux-x64-musl": "19.3.2", + "@nx/nx-win32-arm64-msvc": "19.3.2", + "@nx/nx-win32-x64-msvc": "19.3.2" + }, + "peerDependencies": { + "@swc-node/register": "^1.8.0", + "@swc/core": "^1.3.85" + }, + "peerDependenciesMeta": { + "@swc-node/register": { + "optional": true + }, + "@swc/core": { + "optional": true + } + } + }, + "node_modules/@nx/eslint-plugin/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@nx/eslint-plugin/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@nx/eslint-plugin/node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/@nx/eslint-plugin/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@nx/eslint/node_modules/@nrwl/devkit": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.3.2.tgz", + "integrity": "sha512-n3tFalVPUk1HAJ2VYNnF34yzB9j2+6swFUi4Y92PxD1vN7vrIXnNeaTx2qcee7JDjBpiJ7Zn0KLg2jwiH6hNwA==", + "dev": true, + "dependencies": { + "@nx/devkit": "19.3.2" + } + }, + "node_modules/@nx/eslint/node_modules/@nrwl/js": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nrwl/js/-/js-19.3.2.tgz", + "integrity": "sha512-ZgCoLsASIlp1xtYpWW/1ZxvKSb6BY3ZNXBmjoUW4LyN7Pk6su55gPAVt6JWIxSMm+HC+v+Cb4XFKZLdtuvE7bg==", + "dev": true, + "dependencies": { + "@nx/js": "19.3.2" + } + }, + "node_modules/@nx/eslint/node_modules/@nrwl/tao": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.3.2.tgz", + "integrity": "sha512-I1gW7woqwU6rdlgwj6XXAKcreJ5ptRKI2WpLdZErkrPmaRG/jMZx/yjZrG4PWdIEuZ4ZmYnRsoXbKN6ilCknQw==", + "dev": true, + "dependencies": { + "nx": "19.3.2", + "tslib": "^2.3.0" + }, + "bin": { + "tao": "index.js" + } + }, + "node_modules/@nx/eslint/node_modules/@nrwl/tao/node_modules/nx": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/nx/-/nx-19.3.2.tgz", + "integrity": "sha512-eKWs+ahkTKnq9EeWJCE4u8JLeq1cOHnq5DKoiisy2nwUg4KGy1odReegxUMLeEgNBcMI40EUtEJFiTMJSXZQeg==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@nrwl/tao": "19.3.2", + "@yarnpkg/lockfile": "^1.1.0", + "@yarnpkg/parsers": "3.0.0-rc.46", + "@zkochan/js-yaml": "0.0.7", + "axios": "^1.6.0", + "chalk": "^4.1.0", + "cli-cursor": "3.1.0", + "cli-spinners": "2.6.1", + "cliui": "^8.0.1", + "dotenv": "~16.4.5", + "dotenv-expand": "~11.0.6", + "enquirer": "~2.3.6", + "figures": "3.2.0", + "flat": "^5.0.2", + "front-matter": "^4.0.2", + "fs-extra": "^11.1.0", + "ignore": "^5.0.4", + "jest-diff": "^29.4.1", + "jsonc-parser": "3.2.0", + "lines-and-columns": "~2.0.3", + "minimatch": "9.0.3", + "node-machine-id": "1.1.12", + "npm-run-path": "^4.0.1", + "open": "^8.4.0", + "ora": "5.3.0", + "semver": "^7.5.3", + "string-width": "^4.2.3", + "strong-log-transformer": "^2.1.0", + "tar-stream": "~2.2.0", + "tmp": "~0.2.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0", + "yargs": "^17.6.2", + "yargs-parser": "21.1.1" + }, + "bin": { + "nx": "bin/nx.js", + "nx-cloud": "bin/nx-cloud.js" + }, + "optionalDependencies": { + "@nx/nx-darwin-arm64": "19.3.2", + "@nx/nx-darwin-x64": "19.3.2", + "@nx/nx-freebsd-x64": "19.3.2", + "@nx/nx-linux-arm-gnueabihf": "19.3.2", + "@nx/nx-linux-arm64-gnu": "19.3.2", + "@nx/nx-linux-arm64-musl": "19.3.2", + "@nx/nx-linux-x64-gnu": "19.3.2", + "@nx/nx-linux-x64-musl": "19.3.2", + "@nx/nx-win32-arm64-msvc": "19.3.2", + "@nx/nx-win32-x64-msvc": "19.3.2" + }, + "peerDependencies": { + "@swc-node/register": "^1.8.0", + "@swc/core": "^1.3.85" + }, + "peerDependenciesMeta": { + "@swc-node/register": { + "optional": true + }, + "@swc/core": { + "optional": true + } + } + }, + "node_modules/@nx/eslint/node_modules/@nrwl/workspace": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-19.3.2.tgz", + "integrity": "sha512-6gV4qa38t3GyRKmO2PLcamDcFRD7I3wl6/R0/E1eC8Wm6K2oBzjOIV5ALpz4iC4LOln88IL+AjuQdG6kdtfXlA==", + "dev": true, + "dependencies": { + "@nx/workspace": "19.3.2" + } + }, + "node_modules/@nx/eslint/node_modules/@nx/devkit": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.3.2.tgz", + "integrity": "sha512-uD3jaJ1Jvf7B6jqH2t2GH0L6REwcCGBLXq1qs1HRQF5SZrEtuUeusn8wvCKP7dftPK3byLHAG0xHRW4+IUAz/g==", + "dev": true, + "dependencies": { + "@nrwl/devkit": "19.3.2", + "ejs": "^3.1.7", + "enquirer": "~2.3.6", + "ignore": "^5.0.4", + "minimatch": "9.0.3", + "semver": "^7.5.3", + "tmp": "~0.2.1", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" + }, + "peerDependencies": { + "nx": ">= 17 <= 20" + } + }, + "node_modules/@nx/eslint/node_modules/@nx/js": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/js/-/js-19.3.2.tgz", + "integrity": "sha512-WXULhOHYDIAvs+SyDiRaNrpn1DmBAl3u7F5Jpu2VIyrcXgllrYGqUAykUqSu6Oyc2J+asfEtiG67I7UucTHLhA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.23.2", + "@babel/plugin-proposal-decorators": "^7.22.7", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-runtime": "^7.23.2", + "@babel/preset-env": "^7.23.2", + "@babel/preset-typescript": "^7.22.5", + "@babel/runtime": "^7.22.6", + "@nrwl/js": "19.3.2", + "@nx/devkit": "19.3.2", + "@nx/workspace": "19.3.2", + "babel-plugin-const-enum": "^1.0.1", + "babel-plugin-macros": "^2.8.0", + "babel-plugin-transform-typescript-metadata": "^0.3.1", + "chalk": "^4.1.0", + "columnify": "^1.6.0", + "detect-port": "^1.5.1", + "fast-glob": "3.2.7", + "fs-extra": "^11.1.0", + "ignore": "^5.0.4", + "js-tokens": "^4.0.0", + "minimatch": "9.0.3", + "npm-package-arg": "11.0.1", + "npm-run-path": "^4.0.1", + "ora": "5.3.0", + "semver": "^7.5.3", + "source-map-support": "0.5.19", + "ts-node": "10.9.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "verdaccio": "^5.0.4" + }, + "peerDependenciesMeta": { + "verdaccio": { + "optional": true + } + } + }, + "node_modules/@nx/eslint/node_modules/@nx/js/node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/@nx/eslint/node_modules/@nx/nx-darwin-arm64": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.3.2.tgz", + "integrity": "sha512-MTqPTR1FwfVfIkHKUw95dFlPBN6mbqfJ+KzLHvUSPcqLKelhi82tsisjMoB5sNK0YWcNNVqYW72ojCnHVB0TUg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/eslint/node_modules/@nx/nx-darwin-x64": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.3.2.tgz", + "integrity": "sha512-C8s9X5AlVgl3V5PycLdX+75lpAWq0qQs6QUEAnyxrLM9l+/HRecgoW6uZ7tX6Fnd8WGfMIwyahBw4LyZgk6zTw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/eslint/node_modules/@nx/nx-freebsd-x64": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.3.2.tgz", + "integrity": "sha512-XeEpEU0iqJ/5cAPMmjqJ0Sdz89ZtDRj4NdksioyhAHri94X5/3lm3lDs4tB3nObT7p3QL7r/HP1itq5DHYmMSQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/eslint/node_modules/@nx/nx-linux-arm-gnueabihf": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.3.2.tgz", + "integrity": "sha512-r4Wl0P94QRBUyiexUcfwKxqFXp48avMG3L0no/ZuNWGODbw1w8ppA4vhnkXtXbIaMdaTGx9eIYO7kFJ2SwMCng==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/eslint/node_modules/@nx/nx-linux-arm64-gnu": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.3.2.tgz", + "integrity": "sha512-oaTC4iS1fXnc61ZgSxwCQ2GGIqY64G22udRqNsX9TOtgrT7UA/mjE3Si01r+0xODimOiB525ueyxdIh1MAu6Vg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/eslint/node_modules/@nx/nx-linux-arm64-musl": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.3.2.tgz", + "integrity": "sha512-yyO9bTM7FW7HTYsSQlL4lgbAexUBpzfhdK+RkgsCiW+U/5bi+jFRxo/SbqGUL+IVliFavWyRXahMqOOM6nBq/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/eslint/node_modules/@nx/nx-linux-x64-gnu": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.3.2.tgz", + "integrity": "sha512-DC+llVdL4toLjQkDGBgzoCe26FWIOT+SzRdVcKePoNliZ4jDhkOh3+p75NEIOEcDUgoE9M2iCWEBUjkV978ogw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/eslint/node_modules/@nx/nx-linux-x64-musl": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.3.2.tgz", + "integrity": "sha512-Wun4v+kuuqv20tJiCENkHGisDqfx029bFufqxx2IOe9TvD6vK4rMMkFVPUoK3FP8EBdaMW4nrR0ZucTFnStl6w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/eslint/node_modules/@nx/nx-win32-arm64-msvc": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.3.2.tgz", + "integrity": "sha512-bNVf6eu5rWFjHvn0rKHeZYlHUcs3naXvvbduW1g0DPkHG6mt8FYffQmyboN+CSeBd/uWDPNyTUekVWwU7PjtLA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/eslint/node_modules/@nx/nx-win32-x64-msvc": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.3.2.tgz", + "integrity": "sha512-8DD5BPa5YrxTOKL3HTAgEd+IXNqRtJfwvbrn2MbOMNMyoMG9Zi5yhFvTH/HTT9Tz6VUHvXP16QWYA3R7eFi7Gg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/eslint/node_modules/@nx/workspace": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-19.3.2.tgz", + "integrity": "sha512-gam41l0hFftYIYTt8eTvZjh+ZWo62HO2p/efqZuFIa/1ZsXF1XG8MDRkCSh5Wfjh1f0jS2ma8HwPV3e8TJm2lw==", + "dev": true, + "dependencies": { + "@nrwl/workspace": "19.3.2", + "@nx/devkit": "19.3.2", + "chalk": "^4.1.0", + "enquirer": "~2.3.6", + "nx": "19.3.2", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" + } + }, + "node_modules/@nx/eslint/node_modules/@nx/workspace/node_modules/nx": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/nx/-/nx-19.3.2.tgz", + "integrity": "sha512-eKWs+ahkTKnq9EeWJCE4u8JLeq1cOHnq5DKoiisy2nwUg4KGy1odReegxUMLeEgNBcMI40EUtEJFiTMJSXZQeg==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@nrwl/tao": "19.3.2", + "@yarnpkg/lockfile": "^1.1.0", + "@yarnpkg/parsers": "3.0.0-rc.46", + "@zkochan/js-yaml": "0.0.7", + "axios": "^1.6.0", + "chalk": "^4.1.0", + "cli-cursor": "3.1.0", + "cli-spinners": "2.6.1", + "cliui": "^8.0.1", + "dotenv": "~16.4.5", + "dotenv-expand": "~11.0.6", + "enquirer": "~2.3.6", + "figures": "3.2.0", + "flat": "^5.0.2", + "front-matter": "^4.0.2", + "fs-extra": "^11.1.0", + "ignore": "^5.0.4", + "jest-diff": "^29.4.1", + "jsonc-parser": "3.2.0", + "lines-and-columns": "~2.0.3", + "minimatch": "9.0.3", + "node-machine-id": "1.1.12", + "npm-run-path": "^4.0.1", + "open": "^8.4.0", + "ora": "5.3.0", + "semver": "^7.5.3", + "string-width": "^4.2.3", + "strong-log-transformer": "^2.1.0", + "tar-stream": "~2.2.0", + "tmp": "~0.2.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0", + "yargs": "^17.6.2", + "yargs-parser": "21.1.1" + }, + "bin": { + "nx": "bin/nx.js", + "nx-cloud": "bin/nx-cloud.js" + }, + "optionalDependencies": { + "@nx/nx-darwin-arm64": "19.3.2", + "@nx/nx-darwin-x64": "19.3.2", + "@nx/nx-freebsd-x64": "19.3.2", + "@nx/nx-linux-arm-gnueabihf": "19.3.2", + "@nx/nx-linux-arm64-gnu": "19.3.2", + "@nx/nx-linux-arm64-musl": "19.3.2", + "@nx/nx-linux-x64-gnu": "19.3.2", + "@nx/nx-linux-x64-musl": "19.3.2", + "@nx/nx-win32-arm64-msvc": "19.3.2", + "@nx/nx-win32-x64-msvc": "19.3.2" + }, + "peerDependencies": { + "@swc-node/register": "^1.8.0", + "@swc/core": "^1.3.85" + }, + "peerDependenciesMeta": { + "@swc-node/register": { + "optional": true + }, + "@swc/core": { + "optional": true + } + } + }, + "node_modules/@nx/eslint/node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/@nx/eslint/node_modules/dotenv-expand": { + "version": "11.0.6", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.6.tgz", + "integrity": "sha512-8NHi73otpWsZGBSZwwknTXS5pqMOrk9+Ssrna8xCaxkzEpU9OTf9R5ArQGVw03//Zmk9MOwLPng9WwndvpAJ5g==", + "dev": true, + "dependencies": { + "dotenv": "^16.4.4" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/@nx/eslint/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/@nx/eslint/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@nx/eslint/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@nx/eslint/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@nx/eslint/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@nx/jest": { + "version": "20.0.8", + "resolved": "https://registry.npmjs.org/@nx/jest/-/jest-20.0.8.tgz", + "integrity": "sha512-LEs1EKl0RezDycGKxCaJivvKKXXHL5HUGp9dxE2FuS2nzimYhYldxlOH+zr73J5SWEZtxnMHHjRPkbDffnoxug==", + "dev": true, + "dependencies": { + "@jest/reporters": "^29.4.1", + "@jest/test-result": "^29.4.1", + "@nx/devkit": "20.0.8", + "@nx/js": "20.0.8", + "@phenomnomnominal/tsquery": "~5.0.1", + "chalk": "^4.1.0", + "identity-obj-proxy": "3.0.0", + "jest-config": "^29.4.1", + "jest-resolve": "^29.4.1", + "jest-util": "^29.4.1", + "minimatch": "9.0.3", + "resolve.exports": "1.1.0", + "semver": "^7.5.3", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" + } + }, + "node_modules/@nx/jest/node_modules/@nx/devkit": { + "version": "20.0.8", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-20.0.8.tgz", + "integrity": "sha512-MRUGgWSMzYtdwtolvWL5EZlX+7xYgu7JIXf1+3rmZU5adMmlqWKrIbyvDf53XocQlT8oxx/xXTEFHhIymGTQCg==", + "dev": true, + "dependencies": { + "ejs": "^3.1.7", + "enquirer": "~2.3.6", + "ignore": "^5.0.4", + "minimatch": "9.0.3", + "semver": "^7.5.3", + "tmp": "~0.2.1", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" + }, + "peerDependencies": { + "nx": ">= 19 <= 21" + } + }, + "node_modules/@nx/jest/node_modules/@nx/js": { + "version": "20.0.8", + "resolved": "https://registry.npmjs.org/@nx/js/-/js-20.0.8.tgz", + "integrity": "sha512-PDkjhen4Gl1bMw65XfgebSceNH7HOeTr1f5C+WY/II+7pcAx2lqWj4n6t0XkzBMWlOyfHt/H+O/F4GuZ/hjIyg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.23.2", + "@babel/plugin-proposal-decorators": "^7.22.7", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-runtime": "^7.23.2", + "@babel/preset-env": "^7.23.2", + "@babel/preset-typescript": "^7.22.5", + "@babel/runtime": "^7.22.6", + "@nx/devkit": "20.0.8", + "@nx/workspace": "20.0.8", + "@zkochan/js-yaml": "0.0.7", + "babel-plugin-const-enum": "^1.0.1", + "babel-plugin-macros": "^2.8.0", + "babel-plugin-transform-typescript-metadata": "^0.3.1", + "chalk": "^4.1.0", + "columnify": "^1.6.0", + "detect-port": "^1.5.1", + "enquirer": "~2.3.6", + "fast-glob": "3.2.7", + "ignore": "^5.0.4", + "js-tokens": "^4.0.0", + "jsonc-parser": "3.2.0", + "minimatch": "9.0.3", + "npm-package-arg": "11.0.1", + "npm-run-path": "^4.0.1", + "ora": "5.3.0", + "semver": "^7.5.3", + "source-map-support": "0.5.19", + "ts-node": "10.9.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "verdaccio": "^5.0.4" + }, + "peerDependenciesMeta": { + "verdaccio": { + "optional": true + } + } + }, + "node_modules/@nx/jest/node_modules/@nx/nx-darwin-arm64": { + "version": "20.0.8", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-20.0.8.tgz", + "integrity": "sha512-tDoafq5YUyOwxR1Y796WXA6j49OLJRO7TA/Fym52SSuD3AULbgo3/X5XeY6oL2PWM044CuUVrp3V4cIDUtyJpA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/jest/node_modules/@nx/nx-darwin-x64": { + "version": "20.0.8", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-20.0.8.tgz", + "integrity": "sha512-bvfZ6VhSvOpPV00veaJDO1a4X+f0dn8S1A73/2ThbGZrZLAQIFrA8v+ysax+bfCGRHNdtlAL+f7TG2buh/4BRg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/jest/node_modules/@nx/nx-freebsd-x64": { + "version": "20.0.8", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-20.0.8.tgz", + "integrity": "sha512-AdOme0o/pTFy+TutIOAamuGTqbh6nOLrkNEX8f4ogfDRH+k/WvjRQ4z4ne58wf/2EVXua4jKTIEipIZAP/Ad1w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/jest/node_modules/@nx/nx-linux-arm-gnueabihf": { + "version": "20.0.8", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-20.0.8.tgz", + "integrity": "sha512-PYf7Z30A1TCZq9HVUP6JjT3ghTLYkaBpR6vDwiGWUV/exuNmhUgfYW6TiTpiSArXwnAgSIbaoGe537iEvYzA7A==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/jest/node_modules/@nx/nx-linux-arm64-gnu": { + "version": "20.0.8", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-20.0.8.tgz", + "integrity": "sha512-3VpvhjmNR78HVxGzpWiwqZsG5sNvLUv2Qfohtxyc3561o8VU41R9Onf/LJmbbZvmdDaPvvXQp3rs0OXT4i7T1g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/jest/node_modules/@nx/nx-linux-arm64-musl": { + "version": "20.0.8", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-20.0.8.tgz", + "integrity": "sha512-3Z7fTJGG8h4VCHhD8Ix0zr6eFMfa1y3YDlzm8Clxu4Enzz0pEsUrT+ph6qrsArnIyUgiCowSi8+xgHFg7V/F1Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/jest/node_modules/@nx/nx-linux-x64-gnu": { + "version": "20.0.8", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-20.0.8.tgz", + "integrity": "sha512-Uttl1RHzWpjZgdzowCUNjC6/b3YhZR31wyXWgVF4PDWpDVgy4EigGc19tdrvv8pUVKQFuj0uaSTPUklguN7c3A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/jest/node_modules/@nx/nx-linux-x64-musl": { + "version": "20.0.8", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-20.0.8.tgz", + "integrity": "sha512-llc6ywSPaOWQzEzD73USyAXd/y3Slu+GHS02IsQqZeA23EIOEzhvEeeeKgs4F8LKuFW/TpV6T5IhvSHw9/mvBg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/jest/node_modules/@nx/nx-win32-arm64-msvc": { + "version": "20.0.8", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-20.0.8.tgz", + "integrity": "sha512-GhPVVNrL0QcQ3B6r0P0Dta3TIesJz7uso7iI5rCZ/oOGa02UsT4NkQBpIhxYQZ4TnHYNy84g4rHtYHrSlpDlEw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/jest/node_modules/@nx/nx-win32-x64-msvc": { + "version": "20.0.8", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-20.0.8.tgz", + "integrity": "sha512-yLlcgM0zFdmsExdLv8O2g5FWQ6d2vyN5OynKV+F5BrWHC4LvrqyYJ99y++5bLFoEi19RYIK6sLnzGIRSF6dHGg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/jest/node_modules/@nx/workspace": { + "version": "20.0.8", + "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-20.0.8.tgz", + "integrity": "sha512-G7nON6s3KDWNAH9P8IBvvAmTGgTsFZPuWH7We9px0ZwsRcURDDP1OqZsYmfr0zTHTS58wu4Uax/uQLwnTVC1xQ==", + "dev": true, + "dependencies": { + "@nx/devkit": "20.0.8", + "chalk": "^4.1.0", + "enquirer": "~2.3.6", + "nx": "20.0.8", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" + } + }, + "node_modules/@nx/jest/node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/@nx/jest/node_modules/axios": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "dev": true, + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/@nx/jest/node_modules/dotenv-expand": { + "version": "11.0.6", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.6.tgz", + "integrity": "sha512-8NHi73otpWsZGBSZwwknTXS5pqMOrk9+Ssrna8xCaxkzEpU9OTf9R5ArQGVw03//Zmk9MOwLPng9WwndvpAJ5g==", + "dev": true, + "dependencies": { + "dotenv": "^16.4.4" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/@nx/jest/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/@nx/jest/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@nx/jest/node_modules/lines-and-columns": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.3.tgz", + "integrity": "sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/@nx/jest/node_modules/nx": { + "version": "20.0.8", + "resolved": "https://registry.npmjs.org/nx/-/nx-20.0.8.tgz", + "integrity": "sha512-cMtb+u5Eji7Xm9xMHZkRXMcO8GH6FFqS2+nMgtLUZ/+ZmquEgoV8mbsKVw1u1sJ6osOpWAu9OwXcilwtvSOoBw==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@napi-rs/wasm-runtime": "0.2.4", + "@yarnpkg/lockfile": "^1.1.0", + "@yarnpkg/parsers": "3.0.0-rc.46", + "@zkochan/js-yaml": "0.0.7", + "axios": "^1.7.4", + "chalk": "^4.1.0", + "cli-cursor": "3.1.0", + "cli-spinners": "2.6.1", + "cliui": "^8.0.1", + "dotenv": "~16.4.5", + "dotenv-expand": "~11.0.6", + "enquirer": "~2.3.6", + "figures": "3.2.0", + "flat": "^5.0.2", + "front-matter": "^4.0.2", + "ignore": "^5.0.4", + "jest-diff": "^29.4.1", + "jsonc-parser": "3.2.0", + "lines-and-columns": "2.0.3", + "minimatch": "9.0.3", + "node-machine-id": "1.1.12", + "npm-run-path": "^4.0.1", + "open": "^8.4.0", + "ora": "5.3.0", + "semver": "^7.5.3", + "string-width": "^4.2.3", + "tar-stream": "~2.2.0", + "tmp": "~0.2.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0", + "yargs": "^17.6.2", + "yargs-parser": "21.1.1" + }, + "bin": { + "nx": "bin/nx.js", + "nx-cloud": "bin/nx-cloud.js" + }, + "optionalDependencies": { + "@nx/nx-darwin-arm64": "20.0.8", + "@nx/nx-darwin-x64": "20.0.8", + "@nx/nx-freebsd-x64": "20.0.8", + "@nx/nx-linux-arm-gnueabihf": "20.0.8", + "@nx/nx-linux-arm64-gnu": "20.0.8", + "@nx/nx-linux-arm64-musl": "20.0.8", + "@nx/nx-linux-x64-gnu": "20.0.8", + "@nx/nx-linux-x64-musl": "20.0.8", + "@nx/nx-win32-arm64-msvc": "20.0.8", + "@nx/nx-win32-x64-msvc": "20.0.8" + }, + "peerDependencies": { + "@swc-node/register": "^1.8.0", + "@swc/core": "^1.3.85" + }, + "peerDependenciesMeta": { + "@swc-node/register": { + "optional": true + }, + "@swc/core": { + "optional": true + } + } + }, + "node_modules/@nx/jest/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@nx/jest/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@nx/jest/node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/@nx/jest/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@nx/js": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/js/-/js-19.2.0.tgz", + "integrity": "sha512-cLz1OSfWpm/y0bZtdv5INlCo9/ED9tC45e6OKBc2ClW5Gz2+IoZz/dK/bCXg7dpEBtF1Y9mHihKisPOmUhaLwQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.23.2", + "@babel/plugin-proposal-decorators": "^7.22.7", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-runtime": "^7.23.2", + "@babel/preset-env": "^7.23.2", + "@babel/preset-typescript": "^7.22.5", + "@babel/runtime": "^7.22.6", + "@nrwl/js": "19.2.0", + "@nx/devkit": "19.2.0", + "@nx/workspace": "19.2.0", + "babel-plugin-const-enum": "^1.0.1", + "babel-plugin-macros": "^2.8.0", + "babel-plugin-transform-typescript-metadata": "^0.3.1", + "chalk": "^4.1.0", + "columnify": "^1.6.0", + "detect-port": "^1.5.1", + "fast-glob": "3.2.7", + "fs-extra": "^11.1.0", + "ignore": "^5.0.4", + "js-tokens": "^4.0.0", + "minimatch": "9.0.3", + "npm-package-arg": "11.0.1", + "npm-run-path": "^4.0.1", + "ora": "5.3.0", + "semver": "^7.5.3", + "source-map-support": "0.5.19", + "ts-node": "10.9.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "verdaccio": "^5.0.4" + }, + "peerDependenciesMeta": { + "verdaccio": { + "optional": true + } + } + }, + "node_modules/@nx/js/node_modules/@nrwl/devkit": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.2.0.tgz", + "integrity": "sha512-Ew5AJZkLXJwt15HjaIbHve8FOXmZ3HK8KPqTXqwKHX8jQW+fDUCaSXKe/lCZMNg0RvY+jMNecuC86uGdiIbLMg==", + "dev": true, + "dependencies": { + "@nx/devkit": "19.2.0" + } + }, + "node_modules/@nx/js/node_modules/@nrwl/tao": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.2.0.tgz", + "integrity": "sha512-9AOwbY/E7OlLCFu+6jhJGUIs+qurE2/3Pldooe7cJPqQmSQeJuVZuL6A2xHtbSG7VsXTq5Yj8dVvK1KmT45SIA==", + "dev": true, + "dependencies": { + "nx": "19.2.0", + "tslib": "^2.3.0" + }, + "bin": { + "tao": "index.js" + } + }, + "node_modules/@nx/js/node_modules/@nrwl/workspace": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-19.2.0.tgz", + "integrity": "sha512-/3p9KNpGHgEVjM5aMFhzdp0Vh+Bt16OnlSA+eSKPd5r0eQyLY+T4zTQ1kjyHGYa/xcN8vsWKEnbZW2fD/HWSng==", + "dev": true, + "dependencies": { + "@nx/workspace": "19.2.0" + } + }, + "node_modules/@nx/js/node_modules/@nx/devkit": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.2.0.tgz", + "integrity": "sha512-fK3zRUE2SLp9BUomFiyCuAX2E1yfWYE/hKimniscsvM34/u/xLZYVmmZ0/jfpGPbyaonXKZr2KTb7RimX/hyqg==", + "dev": true, + "dependencies": { + "@nrwl/devkit": "19.2.0", + "ejs": "^3.1.7", + "enquirer": "~2.3.6", + "ignore": "^5.0.4", + "minimatch": "9.0.3", + "semver": "^7.5.3", + "tmp": "~0.2.1", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" + }, + "peerDependencies": { + "nx": ">= 17 <= 20" + } + }, + "node_modules/@nx/js/node_modules/@nx/nx-darwin-arm64": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.2.0.tgz", + "integrity": "sha512-W+OpGyzr10oaycf4atPc5uH2wN1G6LJGHkWDN3LGSQhoDWuj13idFpjSy6rJ8WxtL8kIvPXq78GEi1yAADsakA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/js/node_modules/@nx/nx-darwin-x64": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.2.0.tgz", + "integrity": "sha512-4l1BDn29R0ugf7ATcGcZGEwK0frZSCtiyXnX3JFq55dNS4Bv3FiZLew7JULjdumXEXr773bH326FQlocLVlcXg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/js/node_modules/@nx/nx-freebsd-x64": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.2.0.tgz", + "integrity": "sha512-9zdwLRSkEg/H7bbIVWATn0H8QNgnHaTe23tciZPaBr95J6CXVJWWpC4wn9duURhvbscnqUSSSfKK1f+MSEDTbw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/js/node_modules/@nx/nx-linux-arm-gnueabihf": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.2.0.tgz", + "integrity": "sha512-KNVnqRPegJza3kU4q3pY8m0pT8OSQZnLGsDZti6morhXh2sE79f/zeevOrbhf8JnaJfQtyrXfGvjYAiL3+I8bw==", "cpu": [ "arm" ], + "dev": true, "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": ">= 10" + } }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz", - "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==", + "node_modules/@nx/js/node_modules/@nx/nx-linux-arm64-gnu": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.2.0.tgz", + "integrity": "sha512-UXIl90l+cDecU17OOLlI+uzbjzQucnNu4Mee67EqE3TyfpSvuU1l3FWZ9sbE0effp8IwKpbL7Gt5KirJKtWzIA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/js/node_modules/@nx/nx-linux-arm64-musl": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.2.0.tgz", + "integrity": "sha512-4Z8XO3WljS2GWOL2SQ1p8SRNn2Kn6FU1FWClh7KBzMtpzjsHdmOXenMP9UOGZ6gBnfBIknCEDjE3uJUHmuShGg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/js/node_modules/@nx/nx-linux-x64-gnu": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.2.0.tgz", + "integrity": "sha512-EwAkZEp0KB99VEPTskW2feCpSKqWScKdRd6UaIM9Vmqqtb5hSk6yR6p0mprjytbDtFVoKQJMOFa35qe+2R8mKQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/js/node_modules/@nx/nx-linux-x64-musl": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.2.0.tgz", + "integrity": "sha512-LbFcHe83YZUS/my/8nBxQ2i3JWakcXd7zbzZ0cSAQk6DuJVCUk8PLdgZzhrVcmT82Pv7H0fM/4jgEl+oHGoc/g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/js/node_modules/@nx/nx-win32-arm64-msvc": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.2.0.tgz", + "integrity": "sha512-BxOveRfRCdhuCs2GWbsdzGsjtLC3N+MuUlVaXSWADksF6/QKuCHM/2Kq3RYkLVVtlls6NCBp410RSx/XsbSEug==", "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ - "linux" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz", - "integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==", - "cpu": [ - "x64" + "win32" ], - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": ">= 10" + } }, - "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz", - "integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==", + "node_modules/@nx/js/node_modules/@nx/nx-win32-x64-msvc": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.2.0.tgz", + "integrity": "sha512-QiDxtOHIiRka9Bz7tSpBvQgQPrX5grLhoz6miD6LX1WjO56bZIkEAVefGnMc3WZ1PacS1ZECtymHwUy+WpEqAQ==", "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "win32" - ] + ], + "engines": { + "node": ">= 10" + } }, - "node_modules/@mswjs/interceptors": { - "version": "0.37.3", - "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.37.3.tgz", - "integrity": "sha512-USvgCL/uOGFtVa6SVyRrC8kIAedzRohxIXN5LISlg5C5vLZCn7dgMFVSNhSF9cuBEFrm/O2spDWEZeMnw4ZXYg==", + "node_modules/@nx/js/node_modules/@nx/workspace": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-19.2.0.tgz", + "integrity": "sha512-0wdv8jrGIGcf/ZF4r2/xWz/jrQjwftgLPmh7BawYPFbDZlRXkzb7a4MTJOxXH8QcR3ZJNhRjkFfHRPbB0luf1A==", "dev": true, - "license": "MIT", "dependencies": { - "@open-draft/deferred-promise": "^2.2.0", - "@open-draft/logger": "^0.3.0", - "@open-draft/until": "^2.0.0", - "is-node-process": "^1.2.0", - "outvariant": "^1.4.3", - "strict-event-emitter": "^0.5.1" + "@nrwl/workspace": "19.2.0", + "@nx/devkit": "19.2.0", + "chalk": "^4.1.0", + "enquirer": "~2.3.6", + "nx": "19.2.0", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" + } + }, + "node_modules/@nx/js/node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/@nx/js/node_modules/dotenv": { + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.2.tgz", + "integrity": "sha512-HTlk5nmhkm8F6JcdXvHIzaorzCoziNQT9mGxLPVXW8wJF1TiGSL60ZGB4gHWabHOaMmWmhvk2/lPHfnBiT78AQ==", + "dev": true, + "engines": { + "node": ">=12" }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" + } + }, + "node_modules/@nx/js/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/@nx/js/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.4.tgz", - "integrity": "sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==", + "node_modules/@nx/js/node_modules/nx": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/nx/-/nx-19.2.0.tgz", + "integrity": "sha512-IewqV0eGOpp569TSjfQVIQODxkRYKSDTP0e0j20GKkMTvCAmdbJRYZxyTr6Aw6gSM7lEVgK/4yESRO5YidfV2Q==", "dev": true, + "hasInstallScript": true, "dependencies": { - "@emnapi/core": "^1.1.0", - "@emnapi/runtime": "^1.1.0", - "@tybys/wasm-util": "^0.9.0" + "@nrwl/tao": "19.2.0", + "@yarnpkg/lockfile": "^1.1.0", + "@yarnpkg/parsers": "3.0.0-rc.46", + "@zkochan/js-yaml": "0.0.7", + "axios": "^1.6.0", + "chalk": "^4.1.0", + "cli-cursor": "3.1.0", + "cli-spinners": "2.6.1", + "cliui": "^8.0.1", + "dotenv": "~16.3.1", + "dotenv-expand": "~10.0.0", + "enquirer": "~2.3.6", + "figures": "3.2.0", + "flat": "^5.0.2", + "front-matter": "^4.0.2", + "fs-extra": "^11.1.0", + "ignore": "^5.0.4", + "jest-diff": "^29.4.1", + "jsonc-parser": "3.2.0", + "lines-and-columns": "~2.0.3", + "minimatch": "9.0.3", + "node-machine-id": "1.1.12", + "npm-run-path": "^4.0.1", + "open": "^8.4.0", + "ora": "5.3.0", + "semver": "^7.5.3", + "string-width": "^4.2.3", + "strong-log-transformer": "^2.1.0", + "tar-stream": "~2.2.0", + "tmp": "~0.2.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0", + "yargs": "^17.6.2", + "yargs-parser": "21.1.1" + }, + "bin": { + "nx": "bin/nx.js", + "nx-cloud": "bin/nx-cloud.js" + }, + "optionalDependencies": { + "@nx/nx-darwin-arm64": "19.2.0", + "@nx/nx-darwin-x64": "19.2.0", + "@nx/nx-freebsd-x64": "19.2.0", + "@nx/nx-linux-arm-gnueabihf": "19.2.0", + "@nx/nx-linux-arm64-gnu": "19.2.0", + "@nx/nx-linux-arm64-musl": "19.2.0", + "@nx/nx-linux-x64-gnu": "19.2.0", + "@nx/nx-linux-x64-musl": "19.2.0", + "@nx/nx-win32-arm64-msvc": "19.2.0", + "@nx/nx-win32-x64-msvc": "19.2.0" + }, + "peerDependencies": { + "@swc-node/register": "^1.8.0", + "@swc/core": "^1.3.85" + }, + "peerDependenciesMeta": { + "@swc-node/register": { + "optional": true + }, + "@swc/core": { + "optional": true + } } }, - "node_modules/@narval-xyz/armory-mpc-module": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/@narval-xyz/armory-mpc-module/-/armory-mpc-module-0.0.1.tgz", - "integrity": "sha512-jAUKXB4tf5KgcNeqpcpVNzivvB4IiOMKpVufdhaRx+JHQDSxfCkFYcghtoWavZGA5csryrGMFHwPUZnA7q594g==", - "bundleDependencies": [ - "@narval-xyz/armory-sdk" - ], - "optional": true, - "dependencies": { - "@narval-xyz/armory-sdk": "^0.0.5", - "@nestjs/common": "^10.0.0", - "@nestjs/core": "^10.0.0", - "@nestjs/platform-express": "^10.0.0", - "@noble/curves": "^1.4.2", - "@sepior/tsmsdkv2": "^63.0.0", - "reflect-metadata": "^0.1.13", - "rxjs": "^7.8.1" + "node_modules/@nx/js/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/@adraffy/ens-normalize": { - "version": "1.10.0", - "inBundle": true, - "license": "MIT", - "optional": true + "node_modules/@nx/js/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/@narval-xyz/armory-sdk": { - "version": "0.0.5", - "inBundle": true, - "license": "MPL-2.0", - "optional": true, + "node_modules/@nx/js/node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, "dependencies": { - "@noble/curves": "1.4.0", - "axios": "1.7.2", - "jose": "5.5.0", - "lodash": "4.17.21", - "tslib": "2.6.3", - "uuid": "9.0.1", - "viem": "2.16.2", - "zod": "3.23.8" + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } } }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/@narval-xyz/armory-sdk/node_modules/@noble/curves": { - "version": "1.4.0", - "inBundle": true, - "license": "MIT", - "optional": true, + "node_modules/@nx/js/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, "dependencies": { - "@noble/hashes": "1.4.0" + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" }, - "funding": { - "url": "https://paulmillr.com/funding/" + "engines": { + "node": ">=12" } }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/@narval-xyz/armory-sdk/node_modules/tslib": { - "version": "2.6.3", - "inBundle": true, - "license": "0BSD", - "optional": true + "node_modules/@nx/linter": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/linter/-/linter-19.3.2.tgz", + "integrity": "sha512-ODGoo0Xcl+zjRrAfcNrMoOk8m/RnDSF7kr1nXLwfNv7VnMm4gcqmwLePfvA/nQZdaNQjaweQ22OOVEAfyrmqFw==", + "dev": true, + "dependencies": { + "@nx/eslint": "19.3.2" + } }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/@noble/hashes": { - "version": "1.4.0", - "inBundle": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "node_modules/@nx/nest": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nest/-/nest-19.2.0.tgz", + "integrity": "sha512-soFP2FpznJuGQ5+MoCdBft2I4ldU0kvkoluGn9bt89D1K3NJGbnp6YS8Hu19nlsgovN27SZXCK0AtVFmxLFfHQ==", + "dev": true, + "dependencies": { + "@nestjs/schematics": "^9.1.0", + "@nrwl/nest": "19.2.0", + "@nx/devkit": "19.2.0", + "@nx/eslint": "19.2.0", + "@nx/js": "19.2.0", + "@nx/node": "19.2.0", + "@phenomnomnominal/tsquery": "~5.0.1", + "tslib": "^2.3.0" } }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/@scure/base": { - "version": "1.1.7", - "inBundle": true, - "license": "MIT", - "optional": true, - "funding": { - "url": "https://paulmillr.com/funding/" + "node_modules/@nx/nest/node_modules/@nrwl/devkit": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.2.0.tgz", + "integrity": "sha512-Ew5AJZkLXJwt15HjaIbHve8FOXmZ3HK8KPqTXqwKHX8jQW+fDUCaSXKe/lCZMNg0RvY+jMNecuC86uGdiIbLMg==", + "dev": true, + "dependencies": { + "@nx/devkit": "19.2.0" } }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/@scure/bip32": { - "version": "1.3.2", - "inBundle": true, - "license": "MIT", - "optional": true, + "node_modules/@nx/nest/node_modules/@nx/devkit": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.2.0.tgz", + "integrity": "sha512-fK3zRUE2SLp9BUomFiyCuAX2E1yfWYE/hKimniscsvM34/u/xLZYVmmZ0/jfpGPbyaonXKZr2KTb7RimX/hyqg==", + "dev": true, "dependencies": { - "@noble/curves": "~1.2.0", - "@noble/hashes": "~1.3.2", - "@scure/base": "~1.1.2" + "@nrwl/devkit": "19.2.0", + "ejs": "^3.1.7", + "enquirer": "~2.3.6", + "ignore": "^5.0.4", + "minimatch": "9.0.3", + "semver": "^7.5.3", + "tmp": "~0.2.1", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" }, - "funding": { - "url": "https://paulmillr.com/funding/" + "peerDependencies": { + "nx": ">= 17 <= 20" } }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/@scure/bip32/node_modules/@noble/curves": { - "version": "1.2.0", - "inBundle": true, - "license": "MIT", - "optional": true, + "node_modules/@nx/nest/node_modules/@nx/eslint": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/eslint/-/eslint-19.2.0.tgz", + "integrity": "sha512-9OIMntrLDPrQNZjYxOncIX+65r4RhV2dJ3PrjJ9lwCVqJKZGxfCn6f8JK8ubeLoWFPVjKEtfLTHK529vvfXifQ==", + "dev": true, "dependencies": { - "@noble/hashes": "1.3.2" + "@nx/devkit": "19.2.0", + "@nx/js": "19.2.0", + "@nx/linter": "19.2.0", + "semver": "^7.5.3", + "tslib": "^2.3.0", + "typescript": "~5.4.2" }, - "funding": { - "url": "https://paulmillr.com/funding/" + "peerDependencies": { + "@zkochan/js-yaml": "0.0.7", + "eslint": "^8.0.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "@zkochan/js-yaml": { + "optional": true + } } }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/@scure/bip32/node_modules/@noble/curves/node_modules/@noble/hashes": { - "version": "1.3.2", - "inBundle": true, - "license": "MIT", - "optional": true, + "node_modules/@nx/nest/node_modules/@nx/linter": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/linter/-/linter-19.2.0.tgz", + "integrity": "sha512-Rahjy3+OLc4aXT8VNXpwyMozeU4RB6HIQOh5NAdcA6PoOH8cG1VtbyjryIZE8l5HT1hrpI5EkONZt1UXiIGw3w==", + "dev": true, + "dependencies": { + "@nx/eslint": "19.2.0" + } + }, + "node_modules/@nx/nest/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">= 16" + "node": ">=10" + } + }, + "node_modules/@nx/next": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/next/-/next-19.2.0.tgz", + "integrity": "sha512-GL/5J80rKL5ZWmsyUxiB8aEeKy4XC8Gb+9xhV6RunCF/hOQI+B/ScHQW0N7mgYoD86QL40HhvFIa7qYbKjQwnw==", + "dev": true, + "dependencies": { + "@babel/plugin-proposal-decorators": "^7.22.7", + "@nrwl/next": "19.2.0", + "@nx/devkit": "19.2.0", + "@nx/eslint": "19.2.0", + "@nx/js": "19.2.0", + "@nx/react": "19.2.0", + "@nx/web": "19.2.0", + "@nx/webpack": "19.2.0", + "@nx/workspace": "19.2.0", + "@svgr/webpack": "^8.0.1", + "chalk": "^4.1.0", + "copy-webpack-plugin": "^10.2.4", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.0", + "ignore": "^5.0.4", + "semver": "^7.5.3", + "tslib": "^2.3.0", + "webpack-merge": "^5.8.0" + }, + "peerDependencies": { + "next": ">=14.0.0" + } + }, + "node_modules/@nx/next/node_modules/@nrwl/devkit": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.2.0.tgz", + "integrity": "sha512-Ew5AJZkLXJwt15HjaIbHve8FOXmZ3HK8KPqTXqwKHX8jQW+fDUCaSXKe/lCZMNg0RvY+jMNecuC86uGdiIbLMg==", + "dev": true, + "dependencies": { + "@nx/devkit": "19.2.0" + } + }, + "node_modules/@nx/next/node_modules/@nrwl/tao": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.2.0.tgz", + "integrity": "sha512-9AOwbY/E7OlLCFu+6jhJGUIs+qurE2/3Pldooe7cJPqQmSQeJuVZuL6A2xHtbSG7VsXTq5Yj8dVvK1KmT45SIA==", + "dev": true, + "dependencies": { + "nx": "19.2.0", + "tslib": "^2.3.0" + }, + "bin": { + "tao": "index.js" + } + }, + "node_modules/@nx/next/node_modules/@nrwl/tao/node_modules/nx": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/nx/-/nx-19.2.0.tgz", + "integrity": "sha512-IewqV0eGOpp569TSjfQVIQODxkRYKSDTP0e0j20GKkMTvCAmdbJRYZxyTr6Aw6gSM7lEVgK/4yESRO5YidfV2Q==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@nrwl/tao": "19.2.0", + "@yarnpkg/lockfile": "^1.1.0", + "@yarnpkg/parsers": "3.0.0-rc.46", + "@zkochan/js-yaml": "0.0.7", + "axios": "^1.6.0", + "chalk": "^4.1.0", + "cli-cursor": "3.1.0", + "cli-spinners": "2.6.1", + "cliui": "^8.0.1", + "dotenv": "~16.3.1", + "dotenv-expand": "~10.0.0", + "enquirer": "~2.3.6", + "figures": "3.2.0", + "flat": "^5.0.2", + "front-matter": "^4.0.2", + "fs-extra": "^11.1.0", + "ignore": "^5.0.4", + "jest-diff": "^29.4.1", + "jsonc-parser": "3.2.0", + "lines-and-columns": "~2.0.3", + "minimatch": "9.0.3", + "node-machine-id": "1.1.12", + "npm-run-path": "^4.0.1", + "open": "^8.4.0", + "ora": "5.3.0", + "semver": "^7.5.3", + "string-width": "^4.2.3", + "strong-log-transformer": "^2.1.0", + "tar-stream": "~2.2.0", + "tmp": "~0.2.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0", + "yargs": "^17.6.2", + "yargs-parser": "21.1.1" + }, + "bin": { + "nx": "bin/nx.js", + "nx-cloud": "bin/nx-cloud.js" + }, + "optionalDependencies": { + "@nx/nx-darwin-arm64": "19.2.0", + "@nx/nx-darwin-x64": "19.2.0", + "@nx/nx-freebsd-x64": "19.2.0", + "@nx/nx-linux-arm-gnueabihf": "19.2.0", + "@nx/nx-linux-arm64-gnu": "19.2.0", + "@nx/nx-linux-arm64-musl": "19.2.0", + "@nx/nx-linux-x64-gnu": "19.2.0", + "@nx/nx-linux-x64-musl": "19.2.0", + "@nx/nx-win32-arm64-msvc": "19.2.0", + "@nx/nx-win32-x64-msvc": "19.2.0" }, - "funding": { - "url": "https://paulmillr.com/funding/" + "peerDependencies": { + "@swc-node/register": "^1.8.0", + "@swc/core": "^1.3.85" + }, + "peerDependenciesMeta": { + "@swc-node/register": { + "optional": true + }, + "@swc/core": { + "optional": true + } } }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/@scure/bip32/node_modules/@noble/hashes": { - "version": "1.3.3", - "inBundle": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "node_modules/@nx/next/node_modules/@nrwl/webpack": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/webpack/-/webpack-19.2.0.tgz", + "integrity": "sha512-lYj7T967iCgo6fWzZ727oYnmtdKHhM/6A8Li945iWLg+wY/IJdTevaU+0uEvmeSsGFyr0a0DZJ1todk0gHs0Kw==", + "dev": true, + "dependencies": { + "@nx/webpack": "19.2.0" } }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/@scure/bip39": { - "version": "1.2.1", - "inBundle": true, - "license": "MIT", - "optional": true, + "node_modules/@nx/next/node_modules/@nrwl/workspace": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-19.2.0.tgz", + "integrity": "sha512-/3p9KNpGHgEVjM5aMFhzdp0Vh+Bt16OnlSA+eSKPd5r0eQyLY+T4zTQ1kjyHGYa/xcN8vsWKEnbZW2fD/HWSng==", + "dev": true, "dependencies": { - "@noble/hashes": "~1.3.0", - "@scure/base": "~1.1.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "@nx/workspace": "19.2.0" } }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/@scure/bip39/node_modules/@noble/hashes": { - "version": "1.3.3", - "inBundle": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 16" + "node_modules/@nx/next/node_modules/@nx/devkit": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.2.0.tgz", + "integrity": "sha512-fK3zRUE2SLp9BUomFiyCuAX2E1yfWYE/hKimniscsvM34/u/xLZYVmmZ0/jfpGPbyaonXKZr2KTb7RimX/hyqg==", + "dev": true, + "dependencies": { + "@nrwl/devkit": "19.2.0", + "ejs": "^3.1.7", + "enquirer": "~2.3.6", + "ignore": "^5.0.4", + "minimatch": "9.0.3", + "semver": "^7.5.3", + "tmp": "~0.2.1", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" }, - "funding": { - "url": "https://paulmillr.com/funding/" + "peerDependencies": { + "nx": ">= 17 <= 20" } }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/abitype": { - "version": "1.0.4", - "inBundle": true, - "license": "MIT", - "optional": true, - "funding": { - "url": "https://github.com/sponsors/wevm" + "node_modules/@nx/next/node_modules/@nx/eslint": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/eslint/-/eslint-19.2.0.tgz", + "integrity": "sha512-9OIMntrLDPrQNZjYxOncIX+65r4RhV2dJ3PrjJ9lwCVqJKZGxfCn6f8JK8ubeLoWFPVjKEtfLTHK529vvfXifQ==", + "dev": true, + "dependencies": { + "@nx/devkit": "19.2.0", + "@nx/js": "19.2.0", + "@nx/linter": "19.2.0", + "semver": "^7.5.3", + "tslib": "^2.3.0", + "typescript": "~5.4.2" }, "peerDependencies": { - "typescript": ">=5.0.4", - "zod": "^3 >=3.22.0" + "@zkochan/js-yaml": "0.0.7", + "eslint": "^8.0.0 || ^9.0.0" }, "peerDependenciesMeta": { - "typescript": { - "optional": true - }, - "zod": { + "@zkochan/js-yaml": { "optional": true } } }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/asynckit": { - "version": "0.4.0", - "inBundle": true, - "license": "MIT", - "optional": true - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/axios": { - "version": "1.7.2", - "inBundle": true, - "license": "MIT", - "optional": true, + "node_modules/@nx/next/node_modules/@nx/linter": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/linter/-/linter-19.2.0.tgz", + "integrity": "sha512-Rahjy3+OLc4aXT8VNXpwyMozeU4RB6HIQOh5NAdcA6PoOH8cG1VtbyjryIZE8l5HT1hrpI5EkONZt1UXiIGw3w==", + "dev": true, "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" + "@nx/eslint": "19.2.0" } }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/combined-stream": { - "version": "1.0.8", - "inBundle": true, - "license": "MIT", + "node_modules/@nx/next/node_modules/@nx/nx-darwin-arm64": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.2.0.tgz", + "integrity": "sha512-W+OpGyzr10oaycf4atPc5uH2wN1G6LJGHkWDN3LGSQhoDWuj13idFpjSy6rJ8WxtL8kIvPXq78GEi1yAADsakA==", + "cpu": [ + "arm64" + ], + "dev": true, "optional": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, + "os": [ + "darwin" + ], "engines": { - "node": ">= 0.8" + "node": ">= 10" } }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/delayed-stream": { - "version": "1.0.0", - "inBundle": true, - "license": "MIT", + "node_modules/@nx/next/node_modules/@nx/nx-darwin-x64": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.2.0.tgz", + "integrity": "sha512-4l1BDn29R0ugf7ATcGcZGEwK0frZSCtiyXnX3JFq55dNS4Bv3FiZLew7JULjdumXEXr773bH326FQlocLVlcXg==", + "cpu": [ + "x64" + ], + "dev": true, "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=0.4.0" + "node": ">= 10" } }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/follow-redirects": { - "version": "1.15.6", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } + "node_modules/@nx/next/node_modules/@nx/nx-freebsd-x64": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.2.0.tgz", + "integrity": "sha512-9zdwLRSkEg/H7bbIVWATn0H8QNgnHaTe23tciZPaBr95J6CXVJWWpC4wn9duURhvbscnqUSSSfKK1f+MSEDTbw==", + "cpu": [ + "x64" ], - "inBundle": true, - "license": "MIT", + "dev": true, "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } + "node": ">= 10" } }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/form-data": { - "version": "4.0.0", - "inBundle": true, - "license": "MIT", + "node_modules/@nx/next/node_modules/@nx/nx-linux-arm-gnueabihf": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.2.0.tgz", + "integrity": "sha512-KNVnqRPegJza3kU4q3pY8m0pT8OSQZnLGsDZti6morhXh2sE79f/zeevOrbhf8JnaJfQtyrXfGvjYAiL3+I8bw==", + "cpu": [ + "arm" + ], + "dev": true, "optional": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, + "os": [ + "linux" + ], "engines": { - "node": ">= 6" + "node": ">= 10" } }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/isows": { - "version": "1.0.4", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wagmi-dev" - } + "node_modules/@nx/next/node_modules/@nx/nx-linux-arm64-gnu": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.2.0.tgz", + "integrity": "sha512-UXIl90l+cDecU17OOLlI+uzbjzQucnNu4Mee67EqE3TyfpSvuU1l3FWZ9sbE0effp8IwKpbL7Gt5KirJKtWzIA==", + "cpu": [ + "arm64" ], - "inBundle": true, - "license": "MIT", + "dev": true, "optional": true, - "peerDependencies": { - "ws": "*" + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" } }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/jose": { - "version": "5.5.0", - "inBundle": true, - "license": "MIT", + "node_modules/@nx/next/node_modules/@nx/nx-linux-arm64-musl": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.2.0.tgz", + "integrity": "sha512-4Z8XO3WljS2GWOL2SQ1p8SRNn2Kn6FU1FWClh7KBzMtpzjsHdmOXenMP9UOGZ6gBnfBIknCEDjE3uJUHmuShGg==", + "cpu": [ + "arm64" + ], + "dev": true, "optional": true, - "funding": { - "url": "https://github.com/sponsors/panva" + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" } }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/lodash": { - "version": "4.17.21", - "inBundle": true, - "license": "MIT", - "optional": true - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/mime-db": { - "version": "1.52.0", - "inBundle": true, - "license": "MIT", + "node_modules/@nx/next/node_modules/@nx/nx-linux-x64-gnu": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.2.0.tgz", + "integrity": "sha512-EwAkZEp0KB99VEPTskW2feCpSKqWScKdRd6UaIM9Vmqqtb5hSk6yR6p0mprjytbDtFVoKQJMOFa35qe+2R8mKQ==", + "cpu": [ + "x64" + ], + "dev": true, "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.6" + "node": ">= 10" } }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/mime-types": { - "version": "2.1.35", - "inBundle": true, - "license": "MIT", + "node_modules/@nx/next/node_modules/@nx/nx-linux-x64-musl": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.2.0.tgz", + "integrity": "sha512-LbFcHe83YZUS/my/8nBxQ2i3JWakcXd7zbzZ0cSAQk6DuJVCUk8PLdgZzhrVcmT82Pv7H0fM/4jgEl+oHGoc/g==", + "cpu": [ + "x64" + ], + "dev": true, "optional": true, - "dependencies": { - "mime-db": "1.52.0" - }, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.6" + "node": ">= 10" } }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/proxy-from-env": { - "version": "1.1.0", - "inBundle": true, - "license": "MIT", - "optional": true - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/uuid": { - "version": "9.0.1", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" + "node_modules/@nx/next/node_modules/@nx/nx-win32-arm64-msvc": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.2.0.tgz", + "integrity": "sha512-BxOveRfRCdhuCs2GWbsdzGsjtLC3N+MuUlVaXSWADksF6/QKuCHM/2Kq3RYkLVVtlls6NCBp410RSx/XsbSEug==", + "cpu": [ + "arm64" ], - "inBundle": true, - "license": "MIT", + "dev": true, "optional": true, - "bin": { - "uuid": "dist/bin/uuid" + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" } }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/viem": { - "version": "2.16.2", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wevm" - } + "node_modules/@nx/next/node_modules/@nx/nx-win32-x64-msvc": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.2.0.tgz", + "integrity": "sha512-QiDxtOHIiRka9Bz7tSpBvQgQPrX5grLhoz6miD6LX1WjO56bZIkEAVefGnMc3WZ1PacS1ZECtymHwUy+WpEqAQ==", + "cpu": [ + "x64" ], - "inBundle": true, - "license": "MIT", + "dev": true, "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/next/node_modules/@nx/webpack": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/webpack/-/webpack-19.2.0.tgz", + "integrity": "sha512-/YGLknUIOmYd2r1DOUcyDnHJ4tZeVU6iHnuqUx2zv6pVZYnBs2cW6JjejH6s+n6y8hMQ7H/mXa7RR2eQI2KgaQ==", + "dev": true, "dependencies": { - "@adraffy/ens-normalize": "1.10.0", - "@noble/curves": "1.2.0", - "@noble/hashes": "1.3.2", - "@scure/bip32": "1.3.2", - "@scure/bip39": "1.2.1", - "abitype": "1.0.4", - "isows": "1.0.4", - "ws": "8.17.1" + "@babel/core": "^7.23.2", + "@nrwl/webpack": "19.2.0", + "@nx/devkit": "19.2.0", + "@nx/js": "19.2.0", + "ajv": "^8.12.0", + "autoprefixer": "^10.4.9", + "babel-loader": "^9.1.2", + "browserslist": "^4.21.4", + "chalk": "^4.1.0", + "copy-webpack-plugin": "^10.2.4", + "css-loader": "^6.4.0", + "css-minimizer-webpack-plugin": "^5.0.0", + "fork-ts-checker-webpack-plugin": "7.2.13", + "less": "4.1.3", + "less-loader": "11.1.0", + "license-webpack-plugin": "^4.0.2", + "loader-utils": "^2.0.3", + "mini-css-extract-plugin": "~2.4.7", + "parse5": "4.0.0", + "postcss": "^8.4.38", + "postcss-import": "~14.1.0", + "postcss-loader": "^6.1.1", + "rxjs": "^7.8.0", + "sass": "^1.42.1", + "sass-loader": "^12.2.0", + "source-map-loader": "^3.0.0", + "style-loader": "^3.3.0", + "stylus": "^0.59.0", + "stylus-loader": "^7.1.0", + "terser-webpack-plugin": "^5.3.3", + "ts-loader": "^9.3.1", + "tsconfig-paths-webpack-plugin": "4.0.0", + "tslib": "^2.3.0", + "webpack": "^5.80.0", + "webpack-dev-server": "^4.9.3", + "webpack-node-externals": "^3.0.0", + "webpack-subresource-integrity": "^5.1.0" + } + }, + "node_modules/@nx/next/node_modules/@nx/workspace": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-19.2.0.tgz", + "integrity": "sha512-0wdv8jrGIGcf/ZF4r2/xWz/jrQjwftgLPmh7BawYPFbDZlRXkzb7a4MTJOxXH8QcR3ZJNhRjkFfHRPbB0luf1A==", + "dev": true, + "dependencies": { + "@nrwl/workspace": "19.2.0", + "@nx/devkit": "19.2.0", + "chalk": "^4.1.0", + "enquirer": "~2.3.6", + "nx": "19.2.0", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" + } + }, + "node_modules/@nx/next/node_modules/@nx/workspace/node_modules/nx": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/nx/-/nx-19.2.0.tgz", + "integrity": "sha512-IewqV0eGOpp569TSjfQVIQODxkRYKSDTP0e0j20GKkMTvCAmdbJRYZxyTr6Aw6gSM7lEVgK/4yESRO5YidfV2Q==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@nrwl/tao": "19.2.0", + "@yarnpkg/lockfile": "^1.1.0", + "@yarnpkg/parsers": "3.0.0-rc.46", + "@zkochan/js-yaml": "0.0.7", + "axios": "^1.6.0", + "chalk": "^4.1.0", + "cli-cursor": "3.1.0", + "cli-spinners": "2.6.1", + "cliui": "^8.0.1", + "dotenv": "~16.3.1", + "dotenv-expand": "~10.0.0", + "enquirer": "~2.3.6", + "figures": "3.2.0", + "flat": "^5.0.2", + "front-matter": "^4.0.2", + "fs-extra": "^11.1.0", + "ignore": "^5.0.4", + "jest-diff": "^29.4.1", + "jsonc-parser": "3.2.0", + "lines-and-columns": "~2.0.3", + "minimatch": "9.0.3", + "node-machine-id": "1.1.12", + "npm-run-path": "^4.0.1", + "open": "^8.4.0", + "ora": "5.3.0", + "semver": "^7.5.3", + "string-width": "^4.2.3", + "strong-log-transformer": "^2.1.0", + "tar-stream": "~2.2.0", + "tmp": "~0.2.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0", + "yargs": "^17.6.2", + "yargs-parser": "21.1.1" + }, + "bin": { + "nx": "bin/nx.js", + "nx-cloud": "bin/nx-cloud.js" + }, + "optionalDependencies": { + "@nx/nx-darwin-arm64": "19.2.0", + "@nx/nx-darwin-x64": "19.2.0", + "@nx/nx-freebsd-x64": "19.2.0", + "@nx/nx-linux-arm-gnueabihf": "19.2.0", + "@nx/nx-linux-arm64-gnu": "19.2.0", + "@nx/nx-linux-arm64-musl": "19.2.0", + "@nx/nx-linux-x64-gnu": "19.2.0", + "@nx/nx-linux-x64-musl": "19.2.0", + "@nx/nx-win32-arm64-msvc": "19.2.0", + "@nx/nx-win32-x64-msvc": "19.2.0" }, "peerDependencies": { - "typescript": ">=5.0.4" + "@swc-node/register": "^1.8.0", + "@swc/core": "^1.3.85" }, "peerDependenciesMeta": { - "typescript": { + "@swc-node/register": { + "optional": true + }, + "@swc/core": { "optional": true } } }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/viem/node_modules/@noble/curves": { - "version": "1.2.0", - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@noble/hashes": "1.3.2" + "node_modules/@nx/next/node_modules/array-union": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz", + "integrity": "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==", + "dev": true, + "engines": { + "node": ">=12" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/viem/node_modules/@noble/hashes": { - "version": "1.3.2", - "inBundle": true, - "license": "MIT", - "optional": true, + "node_modules/@nx/next/node_modules/copy-webpack-plugin": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz", + "integrity": "sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg==", + "dev": true, + "dependencies": { + "fast-glob": "^3.2.7", + "glob-parent": "^6.0.1", + "globby": "^12.0.2", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0" + }, "engines": { - "node": ">= 16" + "node": ">= 12.20.0" }, "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/ws": { - "version": "8.17.1", - "inBundle": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=10.0.0" + "type": "opencollective", + "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" + "webpack": "^5.1.0" + } + }, + "node_modules/@nx/next/node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dev": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "engines": { + "node": ">=10" } }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/zod": { - "version": "3.23.8", - "inBundle": true, - "license": "MIT", - "optional": true, + "node_modules/@nx/next/node_modules/dotenv": { + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.2.tgz", + "integrity": "sha512-HTlk5nmhkm8F6JcdXvHIzaorzCoziNQT9mGxLPVXW8wJF1TiGSL60ZGB4gHWabHOaMmWmhvk2/lPHfnBiT78AQ==", + "dev": true, + "engines": { + "node": ">=12" + }, "funding": { - "url": "https://github.com/sponsors/colinhacks" + "url": "https://github.com/motdotla/dotenv?sponsor=1" } }, - "node_modules/@narval-xyz/armory-sdk": { - "resolved": "packages/armory-sdk", - "link": true + "node_modules/@nx/next/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, - "node_modules/@nestjs/axios": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-3.0.2.tgz", - "integrity": "sha512-Z6GuOUdNQjP7FX+OuV2Ybyamse+/e0BFdTWBX5JxpBDKA+YkdLynDgG6HTF04zy6e9zPa19UX0WA2VDoehwhXQ==", - "peerDependencies": { - "@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0", - "axios": "^1.3.1", - "rxjs": "^6.0.0 || ^7.0.0" + "node_modules/@nx/next/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" } }, - "node_modules/@nestjs/bull": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/@nestjs/bull/-/bull-10.2.0.tgz", - "integrity": "sha512-byQI3cgAVP8BNa71h5g33D1pNwOaK2O9+zYmT98eU8LxxJHh53aWMwEUrCHrwgSz4P8bD+jY8ObQ5vtU4SsidA==", + "node_modules/@nx/next/node_modules/globby": { + "version": "12.2.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-12.2.0.tgz", + "integrity": "sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA==", + "dev": true, "dependencies": { - "@nestjs/bull-shared": "^10.2.0", - "tslib": "2.6.3" + "array-union": "^3.0.1", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.7", + "ignore": "^5.1.9", + "merge2": "^1.4.1", + "slash": "^4.0.0" }, - "peerDependencies": { - "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", - "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0", - "bull": "^3.3 || ^4.0.0" + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@nestjs/bull-shared": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/@nestjs/bull-shared/-/bull-shared-10.2.0.tgz", - "integrity": "sha512-cSi6CyPECHDFumnHWWfwLCnbc6hm5jXt7FqzJ0Id6EhGqdz5ja0FmgRwXoS4xoMA2RRjlxn2vGXr4YOaHBAeig==", + "node_modules/@nx/next/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, "dependencies": { - "tslib": "2.6.3" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, - "peerDependencies": { - "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", - "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/@nestjs/cache-manager": { + "node_modules/@nx/next/node_modules/is-fullwidth-code-point": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@nestjs/cache-manager/-/cache-manager-3.0.0.tgz", - "integrity": "sha512-csKvxHSQWfC0OiDo0bNEhLqrmYDopHEvRyC81MxV9xFj1AO+rOKocpHa4M1ZGH//6uKFIPGN9oiR0mvZY77APA==", - "license": "MIT", - "peerDependencies": { - "@nestjs/common": "^9.0.0 || ^10.0.0 || ^11.0.0", - "@nestjs/core": "^9.0.0 || ^10.0.0 || ^11.0.0", - "cache-manager": ">=6", - "rxjs": "^7.8.1" + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" } }, - "node_modules/@nestjs/common": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.3.10.tgz", - "integrity": "sha512-H8k0jZtxk1IdtErGDmxFRy0PfcOAUg41Prrqpx76DQusGGJjsaovs1zjXVD1rZWaVYchfT1uczJ6L4Kio10VNg==", + "node_modules/@nx/next/node_modules/mini-css-extract-plugin": { + "version": "2.4.7", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.4.7.tgz", + "integrity": "sha512-euWmddf0sk9Nv1O0gfeeUAvAkoSlWncNLF77C0TP2+WoPvy8mAHKOzMajcCz2dzvyt3CNgxb1obIEVFIRxaipg==", + "dev": true, "dependencies": { - "iterare": "1.2.1", - "tslib": "2.6.3", - "uid": "2.0.2" + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/nest" + "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "class-transformer": "*", - "class-validator": "*", - "reflect-metadata": "^0.1.12 || ^0.2.0", - "rxjs": "^7.1.0" - }, - "peerDependenciesMeta": { - "class-transformer": { - "optional": true - }, - "class-validator": { - "optional": true - } + "webpack": "^5.0.0" } }, - "node_modules/@nestjs/config": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-3.1.1.tgz", - "integrity": "sha512-qu5QlNiJdqQtOsnB6lx4JCXPQ96jkKUsOGd+JXfXwqJqZcOSAq6heNFg0opW4pq4J/VZoNwoo87TNnx9wthnqQ==", + "node_modules/@nx/next/node_modules/postcss-loader": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", + "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", + "dev": true, "dependencies": { - "dotenv": "16.3.1", - "dotenv-expand": "10.0.0", - "lodash": "4.17.21", - "uuid": "9.0.0" + "cosmiconfig": "^7.0.0", + "klona": "^2.0.5", + "semver": "^7.3.5" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", - "reflect-metadata": "^0.1.13" + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" } }, - "node_modules/@nestjs/config/node_modules/dotenv": { - "version": "16.3.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", - "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", + "node_modules/@nx/next/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@nx/next/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "dev": true, "engines": { "node": ">=12" }, "funding": { - "url": "https://github.com/motdotla/dotenv?sponsor=1" - } - }, - "node_modules/@nestjs/config/node_modules/uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", - "bin": { - "uuid": "dist/bin/uuid" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@nestjs/core": { - "version": "10.4.7", - "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.4.7.tgz", - "integrity": "sha512-AIpQzW/vGGqSLkKvll1R7uaSNv99AxZI2EFyVJPNGDgFsfXaohfV1Ukl6f+s75Km+6Fj/7aNl80EqzNWQCS8Ig==", - "hasInstallScript": true, + "node_modules/@nx/next/node_modules/source-map-loader": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-3.0.2.tgz", + "integrity": "sha512-BokxPoLjyl3iOrgkWaakaxqnelAJSS+0V+De0kKIq6lyWrXuiPgYTGp6z3iHmqljKAaLXwZa+ctD8GccRJeVvg==", + "dev": true, "dependencies": { - "@nuxtjs/opencollective": "0.3.2", - "fast-safe-stringify": "2.1.1", - "iterare": "1.2.1", - "path-to-regexp": "3.3.0", - "tslib": "2.7.0", - "uid": "2.0.2" + "abab": "^2.0.5", + "iconv-lite": "^0.6.3", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": ">= 12.13.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/nest" + "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "@nestjs/common": "^10.0.0", - "@nestjs/microservices": "^10.0.0", - "@nestjs/platform-express": "^10.0.0", - "@nestjs/websockets": "^10.0.0", - "reflect-metadata": "^0.1.12 || ^0.2.0", - "rxjs": "^7.1.0" - }, - "peerDependenciesMeta": { - "@nestjs/microservices": { - "optional": true - }, - "@nestjs/platform-express": { - "optional": true - }, - "@nestjs/websockets": { - "optional": true - } + "webpack": "^5.0.0" } }, - "node_modules/@nestjs/core/node_modules/path-to-regexp": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.3.0.tgz", - "integrity": "sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==" - }, - "node_modules/@nestjs/core/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" - }, - "node_modules/@nestjs/event-emitter": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@nestjs/event-emitter/-/event-emitter-2.1.1.tgz", - "integrity": "sha512-6L6fBOZTyfFlL7Ih/JDdqlCzZeCW0RjCX28wnzGyg/ncv5F/EOeT1dfopQr1loBRQ3LTgu8OWM7n4zLN4xigsg==", - "license": "MIT", + "node_modules/@nx/next/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "dependencies": { - "eventemitter2": "6.4.9" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, - "peerDependencies": { - "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", - "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0" + "engines": { + "node": ">=8" } }, - "node_modules/@nestjs/mapped-types": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-2.0.5.tgz", - "integrity": "sha512-bSJv4pd6EY99NX9CjBIyn4TVDoSit82DUZlL4I3bqNfy5Gt+gXTa86i3I/i0iIV9P4hntcGM5GyO+FhZAhxtyg==", - "peerDependencies": { - "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", - "class-transformer": "^0.4.0 || ^0.5.0", - "class-validator": "^0.13.0 || ^0.14.0", - "reflect-metadata": "^0.1.12 || ^0.2.0" - }, - "peerDependenciesMeta": { - "class-transformer": { - "optional": true - }, - "class-validator": { - "optional": true - } + "node_modules/@nx/next/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 6" } }, - "node_modules/@nestjs/platform-express": { - "version": "10.3.9", - "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.3.9.tgz", - "integrity": "sha512-si/UzobP6YUtYtCT1cSyQYHHzU3yseqYT6l7OHSMVvfG1+TqxaAqI6nmrix02LO+l1YntHRXEs3p+v9a7EfrSQ==", - "license": "MIT", + "node_modules/@nx/next/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, "dependencies": { - "body-parser": "1.20.2", - "cors": "2.8.5", - "express": "4.19.2", - "multer": "1.4.4-lts.1", - "tslib": "2.6.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nest" + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" }, - "peerDependencies": { - "@nestjs/common": "^10.0.0", - "@nestjs/core": "^10.0.0" + "engines": { + "node": ">=12" } }, - "node_modules/@nestjs/platform-express/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "license": "0BSD" + "node_modules/@nx/node": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/node/-/node-19.2.0.tgz", + "integrity": "sha512-d4VnUY5i4nWw2dIkc3OJx4tiBNPsym9Xvq0XyyHjCn3DXTFOH9UiYpVR3kOL/22DeQs8hGOkb3jaSNdi2W8Dlg==", + "dev": true, + "dependencies": { + "@nrwl/node": "19.2.0", + "@nx/devkit": "19.2.0", + "@nx/eslint": "19.2.0", + "@nx/jest": "19.2.0", + "@nx/js": "19.2.0", + "tslib": "^2.3.0" + } }, - "node_modules/@nestjs/schematics": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-9.2.0.tgz", - "integrity": "sha512-wHpNJDPzM6XtZUOB3gW0J6mkFCSJilzCM3XrHI1o0C8vZmFE1snbmkIXNyoi1eV0Nxh1BMymcgz5vIMJgQtTqw==", + "node_modules/@nx/node/node_modules/@nrwl/devkit": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.2.0.tgz", + "integrity": "sha512-Ew5AJZkLXJwt15HjaIbHve8FOXmZ3HK8KPqTXqwKHX8jQW+fDUCaSXKe/lCZMNg0RvY+jMNecuC86uGdiIbLMg==", "dev": true, "dependencies": { - "@angular-devkit/core": "16.0.1", - "@angular-devkit/schematics": "16.0.1", - "jsonc-parser": "3.2.0", - "pluralize": "8.0.0" - }, - "peerDependencies": { - "typescript": ">=4.3.5" + "@nx/devkit": "19.2.0" } }, - "node_modules/@nestjs/swagger": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-7.4.0.tgz", - "integrity": "sha512-dCiwKkRxcR7dZs5jtrGspBAe/nqJd1AYzOBTzw9iCdbq3BGrLpwokelk6lFZPe4twpTsPQqzNKBwKzVbI6AR/g==", + "node_modules/@nx/node/node_modules/@nx/devkit": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.2.0.tgz", + "integrity": "sha512-fK3zRUE2SLp9BUomFiyCuAX2E1yfWYE/hKimniscsvM34/u/xLZYVmmZ0/jfpGPbyaonXKZr2KTb7RimX/hyqg==", + "dev": true, "dependencies": { - "@microsoft/tsdoc": "^0.15.0", - "@nestjs/mapped-types": "2.0.5", - "js-yaml": "4.1.0", - "lodash": "4.17.21", - "path-to-regexp": "3.2.0", - "swagger-ui-dist": "5.17.14" + "@nrwl/devkit": "19.2.0", + "ejs": "^3.1.7", + "enquirer": "~2.3.6", + "ignore": "^5.0.4", + "minimatch": "9.0.3", + "semver": "^7.5.3", + "tmp": "~0.2.1", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" }, "peerDependencies": { - "@fastify/static": "^6.0.0 || ^7.0.0", - "@nestjs/common": "^9.0.0 || ^10.0.0", - "@nestjs/core": "^9.0.0 || ^10.0.0", - "class-transformer": "*", - "class-validator": "*", - "reflect-metadata": "^0.1.12 || ^0.2.0" - }, - "peerDependenciesMeta": { - "@fastify/static": { - "optional": true - }, - "class-transformer": { - "optional": true - }, - "class-validator": { - "optional": true - } + "nx": ">= 17 <= 20" } }, - "node_modules/@nestjs/testing": { - "version": "10.4.1", - "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.4.1.tgz", - "integrity": "sha512-pR+su5+YGqCLH0RhhVkPowQK7FCORU0/PWAywPK7LScAOtD67ZoviZ7hAU4vnGdwkg4HCB0D7W8Bkg19CGU8Xw==", + "node_modules/@nx/node/node_modules/@nx/eslint": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/eslint/-/eslint-19.2.0.tgz", + "integrity": "sha512-9OIMntrLDPrQNZjYxOncIX+65r4RhV2dJ3PrjJ9lwCVqJKZGxfCn6f8JK8ubeLoWFPVjKEtfLTHK529vvfXifQ==", "dev": true, "dependencies": { - "tslib": "2.6.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nest" + "@nx/devkit": "19.2.0", + "@nx/js": "19.2.0", + "@nx/linter": "19.2.0", + "semver": "^7.5.3", + "tslib": "^2.3.0", + "typescript": "~5.4.2" }, "peerDependencies": { - "@nestjs/common": "^10.0.0", - "@nestjs/core": "^10.0.0", - "@nestjs/microservices": "^10.0.0", - "@nestjs/platform-express": "^10.0.0" + "@zkochan/js-yaml": "0.0.7", + "eslint": "^8.0.0 || ^9.0.0" }, "peerDependenciesMeta": { - "@nestjs/microservices": { - "optional": true - }, - "@nestjs/platform-express": { + "@zkochan/js-yaml": { "optional": true } } }, - "node_modules/@next/env": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.4.tgz", - "integrity": "sha512-3EtkY5VDkuV2+lNmKlbkibIJxcO4oIHEhBWne6PaAp+76J9KoSsGvNikp6ivzAT8dhhBMYrm6op2pS1ApG0Hzg==" - }, - "node_modules/@next/eslint-plugin-next": { - "version": "14.2.6", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.6.tgz", - "integrity": "sha512-d3+p4AjIYmhqzYHhhmkRYYN6ZU35TwZAKX08xKRfnHkz72KhWL2kxMFsDptpZs5e8bBGdepn7vn1+9DaF8iX+A==", + "node_modules/@nx/node/node_modules/@nx/jest": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/jest/-/jest-19.2.0.tgz", + "integrity": "sha512-iJMqfwkIB4T7NRYAQe3nZWFEAQGGblMGcxWczMKEixCIZWcAz4up74eb0H6Yv+tUVOQHrFTm6J1OnrW3BqvOZA==", "dev": true, "dependencies": { - "glob": "10.3.10" + "@jest/reporters": "^29.4.1", + "@jest/test-result": "^29.4.1", + "@nrwl/jest": "19.2.0", + "@nx/devkit": "19.2.0", + "@nx/js": "19.2.0", + "@phenomnomnominal/tsquery": "~5.0.1", + "chalk": "^4.1.0", + "identity-obj-proxy": "3.0.0", + "jest-config": "^29.4.1", + "jest-resolve": "^29.4.1", + "jest-util": "^29.4.1", + "minimatch": "9.0.3", + "resolve.exports": "1.1.0", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" } }, - "node_modules/@next/eslint-plugin-next/node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "node_modules/@nx/node/node_modules/@nx/linter": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/linter/-/linter-19.2.0.tgz", + "integrity": "sha512-Rahjy3+OLc4aXT8VNXpwyMozeU4RB6HIQOh5NAdcA6PoOH8cG1VtbyjryIZE8l5HT1hrpI5EkONZt1UXiIGw3w==", "dev": true, "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - }, + "@nx/eslint": "19.2.0" + } + }, + "node_modules/@nx/node/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, "bin": { - "glob": "dist/esm/bin.mjs" + "semver": "bin/semver.js" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=10" } }, - "node_modules/@next/swc-darwin-arm64": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.4.tgz", - "integrity": "sha512-AH3mO4JlFUqsYcwFUHb1wAKlebHU/Hv2u2kb1pAuRanDZ7pD/A/KPD98RHZmwsJpdHQwfEc/06mgpSzwrJYnNg==", + "node_modules/@nx/nx-darwin-arm64": { + "version": "19.4.4", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.4.4.tgz", + "integrity": "sha512-qmPz1PYsV1zlpSWBHLmy3J7Hw5H5pPWAps6ObcxwUuQwli6uySi4OKFKCLnmWgi1ICvB2NviChK45OIDtxJ2Iw==", "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "darwin" @@ -7226,13 +18790,14 @@ "node": ">= 10" } }, - "node_modules/@next/swc-darwin-x64": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.4.tgz", - "integrity": "sha512-QVadW73sWIO6E2VroyUjuAxhWLZWEpiFqHdZdoQ/AMpN9YWGuHV8t2rChr0ahy+irKX5mlDU7OY68k3n4tAZTg==", + "node_modules/@nx/nx-darwin-x64": { + "version": "19.4.4", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.4.4.tgz", + "integrity": "sha512-/M+KQrjaIovhTP81BGMQ3AezSy9ZYhubXg7G3ltcMfox07yw5Pj10Ip9ZwkE5zF6CuJXNAoLesmNhbqMXodsag==", "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "darwin" @@ -7241,13 +18806,30 @@ "node": ">= 10" } }, - "node_modules/@next/swc-linux-arm64-gnu": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.4.tgz", - "integrity": "sha512-KT6GUrb3oyCfcfJ+WliXuJnD6pCpZiosx2X3k66HLR+DMoilRb76LpWPGb4tZprawTtcnyrv75ElD6VncVamUQ==", + "node_modules/@nx/nx-freebsd-x64": { + "version": "19.4.4", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.4.4.tgz", + "integrity": "sha512-PegR8GgHn24/eXqVRme3iRPHVYmH94rSBNoKOrWHJ8RTA/Dw+ZoOmhdLssOSs6z7JQ0S63MKo8x/HILI3+WyXw==", "cpu": [ - "arm64" + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-linux-arm-gnueabihf": { + "version": "19.4.4", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.4.4.tgz", + "integrity": "sha512-6Yz0aTR8XE/MXpjbQ5HRlGcngYXUv156tJeynO8lyiZ0HK1RkUq+MsbSLw0zvqBUljWQwQwK20rsAx9AUqM9kQ==", + "cpu": [ + "arm" ], + "dev": true, "optional": true, "os": [ "linux" @@ -7256,13 +18838,14 @@ "node": ">= 10" } }, - "node_modules/@next/swc-linux-arm64-musl": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.4.tgz", - "integrity": "sha512-Alv8/XGSs/ytwQcbCHwze1HmiIkIVhDHYLjczSVrf0Wi2MvKn/blt7+S6FJitj3yTlMwMxII1gIJ9WepI4aZ/A==", + "node_modules/@nx/nx-linux-arm64-gnu": { + "version": "19.4.4", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.4.4.tgz", + "integrity": "sha512-33zZ+ytnRgXnx7Ls8hoEtXSRDJF8PuZaJBbGocrpfXku58fHj7+AJtQZWjQe3STGJuVUbmIZNfGJ/st+3Zeccg==", "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -7271,13 +18854,14 @@ "node": ">= 10" } }, - "node_modules/@next/swc-linux-x64-gnu": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.4.tgz", - "integrity": "sha512-ze0ShQDBPCqxLImzw4sCdfnB3lRmN3qGMB2GWDRlq5Wqy4G36pxtNOo2usu/Nm9+V2Rh/QQnrRc2l94kYFXO6Q==", + "node_modules/@nx/nx-linux-arm64-musl": { + "version": "19.4.4", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.4.4.tgz", + "integrity": "sha512-00qPmFs0LGmeudYSwhcuMLNRb4/Eaaf6SMkqdbJU2iKEbq6rY7clORAJlOn3FQPmxi/j2uEfbkONMfO8pqsu3A==", "cpu": [ - "x64" + "arm64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -7286,13 +18870,14 @@ "node": ">= 10" } }, - "node_modules/@next/swc-linux-x64-musl": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.4.tgz", - "integrity": "sha512-8dwC0UJoc6fC7PX70csdaznVMNr16hQrTDAMPvLPloazlcaWfdPogq+UpZX6Drqb1OBlwowz8iG7WR0Tzk/diQ==", + "node_modules/@nx/nx-linux-x64-gnu": { + "version": "19.4.4", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.4.4.tgz", + "integrity": "sha512-R7wIdVzSVvKTsLPRBIo9eouEik4ZiYhR4eG2XybhdWNhv8vC+VzOdbWWUyxQzzxj2Lo5o7d4UlFxvblTftQJJw==", "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -7301,28 +18886,30 @@ "node": ">= 10" } }, - "node_modules/@next/swc-win32-arm64-msvc": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.4.tgz", - "integrity": "sha512-jxyg67NbEWkDyvM+O8UDbPAyYRZqGLQDTPwvrBBeOSyVWW/jFQkQKQ70JDqDSYg1ZDdl+E3nkbFbq8xM8E9x8A==", + "node_modules/@nx/nx-linux-x64-musl": { + "version": "19.4.4", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.4.4.tgz", + "integrity": "sha512-2Xu71Jwa0Ti2fwvvGXb21kpMaga4eZeS5+2MKMJnE2hzW6NWSx68xnw6TPJIdEKbkJUHWk32vF4vob79puunHQ==", "cpu": [ - "arm64" + "x64" ], + "dev": true, "optional": true, "os": [ - "win32" + "linux" ], "engines": { "node": ">= 10" } }, - "node_modules/@next/swc-win32-ia32-msvc": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.4.tgz", - "integrity": "sha512-twrmN753hjXRdcrZmZttb/m5xaCBFa48Dt3FbeEItpJArxriYDunWxJn+QFXdJ3hPkm4u7CKxncVvnmgQMY1ag==", + "node_modules/@nx/nx-win32-arm64-msvc": { + "version": "19.4.4", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.4.4.tgz", + "integrity": "sha512-ztF1MhxB+IdLIqwx1DbAdqJvTHrFstUavinFTxTaGBTu9AtFwziRP567XB8TiyzyCSmY9H8JJHGByQ0Mr6cUbQ==", "cpu": [ - "ia32" + "arm64" ], + "dev": true, "optional": true, "os": [ "win32" @@ -7331,13 +18918,14 @@ "node": ">= 10" } }, - "node_modules/@next/swc-win32-x64-msvc": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.4.tgz", - "integrity": "sha512-tkLrjBzqFTP8DVrAAQmZelEahfR9OxWpFR++vAI9FBhCiIxtwHwBHC23SBHCTURBtwB4kc/x44imVOnkKGNVGg==", + "node_modules/@nx/nx-win32-x64-msvc": { + "version": "19.4.4", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.4.4.tgz", + "integrity": "sha512-AdcjRiQ3MXlhpwCt5QprxtwAvG+VcYymF6ZI37aHZ9EkSEkD77iFgpkAhfhhHEgbTmnGBcMZMwJ5MENXjwdW8A==", "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "win32" @@ -7346,124 +18934,26 @@ "node": ">= 10" } }, - "node_modules/@noble/ciphers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.0.0.tgz", - "integrity": "sha512-wH5EHOmLi0rEazphPbecAzmjd12I6/Yv/SiHdkA9LSycsQk7RuuTp7am5/o62qYr0RScE7Pc9icXGBbsr6cesA==", - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@noble/curves": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.6.0.tgz", - "integrity": "sha512-TlaHRXDehJuRNR9TfZDNQ45mMEd5dwUwmicsafcIX4SsNiqnCHKjE/1alYPd/lDRVhxdhUAlv8uEhMCI5zjIJQ==", - "dependencies": { - "@noble/hashes": "1.5.0" - }, - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@noble/curves/node_modules/@noble/hashes": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.5.0.tgz", - "integrity": "sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==", - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@noble/ed25519": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@noble/ed25519/-/ed25519-1.7.1.tgz", - "integrity": "sha512-Rk4SkJFaXZiznFyC/t77Q0NKS4FL7TLJJsVG2V2oiEq3kJVeTdxysEe/yRWSpnWMe808XRDJ+VFh5pt/FN5plw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ] - }, - "node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nrwl/devkit": { - "version": "19.5.1", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.5.1.tgz", - "integrity": "sha512-ZsckDZszLTv3oshNsY5fZ86g8a/VcGvgDpdiP/z/A/krtOHL8iUjdT/72Eo5DIult5WcSFjnifyWcyWIGe1PeA==", - "dev": true, - "dependencies": { - "@nx/devkit": "19.5.1" - } - }, - "node_modules/@nrwl/eslint-plugin-nx": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nrwl/eslint-plugin-nx/-/eslint-plugin-nx-19.3.2.tgz", - "integrity": "sha512-OD9WYOpTCgMQWTwUKRUuXlVfegkbkqNqkVQ3hsftjTn1dkB8QbvMa9ajqDGU+pbQDLeMMwtjc4itVpUimvmudQ==", - "dev": true, - "dependencies": { - "@nx/eslint-plugin": "19.3.2" - } - }, - "node_modules/@nrwl/jest": { + "node_modules/@nx/react": { "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/jest/-/jest-19.2.0.tgz", - "integrity": "sha512-s3qb0AblY+wqPUJFraWP9MYVyv3EA8bbEsMRCuvDDbhoe2nnyd/7PmluyPsWgJVdgbY9Ajgs3ZjuBEfFQ3VV9A==", + "resolved": "https://registry.npmjs.org/@nx/react/-/react-19.2.0.tgz", + "integrity": "sha512-G9PSRnX8X4lCaJ7808xwL+kfZ/LWLi/Rph6mGJFnSS+0Y89WyHNcQTIWdvzabQy2RwXgi/eDy1FToDx/5rTZbA==", "dev": true, "dependencies": { - "@nx/jest": "19.2.0" + "@nrwl/react": "19.2.0", + "@nx/devkit": "19.2.0", + "@nx/eslint": "19.2.0", + "@nx/js": "19.2.0", + "@nx/web": "19.2.0", + "@phenomnomnominal/tsquery": "~5.0.1", + "@svgr/webpack": "^8.0.1", + "chalk": "^4.1.0", + "file-loader": "^6.2.0", + "minimatch": "9.0.3", + "tslib": "^2.3.0" } }, - "node_modules/@nrwl/jest/node_modules/@nrwl/devkit": { + "node_modules/@nx/react/node_modules/@nrwl/devkit": { "version": "19.2.0", "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.2.0.tgz", "integrity": "sha512-Ew5AJZkLXJwt15HjaIbHve8FOXmZ3HK8KPqTXqwKHX8jQW+fDUCaSXKe/lCZMNg0RvY+jMNecuC86uGdiIbLMg==", @@ -7472,7 +18962,7 @@ "@nx/devkit": "19.2.0" } }, - "node_modules/@nrwl/jest/node_modules/@nx/devkit": { + "node_modules/@nx/react/node_modules/@nx/devkit": { "version": "19.2.0", "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.2.0.tgz", "integrity": "sha512-fK3zRUE2SLp9BUomFiyCuAX2E1yfWYE/hKimniscsvM34/u/xLZYVmmZ0/jfpGPbyaonXKZr2KTb7RimX/hyqg==", @@ -7492,150 +18982,81 @@ "nx": ">= 17 <= 20" } }, - "node_modules/@nrwl/jest/node_modules/@nx/jest": { + "node_modules/@nx/react/node_modules/@nx/eslint": { "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/jest/-/jest-19.2.0.tgz", - "integrity": "sha512-iJMqfwkIB4T7NRYAQe3nZWFEAQGGblMGcxWczMKEixCIZWcAz4up74eb0H6Yv+tUVOQHrFTm6J1OnrW3BqvOZA==", + "resolved": "https://registry.npmjs.org/@nx/eslint/-/eslint-19.2.0.tgz", + "integrity": "sha512-9OIMntrLDPrQNZjYxOncIX+65r4RhV2dJ3PrjJ9lwCVqJKZGxfCn6f8JK8ubeLoWFPVjKEtfLTHK529vvfXifQ==", "dev": true, "dependencies": { - "@jest/reporters": "^29.4.1", - "@jest/test-result": "^29.4.1", - "@nrwl/jest": "19.2.0", "@nx/devkit": "19.2.0", "@nx/js": "19.2.0", - "@phenomnomnominal/tsquery": "~5.0.1", - "chalk": "^4.1.0", - "identity-obj-proxy": "3.0.0", - "jest-config": "^29.4.1", - "jest-resolve": "^29.4.1", - "jest-util": "^29.4.1", - "minimatch": "9.0.3", - "resolve.exports": "1.1.0", + "@nx/linter": "19.2.0", + "semver": "^7.5.3", "tslib": "^2.3.0", - "yargs-parser": "21.1.1" - } - }, - "node_modules/@nrwl/jest/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" + "typescript": "~5.4.2" }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@nrwl/js": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/js/-/js-19.2.0.tgz", - "integrity": "sha512-i6CyQvTP1etmTxjFhUIw/HAtoZCENbhkc7UmAsyCgTX5IJeo0U3YoHsmDI0TE45yu+4x4gcKLqOHs2zqWj7WCw==", - "dev": true, - "dependencies": { - "@nx/js": "19.2.0" - } - }, - "node_modules/@nrwl/nest": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/nest/-/nest-19.2.0.tgz", - "integrity": "sha512-JjhGurz1neZHyrRtmstBHpIAfh/TE3h/untSMqiixrRg8k+qPZBi2dpcV6HZxWVoDkgKrL6ro7olmiXvWMQdqw==", - "dev": true, - "dependencies": { - "@nx/nest": "19.2.0" + "peerDependencies": { + "@zkochan/js-yaml": "0.0.7", + "eslint": "^8.0.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "@zkochan/js-yaml": { + "optional": true + } } }, - "node_modules/@nrwl/next": { + "node_modules/@nx/react/node_modules/@nx/linter": { "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/next/-/next-19.2.0.tgz", - "integrity": "sha512-+DFtnuB33w/x5A5c1EuSjnKE0i2YKJT5tltZ1bX7fyDcqukwESmTL+CNpYNlp5VuejDzV/3wp1pNdeqt+85/YA==", + "resolved": "https://registry.npmjs.org/@nx/linter/-/linter-19.2.0.tgz", + "integrity": "sha512-Rahjy3+OLc4aXT8VNXpwyMozeU4RB6HIQOh5NAdcA6PoOH8cG1VtbyjryIZE8l5HT1hrpI5EkONZt1UXiIGw3w==", "dev": true, "dependencies": { - "@nx/next": "19.2.0" + "@nx/eslint": "19.2.0" } }, - "node_modules/@nrwl/node": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/node/-/node-19.2.0.tgz", - "integrity": "sha512-fy4GPMGRT7/t3sUljOot2h9CVq0QWOv/nPxyK7YVk2jkwkjo9gTovVoZrjacv8DOOL4DE1tRr7yHfEQY6fnDig==", + "node_modules/@nx/react/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", "dev": true, - "dependencies": { - "@nx/node": "19.2.0" + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/@nrwl/react": { + "node_modules/@nx/web": { "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/react/-/react-19.2.0.tgz", - "integrity": "sha512-Zz4lJK1S511s8F1OmbH0HiMz9xX/OCL8UQ5FJ9uViMNnkaLPx0NUGzrAbliDUq2XGYDBZ8ZtGFgC1DTlL9iK+w==", - "dev": true, - "dependencies": { - "@nx/react": "19.2.0" - } - }, - "node_modules/@nrwl/tao": { - "version": "19.4.4", - "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.4.4.tgz", - "integrity": "sha512-iwswcp7fW5GiIeAFvA/Ssr9fe2ZZHcuOS20bQx+mLEnEgBaARkgWqNdYMZ594NRqXQ1CrOEy5jncahS6K+pRbw==", + "resolved": "https://registry.npmjs.org/@nx/web/-/web-19.2.0.tgz", + "integrity": "sha512-iMRwDjkU7GfJql4wT6pGCimFoHYV/2bQuI/N9b9T3NEL9sk5tlMqlik6bbSGtje8XoUAbxaQrTpr9pJeaUPYwg==", "dev": true, "dependencies": { - "nx": "19.4.4", + "@nrwl/web": "19.2.0", + "@nx/devkit": "19.2.0", + "@nx/js": "19.2.0", + "chalk": "^4.1.0", + "detect-port": "^1.5.1", + "http-server": "^14.1.0", "tslib": "^2.3.0" - }, - "bin": { - "tao": "index.js" } }, - "node_modules/@nrwl/web": { + "node_modules/@nx/web/node_modules/@nrwl/devkit": { "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/web/-/web-19.2.0.tgz", - "integrity": "sha512-s6fEyic1cCwZAoKxZ64RMdCfG2jQGZC/FTyO4J7a8iB8oRD8mRLw0lWamXIcW10O0KPrE0zO63+kpjfKJ/ZK+w==", - "dev": true, - "dependencies": { - "@nx/web": "19.2.0" - } - }, - "node_modules/@nrwl/webpack": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nrwl/webpack/-/webpack-19.6.3.tgz", - "integrity": "sha512-e1Y493FBdNPO3TrXNAJSzbeGWAZiLUsDUfQDXjlAboQRL5n3bn1W/zc98DGMxobJWAzw2vWW7UEm2ZyYyeU/lA==", - "dev": true, - "dependencies": { - "@nx/webpack": "19.6.3" - } - }, - "node_modules/@nrwl/workspace": { - "version": "19.7.3", - "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-19.7.3.tgz", - "integrity": "sha512-2ffUbLzBYGQte6zQ6dDLefgU9X812Uh7v61yTV7z4zfYbUtjwInkWqlkTvRuK08DRhD5vWo9xyUDp7acAdZaxw==", + "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.2.0.tgz", + "integrity": "sha512-Ew5AJZkLXJwt15HjaIbHve8FOXmZ3HK8KPqTXqwKHX8jQW+fDUCaSXKe/lCZMNg0RvY+jMNecuC86uGdiIbLMg==", "dev": true, "dependencies": { - "@nx/workspace": "19.7.3" - } - }, - "node_modules/@nuxtjs/opencollective": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz", - "integrity": "sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==", - "dependencies": { - "chalk": "^4.1.0", - "consola": "^2.15.0", - "node-fetch": "^2.6.1" - }, - "bin": { - "opencollective": "bin/opencollective.js" - }, - "engines": { - "node": ">=8.0.0", - "npm": ">=5.0.0" + "@nx/devkit": "19.2.0" } }, - "node_modules/@nx/devkit": { - "version": "19.5.1", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.5.1.tgz", - "integrity": "sha512-Vj8wwzNIR5VIWmuLHhOi4aUVq7eVV5YTbctnEewKT+V/O4LZj+hClGyVNyT8s6b8JIjNWoIO4HXStLnH8rDOlw==", + "node_modules/@nx/web/node_modules/@nx/devkit": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.2.0.tgz", + "integrity": "sha512-fK3zRUE2SLp9BUomFiyCuAX2E1yfWYE/hKimniscsvM34/u/xLZYVmmZ0/jfpGPbyaonXKZr2KTb7RimX/hyqg==", "dev": true, "dependencies": { - "@nrwl/devkit": "19.5.1", + "@nrwl/devkit": "19.2.0", "ejs": "^3.1.7", "enquirer": "~2.3.6", "ignore": "^5.0.4", @@ -7649,7 +19070,7 @@ "nx": ">= 17 <= 20" } }, - "node_modules/@nx/devkit/node_modules/semver": { + "node_modules/@nx/web/node_modules/semver": { "version": "7.6.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", @@ -7661,103 +19082,103 @@ "node": ">=10" } }, - "node_modules/@nx/eslint": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/eslint/-/eslint-19.3.2.tgz", - "integrity": "sha512-ICUX8ADAIj9xA7Yc6hY9pfeC55ZxRjiAaqslsK3h4pCrFADVFDluShhrxSpUkp4doBzGUR7s1K7GIbeRrwD4qA==", - "dev": true, - "dependencies": { - "@nx/devkit": "19.3.2", - "@nx/js": "19.3.2", - "@nx/linter": "19.3.2", - "semver": "^7.5.3", - "tslib": "^2.3.0", - "typescript": "~5.4.2" - }, - "peerDependencies": { - "@zkochan/js-yaml": "0.0.7", - "eslint": "^8.0.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "@zkochan/js-yaml": { - "optional": true - } - } - }, - "node_modules/@nx/eslint-plugin": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/eslint-plugin/-/eslint-plugin-19.3.2.tgz", - "integrity": "sha512-ZhnFrnAKILA29EwiHQhUQnLfXleUH/YrDS3FUYBpwKnICAPXARsgb7Qi+3Uick0q4HlkL6xGRkkQSfA5cZ9Qtw==", + "node_modules/@nx/webpack": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nx/webpack/-/webpack-19.6.3.tgz", + "integrity": "sha512-AUz4SPdD6LtIh+hB8AJX7GdzLHmlj5aU/yXp4UTKF5DZlha4NphN8YIP+NN56nCgEZMxM8txp7U0zytqhcFP1Q==", "dev": true, "dependencies": { - "@nrwl/eslint-plugin-nx": "19.3.2", - "@nx/devkit": "19.3.2", - "@nx/js": "19.3.2", - "@typescript-eslint/type-utils": "^7.3.0", - "@typescript-eslint/utils": "^7.3.0", + "@babel/core": "^7.23.2", + "@module-federation/enhanced": "^0.2.3", + "@module-federation/sdk": "^0.2.3", + "@nrwl/webpack": "19.6.3", + "@nx/devkit": "19.6.3", + "@nx/js": "19.6.3", + "@phenomnomnominal/tsquery": "~5.0.1", + "ajv": "^8.12.0", + "autoprefixer": "^10.4.9", + "babel-loader": "^9.1.2", + "browserslist": "^4.21.4", "chalk": "^4.1.0", - "confusing-browser-globals": "^1.0.9", - "jsonc-eslint-parser": "^2.1.0", - "semver": "^7.5.3", - "tslib": "^2.3.0" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^6.13.2 || ^7.0.0", - "eslint-config-prettier": "^9.0.0" - }, - "peerDependenciesMeta": { - "eslint-config-prettier": { - "optional": true - } + "copy-webpack-plugin": "^10.2.4", + "css-loader": "^6.4.0", + "css-minimizer-webpack-plugin": "^5.0.0", + "express": "^4.19.2", + "fork-ts-checker-webpack-plugin": "7.2.13", + "http-proxy-middleware": "^3.0.0", + "less": "4.1.3", + "less-loader": "11.1.0", + "license-webpack-plugin": "^4.0.2", + "loader-utils": "^2.0.3", + "mini-css-extract-plugin": "~2.4.7", + "parse5": "4.0.0", + "postcss": "^8.4.38", + "postcss-import": "~14.1.0", + "postcss-loader": "^6.1.1", + "rxjs": "^7.8.0", + "sass": "^1.42.1", + "sass-loader": "^12.2.0", + "source-map-loader": "^5.0.0", + "style-loader": "^3.3.0", + "stylus": "^0.59.0", + "stylus-loader": "^7.1.0", + "terser-webpack-plugin": "^5.3.3", + "ts-loader": "^9.3.1", + "tsconfig-paths-webpack-plugin": "4.0.0", + "tslib": "^2.3.0", + "webpack": "^5.80.0", + "webpack-dev-server": "^5.0.4", + "webpack-node-externals": "^3.0.0", + "webpack-subresource-integrity": "^5.1.0" } }, - "node_modules/@nx/eslint-plugin/node_modules/@nrwl/devkit": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.3.2.tgz", - "integrity": "sha512-n3tFalVPUk1HAJ2VYNnF34yzB9j2+6swFUi4Y92PxD1vN7vrIXnNeaTx2qcee7JDjBpiJ7Zn0KLg2jwiH6hNwA==", + "node_modules/@nx/webpack/node_modules/@nrwl/devkit": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.6.3.tgz", + "integrity": "sha512-zrAboArNfrEMjimBl/0YeM08HfjqOEG/VHdCHKO+5QMDg65w7vDJ2flwyNhlmnMl8BMJSy9fNo6PNGhboOf3+w==", "dev": true, "dependencies": { - "@nx/devkit": "19.3.2" + "@nx/devkit": "19.6.3" } }, - "node_modules/@nx/eslint-plugin/node_modules/@nrwl/js": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nrwl/js/-/js-19.3.2.tgz", - "integrity": "sha512-ZgCoLsASIlp1xtYpWW/1ZxvKSb6BY3ZNXBmjoUW4LyN7Pk6su55gPAVt6JWIxSMm+HC+v+Cb4XFKZLdtuvE7bg==", + "node_modules/@nx/webpack/node_modules/@nrwl/js": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nrwl/js/-/js-19.6.3.tgz", + "integrity": "sha512-Z5tYcUQNfgmNFMJpGmZd6fB0D1pCKNiS3aci2gxHAUIP0Z5cznTyCuzcJSIRx3uMHENhxXwzLwv2l/cqOqnD8A==", "dev": true, "dependencies": { - "@nx/js": "19.3.2" + "@nx/js": "19.6.3" } }, - "node_modules/@nx/eslint-plugin/node_modules/@nrwl/tao": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.3.2.tgz", - "integrity": "sha512-I1gW7woqwU6rdlgwj6XXAKcreJ5ptRKI2WpLdZErkrPmaRG/jMZx/yjZrG4PWdIEuZ4ZmYnRsoXbKN6ilCknQw==", + "node_modules/@nx/webpack/node_modules/@nrwl/tao": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.6.3.tgz", + "integrity": "sha512-j4vPU87yBhTrdyPFSNhlUkN29w4BQ+M14khT8PFGe+Y26gHMxNRNXNFUCwtVARYAc6IwxS8Uvlwy7AwXG2ETPA==", "dev": true, "dependencies": { - "nx": "19.3.2", + "nx": "19.6.3", "tslib": "^2.3.0" }, "bin": { "tao": "index.js" } }, - "node_modules/@nx/eslint-plugin/node_modules/@nrwl/workspace": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-19.3.2.tgz", - "integrity": "sha512-6gV4qa38t3GyRKmO2PLcamDcFRD7I3wl6/R0/E1eC8Wm6K2oBzjOIV5ALpz4iC4LOln88IL+AjuQdG6kdtfXlA==", + "node_modules/@nx/webpack/node_modules/@nrwl/workspace": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-19.6.3.tgz", + "integrity": "sha512-NGJ6Mxpw8U6tZRT4ijGzqthr1NMgT/22uteu4otetLEdlqkh1VvLqJC9tjzLkYXmXF9QuoUrkwQib/HafsZmkg==", "dev": true, "dependencies": { - "@nx/workspace": "19.3.2" + "@nx/workspace": "19.6.3" } }, - "node_modules/@nx/eslint-plugin/node_modules/@nx/devkit": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.3.2.tgz", - "integrity": "sha512-uD3jaJ1Jvf7B6jqH2t2GH0L6REwcCGBLXq1qs1HRQF5SZrEtuUeusn8wvCKP7dftPK3byLHAG0xHRW4+IUAz/g==", + "node_modules/@nx/webpack/node_modules/@nx/devkit": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.6.3.tgz", + "integrity": "sha512-/d8Z5/Cy/H/1rIHxW3VjeK5dlvHwRxRj8rCm8/sj5Pz3GmGX03uuEK+J/p+VlP3gP8dAYMgZu3ImeqTAu6rBtw==", "dev": true, "dependencies": { - "@nrwl/devkit": "19.3.2", + "@nrwl/devkit": "19.6.3", "ejs": "^3.1.7", "enquirer": "~2.3.6", "ignore": "^5.0.4", @@ -7771,10 +19192,10 @@ "nx": ">= 17 <= 20" } }, - "node_modules/@nx/eslint-plugin/node_modules/@nx/js": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/js/-/js-19.3.2.tgz", - "integrity": "sha512-WXULhOHYDIAvs+SyDiRaNrpn1DmBAl3u7F5Jpu2VIyrcXgllrYGqUAykUqSu6Oyc2J+asfEtiG67I7UucTHLhA==", + "node_modules/@nx/webpack/node_modules/@nx/js": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nx/js/-/js-19.6.3.tgz", + "integrity": "sha512-Ip7DseodvJSRM2sKhUjNMlNLegBtsB1u6TuQUiYOJa2FnIGzXETT2HuDMxBcL+u23xDTNyNvifNZ92mFywa00Q==", "dev": true, "dependencies": { "@babel/core": "^7.23.2", @@ -7784,9 +19205,9 @@ "@babel/preset-env": "^7.23.2", "@babel/preset-typescript": "^7.22.5", "@babel/runtime": "^7.22.6", - "@nrwl/js": "19.3.2", - "@nx/devkit": "19.3.2", - "@nx/workspace": "19.3.2", + "@nrwl/js": "19.6.3", + "@nx/devkit": "19.6.3", + "@nx/workspace": "19.6.3", "babel-plugin-const-enum": "^1.0.1", "babel-plugin-macros": "^2.8.0", "babel-plugin-transform-typescript-metadata": "^0.3.1", @@ -7797,6 +19218,7 @@ "fs-extra": "^11.1.0", "ignore": "^5.0.4", "js-tokens": "^4.0.0", + "jsonc-parser": "3.2.0", "minimatch": "9.0.3", "npm-package-arg": "11.0.1", "npm-run-path": "^4.0.1", @@ -7816,10 +19238,10 @@ } } }, - "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-darwin-arm64": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.3.2.tgz", - "integrity": "sha512-MTqPTR1FwfVfIkHKUw95dFlPBN6mbqfJ+KzLHvUSPcqLKelhi82tsisjMoB5sNK0YWcNNVqYW72ojCnHVB0TUg==", + "node_modules/@nx/webpack/node_modules/@nx/nx-darwin-arm64": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.6.3.tgz", + "integrity": "sha512-P7WlX5YDZOABAlyfpR6eObigQTNuUuy3iJVUuGwp1Nuo3VPMPkpK1GMWKWLwOR9+2jGnF5MzuqWHk7CdF33uqQ==", "cpu": [ "arm64" ], @@ -7832,10 +19254,10 @@ "node": ">= 10" } }, - "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-darwin-x64": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.3.2.tgz", - "integrity": "sha512-C8s9X5AlVgl3V5PycLdX+75lpAWq0qQs6QUEAnyxrLM9l+/HRecgoW6uZ7tX6Fnd8WGfMIwyahBw4LyZgk6zTw==", + "node_modules/@nx/webpack/node_modules/@nx/nx-darwin-x64": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.6.3.tgz", + "integrity": "sha512-HF28dPc7h0EmEGYJWJUPA3cBvjXyHbSbGQP5oP885gos9zcyVBjQ2kdJEUZDNMHB9KlZraeXbmV1umFkikjn6A==", "cpu": [ "x64" ], @@ -7848,10 +19270,10 @@ "node": ">= 10" } }, - "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-freebsd-x64": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.3.2.tgz", - "integrity": "sha512-XeEpEU0iqJ/5cAPMmjqJ0Sdz89ZtDRj4NdksioyhAHri94X5/3lm3lDs4tB3nObT7p3QL7r/HP1itq5DHYmMSQ==", + "node_modules/@nx/webpack/node_modules/@nx/nx-freebsd-x64": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.6.3.tgz", + "integrity": "sha512-y52dWxQ/x2ccyPqA4Vou4CnTqZX4gr/wV9myJX56G1CyEpWasmcqmPFeOKQd6dj7llGM/KJ/4Gz29RYxcWffcA==", "cpu": [ "x64" ], @@ -7864,10 +19286,10 @@ "node": ">= 10" } }, - "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.3.2.tgz", - "integrity": "sha512-r4Wl0P94QRBUyiexUcfwKxqFXp48avMG3L0no/ZuNWGODbw1w8ppA4vhnkXtXbIaMdaTGx9eIYO7kFJ2SwMCng==", + "node_modules/@nx/webpack/node_modules/@nx/nx-linux-arm-gnueabihf": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.6.3.tgz", + "integrity": "sha512-RneCg1tglLbP4cmGnGUs4FgZVT0aOA9wA53tO4IbyxLnlRXNY9OE452YLgqv3H7sLtNjsey2Lkq1seBHtr3p/Q==", "cpu": [ "arm" ], @@ -7880,10 +19302,10 @@ "node": ">= 10" } }, - "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-linux-arm64-gnu": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.3.2.tgz", - "integrity": "sha512-oaTC4iS1fXnc61ZgSxwCQ2GGIqY64G22udRqNsX9TOtgrT7UA/mjE3Si01r+0xODimOiB525ueyxdIh1MAu6Vg==", + "node_modules/@nx/webpack/node_modules/@nx/nx-linux-arm64-gnu": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.6.3.tgz", + "integrity": "sha512-Y+vgqaxrPQUEtCzxK25QY4ahO90l0eWgVrvCALexGmq0lW41JrVpfTTsbH/BAPLsx+u8A/GPAQAgrmg7d5lSxw==", "cpu": [ "arm64" ], @@ -7896,10 +19318,10 @@ "node": ">= 10" } }, - "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-linux-arm64-musl": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.3.2.tgz", - "integrity": "sha512-yyO9bTM7FW7HTYsSQlL4lgbAexUBpzfhdK+RkgsCiW+U/5bi+jFRxo/SbqGUL+IVliFavWyRXahMqOOM6nBq/w==", + "node_modules/@nx/webpack/node_modules/@nx/nx-linux-arm64-musl": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.6.3.tgz", + "integrity": "sha512-o/99DBgafbjiJ4e9KFxaldvtlZta/FdzEiQQW+SQQ0JGSYlLCZZ8tIT6t3edV7cmG+gQLNMwolJzgpY53O9wjA==", "cpu": [ "arm64" ], @@ -7912,10 +19334,10 @@ "node": ">= 10" } }, - "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-linux-x64-gnu": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.3.2.tgz", - "integrity": "sha512-DC+llVdL4toLjQkDGBgzoCe26FWIOT+SzRdVcKePoNliZ4jDhkOh3+p75NEIOEcDUgoE9M2iCWEBUjkV978ogw==", + "node_modules/@nx/webpack/node_modules/@nx/nx-linux-x64-gnu": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.6.3.tgz", + "integrity": "sha512-ppp0NBOhwJ39U1vR7h8jhFSfiur6CZPSUYjXsV44BlaNGc1wHZ+7FDXhzOTokgTNWHavYgYOJuVan5LtTLKJkA==", "cpu": [ "x64" ], @@ -7928,10 +19350,10 @@ "node": ">= 10" } }, - "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-linux-x64-musl": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.3.2.tgz", - "integrity": "sha512-Wun4v+kuuqv20tJiCENkHGisDqfx029bFufqxx2IOe9TvD6vK4rMMkFVPUoK3FP8EBdaMW4nrR0ZucTFnStl6w==", + "node_modules/@nx/webpack/node_modules/@nx/nx-linux-x64-musl": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.6.3.tgz", + "integrity": "sha512-H7xgsT5OTtVYCXjXBLZu28v+rIInhbUggrgVJ2iQJFGBT2A2qmvGmDJdcDz8+K90ku1f4VuWmm8i+TEyDEcBuQ==", "cpu": [ "x64" ], @@ -7944,10 +19366,10 @@ "node": ">= 10" } }, - "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-win32-arm64-msvc": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.3.2.tgz", - "integrity": "sha512-bNVf6eu5rWFjHvn0rKHeZYlHUcs3naXvvbduW1g0DPkHG6mt8FYffQmyboN+CSeBd/uWDPNyTUekVWwU7PjtLA==", + "node_modules/@nx/webpack/node_modules/@nx/nx-win32-arm64-msvc": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.6.3.tgz", + "integrity": "sha512-o9O6lSmx67zUnqOtlDC4YpC++fiUkixgIsQEG8J/2jdNgAATqOtERcqCNra/uke/Q94Vht2tVXjXF3uj92APhw==", "cpu": [ "arm64" ], @@ -7960,10 +19382,10 @@ "node": ">= 10" } }, - "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-win32-x64-msvc": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.3.2.tgz", - "integrity": "sha512-8DD5BPa5YrxTOKL3HTAgEd+IXNqRtJfwvbrn2MbOMNMyoMG9Zi5yhFvTH/HTT9Tz6VUHvXP16QWYA3R7eFi7Gg==", + "node_modules/@nx/webpack/node_modules/@nx/nx-win32-x64-msvc": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.6.3.tgz", + "integrity": "sha512-6NQhc7jYQ/sqPt5fDy8C+br73kTd5jhb8ZkPtEy2Amr1aA1K9SAxZAYfyvxLHS2z1nBEelNFgXe6HBmDX92FkA==", "cpu": [ "x64" ], @@ -7976,28 +19398,98 @@ "node": ">= 10" } }, - "node_modules/@nx/eslint-plugin/node_modules/@nx/workspace": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-19.3.2.tgz", - "integrity": "sha512-gam41l0hFftYIYTt8eTvZjh+ZWo62HO2p/efqZuFIa/1ZsXF1XG8MDRkCSh5Wfjh1f0jS2ma8HwPV3e8TJm2lw==", + "node_modules/@nx/webpack/node_modules/@nx/workspace": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-19.6.3.tgz", + "integrity": "sha512-DTvVJZuXHQd+F4M9JkTHGjLQADQZfUTs/h+v9/NC+YQHml8eixaNXSSvoHQcvBqO8HntbJz5LAJfQuiJ4IGBKw==", "dev": true, "dependencies": { - "@nrwl/workspace": "19.3.2", - "@nx/devkit": "19.3.2", + "@nrwl/workspace": "19.6.3", + "@nx/devkit": "19.6.3", "chalk": "^4.1.0", "enquirer": "~2.3.6", - "nx": "19.3.2", + "nx": "19.6.3", "tslib": "^2.3.0", "yargs-parser": "21.1.1" } }, - "node_modules/@nx/eslint-plugin/node_modules/arg": { + "node_modules/@nx/webpack/node_modules/@types/retry": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", + "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", + "dev": true + }, + "node_modules/@nx/webpack/node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true }, - "node_modules/@nx/eslint-plugin/node_modules/dotenv-expand": { + "node_modules/@nx/webpack/node_modules/array-union": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz", + "integrity": "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@nx/webpack/node_modules/copy-webpack-plugin": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz", + "integrity": "sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg==", + "dev": true, + "dependencies": { + "fast-glob": "^3.2.7", + "glob-parent": "^6.0.1", + "globby": "^12.0.2", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0" + }, + "engines": { + "node": ">= 12.20.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + } + }, + "node_modules/@nx/webpack/node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dev": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@nx/webpack/node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@nx/webpack/node_modules/dotenv-expand": { "version": "11.0.6", "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.6.tgz", "integrity": "sha512-8NHi73otpWsZGBSZwwknTXS5pqMOrk9+Ssrna8xCaxkzEpU9OTf9R5ArQGVw03//Zmk9MOwLPng9WwndvpAJ5g==", @@ -8012,222 +19504,207 @@ "url": "https://dotenvx.com" } }, - "node_modules/@nx/eslint-plugin/node_modules/emoji-regex": { + "node_modules/@nx/webpack/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "node_modules/@nx/eslint-plugin/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/@nx/webpack/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@nx/eslint-plugin/node_modules/nx": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/nx/-/nx-19.3.2.tgz", - "integrity": "sha512-eKWs+ahkTKnq9EeWJCE4u8JLeq1cOHnq5DKoiisy2nwUg4KGy1odReegxUMLeEgNBcMI40EUtEJFiTMJSXZQeg==", + "node_modules/@nx/webpack/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, - "hasInstallScript": true, "dependencies": { - "@nrwl/tao": "19.3.2", - "@yarnpkg/lockfile": "^1.1.0", - "@yarnpkg/parsers": "3.0.0-rc.46", - "@zkochan/js-yaml": "0.0.7", - "axios": "^1.6.0", - "chalk": "^4.1.0", - "cli-cursor": "3.1.0", - "cli-spinners": "2.6.1", - "cliui": "^8.0.1", - "dotenv": "~16.4.5", - "dotenv-expand": "~11.0.6", - "enquirer": "~2.3.6", - "figures": "3.2.0", - "flat": "^5.0.2", - "front-matter": "^4.0.2", - "fs-extra": "^11.1.0", - "ignore": "^5.0.4", - "jest-diff": "^29.4.1", - "jsonc-parser": "3.2.0", - "lines-and-columns": "~2.0.3", - "minimatch": "9.0.3", - "node-machine-id": "1.1.12", - "npm-run-path": "^4.0.1", - "open": "^8.4.0", - "ora": "5.3.0", - "semver": "^7.5.3", - "string-width": "^4.2.3", - "strong-log-transformer": "^2.1.0", - "tar-stream": "~2.2.0", - "tmp": "~0.2.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0", - "yargs": "^17.6.2", - "yargs-parser": "21.1.1" - }, - "bin": { - "nx": "bin/nx.js", - "nx-cloud": "bin/nx-cloud.js" + "is-glob": "^4.0.3" }, - "optionalDependencies": { - "@nx/nx-darwin-arm64": "19.3.2", - "@nx/nx-darwin-x64": "19.3.2", - "@nx/nx-freebsd-x64": "19.3.2", - "@nx/nx-linux-arm-gnueabihf": "19.3.2", - "@nx/nx-linux-arm64-gnu": "19.3.2", - "@nx/nx-linux-arm64-musl": "19.3.2", - "@nx/nx-linux-x64-gnu": "19.3.2", - "@nx/nx-linux-x64-musl": "19.3.2", - "@nx/nx-win32-arm64-msvc": "19.3.2", - "@nx/nx-win32-x64-msvc": "19.3.2" + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@nx/webpack/node_modules/glob/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" }, - "peerDependencies": { - "@swc-node/register": "^1.8.0", - "@swc/core": "^1.3.85" + "engines": { + "node": ">=16 || 14 >=14.17" }, - "peerDependenciesMeta": { - "@swc-node/register": { - "optional": true - }, - "@swc/core": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@nx/eslint-plugin/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "node_modules/@nx/webpack/node_modules/globby": { + "version": "12.2.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-12.2.0.tgz", + "integrity": "sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "dependencies": { + "array-union": "^3.0.1", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.7", + "ignore": "^5.1.9", + "merge2": "^1.4.1", + "slash": "^4.0.0" }, "engines": { - "node": ">=10" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@nx/eslint-plugin/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/@nx/webpack/node_modules/http-proxy-middleware": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-3.0.0.tgz", + "integrity": "sha512-36AV1fIaI2cWRzHo+rbcxhe3M3jUDCNzc4D5zRl57sEWRAxdXYtw7FSQKYY6PDKssiAKjLYypbssHk+xs/kMXw==", "dev": true, "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "@types/http-proxy": "^1.17.10", + "debug": "^4.3.4", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.5" }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@nx/webpack/node_modules/ipaddr.js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/webpack/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { "node": ">=8" } }, - "node_modules/@nx/eslint-plugin/node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "node_modules/@nx/webpack/node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", "dev": true, - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" + "engines": { + "node": ">=10" }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@nx/eslint-plugin/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "node_modules/@nx/webpack/node_modules/is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", "dev": true, "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" + "is-inside-container": "^1.0.0" }, "engines": { - "node": ">=12" + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@nx/eslint/node_modules/@nrwl/devkit": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.3.2.tgz", - "integrity": "sha512-n3tFalVPUk1HAJ2VYNnF34yzB9j2+6swFUi4Y92PxD1vN7vrIXnNeaTx2qcee7JDjBpiJ7Zn0KLg2jwiH6hNwA==", + "node_modules/@nx/webpack/node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, "dependencies": { - "@nx/devkit": "19.3.2" + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/@nx/eslint/node_modules/@nrwl/js": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nrwl/js/-/js-19.3.2.tgz", - "integrity": "sha512-ZgCoLsASIlp1xtYpWW/1ZxvKSb6BY3ZNXBmjoUW4LyN7Pk6su55gPAVt6JWIxSMm+HC+v+Cb4XFKZLdtuvE7bg==", + "node_modules/@nx/webpack/node_modules/memfs": { + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.11.1.tgz", + "integrity": "sha512-LZcMTBAgqUUKNXZagcZxvXXfgF1bHX7Y7nQ0QyEiNbRJgE29GhgPd8Yna1VQcLlPiHt/5RFJMWYN9Uv/VPNvjQ==", "dev": true, "dependencies": { - "@nx/js": "19.3.2" + "@jsonjoy.com/json-pack": "^1.0.3", + "@jsonjoy.com/util": "^1.3.0", + "tree-dump": "^1.0.1", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">= 4.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" } }, - "node_modules/@nx/eslint/node_modules/@nrwl/tao": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.3.2.tgz", - "integrity": "sha512-I1gW7woqwU6rdlgwj6XXAKcreJ5ptRKI2WpLdZErkrPmaRG/jMZx/yjZrG4PWdIEuZ4ZmYnRsoXbKN6ilCknQw==", + "node_modules/@nx/webpack/node_modules/mini-css-extract-plugin": { + "version": "2.4.7", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.4.7.tgz", + "integrity": "sha512-euWmddf0sk9Nv1O0gfeeUAvAkoSlWncNLF77C0TP2+WoPvy8mAHKOzMajcCz2dzvyt3CNgxb1obIEVFIRxaipg==", "dev": true, "dependencies": { - "nx": "19.3.2", - "tslib": "^2.3.0" + "schema-utils": "^4.0.0" }, - "bin": { - "tao": "index.js" + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" } }, - "node_modules/@nx/eslint/node_modules/@nrwl/tao/node_modules/nx": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/nx/-/nx-19.3.2.tgz", - "integrity": "sha512-eKWs+ahkTKnq9EeWJCE4u8JLeq1cOHnq5DKoiisy2nwUg4KGy1odReegxUMLeEgNBcMI40EUtEJFiTMJSXZQeg==", + "node_modules/@nx/webpack/node_modules/nx": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/nx/-/nx-19.6.3.tgz", + "integrity": "sha512-JbgrEKaIBvTfhw3mG3GeyyzJHBAMfuQkMNrxxIto1fn94gxdjXdMfqUnAzrW6xRAt5OEEU+rf7v2OA3vEXYc3A==", "dev": true, "hasInstallScript": true, "dependencies": { - "@nrwl/tao": "19.3.2", + "@napi-rs/wasm-runtime": "0.2.4", + "@nrwl/tao": "19.6.3", "@yarnpkg/lockfile": "^1.1.0", "@yarnpkg/parsers": "3.0.0-rc.46", "@zkochan/js-yaml": "0.0.7", - "axios": "^1.6.0", + "axios": "^1.7.4", "chalk": "^4.1.0", "cli-cursor": "3.1.0", "cli-spinners": "2.6.1", @@ -8263,16 +19740,16 @@ "nx-cloud": "bin/nx-cloud.js" }, "optionalDependencies": { - "@nx/nx-darwin-arm64": "19.3.2", - "@nx/nx-darwin-x64": "19.3.2", - "@nx/nx-freebsd-x64": "19.3.2", - "@nx/nx-linux-arm-gnueabihf": "19.3.2", - "@nx/nx-linux-arm64-gnu": "19.3.2", - "@nx/nx-linux-arm64-musl": "19.3.2", - "@nx/nx-linux-x64-gnu": "19.3.2", - "@nx/nx-linux-x64-musl": "19.3.2", - "@nx/nx-win32-arm64-msvc": "19.3.2", - "@nx/nx-win32-x64-msvc": "19.3.2" + "@nx/nx-darwin-arm64": "19.6.3", + "@nx/nx-darwin-x64": "19.6.3", + "@nx/nx-freebsd-x64": "19.6.3", + "@nx/nx-linux-arm-gnueabihf": "19.6.3", + "@nx/nx-linux-arm64-gnu": "19.6.3", + "@nx/nx-linux-arm64-musl": "19.6.3", + "@nx/nx-linux-x64-gnu": "19.6.3", + "@nx/nx-linux-x64-musl": "19.6.3", + "@nx/nx-win32-arm64-msvc": "19.6.3", + "@nx/nx-win32-x64-msvc": "19.6.3" }, "peerDependencies": { "@swc-node/register": "^1.8.0", @@ -8287,81 +19764,99 @@ } } }, - "node_modules/@nx/eslint/node_modules/@nrwl/workspace": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-19.3.2.tgz", - "integrity": "sha512-6gV4qa38t3GyRKmO2PLcamDcFRD7I3wl6/R0/E1eC8Wm6K2oBzjOIV5ALpz4iC4LOln88IL+AjuQdG6kdtfXlA==", + "node_modules/@nx/webpack/node_modules/p-retry": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.0.tgz", + "integrity": "sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==", "dev": true, "dependencies": { - "@nx/workspace": "19.3.2" + "@types/retry": "0.12.2", + "is-network-error": "^1.0.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@nx/eslint/node_modules/@nx/devkit": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.3.2.tgz", - "integrity": "sha512-uD3jaJ1Jvf7B6jqH2t2GH0L6REwcCGBLXq1qs1HRQF5SZrEtuUeusn8wvCKP7dftPK3byLHAG0xHRW4+IUAz/g==", + "node_modules/@nx/webpack/node_modules/postcss-loader": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", + "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", "dev": true, "dependencies": { - "@nrwl/devkit": "19.3.2", - "ejs": "^3.1.7", - "enquirer": "~2.3.6", - "ignore": "^5.0.4", - "minimatch": "9.0.3", - "semver": "^7.5.3", - "tmp": "~0.2.1", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" + "cosmiconfig": "^7.0.0", + "klona": "^2.0.5", + "semver": "^7.3.5" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "nx": ">= 17 <= 20" + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" } }, - "node_modules/@nx/eslint/node_modules/@nx/js": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/js/-/js-19.3.2.tgz", - "integrity": "sha512-WXULhOHYDIAvs+SyDiRaNrpn1DmBAl3u7F5Jpu2VIyrcXgllrYGqUAykUqSu6Oyc2J+asfEtiG67I7UucTHLhA==", + "node_modules/@nx/webpack/node_modules/rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", "dev": true, "dependencies": { - "@babel/core": "^7.23.2", - "@babel/plugin-proposal-decorators": "^7.22.7", - "@babel/plugin-transform-class-properties": "^7.22.5", - "@babel/plugin-transform-runtime": "^7.23.2", - "@babel/preset-env": "^7.23.2", - "@babel/preset-typescript": "^7.22.5", - "@babel/runtime": "^7.22.6", - "@nrwl/js": "19.3.2", - "@nx/devkit": "19.3.2", - "@nx/workspace": "19.3.2", - "babel-plugin-const-enum": "^1.0.1", - "babel-plugin-macros": "^2.8.0", - "babel-plugin-transform-typescript-metadata": "^0.3.1", - "chalk": "^4.1.0", - "columnify": "^1.6.0", - "detect-port": "^1.5.1", - "fast-glob": "3.2.7", - "fs-extra": "^11.1.0", - "ignore": "^5.0.4", - "js-tokens": "^4.0.0", - "minimatch": "9.0.3", - "npm-package-arg": "11.0.1", - "npm-run-path": "^4.0.1", - "ora": "5.3.0", - "semver": "^7.5.3", - "source-map-support": "0.5.19", - "ts-node": "10.9.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0" + "glob": "^10.3.7" }, - "peerDependencies": { - "verdaccio": "^5.0.4" + "bin": { + "rimraf": "dist/esm/bin.mjs" }, - "peerDependenciesMeta": { - "verdaccio": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@nx/eslint/node_modules/@nx/js/node_modules/ts-node": { + "node_modules/@nx/webpack/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@nx/webpack/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@nx/webpack/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@nx/webpack/node_modules/ts-node": { "version": "10.9.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", @@ -8404,315 +19899,147 @@ } } }, - "node_modules/@nx/eslint/node_modules/@nx/nx-darwin-arm64": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.3.2.tgz", - "integrity": "sha512-MTqPTR1FwfVfIkHKUw95dFlPBN6mbqfJ+KzLHvUSPcqLKelhi82tsisjMoB5sNK0YWcNNVqYW72ojCnHVB0TUg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/eslint/node_modules/@nx/nx-darwin-x64": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.3.2.tgz", - "integrity": "sha512-C8s9X5AlVgl3V5PycLdX+75lpAWq0qQs6QUEAnyxrLM9l+/HRecgoW6uZ7tX6Fnd8WGfMIwyahBw4LyZgk6zTw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/eslint/node_modules/@nx/nx-freebsd-x64": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.3.2.tgz", - "integrity": "sha512-XeEpEU0iqJ/5cAPMmjqJ0Sdz89ZtDRj4NdksioyhAHri94X5/3lm3lDs4tB3nObT7p3QL7r/HP1itq5DHYmMSQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/eslint/node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.3.2.tgz", - "integrity": "sha512-r4Wl0P94QRBUyiexUcfwKxqFXp48avMG3L0no/ZuNWGODbw1w8ppA4vhnkXtXbIaMdaTGx9eIYO7kFJ2SwMCng==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/eslint/node_modules/@nx/nx-linux-arm64-gnu": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.3.2.tgz", - "integrity": "sha512-oaTC4iS1fXnc61ZgSxwCQ2GGIqY64G22udRqNsX9TOtgrT7UA/mjE3Si01r+0xODimOiB525ueyxdIh1MAu6Vg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/eslint/node_modules/@nx/nx-linux-arm64-musl": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.3.2.tgz", - "integrity": "sha512-yyO9bTM7FW7HTYsSQlL4lgbAexUBpzfhdK+RkgsCiW+U/5bi+jFRxo/SbqGUL+IVliFavWyRXahMqOOM6nBq/w==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/eslint/node_modules/@nx/nx-linux-x64-gnu": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.3.2.tgz", - "integrity": "sha512-DC+llVdL4toLjQkDGBgzoCe26FWIOT+SzRdVcKePoNliZ4jDhkOh3+p75NEIOEcDUgoE9M2iCWEBUjkV978ogw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/eslint/node_modules/@nx/nx-linux-x64-musl": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.3.2.tgz", - "integrity": "sha512-Wun4v+kuuqv20tJiCENkHGisDqfx029bFufqxx2IOe9TvD6vK4rMMkFVPUoK3FP8EBdaMW4nrR0ZucTFnStl6w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/eslint/node_modules/@nx/nx-win32-arm64-msvc": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.3.2.tgz", - "integrity": "sha512-bNVf6eu5rWFjHvn0rKHeZYlHUcs3naXvvbduW1g0DPkHG6mt8FYffQmyboN+CSeBd/uWDPNyTUekVWwU7PjtLA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/eslint/node_modules/@nx/nx-win32-x64-msvc": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.3.2.tgz", - "integrity": "sha512-8DD5BPa5YrxTOKL3HTAgEd+IXNqRtJfwvbrn2MbOMNMyoMG9Zi5yhFvTH/HTT9Tz6VUHvXP16QWYA3R7eFi7Gg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/eslint/node_modules/@nx/workspace": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-19.3.2.tgz", - "integrity": "sha512-gam41l0hFftYIYTt8eTvZjh+ZWo62HO2p/efqZuFIa/1ZsXF1XG8MDRkCSh5Wfjh1f0jS2ma8HwPV3e8TJm2lw==", + "node_modules/@nx/webpack/node_modules/webpack-dev-middleware": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.4.2.tgz", + "integrity": "sha512-xOO8n6eggxnwYpy1NlzUKpvrjfJTvae5/D6WOK0S2LSo7vjmo5gCM1DbLUmFqrMTJP+W/0YZNctm7jasWvLuBA==", "dev": true, "dependencies": { - "@nrwl/workspace": "19.3.2", - "@nx/devkit": "19.3.2", - "chalk": "^4.1.0", - "enquirer": "~2.3.6", - "nx": "19.3.2", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" + "colorette": "^2.0.10", + "memfs": "^4.6.0", + "mime-types": "^2.1.31", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } } }, - "node_modules/@nx/eslint/node_modules/@nx/workspace/node_modules/nx": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/nx/-/nx-19.3.2.tgz", - "integrity": "sha512-eKWs+ahkTKnq9EeWJCE4u8JLeq1cOHnq5DKoiisy2nwUg4KGy1odReegxUMLeEgNBcMI40EUtEJFiTMJSXZQeg==", + "node_modules/@nx/webpack/node_modules/webpack-dev-server": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.0.4.tgz", + "integrity": "sha512-dljXhUgx3HqKP2d8J/fUMvhxGhzjeNVarDLcbO/EWMSgRizDkxHQDZQaLFL5VJY9tRBj2Gz+rvCEYYvhbqPHNA==", "dev": true, - "hasInstallScript": true, "dependencies": { - "@nrwl/tao": "19.3.2", - "@yarnpkg/lockfile": "^1.1.0", - "@yarnpkg/parsers": "3.0.0-rc.46", - "@zkochan/js-yaml": "0.0.7", - "axios": "^1.6.0", - "chalk": "^4.1.0", - "cli-cursor": "3.1.0", - "cli-spinners": "2.6.1", - "cliui": "^8.0.1", - "dotenv": "~16.4.5", - "dotenv-expand": "~11.0.6", - "enquirer": "~2.3.6", - "figures": "3.2.0", - "flat": "^5.0.2", - "front-matter": "^4.0.2", - "fs-extra": "^11.1.0", - "ignore": "^5.0.4", - "jest-diff": "^29.4.1", - "jsonc-parser": "3.2.0", - "lines-and-columns": "~2.0.3", - "minimatch": "9.0.3", - "node-machine-id": "1.1.12", - "npm-run-path": "^4.0.1", - "open": "^8.4.0", - "ora": "5.3.0", - "semver": "^7.5.3", - "string-width": "^4.2.3", - "strong-log-transformer": "^2.1.0", - "tar-stream": "~2.2.0", - "tmp": "~0.2.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0", - "yargs": "^17.6.2", - "yargs-parser": "21.1.1" + "@types/bonjour": "^3.5.13", + "@types/connect-history-api-fallback": "^1.5.4", + "@types/express": "^4.17.21", + "@types/serve-index": "^1.9.4", + "@types/serve-static": "^1.15.5", + "@types/sockjs": "^0.3.36", + "@types/ws": "^8.5.10", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.2.1", + "chokidar": "^3.6.0", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.4.0", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.1.0", + "launch-editor": "^2.6.1", + "open": "^10.0.3", + "p-retry": "^6.2.0", + "rimraf": "^5.0.5", + "schema-utils": "^4.2.0", + "selfsigned": "^2.4.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^7.1.0", + "ws": "^8.16.0" }, "bin": { - "nx": "bin/nx.js", - "nx-cloud": "bin/nx-cloud.js" + "webpack-dev-server": "bin/webpack-dev-server.js" }, - "optionalDependencies": { - "@nx/nx-darwin-arm64": "19.3.2", - "@nx/nx-darwin-x64": "19.3.2", - "@nx/nx-freebsd-x64": "19.3.2", - "@nx/nx-linux-arm-gnueabihf": "19.3.2", - "@nx/nx-linux-arm64-gnu": "19.3.2", - "@nx/nx-linux-arm64-musl": "19.3.2", - "@nx/nx-linux-x64-gnu": "19.3.2", - "@nx/nx-linux-x64-musl": "19.3.2", - "@nx/nx-win32-arm64-msvc": "19.3.2", - "@nx/nx-win32-x64-msvc": "19.3.2" + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "@swc-node/register": "^1.8.0", - "@swc/core": "^1.3.85" + "webpack": "^5.0.0" }, "peerDependenciesMeta": { - "@swc-node/register": { + "webpack": { "optional": true }, - "@swc/core": { + "webpack-cli": { "optional": true } } }, - "node_modules/@nx/eslint/node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "node_modules/@nx/eslint/node_modules/dotenv-expand": { - "version": "11.0.6", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.6.tgz", - "integrity": "sha512-8NHi73otpWsZGBSZwwknTXS5pqMOrk9+Ssrna8xCaxkzEpU9OTf9R5ArQGVw03//Zmk9MOwLPng9WwndvpAJ5g==", + "node_modules/@nx/webpack/node_modules/webpack-dev-server/node_modules/http-proxy-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", "dev": true, "dependencies": { - "dotenv": "^16.4.4" + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" }, "engines": { - "node": ">=12" + "node": ">=12.0.0" }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/@nx/eslint/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/@nx/eslint/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } } }, - "node_modules/@nx/eslint/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "node_modules/@nx/webpack/node_modules/webpack-dev-server/node_modules/open": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz", + "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^3.1.0" }, "engines": { - "node": ">=10" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@nx/eslint/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/@nx/webpack/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, + "license": "ISC", "engines": { - "node": ">=8" + "node": ">= 6" } }, - "node_modules/@nx/eslint/node_modules/yargs": { + "node_modules/@nx/webpack/node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", @@ -8730,98 +20057,67 @@ "node": ">=12" } }, - "node_modules/@nx/jest": { - "version": "20.0.8", - "resolved": "https://registry.npmjs.org/@nx/jest/-/jest-20.0.8.tgz", - "integrity": "sha512-LEs1EKl0RezDycGKxCaJivvKKXXHL5HUGp9dxE2FuS2nzimYhYldxlOH+zr73J5SWEZtxnMHHjRPkbDffnoxug==", + "node_modules/@nx/workspace": { + "version": "19.7.3", + "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-19.7.3.tgz", + "integrity": "sha512-FUHeOLCXdHEB1b6FiNU9swCZIKXbsGWRDfgHpHGeiZHp7uhH41W/EKTVukRxnQ+HXhE7zfxhn8KkllfaXIifPg==", "dev": true, "dependencies": { - "@jest/reporters": "^29.4.1", - "@jest/test-result": "^29.4.1", - "@nx/devkit": "20.0.8", - "@nx/js": "20.0.8", - "@phenomnomnominal/tsquery": "~5.0.1", + "@nrwl/workspace": "19.7.3", + "@nx/devkit": "19.7.3", "chalk": "^4.1.0", - "identity-obj-proxy": "3.0.0", - "jest-config": "^29.4.1", - "jest-resolve": "^29.4.1", - "jest-util": "^29.4.1", - "minimatch": "9.0.3", - "resolve.exports": "1.1.0", - "semver": "^7.5.3", + "enquirer": "~2.3.6", + "nx": "19.7.3", "tslib": "^2.3.0", "yargs-parser": "21.1.1" } }, - "node_modules/@nx/jest/node_modules/@nx/devkit": { - "version": "20.0.8", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-20.0.8.tgz", - "integrity": "sha512-MRUGgWSMzYtdwtolvWL5EZlX+7xYgu7JIXf1+3rmZU5adMmlqWKrIbyvDf53XocQlT8oxx/xXTEFHhIymGTQCg==", + "node_modules/@nx/workspace/node_modules/@nrwl/devkit": { + "version": "19.7.3", + "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.7.3.tgz", + "integrity": "sha512-g9vANTuxgHan6uAkI6M6tkfLjHECLmbZ4A80UqpxJNQJsCJFEHkzIC9oxhf8bWV3PjgCH6Xm4VyQ2GHwb3sgWw==", "dev": true, "dependencies": { - "ejs": "^3.1.7", - "enquirer": "~2.3.6", - "ignore": "^5.0.4", - "minimatch": "9.0.3", - "semver": "^7.5.3", - "tmp": "~0.2.1", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" + "@nx/devkit": "19.7.3" + } + }, + "node_modules/@nx/workspace/node_modules/@nrwl/tao": { + "version": "19.7.3", + "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.7.3.tgz", + "integrity": "sha512-cIGhnSFPZdVTp4bI0fqwFoE9i7ToPg5jXz+hNMl/MTwcOQfKQ1JJY/ZPLM3aBUPORFIZ/GECQEycUb6+xCB56g==", + "dev": true, + "dependencies": { + "nx": "19.7.3", + "tslib": "^2.3.0" }, - "peerDependencies": { - "nx": ">= 19 <= 21" + "bin": { + "tao": "index.js" } }, - "node_modules/@nx/jest/node_modules/@nx/js": { - "version": "20.0.8", - "resolved": "https://registry.npmjs.org/@nx/js/-/js-20.0.8.tgz", - "integrity": "sha512-PDkjhen4Gl1bMw65XfgebSceNH7HOeTr1f5C+WY/II+7pcAx2lqWj4n6t0XkzBMWlOyfHt/H+O/F4GuZ/hjIyg==", + "node_modules/@nx/workspace/node_modules/@nx/devkit": { + "version": "19.7.3", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.7.3.tgz", + "integrity": "sha512-dIavuzfcMLCTa5uhd4R7HsxcFO0w9fHwG4wDg76wyBAbPGJlrR+9zg359hZ/SkXdguO6bMVmmQg/EXIvo6g69A==", "dev": true, "dependencies": { - "@babel/core": "^7.23.2", - "@babel/plugin-proposal-decorators": "^7.22.7", - "@babel/plugin-transform-class-properties": "^7.22.5", - "@babel/plugin-transform-runtime": "^7.23.2", - "@babel/preset-env": "^7.23.2", - "@babel/preset-typescript": "^7.22.5", - "@babel/runtime": "^7.22.6", - "@nx/devkit": "20.0.8", - "@nx/workspace": "20.0.8", - "@zkochan/js-yaml": "0.0.7", - "babel-plugin-const-enum": "^1.0.1", - "babel-plugin-macros": "^2.8.0", - "babel-plugin-transform-typescript-metadata": "^0.3.1", - "chalk": "^4.1.0", - "columnify": "^1.6.0", - "detect-port": "^1.5.1", + "@nrwl/devkit": "19.7.3", + "ejs": "^3.1.7", "enquirer": "~2.3.6", - "fast-glob": "3.2.7", "ignore": "^5.0.4", - "js-tokens": "^4.0.0", - "jsonc-parser": "3.2.0", "minimatch": "9.0.3", - "npm-package-arg": "11.0.1", - "npm-run-path": "^4.0.1", - "ora": "5.3.0", "semver": "^7.5.3", - "source-map-support": "0.5.19", - "ts-node": "10.9.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0" + "tmp": "~0.2.1", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" }, "peerDependencies": { - "verdaccio": "^5.0.4" - }, - "peerDependenciesMeta": { - "verdaccio": { - "optional": true - } + "nx": ">= 17 <= 20" } }, - "node_modules/@nx/jest/node_modules/@nx/nx-darwin-arm64": { - "version": "20.0.8", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-20.0.8.tgz", - "integrity": "sha512-tDoafq5YUyOwxR1Y796WXA6j49OLJRO7TA/Fym52SSuD3AULbgo3/X5XeY6oL2PWM044CuUVrp3V4cIDUtyJpA==", + "node_modules/@nx/workspace/node_modules/@nx/nx-darwin-arm64": { + "version": "19.7.3", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.7.3.tgz", + "integrity": "sha512-0dDK0UkMR0vBv4AP/48Q9A+OC2dvpivdt8su/4W/CPADy69M9B5O3jPiK+jTRsLshQG/soC9JG0Rll1BNWymPg==", "cpu": [ "arm64" ], @@ -8834,10 +20130,10 @@ "node": ">= 10" } }, - "node_modules/@nx/jest/node_modules/@nx/nx-darwin-x64": { - "version": "20.0.8", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-20.0.8.tgz", - "integrity": "sha512-bvfZ6VhSvOpPV00veaJDO1a4X+f0dn8S1A73/2ThbGZrZLAQIFrA8v+ysax+bfCGRHNdtlAL+f7TG2buh/4BRg==", + "node_modules/@nx/workspace/node_modules/@nx/nx-darwin-x64": { + "version": "19.7.3", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.7.3.tgz", + "integrity": "sha512-hTdv5YY2GQTdT7GwVO7ST27ZzvCmAQvmkEapfnCdy74QsL4gapaXJFvtWLHVfG6qHNRHWXbpdegvR3VswRHZVQ==", "cpu": [ "x64" ], @@ -8850,10 +20146,10 @@ "node": ">= 10" } }, - "node_modules/@nx/jest/node_modules/@nx/nx-freebsd-x64": { - "version": "20.0.8", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-20.0.8.tgz", - "integrity": "sha512-AdOme0o/pTFy+TutIOAamuGTqbh6nOLrkNEX8f4ogfDRH+k/WvjRQ4z4ne58wf/2EVXua4jKTIEipIZAP/Ad1w==", + "node_modules/@nx/workspace/node_modules/@nx/nx-freebsd-x64": { + "version": "19.7.3", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.7.3.tgz", + "integrity": "sha512-dwuB/3eoV2RbD0b0LHnagQOXa9PKAjLi7g5vNxzw6LuNT1tdaLaUZZGv2tfG0hHjsV0cOaAX41rEyOIwJyE7zg==", "cpu": [ "x64" ], @@ -8866,10 +20162,10 @@ "node": ">= 10" } }, - "node_modules/@nx/jest/node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "20.0.8", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-20.0.8.tgz", - "integrity": "sha512-PYf7Z30A1TCZq9HVUP6JjT3ghTLYkaBpR6vDwiGWUV/exuNmhUgfYW6TiTpiSArXwnAgSIbaoGe537iEvYzA7A==", + "node_modules/@nx/workspace/node_modules/@nx/nx-linux-arm-gnueabihf": { + "version": "19.7.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.7.3.tgz", + "integrity": "sha512-X/eG3IqvIxlCfIOiCQKv7RKwra54I+SN9zj2TeSOtd/uK0paa3mYSlGUJqoP3wpzasW1+EPIGkTQqV283IA15w==", "cpu": [ "arm" ], @@ -8882,10 +20178,10 @@ "node": ">= 10" } }, - "node_modules/@nx/jest/node_modules/@nx/nx-linux-arm64-gnu": { - "version": "20.0.8", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-20.0.8.tgz", - "integrity": "sha512-3VpvhjmNR78HVxGzpWiwqZsG5sNvLUv2Qfohtxyc3561o8VU41R9Onf/LJmbbZvmdDaPvvXQp3rs0OXT4i7T1g==", + "node_modules/@nx/workspace/node_modules/@nx/nx-linux-arm64-gnu": { + "version": "19.7.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.7.3.tgz", + "integrity": "sha512-LNaX8DVcPlFVJhMf1AAAR6j1DZF9BlVhWlilRM44tIfnmvPfKIahKJIJbuikHE7q+lkvMrQUUDXKiQJlmm/qDw==", "cpu": [ "arm64" ], @@ -8898,10 +20194,10 @@ "node": ">= 10" } }, - "node_modules/@nx/jest/node_modules/@nx/nx-linux-arm64-musl": { - "version": "20.0.8", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-20.0.8.tgz", - "integrity": "sha512-3Z7fTJGG8h4VCHhD8Ix0zr6eFMfa1y3YDlzm8Clxu4Enzz0pEsUrT+ph6qrsArnIyUgiCowSi8+xgHFg7V/F1Q==", + "node_modules/@nx/workspace/node_modules/@nx/nx-linux-arm64-musl": { + "version": "19.7.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.7.3.tgz", + "integrity": "sha512-TJ9PqSebhrn8NfrW+wqMXB9N65U0L0Kjt8FfahWffNKtSAEUvhurbNhqna2Rt5WJe2qaVf6zN2pOHKhF/5pL0w==", "cpu": [ "arm64" ], @@ -8914,10 +20210,10 @@ "node": ">= 10" } }, - "node_modules/@nx/jest/node_modules/@nx/nx-linux-x64-gnu": { - "version": "20.0.8", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-20.0.8.tgz", - "integrity": "sha512-Uttl1RHzWpjZgdzowCUNjC6/b3YhZR31wyXWgVF4PDWpDVgy4EigGc19tdrvv8pUVKQFuj0uaSTPUklguN7c3A==", + "node_modules/@nx/workspace/node_modules/@nx/nx-linux-x64-gnu": { + "version": "19.7.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.7.3.tgz", + "integrity": "sha512-YMb4WGGovwgxsP6VvAEnyWvLoUwsDrdE5CxFQ2yoThD2BixmSHUKLtx6dtPDHz25nOE3v1ZzM0xTwYXBhPaeRQ==", "cpu": [ "x64" ], @@ -8930,10 +20226,10 @@ "node": ">= 10" } }, - "node_modules/@nx/jest/node_modules/@nx/nx-linux-x64-musl": { - "version": "20.0.8", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-20.0.8.tgz", - "integrity": "sha512-llc6ywSPaOWQzEzD73USyAXd/y3Slu+GHS02IsQqZeA23EIOEzhvEeeeKgs4F8LKuFW/TpV6T5IhvSHw9/mvBg==", + "node_modules/@nx/workspace/node_modules/@nx/nx-linux-x64-musl": { + "version": "19.7.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.7.3.tgz", + "integrity": "sha512-zkjgDSvw2eDN+KuJBPPAPhU/lOdiMvJU0UMthJFw85dhQIYfAO8+UgiFg/qBsKo0kQ0MkhntnIPBPF8bH40qWg==", "cpu": [ "x64" ], @@ -8946,10 +20242,10 @@ "node": ">= 10" } }, - "node_modules/@nx/jest/node_modules/@nx/nx-win32-arm64-msvc": { - "version": "20.0.8", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-20.0.8.tgz", - "integrity": "sha512-GhPVVNrL0QcQ3B6r0P0Dta3TIesJz7uso7iI5rCZ/oOGa02UsT4NkQBpIhxYQZ4TnHYNy84g4rHtYHrSlpDlEw==", + "node_modules/@nx/workspace/node_modules/@nx/nx-win32-arm64-msvc": { + "version": "19.7.3", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.7.3.tgz", + "integrity": "sha512-qCTFG6VxNvEe5JfoAELGZsjWDL4G+2NVSoSS3tByJYwVX256qgALcVoUHMjpxBn9FeOvUW9w5PL4Am4PKDdXLw==", "cpu": [ "arm64" ], @@ -8962,10 +20258,10 @@ "node": ">= 10" } }, - "node_modules/@nx/jest/node_modules/@nx/nx-win32-x64-msvc": { - "version": "20.0.8", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-20.0.8.tgz", - "integrity": "sha512-yLlcgM0zFdmsExdLv8O2g5FWQ6d2vyN5OynKV+F5BrWHC4LvrqyYJ99y++5bLFoEi19RYIK6sLnzGIRSF6dHGg==", + "node_modules/@nx/workspace/node_modules/@nx/nx-win32-x64-msvc": { + "version": "19.7.3", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.7.3.tgz", + "integrity": "sha512-ULNf73gLgB5cU/O4dlQe6tetbRIROTmaUNYTUUCCAC0BqVwZwPDxn4u9C5LgiErVyfPwwAhlserCGei5taLASQ==", "cpu": [ "x64" ], @@ -8978,38 +20274,7 @@ "node": ">= 10" } }, - "node_modules/@nx/jest/node_modules/@nx/workspace": { - "version": "20.0.8", - "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-20.0.8.tgz", - "integrity": "sha512-G7nON6s3KDWNAH9P8IBvvAmTGgTsFZPuWH7We9px0ZwsRcURDDP1OqZsYmfr0zTHTS58wu4Uax/uQLwnTVC1xQ==", - "dev": true, - "dependencies": { - "@nx/devkit": "20.0.8", - "chalk": "^4.1.0", - "enquirer": "~2.3.6", - "nx": "20.0.8", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" - } - }, - "node_modules/@nx/jest/node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "node_modules/@nx/jest/node_modules/axios": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", - "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", - "dev": true, - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/@nx/jest/node_modules/dotenv-expand": { + "node_modules/@nx/workspace/node_modules/dotenv-expand": { "version": "11.0.6", "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.6.tgz", "integrity": "sha512-8NHi73otpWsZGBSZwwknTXS5pqMOrk9+Ssrna8xCaxkzEpU9OTf9R5ArQGVw03//Zmk9MOwLPng9WwndvpAJ5g==", @@ -9024,13 +20289,13 @@ "url": "https://dotenvx.com" } }, - "node_modules/@nx/jest/node_modules/emoji-regex": { + "node_modules/@nx/workspace/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "node_modules/@nx/jest/node_modules/is-fullwidth-code-point": { + "node_modules/@nx/workspace/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", @@ -9039,7 +20304,7 @@ "node": ">=8" } }, - "node_modules/@nx/jest/node_modules/lines-and-columns": { + "node_modules/@nx/workspace/node_modules/lines-and-columns": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.3.tgz", "integrity": "sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w==", @@ -9048,14 +20313,15 @@ "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, - "node_modules/@nx/jest/node_modules/nx": { - "version": "20.0.8", - "resolved": "https://registry.npmjs.org/nx/-/nx-20.0.8.tgz", - "integrity": "sha512-cMtb+u5Eji7Xm9xMHZkRXMcO8GH6FFqS2+nMgtLUZ/+ZmquEgoV8mbsKVw1u1sJ6osOpWAu9OwXcilwtvSOoBw==", + "node_modules/@nx/workspace/node_modules/nx": { + "version": "19.7.3", + "resolved": "https://registry.npmjs.org/nx/-/nx-19.7.3.tgz", + "integrity": "sha512-8F4CzKavSuOFv+uKVwXHc00Px0q40CWAYCW6NC5IgU3AMaJVumyHzgB8Sn+yfkaVgfVnZVqznOsyrbZUWuj/VA==", "dev": true, "hasInstallScript": true, "dependencies": { "@napi-rs/wasm-runtime": "0.2.4", + "@nrwl/tao": "19.7.3", "@yarnpkg/lockfile": "^1.1.0", "@yarnpkg/parsers": "3.0.0-rc.46", "@zkochan/js-yaml": "0.0.7", @@ -9070,6 +20336,7 @@ "figures": "3.2.0", "flat": "^5.0.2", "front-matter": "^4.0.2", + "fs-extra": "^11.1.0", "ignore": "^5.0.4", "jest-diff": "^29.4.1", "jsonc-parser": "3.2.0", @@ -9081,6 +20348,7 @@ "ora": "5.3.0", "semver": "^7.5.3", "string-width": "^4.2.3", + "strong-log-transformer": "^2.1.0", "tar-stream": "~2.2.0", "tmp": "~0.2.1", "tsconfig-paths": "^4.1.2", @@ -9093,16 +20361,16 @@ "nx-cloud": "bin/nx-cloud.js" }, "optionalDependencies": { - "@nx/nx-darwin-arm64": "20.0.8", - "@nx/nx-darwin-x64": "20.0.8", - "@nx/nx-freebsd-x64": "20.0.8", - "@nx/nx-linux-arm-gnueabihf": "20.0.8", - "@nx/nx-linux-arm64-gnu": "20.0.8", - "@nx/nx-linux-arm64-musl": "20.0.8", - "@nx/nx-linux-x64-gnu": "20.0.8", - "@nx/nx-linux-x64-musl": "20.0.8", - "@nx/nx-win32-arm64-msvc": "20.0.8", - "@nx/nx-win32-x64-msvc": "20.0.8" + "@nx/nx-darwin-arm64": "19.7.3", + "@nx/nx-darwin-x64": "19.7.3", + "@nx/nx-freebsd-x64": "19.7.3", + "@nx/nx-linux-arm-gnueabihf": "19.7.3", + "@nx/nx-linux-arm64-gnu": "19.7.3", + "@nx/nx-linux-arm64-musl": "19.7.3", + "@nx/nx-linux-x64-gnu": "19.7.3", + "@nx/nx-linux-x64-musl": "19.7.3", + "@nx/nx-win32-arm64-msvc": "19.7.3", + "@nx/nx-win32-x64-msvc": "19.7.3" }, "peerDependencies": { "@swc-node/register": "^1.8.0", @@ -9112,651 +20380,975 @@ "@swc-node/register": { "optional": true }, - "@swc/core": { + "@swc/core": { + "optional": true + } + } + }, + "node_modules/@nx/workspace/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@nx/workspace/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@nx/workspace/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@open-draft/deferred-promise": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", + "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@open-draft/logger": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz", + "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-node-process": "^1.2.0", + "outvariant": "^1.4.0" + } + }, + "node_modules/@open-draft/until": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz", + "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@open-policy-agent/opa-wasm": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@open-policy-agent/opa-wasm/-/opa-wasm-1.9.0.tgz", + "integrity": "sha512-wuxQYoqU80ulYdFtZ1BKaFs29IRZZV3hl48L4wMRxXFlEoLBDfl5rL8iBNIyp+DDymvDxGS4ZMRVaBBWXnPYLQ==", + "dependencies": { + "sprintf-js": "^1.1.2", + "yaml": "^1.10.2" + } + }, + "node_modules/@open-policy-agent/opa-wasm/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/@open-rpc/client-js": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@open-rpc/client-js/-/client-js-1.8.1.tgz", + "integrity": "sha512-vV+Hetl688nY/oWI9IFY0iKDrWuLdYhf7OIKI6U1DcnJV7r4gAgwRJjEr1QVYszUc0gjkHoQJzqevmXMGLyA0g==", + "license": "Apache-2.0", + "dependencies": { + "isomorphic-fetch": "^3.0.0", + "isomorphic-ws": "^5.0.0", + "strict-event-emitter-types": "^2.0.0", + "ws": "^7.0.0" + } + }, + "node_modules/@open-rpc/client-js/node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/@openapitools/openapi-generator-cli": { + "version": "2.15.3", + "resolved": "https://registry.npmjs.org/@openapitools/openapi-generator-cli/-/openapi-generator-cli-2.15.3.tgz", + "integrity": "sha512-2UBnsDlMt36thhdXxisbA1qReVtbCaw+NCvXoslRXlaJBL4qkAmZUhNeDLNu3LCbwA2PASMWhJSqeLwgwMCitw==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@nestjs/axios": "3.1.1", + "@nestjs/common": "10.4.6", + "@nestjs/core": "10.4.6", + "@nuxtjs/opencollective": "0.3.2", + "axios": "1.7.7", + "chalk": "4.1.2", + "commander": "8.3.0", + "compare-versions": "4.1.4", + "concurrently": "6.5.1", + "console.table": "0.10.0", + "fs-extra": "10.1.0", + "glob": "9.3.5", + "inquirer": "8.2.6", + "lodash": "4.17.21", + "proxy-agent": "6.4.0", + "reflect-metadata": "0.1.13", + "rxjs": "7.8.1", + "tslib": "2.8.1" + }, + "bin": { + "openapi-generator-cli": "main.js" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/openapi_generator" + } + }, + "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/axios": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-3.1.1.tgz", + "integrity": "sha512-ySoxrzqX80P1q6LKLKGcgyBd2utg4gbC+4FsJNpXYvILorMlxss/ECNogD9EXLCE4JS5exVFD5ez0nK5hXcNTQ==", + "dev": true, + "peerDependencies": { + "@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0", + "axios": "^1.3.1", + "rxjs": "^6.0.0 || ^7.0.0" + } + }, + "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/common": { + "version": "10.4.6", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.4.6.tgz", + "integrity": "sha512-KkezkZvU9poWaNq4L+lNvx+386hpOxPJkfXBBeSMrcqBOx8kVr36TGN2uYkF4Ta4zNu1KbCjmZbc0rhHSg296g==", + "dev": true, + "dependencies": { + "iterare": "1.2.1", + "tslib": "2.7.0", + "uid": "2.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "class-transformer": "*", + "class-validator": "*", + "reflect-metadata": "^0.1.12 || ^0.2.0", + "rxjs": "^7.1.0" + }, + "peerDependenciesMeta": { + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } + } + }, + "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/common/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + }, + "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/core": { + "version": "10.4.6", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.4.6.tgz", + "integrity": "sha512-zXVPxCNRfO6gAy0yvEDjUxE/8gfZICJFpsl2lZAUH31bPb6m+tXuhUq2mVCTEltyMYQ+DYtRe+fEYM2v152N1g==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@nuxtjs/opencollective": "0.3.2", + "fast-safe-stringify": "2.1.1", + "iterare": "1.2.1", + "path-to-regexp": "3.3.0", + "tslib": "2.7.0", + "uid": "2.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^10.0.0", + "@nestjs/microservices": "^10.0.0", + "@nestjs/platform-express": "^10.0.0", + "@nestjs/websockets": "^10.0.0", + "reflect-metadata": "^0.1.12 || ^0.2.0", + "rxjs": "^7.1.0" + }, + "peerDependenciesMeta": { + "@nestjs/microservices": { + "optional": true + }, + "@nestjs/platform-express": { + "optional": true + }, + "@nestjs/websockets": { "optional": true } } }, - "node_modules/@nx/jest/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/core/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + }, + "node_modules/@openapitools/openapi-generator-cli/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", "dev": true, - "bin": { - "semver": "bin/semver.js" - }, "engines": { - "node": ">=10" + "node": ">= 12" } }, - "node_modules/@nx/jest/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/@openapitools/openapi-generator-cli/node_modules/fs-extra": { + "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==", "dev": true, "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/@nx/jest/node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "node_modules/@openapitools/openapi-generator-cli/node_modules/glob": { + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", + "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", "dev": true, "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" + "fs.realpath": "^1.0.0", + "minimatch": "^8.0.2", + "minipass": "^4.2.4", + "path-scurry": "^1.6.1" }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" + "engines": { + "node": ">=16 || 14 >=14.17" }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@nx/jest/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "node_modules/@openapitools/openapi-generator-cli/node_modules/minimatch": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", + "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", "dev": true, "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=12" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@nx/js": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/js/-/js-19.2.0.tgz", - "integrity": "sha512-cLz1OSfWpm/y0bZtdv5INlCo9/ED9tC45e6OKBc2ClW5Gz2+IoZz/dK/bCXg7dpEBtF1Y9mHihKisPOmUhaLwQ==", + "node_modules/@openapitools/openapi-generator-cli/node_modules/minipass": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", + "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@openapitools/openapi-generator-cli/node_modules/path-to-regexp": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.3.0.tgz", + "integrity": "sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==", + "dev": true + }, + "node_modules/@openapitools/openapi-generator-cli/node_modules/reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", + "dev": true + }, + "node_modules/@openapitools/openapi-generator-cli/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true + }, + "node_modules/@opentelemetry/api": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", + "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@opentelemetry/api-logs": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.53.0.tgz", + "integrity": "sha512-8HArjKx+RaAI8uEIgcORbZIPklyh1YLjPSBus8hjRmvLi6DeFzgOcdZ7KwPabKj8mXF8dX0hyfAyGfycz0DbFw==", "dependencies": { - "@babel/core": "^7.23.2", - "@babel/plugin-proposal-decorators": "^7.22.7", - "@babel/plugin-transform-class-properties": "^7.22.5", - "@babel/plugin-transform-runtime": "^7.23.2", - "@babel/preset-env": "^7.23.2", - "@babel/preset-typescript": "^7.22.5", - "@babel/runtime": "^7.22.6", - "@nrwl/js": "19.2.0", - "@nx/devkit": "19.2.0", - "@nx/workspace": "19.2.0", - "babel-plugin-const-enum": "^1.0.1", - "babel-plugin-macros": "^2.8.0", - "babel-plugin-transform-typescript-metadata": "^0.3.1", - "chalk": "^4.1.0", - "columnify": "^1.6.0", - "detect-port": "^1.5.1", - "fast-glob": "3.2.7", - "fs-extra": "^11.1.0", - "ignore": "^5.0.4", - "js-tokens": "^4.0.0", - "minimatch": "9.0.3", - "npm-package-arg": "11.0.1", - "npm-run-path": "^4.0.1", - "ora": "5.3.0", - "semver": "^7.5.3", - "source-map-support": "0.5.19", - "ts-node": "10.9.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0" + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/auto-instrumentations-node": { + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/auto-instrumentations-node/-/auto-instrumentations-node-0.51.0.tgz", + "integrity": "sha512-xsgydgtJiToxvFsDcmLDrHiFfHOmdomqk4KCnr40YZdsfw7KO4RJEU0om2f7pFh6WUI5q8nSQ53QgZ+DAz6TzA==", + "dependencies": { + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/instrumentation-amqplib": "^0.42.0", + "@opentelemetry/instrumentation-aws-lambda": "^0.45.0", + "@opentelemetry/instrumentation-aws-sdk": "^0.44.0", + "@opentelemetry/instrumentation-bunyan": "^0.41.0", + "@opentelemetry/instrumentation-cassandra-driver": "^0.41.0", + "@opentelemetry/instrumentation-connect": "^0.39.0", + "@opentelemetry/instrumentation-cucumber": "^0.9.0", + "@opentelemetry/instrumentation-dataloader": "^0.12.0", + "@opentelemetry/instrumentation-dns": "^0.39.0", + "@opentelemetry/instrumentation-express": "^0.43.0", + "@opentelemetry/instrumentation-fastify": "^0.40.0", + "@opentelemetry/instrumentation-fs": "^0.15.0", + "@opentelemetry/instrumentation-generic-pool": "^0.39.0", + "@opentelemetry/instrumentation-graphql": "^0.43.0", + "@opentelemetry/instrumentation-grpc": "^0.53.0", + "@opentelemetry/instrumentation-hapi": "^0.41.0", + "@opentelemetry/instrumentation-http": "^0.53.0", + "@opentelemetry/instrumentation-ioredis": "^0.43.0", + "@opentelemetry/instrumentation-kafkajs": "^0.3.0", + "@opentelemetry/instrumentation-knex": "^0.40.0", + "@opentelemetry/instrumentation-koa": "^0.43.0", + "@opentelemetry/instrumentation-lru-memoizer": "^0.40.0", + "@opentelemetry/instrumentation-memcached": "^0.39.0", + "@opentelemetry/instrumentation-mongodb": "^0.47.0", + "@opentelemetry/instrumentation-mongoose": "^0.42.0", + "@opentelemetry/instrumentation-mysql": "^0.41.0", + "@opentelemetry/instrumentation-mysql2": "^0.41.0", + "@opentelemetry/instrumentation-nestjs-core": "^0.40.0", + "@opentelemetry/instrumentation-net": "^0.39.0", + "@opentelemetry/instrumentation-pg": "^0.46.0", + "@opentelemetry/instrumentation-pino": "^0.42.0", + "@opentelemetry/instrumentation-redis": "^0.42.0", + "@opentelemetry/instrumentation-redis-4": "^0.42.1", + "@opentelemetry/instrumentation-restify": "^0.41.0", + "@opentelemetry/instrumentation-router": "^0.40.0", + "@opentelemetry/instrumentation-socket.io": "^0.42.0", + "@opentelemetry/instrumentation-tedious": "^0.14.0", + "@opentelemetry/instrumentation-undici": "^0.6.0", + "@opentelemetry/instrumentation-winston": "^0.40.0", + "@opentelemetry/resource-detector-alibaba-cloud": "^0.29.3", + "@opentelemetry/resource-detector-aws": "^1.6.2", + "@opentelemetry/resource-detector-azure": "^0.2.11", + "@opentelemetry/resource-detector-container": "^0.4.4", + "@opentelemetry/resource-detector-gcp": "^0.29.12", + "@opentelemetry/resources": "^1.24.0", + "@opentelemetry/sdk-node": "^0.53.0" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { - "verdaccio": "^5.0.4" + "@opentelemetry/api": "^1.4.1" + } + }, + "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, - "peerDependenciesMeta": { - "verdaccio": { - "optional": true - } + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/js/node_modules/@nrwl/devkit": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.2.0.tgz", - "integrity": "sha512-Ew5AJZkLXJwt15HjaIbHve8FOXmZ3HK8KPqTXqwKHX8jQW+fDUCaSXKe/lCZMNg0RvY+jMNecuC86uGdiIbLMg==", - "dev": true, + "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/instrumentation-express": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-express/-/instrumentation-express-0.43.0.tgz", + "integrity": "sha512-bxTIlzn9qPXJgrhz8/Do5Q3jIlqfpoJrSUtVGqH+90eM1v2PkPHc+SdE+zSqe4q9Y1UQJosmZ4N4bm7Zj/++MA==", "dependencies": { - "@nx/devkit": "19.2.0" + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/js/node_modules/@nrwl/tao": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.2.0.tgz", - "integrity": "sha512-9AOwbY/E7OlLCFu+6jhJGUIs+qurE2/3Pldooe7cJPqQmSQeJuVZuL6A2xHtbSG7VsXTq5Yj8dVvK1KmT45SIA==", - "dev": true, + "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/instrumentation-http": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.53.0.tgz", + "integrity": "sha512-H74ErMeDuZfj7KgYCTOFGWF5W9AfaPnqLQQxeFq85+D29wwV2yqHbz2IKLYpkOh7EI6QwDEl7rZCIxjJLyc/CQ==", "dependencies": { - "nx": "19.2.0", - "tslib": "^2.3.0" + "@opentelemetry/core": "1.26.0", + "@opentelemetry/instrumentation": "0.53.0", + "@opentelemetry/semantic-conventions": "1.27.0", + "semver": "^7.5.2" }, - "bin": { - "tao": "index.js" + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/js/node_modules/@nrwl/workspace": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-19.2.0.tgz", - "integrity": "sha512-/3p9KNpGHgEVjM5aMFhzdp0Vh+Bt16OnlSA+eSKPd5r0eQyLY+T4zTQ1kjyHGYa/xcN8vsWKEnbZW2fD/HWSng==", - "dev": true, + "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/instrumentation-nestjs-core": { + "version": "0.40.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-nestjs-core/-/instrumentation-nestjs-core-0.40.0.tgz", + "integrity": "sha512-WF1hCUed07vKmf5BzEkL0wSPinqJgH7kGzOjjMAiTGacofNXjb/y4KQ8loj2sNsh5C/NN7s1zxQuCgbWbVTGKg==", "dependencies": { - "@nx/workspace": "19.2.0" + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/js/node_modules/@nx/devkit": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.2.0.tgz", - "integrity": "sha512-fK3zRUE2SLp9BUomFiyCuAX2E1yfWYE/hKimniscsvM34/u/xLZYVmmZ0/jfpGPbyaonXKZr2KTb7RimX/hyqg==", - "dev": true, + "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@opentelemetry/context-async-hooks": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-1.26.0.tgz", + "integrity": "sha512-HedpXXYzzbaoutw6DFLWLDket2FwLkLpil4hGCZ1xYEIMTcivdfwEOISgdbLEWyG3HW52gTq2V9mOVJrONgiwg==", + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/core": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.26.0.tgz", + "integrity": "sha512-1iKxXXE8415Cdv0yjG3G6hQnB5eVEsJce3QaawX8SjDn0mAS0ZM8fAbZZJD4ajvhC15cePvosSCut404KrIIvQ==", "dependencies": { - "@nrwl/devkit": "19.2.0", - "ejs": "^3.1.7", - "enquirer": "~2.3.6", - "ignore": "^5.0.4", - "minimatch": "9.0.3", - "semver": "^7.5.3", - "tmp": "~0.2.1", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" + "@opentelemetry/semantic-conventions": "1.27.0" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { - "nx": ">= 17 <= 20" + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@nx/js/node_modules/@nx/nx-darwin-arm64": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.2.0.tgz", - "integrity": "sha512-W+OpGyzr10oaycf4atPc5uH2wN1G6LJGHkWDN3LGSQhoDWuj13idFpjSy6rJ8WxtL8kIvPXq78GEi1yAADsakA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], + "node_modules/@opentelemetry/exporter-logs-otlp-grpc": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-grpc/-/exporter-logs-otlp-grpc-0.53.0.tgz", + "integrity": "sha512-x5ygAQgWAQOI+UOhyV3z9eW7QU2dCfnfOuIBiyYmC2AWr74f6x/3JBnP27IAcEx6aihpqBYWKnpoUTztkVPAZw==", + "dependencies": { + "@grpc/grpc-js": "^1.7.1", + "@opentelemetry/core": "1.26.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.53.0", + "@opentelemetry/otlp-transformer": "0.53.0", + "@opentelemetry/sdk-logs": "0.53.0" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@nx/js/node_modules/@nx/nx-darwin-x64": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.2.0.tgz", - "integrity": "sha512-4l1BDn29R0ugf7ATcGcZGEwK0frZSCtiyXnX3JFq55dNS4Bv3FiZLew7JULjdumXEXr773bH326FQlocLVlcXg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], + "node_modules/@opentelemetry/exporter-logs-otlp-http": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.53.0.tgz", + "integrity": "sha512-cSRKgD/n8rb+Yd+Cif6EnHEL/VZg1o8lEcEwFji1lwene6BdH51Zh3feAD9p2TyVoBKrl6Q9Zm2WltSp2k9gWQ==", + "dependencies": { + "@opentelemetry/api-logs": "0.53.0", + "@opentelemetry/core": "1.26.0", + "@opentelemetry/otlp-exporter-base": "0.53.0", + "@opentelemetry/otlp-transformer": "0.53.0", + "@opentelemetry/sdk-logs": "0.53.0" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@nx/js/node_modules/@nx/nx-freebsd-x64": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.2.0.tgz", - "integrity": "sha512-9zdwLRSkEg/H7bbIVWATn0H8QNgnHaTe23tciZPaBr95J6CXVJWWpC4wn9duURhvbscnqUSSSfKK1f+MSEDTbw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], + "node_modules/@opentelemetry/exporter-logs-otlp-proto": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.53.0.tgz", + "integrity": "sha512-jhEcVL1deeWNmTUP05UZMriZPSWUBcfg94ng7JuBb1q2NExgnADQFl1VQQ+xo62/JepK+MxQe4xAwlsDQFbISA==", + "dependencies": { + "@opentelemetry/api-logs": "0.53.0", + "@opentelemetry/core": "1.26.0", + "@opentelemetry/otlp-exporter-base": "0.53.0", + "@opentelemetry/otlp-transformer": "0.53.0", + "@opentelemetry/resources": "1.26.0", + "@opentelemetry/sdk-logs": "0.53.0", + "@opentelemetry/sdk-trace-base": "1.26.0" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@nx/js/node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.2.0.tgz", - "integrity": "sha512-KNVnqRPegJza3kU4q3pY8m0pT8OSQZnLGsDZti6morhXh2sE79f/zeevOrbhf8JnaJfQtyrXfGvjYAiL3+I8bw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@opentelemetry/exporter-logs-otlp-proto/node_modules/@opentelemetry/resources": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", + "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@nx/js/node_modules/@nx/nx-linux-arm64-gnu": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.2.0.tgz", - "integrity": "sha512-UXIl90l+cDecU17OOLlI+uzbjzQucnNu4Mee67EqE3TyfpSvuU1l3FWZ9sbE0effp8IwKpbL7Gt5KirJKtWzIA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@opentelemetry/exporter-logs-otlp-proto/node_modules/@opentelemetry/sdk-trace-base": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.26.0.tgz", + "integrity": "sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.26.0", + "@opentelemetry/resources": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@nx/js/node_modules/@nx/nx-linux-arm64-musl": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.2.0.tgz", - "integrity": "sha512-4Z8XO3WljS2GWOL2SQ1p8SRNn2Kn6FU1FWClh7KBzMtpzjsHdmOXenMP9UOGZ6gBnfBIknCEDjE3uJUHmuShGg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@opentelemetry/exporter-metrics-otlp-http": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-http/-/exporter-metrics-otlp-http-0.53.0.tgz", + "integrity": "sha512-nvZtOk23pZOrTW10Za2WPd9pk4tWDvL6ALlHRFfInpcTjtOgCrv+fQDxpzosa5PeXvYeFFUO5aYCTnwiCX4Dzg==", + "dependencies": { + "@opentelemetry/core": "1.26.0", + "@opentelemetry/otlp-exporter-base": "0.53.0", + "@opentelemetry/otlp-transformer": "0.53.0", + "@opentelemetry/resources": "1.26.0", + "@opentelemetry/sdk-metrics": "1.26.0" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/js/node_modules/@nx/nx-linux-x64-gnu": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.2.0.tgz", - "integrity": "sha512-EwAkZEp0KB99VEPTskW2feCpSKqWScKdRd6UaIM9Vmqqtb5hSk6yR6p0mprjytbDtFVoKQJMOFa35qe+2R8mKQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@opentelemetry/exporter-metrics-otlp-http/node_modules/@opentelemetry/resources": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", + "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@nx/js/node_modules/@nx/nx-linux-x64-musl": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.2.0.tgz", - "integrity": "sha512-LbFcHe83YZUS/my/8nBxQ2i3JWakcXd7zbzZ0cSAQk6DuJVCUk8PLdgZzhrVcmT82Pv7H0fM/4jgEl+oHGoc/g==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@opentelemetry/exporter-metrics-otlp-proto": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-proto/-/exporter-metrics-otlp-proto-0.53.0.tgz", + "integrity": "sha512-cO99cY04Oy+i8nfYoY0DOVRWVSb0unlerblvf4Fyt2Ls8CkUECLfgjfUXqdjOhBYOX/OZGOBSGetqqYFtKGdGA==", + "dependencies": { + "@opentelemetry/core": "1.26.0", + "@opentelemetry/exporter-metrics-otlp-http": "0.53.0", + "@opentelemetry/otlp-exporter-base": "0.53.0", + "@opentelemetry/otlp-transformer": "0.53.0", + "@opentelemetry/resources": "1.26.0", + "@opentelemetry/sdk-metrics": "1.26.0" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/js/node_modules/@nx/nx-win32-arm64-msvc": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.2.0.tgz", - "integrity": "sha512-BxOveRfRCdhuCs2GWbsdzGsjtLC3N+MuUlVaXSWADksF6/QKuCHM/2Kq3RYkLVVtlls6NCBp410RSx/XsbSEug==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], + "node_modules/@opentelemetry/exporter-metrics-otlp-proto/node_modules/@opentelemetry/resources": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", + "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@nx/js/node_modules/@nx/nx-win32-x64-msvc": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.2.0.tgz", - "integrity": "sha512-QiDxtOHIiRka9Bz7tSpBvQgQPrX5grLhoz6miD6LX1WjO56bZIkEAVefGnMc3WZ1PacS1ZECtymHwUy+WpEqAQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], + "node_modules/@opentelemetry/exporter-trace-otlp-grpc": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-grpc/-/exporter-trace-otlp-grpc-0.53.0.tgz", + "integrity": "sha512-m6KSh6OBDwfDjpzPVbuJbMgMbkoZfpxYH2r262KckgX9cMYvooWXEKzlJYsNDC6ADr28A1rtRoUVRwNfIN4tUg==", + "dependencies": { + "@grpc/grpc-js": "^1.7.1", + "@opentelemetry/core": "1.26.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.53.0", + "@opentelemetry/otlp-transformer": "0.53.0", + "@opentelemetry/resources": "1.26.0", + "@opentelemetry/sdk-trace-base": "1.26.0" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@nx/js/node_modules/@nx/workspace": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-19.2.0.tgz", - "integrity": "sha512-0wdv8jrGIGcf/ZF4r2/xWz/jrQjwftgLPmh7BawYPFbDZlRXkzb7a4MTJOxXH8QcR3ZJNhRjkFfHRPbB0luf1A==", - "dev": true, + "node_modules/@opentelemetry/exporter-trace-otlp-grpc/node_modules/@opentelemetry/resources": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", + "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", + "license": "Apache-2.0", "dependencies": { - "@nrwl/workspace": "19.2.0", - "@nx/devkit": "19.2.0", - "chalk": "^4.1.0", - "enquirer": "~2.3.6", - "nx": "19.2.0", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" + "@opentelemetry/core": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@nx/js/node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "node_modules/@nx/js/node_modules/dotenv": { - "version": "16.3.2", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.2.tgz", - "integrity": "sha512-HTlk5nmhkm8F6JcdXvHIzaorzCoziNQT9mGxLPVXW8wJF1TiGSL60ZGB4gHWabHOaMmWmhvk2/lPHfnBiT78AQ==", - "dev": true, + "node_modules/@opentelemetry/exporter-trace-otlp-grpc/node_modules/@opentelemetry/sdk-trace-base": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.26.0.tgz", + "integrity": "sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.26.0", + "@opentelemetry/resources": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" + }, "engines": { - "node": ">=12" + "node": ">=14" }, - "funding": { - "url": "https://github.com/motdotla/dotenv?sponsor=1" + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@nx/js/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/@nx/js/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, + "node_modules/@opentelemetry/exporter-trace-otlp-proto": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-proto/-/exporter-trace-otlp-proto-0.53.0.tgz", + "integrity": "sha512-T/bdXslwRKj23S96qbvGtaYOdfyew3TjPEKOk5mHjkCmkVl1O9C/YMdejwSsdLdOq2YW30KjR9kVi0YMxZushQ==", + "dependencies": { + "@opentelemetry/core": "1.26.0", + "@opentelemetry/otlp-exporter-base": "0.53.0", + "@opentelemetry/otlp-transformer": "0.53.0", + "@opentelemetry/resources": "1.26.0", + "@opentelemetry/sdk-trace-base": "1.26.0" + }, "engines": { - "node": ">=8" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@nx/js/node_modules/nx": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/nx/-/nx-19.2.0.tgz", - "integrity": "sha512-IewqV0eGOpp569TSjfQVIQODxkRYKSDTP0e0j20GKkMTvCAmdbJRYZxyTr6Aw6gSM7lEVgK/4yESRO5YidfV2Q==", - "dev": true, - "hasInstallScript": true, + "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/resources": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", + "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", + "license": "Apache-2.0", "dependencies": { - "@nrwl/tao": "19.2.0", - "@yarnpkg/lockfile": "^1.1.0", - "@yarnpkg/parsers": "3.0.0-rc.46", - "@zkochan/js-yaml": "0.0.7", - "axios": "^1.6.0", - "chalk": "^4.1.0", - "cli-cursor": "3.1.0", - "cli-spinners": "2.6.1", - "cliui": "^8.0.1", - "dotenv": "~16.3.1", - "dotenv-expand": "~10.0.0", - "enquirer": "~2.3.6", - "figures": "3.2.0", - "flat": "^5.0.2", - "front-matter": "^4.0.2", - "fs-extra": "^11.1.0", - "ignore": "^5.0.4", - "jest-diff": "^29.4.1", - "jsonc-parser": "3.2.0", - "lines-and-columns": "~2.0.3", - "minimatch": "9.0.3", - "node-machine-id": "1.1.12", - "npm-run-path": "^4.0.1", - "open": "^8.4.0", - "ora": "5.3.0", - "semver": "^7.5.3", - "string-width": "^4.2.3", - "strong-log-transformer": "^2.1.0", - "tar-stream": "~2.2.0", - "tmp": "~0.2.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0", - "yargs": "^17.6.2", - "yargs-parser": "21.1.1" - }, - "bin": { - "nx": "bin/nx.js", - "nx-cloud": "bin/nx-cloud.js" + "@opentelemetry/core": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" }, - "optionalDependencies": { - "@nx/nx-darwin-arm64": "19.2.0", - "@nx/nx-darwin-x64": "19.2.0", - "@nx/nx-freebsd-x64": "19.2.0", - "@nx/nx-linux-arm-gnueabihf": "19.2.0", - "@nx/nx-linux-arm64-gnu": "19.2.0", - "@nx/nx-linux-arm64-musl": "19.2.0", - "@nx/nx-linux-x64-gnu": "19.2.0", - "@nx/nx-linux-x64-musl": "19.2.0", - "@nx/nx-win32-arm64-msvc": "19.2.0", - "@nx/nx-win32-x64-msvc": "19.2.0" + "engines": { + "node": ">=14" }, "peerDependencies": { - "@swc-node/register": "^1.8.0", - "@swc/core": "^1.3.85" - }, - "peerDependenciesMeta": { - "@swc-node/register": { - "optional": true - }, - "@swc/core": { - "optional": true - } + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@nx/js/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, - "bin": { - "semver": "bin/semver.js" + "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/sdk-trace-base": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.26.0.tgz", + "integrity": "sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.26.0", + "@opentelemetry/resources": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" }, "engines": { - "node": ">=10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@nx/js/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, + "node_modules/@opentelemetry/exporter-zipkin": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-zipkin/-/exporter-zipkin-1.26.0.tgz", + "integrity": "sha512-PW5R34n3SJHO4t0UetyHKiXL6LixIqWN6lWncg3eRXhKuT30x+b7m5sDJS0kEWRfHeS+kG7uCw2vBzmB2lk3Dw==", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "@opentelemetry/core": "1.26.0", + "@opentelemetry/resources": "1.26.0", + "@opentelemetry/sdk-trace-base": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" }, "engines": { - "node": ">=8" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@nx/js/node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", - "dev": true, + "node_modules/@opentelemetry/exporter-zipkin/node_modules/@opentelemetry/resources": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", + "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", + "license": "Apache-2.0", "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" + "@opentelemetry/core": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" + "engines": { + "node": ">=14" }, "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@nx/js/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, + "node_modules/@opentelemetry/exporter-zipkin/node_modules/@opentelemetry/sdk-trace-base": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.26.0.tgz", + "integrity": "sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw==", + "license": "Apache-2.0", "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" + "@opentelemetry/core": "1.26.0", + "@opentelemetry/resources": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" }, "engines": { - "node": ">=12" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@nx/linter": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/linter/-/linter-19.3.2.tgz", - "integrity": "sha512-ODGoo0Xcl+zjRrAfcNrMoOk8m/RnDSF7kr1nXLwfNv7VnMm4gcqmwLePfvA/nQZdaNQjaweQ22OOVEAfyrmqFw==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-amqplib": { + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-amqplib/-/instrumentation-amqplib-0.42.0.tgz", + "integrity": "sha512-fiuU6OKsqHJiydHWgTRQ7MnIrJ2lEqsdgFtNIH4LbAUJl/5XmrIeoDzDnox+hfkgWK65jsleFuQDtYb5hW1koQ==", "dependencies": { - "@nx/eslint": "19.3.2" + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/nest": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nest/-/nest-19.2.0.tgz", - "integrity": "sha512-soFP2FpznJuGQ5+MoCdBft2I4ldU0kvkoluGn9bt89D1K3NJGbnp6YS8Hu19nlsgovN27SZXCK0AtVFmxLFfHQ==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-amqplib/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@nestjs/schematics": "^9.1.0", - "@nrwl/nest": "19.2.0", - "@nx/devkit": "19.2.0", - "@nx/eslint": "19.2.0", - "@nx/js": "19.2.0", - "@nx/node": "19.2.0", - "@phenomnomnominal/tsquery": "~5.0.1", - "tslib": "^2.3.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/nest/node_modules/@nrwl/devkit": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.2.0.tgz", - "integrity": "sha512-Ew5AJZkLXJwt15HjaIbHve8FOXmZ3HK8KPqTXqwKHX8jQW+fDUCaSXKe/lCZMNg0RvY+jMNecuC86uGdiIbLMg==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-amqplib/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@opentelemetry/instrumentation-aws-lambda": { + "version": "0.45.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-aws-lambda/-/instrumentation-aws-lambda-0.45.0.tgz", + "integrity": "sha512-22ZnmYftKjFoiqC1k3tu2AVKiXSZv+ohuHWk4V4MdJpPuNkadY624aDkv5BmwDeavDxVFgqE9nGgDM9s3Q94mg==", "dependencies": { - "@nx/devkit": "19.2.0" + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/propagator-aws-xray": "^1.3.1", + "@opentelemetry/resources": "^1.8.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/aws-lambda": "8.10.143" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/nest/node_modules/@nx/devkit": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.2.0.tgz", - "integrity": "sha512-fK3zRUE2SLp9BUomFiyCuAX2E1yfWYE/hKimniscsvM34/u/xLZYVmmZ0/jfpGPbyaonXKZr2KTb7RimX/hyqg==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-aws-lambda/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@nrwl/devkit": "19.2.0", - "ejs": "^3.1.7", - "enquirer": "~2.3.6", - "ignore": "^5.0.4", - "minimatch": "9.0.3", - "semver": "^7.5.3", - "tmp": "~0.2.1", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { - "nx": ">= 17 <= 20" + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/nest/node_modules/@nx/eslint": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/eslint/-/eslint-19.2.0.tgz", - "integrity": "sha512-9OIMntrLDPrQNZjYxOncIX+65r4RhV2dJ3PrjJ9lwCVqJKZGxfCn6f8JK8ubeLoWFPVjKEtfLTHK529vvfXifQ==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-aws-lambda/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@opentelemetry/instrumentation-aws-sdk": { + "version": "0.44.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-aws-sdk/-/instrumentation-aws-sdk-0.44.0.tgz", + "integrity": "sha512-HIWFg4TDQsayceiikOnruMmyQ0SZYW6WiR+wknWwWVLHC3lHTCpAnqzp5V42ckArOdlwHZu2Jvq2GMSM4Myx3w==", "dependencies": { - "@nx/devkit": "19.2.0", - "@nx/js": "19.2.0", - "@nx/linter": "19.2.0", - "semver": "^7.5.3", - "tslib": "^2.3.0", - "typescript": "~5.4.2" + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/propagation-utils": "^0.30.11", + "@opentelemetry/semantic-conventions": "^1.27.0" }, - "peerDependencies": { - "@zkochan/js-yaml": "0.0.7", - "eslint": "^8.0.0 || ^9.0.0" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@zkochan/js-yaml": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/nest/node_modules/@nx/linter": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/linter/-/linter-19.2.0.tgz", - "integrity": "sha512-Rahjy3+OLc4aXT8VNXpwyMozeU4RB6HIQOh5NAdcA6PoOH8cG1VtbyjryIZE8l5HT1hrpI5EkONZt1UXiIGw3w==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-aws-sdk/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@nx/eslint": "19.2.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/nest/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-aws-sdk/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -9764,658 +21356,524 @@ "node": ">=10" } }, - "node_modules/@nx/next": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/next/-/next-19.2.0.tgz", - "integrity": "sha512-GL/5J80rKL5ZWmsyUxiB8aEeKy4XC8Gb+9xhV6RunCF/hOQI+B/ScHQW0N7mgYoD86QL40HhvFIa7qYbKjQwnw==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-bunyan": { + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-bunyan/-/instrumentation-bunyan-0.41.0.tgz", + "integrity": "sha512-NoQS+gcwQ7pzb2PZFyra6bAxDAVXBMmpKxBblEuXJWirGrAksQllg9XTdmqhrwT/KxUYrbVca/lMams7e51ysg==", "dependencies": { - "@babel/plugin-proposal-decorators": "^7.22.7", - "@nrwl/next": "19.2.0", - "@nx/devkit": "19.2.0", - "@nx/eslint": "19.2.0", - "@nx/js": "19.2.0", - "@nx/react": "19.2.0", - "@nx/web": "19.2.0", - "@nx/webpack": "19.2.0", - "@nx/workspace": "19.2.0", - "@svgr/webpack": "^8.0.1", - "chalk": "^4.1.0", - "copy-webpack-plugin": "^10.2.4", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.0", - "ignore": "^5.0.4", - "semver": "^7.5.3", - "tslib": "^2.3.0", - "webpack-merge": "^5.8.0" + "@opentelemetry/api-logs": "^0.53.0", + "@opentelemetry/instrumentation": "^0.53.0", + "@types/bunyan": "1.8.9" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { - "next": ">=14.0.0" + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/next/node_modules/@nrwl/devkit": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.2.0.tgz", - "integrity": "sha512-Ew5AJZkLXJwt15HjaIbHve8FOXmZ3HK8KPqTXqwKHX8jQW+fDUCaSXKe/lCZMNg0RvY+jMNecuC86uGdiIbLMg==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-bunyan/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@nx/devkit": "19.2.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/next/node_modules/@nrwl/tao": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.2.0.tgz", - "integrity": "sha512-9AOwbY/E7OlLCFu+6jhJGUIs+qurE2/3Pldooe7cJPqQmSQeJuVZuL6A2xHtbSG7VsXTq5Yj8dVvK1KmT45SIA==", - "dev": true, - "dependencies": { - "nx": "19.2.0", - "tslib": "^2.3.0" - }, + "node_modules/@opentelemetry/instrumentation-bunyan/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", "bin": { - "tao": "index.js" + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/@nx/next/node_modules/@nrwl/tao/node_modules/nx": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/nx/-/nx-19.2.0.tgz", - "integrity": "sha512-IewqV0eGOpp569TSjfQVIQODxkRYKSDTP0e0j20GKkMTvCAmdbJRYZxyTr6Aw6gSM7lEVgK/4yESRO5YidfV2Q==", - "dev": true, - "hasInstallScript": true, + "node_modules/@opentelemetry/instrumentation-cassandra-driver": { + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-cassandra-driver/-/instrumentation-cassandra-driver-0.41.0.tgz", + "integrity": "sha512-hvTNcC8qjCQEHZTLAlTmDptjsEGqCKpN+90hHH8Nn/GwilGr5TMSwGrlfstdJuZWyw8HAnRUed6bcjvmHHk2Xw==", "dependencies": { - "@nrwl/tao": "19.2.0", - "@yarnpkg/lockfile": "^1.1.0", - "@yarnpkg/parsers": "3.0.0-rc.46", - "@zkochan/js-yaml": "0.0.7", - "axios": "^1.6.0", - "chalk": "^4.1.0", - "cli-cursor": "3.1.0", - "cli-spinners": "2.6.1", - "cliui": "^8.0.1", - "dotenv": "~16.3.1", - "dotenv-expand": "~10.0.0", - "enquirer": "~2.3.6", - "figures": "3.2.0", - "flat": "^5.0.2", - "front-matter": "^4.0.2", - "fs-extra": "^11.1.0", - "ignore": "^5.0.4", - "jest-diff": "^29.4.1", - "jsonc-parser": "3.2.0", - "lines-and-columns": "~2.0.3", - "minimatch": "9.0.3", - "node-machine-id": "1.1.12", - "npm-run-path": "^4.0.1", - "open": "^8.4.0", - "ora": "5.3.0", - "semver": "^7.5.3", - "string-width": "^4.2.3", - "strong-log-transformer": "^2.1.0", - "tar-stream": "~2.2.0", - "tmp": "~0.2.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0", - "yargs": "^17.6.2", - "yargs-parser": "21.1.1" - }, - "bin": { - "nx": "bin/nx.js", - "nx-cloud": "bin/nx-cloud.js" + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0" }, - "optionalDependencies": { - "@nx/nx-darwin-arm64": "19.2.0", - "@nx/nx-darwin-x64": "19.2.0", - "@nx/nx-freebsd-x64": "19.2.0", - "@nx/nx-linux-arm-gnueabihf": "19.2.0", - "@nx/nx-linux-arm64-gnu": "19.2.0", - "@nx/nx-linux-arm64-musl": "19.2.0", - "@nx/nx-linux-x64-gnu": "19.2.0", - "@nx/nx-linux-x64-musl": "19.2.0", - "@nx/nx-win32-arm64-msvc": "19.2.0", - "@nx/nx-win32-x64-msvc": "19.2.0" + "engines": { + "node": ">=14" }, "peerDependencies": { - "@swc-node/register": "^1.8.0", - "@swc/core": "^1.3.85" - }, - "peerDependenciesMeta": { - "@swc-node/register": { - "optional": true - }, - "@swc/core": { - "optional": true - } + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/next/node_modules/@nrwl/webpack": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/webpack/-/webpack-19.2.0.tgz", - "integrity": "sha512-lYj7T967iCgo6fWzZ727oYnmtdKHhM/6A8Li945iWLg+wY/IJdTevaU+0uEvmeSsGFyr0a0DZJ1todk0gHs0Kw==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-cassandra-driver/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@nx/webpack": "19.2.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/next/node_modules/@nrwl/workspace": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-19.2.0.tgz", - "integrity": "sha512-/3p9KNpGHgEVjM5aMFhzdp0Vh+Bt16OnlSA+eSKPd5r0eQyLY+T4zTQ1kjyHGYa/xcN8vsWKEnbZW2fD/HWSng==", - "dev": true, - "dependencies": { - "@nx/workspace": "19.2.0" + "node_modules/@opentelemetry/instrumentation-cassandra-driver/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/@nx/next/node_modules/@nx/devkit": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.2.0.tgz", - "integrity": "sha512-fK3zRUE2SLp9BUomFiyCuAX2E1yfWYE/hKimniscsvM34/u/xLZYVmmZ0/jfpGPbyaonXKZr2KTb7RimX/hyqg==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-connect": { + "version": "0.39.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.39.0.tgz", + "integrity": "sha512-pGBiKevLq7NNglMgqzmeKczF4XQMTOUOTkK8afRHMZMnrK3fcETyTH7lVaSozwiOM3Ws+SuEmXZT7DYrrhxGlg==", "dependencies": { - "@nrwl/devkit": "19.2.0", - "ejs": "^3.1.7", - "enquirer": "~2.3.6", - "ignore": "^5.0.4", - "minimatch": "9.0.3", - "semver": "^7.5.3", - "tmp": "~0.2.1", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/connect": "3.4.36" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { - "nx": ">= 17 <= 20" + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/next/node_modules/@nx/eslint": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/eslint/-/eslint-19.2.0.tgz", - "integrity": "sha512-9OIMntrLDPrQNZjYxOncIX+65r4RhV2dJ3PrjJ9lwCVqJKZGxfCn6f8JK8ubeLoWFPVjKEtfLTHK529vvfXifQ==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-connect/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@nx/devkit": "19.2.0", - "@nx/js": "19.2.0", - "@nx/linter": "19.2.0", - "semver": "^7.5.3", - "tslib": "^2.3.0", - "typescript": "~5.4.2" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, - "peerDependencies": { - "@zkochan/js-yaml": "0.0.7", - "eslint": "^8.0.0 || ^9.0.0" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@zkochan/js-yaml": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/next/node_modules/@nx/linter": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/linter/-/linter-19.2.0.tgz", - "integrity": "sha512-Rahjy3+OLc4aXT8VNXpwyMozeU4RB6HIQOh5NAdcA6PoOH8cG1VtbyjryIZE8l5HT1hrpI5EkONZt1UXiIGw3w==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-connect/node_modules/@types/connect": { + "version": "3.4.36", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.36.tgz", + "integrity": "sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==", "dependencies": { - "@nx/eslint": "19.2.0" - } - }, - "node_modules/@nx/next/node_modules/@nx/nx-darwin-arm64": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.2.0.tgz", - "integrity": "sha512-W+OpGyzr10oaycf4atPc5uH2wN1G6LJGHkWDN3LGSQhoDWuj13idFpjSy6rJ8WxtL8kIvPXq78GEi1yAADsakA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" + "@types/node": "*" } }, - "node_modules/@nx/next/node_modules/@nx/nx-darwin-x64": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.2.0.tgz", - "integrity": "sha512-4l1BDn29R0ugf7ATcGcZGEwK0frZSCtiyXnX3JFq55dNS4Bv3FiZLew7JULjdumXEXr773bH326FQlocLVlcXg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], + "node_modules/@opentelemetry/instrumentation-connect/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">= 10" + "node": ">=10" } }, - "node_modules/@nx/next/node_modules/@nx/nx-freebsd-x64": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.2.0.tgz", - "integrity": "sha512-9zdwLRSkEg/H7bbIVWATn0H8QNgnHaTe23tciZPaBr95J6CXVJWWpC4wn9duURhvbscnqUSSSfKK1f+MSEDTbw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], + "node_modules/@opentelemetry/instrumentation-cucumber": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-cucumber/-/instrumentation-cucumber-0.9.0.tgz", + "integrity": "sha512-4PQNFnIqnA2WM3ZHpr0xhZpHSqJ5xJ6ppTIzZC7wPqe+ZBpj41vG8B6ieqiPfq+im4QdqbYnzLb3rj48GDEN9g==", + "dependencies": { + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@nx/next/node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.2.0.tgz", - "integrity": "sha512-KNVnqRPegJza3kU4q3pY8m0pT8OSQZnLGsDZti6morhXh2sE79f/zeevOrbhf8JnaJfQtyrXfGvjYAiL3+I8bw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@opentelemetry/instrumentation-cucumber/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/next/node_modules/@nx/nx-linux-arm64-gnu": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.2.0.tgz", - "integrity": "sha512-UXIl90l+cDecU17OOLlI+uzbjzQucnNu4Mee67EqE3TyfpSvuU1l3FWZ9sbE0effp8IwKpbL7Gt5KirJKtWzIA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@opentelemetry/instrumentation-cucumber/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">= 10" + "node": ">=10" } }, - "node_modules/@nx/next/node_modules/@nx/nx-linux-arm64-musl": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.2.0.tgz", - "integrity": "sha512-4Z8XO3WljS2GWOL2SQ1p8SRNn2Kn6FU1FWClh7KBzMtpzjsHdmOXenMP9UOGZ6gBnfBIknCEDjE3uJUHmuShGg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@opentelemetry/instrumentation-dataloader": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dataloader/-/instrumentation-dataloader-0.12.0.tgz", + "integrity": "sha512-pnPxatoFE0OXIZDQhL2okF//dmbiWFzcSc8pUg9TqofCLYZySSxDCgQc69CJBo5JnI3Gz1KP+mOjS4WAeRIH4g==", + "dependencies": { + "@opentelemetry/instrumentation": "^0.53.0" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/next/node_modules/@nx/nx-linux-x64-gnu": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.2.0.tgz", - "integrity": "sha512-EwAkZEp0KB99VEPTskW2feCpSKqWScKdRd6UaIM9Vmqqtb5hSk6yR6p0mprjytbDtFVoKQJMOFa35qe+2R8mKQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@opentelemetry/instrumentation-dataloader/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/next/node_modules/@nx/nx-linux-x64-musl": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.2.0.tgz", - "integrity": "sha512-LbFcHe83YZUS/my/8nBxQ2i3JWakcXd7zbzZ0cSAQk6DuJVCUk8PLdgZzhrVcmT82Pv7H0fM/4jgEl+oHGoc/g==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@opentelemetry/instrumentation-dataloader/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">= 10" + "node": ">=10" } }, - "node_modules/@nx/next/node_modules/@nx/nx-win32-arm64-msvc": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.2.0.tgz", - "integrity": "sha512-BxOveRfRCdhuCs2GWbsdzGsjtLC3N+MuUlVaXSWADksF6/QKuCHM/2Kq3RYkLVVtlls6NCBp410RSx/XsbSEug==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], + "node_modules/@opentelemetry/instrumentation-dns": { + "version": "0.39.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dns/-/instrumentation-dns-0.39.0.tgz", + "integrity": "sha512-+iPzvXqVdJa67QBuz2tuP0UI3LS1/cMMo6dS7360DDtOQX+sQzkiN+mo3Omn4T6ZRhkTDw6c7uwsHBcmL31+1g==", + "dependencies": { + "@opentelemetry/instrumentation": "^0.53.0", + "semver": "^7.5.4" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/next/node_modules/@nx/nx-win32-x64-msvc": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.2.0.tgz", - "integrity": "sha512-QiDxtOHIiRka9Bz7tSpBvQgQPrX5grLhoz6miD6LX1WjO56bZIkEAVefGnMc3WZ1PacS1ZECtymHwUy+WpEqAQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], + "node_modules/@opentelemetry/instrumentation-dns/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/next/node_modules/@nx/webpack": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/webpack/-/webpack-19.2.0.tgz", - "integrity": "sha512-/YGLknUIOmYd2r1DOUcyDnHJ4tZeVU6iHnuqUx2zv6pVZYnBs2cW6JjejH6s+n6y8hMQ7H/mXa7RR2eQI2KgaQ==", - "dev": true, - "dependencies": { - "@babel/core": "^7.23.2", - "@nrwl/webpack": "19.2.0", - "@nx/devkit": "19.2.0", - "@nx/js": "19.2.0", - "ajv": "^8.12.0", - "autoprefixer": "^10.4.9", - "babel-loader": "^9.1.2", - "browserslist": "^4.21.4", - "chalk": "^4.1.0", - "copy-webpack-plugin": "^10.2.4", - "css-loader": "^6.4.0", - "css-minimizer-webpack-plugin": "^5.0.0", - "fork-ts-checker-webpack-plugin": "7.2.13", - "less": "4.1.3", - "less-loader": "11.1.0", - "license-webpack-plugin": "^4.0.2", - "loader-utils": "^2.0.3", - "mini-css-extract-plugin": "~2.4.7", - "parse5": "4.0.0", - "postcss": "^8.4.38", - "postcss-import": "~14.1.0", - "postcss-loader": "^6.1.1", - "rxjs": "^7.8.0", - "sass": "^1.42.1", - "sass-loader": "^12.2.0", - "source-map-loader": "^3.0.0", - "style-loader": "^3.3.0", - "stylus": "^0.59.0", - "stylus-loader": "^7.1.0", - "terser-webpack-plugin": "^5.3.3", - "ts-loader": "^9.3.1", - "tsconfig-paths-webpack-plugin": "4.0.0", - "tslib": "^2.3.0", - "webpack": "^5.80.0", - "webpack-dev-server": "^4.9.3", - "webpack-node-externals": "^3.0.0", - "webpack-subresource-integrity": "^5.1.0" + "node_modules/@opentelemetry/instrumentation-dns/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/@nx/next/node_modules/@nx/workspace": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-19.2.0.tgz", - "integrity": "sha512-0wdv8jrGIGcf/ZF4r2/xWz/jrQjwftgLPmh7BawYPFbDZlRXkzb7a4MTJOxXH8QcR3ZJNhRjkFfHRPbB0luf1A==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-fastify": { + "version": "0.40.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fastify/-/instrumentation-fastify-0.40.0.tgz", + "integrity": "sha512-74qj4nG3zPtU7g2x4sm2T4R3/pBMyrYstTsqSZwdlhQk1SD4l8OSY9sPRX1qkhfxOuW3U4KZQAV/Cymb3fB6hg==", "dependencies": { - "@nrwl/workspace": "19.2.0", - "@nx/devkit": "19.2.0", - "chalk": "^4.1.0", - "enquirer": "~2.3.6", - "nx": "19.2.0", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/next/node_modules/@nx/workspace/node_modules/nx": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/nx/-/nx-19.2.0.tgz", - "integrity": "sha512-IewqV0eGOpp569TSjfQVIQODxkRYKSDTP0e0j20GKkMTvCAmdbJRYZxyTr6Aw6gSM7lEVgK/4yESRO5YidfV2Q==", - "dev": true, - "hasInstallScript": true, + "node_modules/@opentelemetry/instrumentation-fastify/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@nrwl/tao": "19.2.0", - "@yarnpkg/lockfile": "^1.1.0", - "@yarnpkg/parsers": "3.0.0-rc.46", - "@zkochan/js-yaml": "0.0.7", - "axios": "^1.6.0", - "chalk": "^4.1.0", - "cli-cursor": "3.1.0", - "cli-spinners": "2.6.1", - "cliui": "^8.0.1", - "dotenv": "~16.3.1", - "dotenv-expand": "~10.0.0", - "enquirer": "~2.3.6", - "figures": "3.2.0", - "flat": "^5.0.2", - "front-matter": "^4.0.2", - "fs-extra": "^11.1.0", - "ignore": "^5.0.4", - "jest-diff": "^29.4.1", - "jsonc-parser": "3.2.0", - "lines-and-columns": "~2.0.3", - "minimatch": "9.0.3", - "node-machine-id": "1.1.12", - "npm-run-path": "^4.0.1", - "open": "^8.4.0", - "ora": "5.3.0", - "semver": "^7.5.3", - "string-width": "^4.2.3", - "strong-log-transformer": "^2.1.0", - "tar-stream": "~2.2.0", - "tmp": "~0.2.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0", - "yargs": "^17.6.2", - "yargs-parser": "21.1.1" - }, - "bin": { - "nx": "bin/nx.js", - "nx-cloud": "bin/nx-cloud.js" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, - "optionalDependencies": { - "@nx/nx-darwin-arm64": "19.2.0", - "@nx/nx-darwin-x64": "19.2.0", - "@nx/nx-freebsd-x64": "19.2.0", - "@nx/nx-linux-arm-gnueabihf": "19.2.0", - "@nx/nx-linux-arm64-gnu": "19.2.0", - "@nx/nx-linux-arm64-musl": "19.2.0", - "@nx/nx-linux-x64-gnu": "19.2.0", - "@nx/nx-linux-x64-musl": "19.2.0", - "@nx/nx-win32-arm64-msvc": "19.2.0", - "@nx/nx-win32-x64-msvc": "19.2.0" + "engines": { + "node": ">=14" }, "peerDependencies": { - "@swc-node/register": "^1.8.0", - "@swc/core": "^1.3.85" + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-fastify/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, - "peerDependenciesMeta": { - "@swc-node/register": { - "optional": true - }, - "@swc/core": { - "optional": true - } + "engines": { + "node": ">=10" } }, - "node_modules/@nx/next/node_modules/array-union": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz", - "integrity": "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-fs": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fs/-/instrumentation-fs-0.15.0.tgz", + "integrity": "sha512-JWVKdNLpu1skqZQA//jKOcKdJC66TWKqa2FUFq70rKohvaSq47pmXlnabNO+B/BvLfmidfiaN35XakT5RyMl2Q==", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.53.0" + }, "engines": { - "node": ">=12" + "node": ">=14" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/next/node_modules/copy-webpack-plugin": { - "version": "10.2.4", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz", - "integrity": "sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-fs/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "fast-glob": "^3.2.7", - "glob-parent": "^6.0.1", - "globby": "^12.0.2", - "normalize-path": "^3.0.0", - "schema-utils": "^4.0.0", - "serialize-javascript": "^6.0.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, "engines": { - "node": ">= 12.20.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">=14" }, "peerDependencies": { - "webpack": "^5.1.0" + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/next/node_modules/cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", - "dev": true, - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" + "node_modules/@opentelemetry/instrumentation-fs/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, "engines": { "node": ">=10" } }, - "node_modules/@nx/next/node_modules/dotenv": { - "version": "16.3.2", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.2.tgz", - "integrity": "sha512-HTlk5nmhkm8F6JcdXvHIzaorzCoziNQT9mGxLPVXW8wJF1TiGSL60ZGB4gHWabHOaMmWmhvk2/lPHfnBiT78AQ==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-generic-pool": { + "version": "0.39.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.39.0.tgz", + "integrity": "sha512-y4v8Y+tSfRB3NNBvHjbjrn7rX/7sdARG7FuK6zR8PGb28CTa0kHpEGCJqvL9L8xkTNvTXo+lM36ajFGUaK1aNw==", + "dependencies": { + "@opentelemetry/instrumentation": "^0.53.0" + }, "engines": { - "node": ">=12" + "node": ">=14" }, - "funding": { - "url": "https://github.com/motdotla/dotenv?sponsor=1" + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/next/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/@nx/next/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-generic-pool/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "is-glob": "^4.0.3" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, "engines": { - "node": ">=10.13.0" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/next/node_modules/globby": { - "version": "12.2.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-12.2.0.tgz", - "integrity": "sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-generic-pool/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@opentelemetry/instrumentation-graphql": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.43.0.tgz", + "integrity": "sha512-aI3YMmC2McGd8KW5du1a2gBA0iOMOGLqg4s9YjzwbjFwjlmMNFSK1P3AIg374GWg823RPUGfVTIgZ/juk9CVOA==", "dependencies": { - "array-union": "^3.0.1", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.7", - "ignore": "^5.1.9", - "merge2": "^1.4.1", - "slash": "^4.0.0" + "@opentelemetry/instrumentation": "^0.53.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=14" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/next/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-graphql/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/next/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-graphql/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/@nx/next/node_modules/mini-css-extract-plugin": { - "version": "2.4.7", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.4.7.tgz", - "integrity": "sha512-euWmddf0sk9Nv1O0gfeeUAvAkoSlWncNLF77C0TP2+WoPvy8mAHKOzMajcCz2dzvyt3CNgxb1obIEVFIRxaipg==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-grpc": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-grpc/-/instrumentation-grpc-0.53.0.tgz", + "integrity": "sha512-Ss338T92yE1UCgr9zXSY3cPuaAy27uQw+wAC5IwsQKCXL5wwkiOgkd+2Ngksa9EGsgUEMwGeHi76bDdHFJ5Rrw==", "dependencies": { - "schema-utils": "^4.0.0" + "@opentelemetry/instrumentation": "0.53.0", + "@opentelemetry/semantic-conventions": "1.27.0" }, "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">=14" }, "peerDependencies": { - "webpack": "^5.0.0" + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/next/node_modules/postcss-loader": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", - "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-grpc/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "cosmiconfig": "^7.0.0", - "klona": "^2.0.5", - "semver": "^7.3.5" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">=14" }, "peerDependencies": { - "postcss": "^7.0.0 || ^8.0.1", - "webpack": "^5.0.0" + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/next/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-grpc/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -10423,184 +21881,142 @@ "node": ">=10" } }, - "node_modules/@nx/next/node_modules/slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@nx/next/node_modules/source-map-loader": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-3.0.2.tgz", - "integrity": "sha512-BokxPoLjyl3iOrgkWaakaxqnelAJSS+0V+De0kKIq6lyWrXuiPgYTGp6z3iHmqljKAaLXwZa+ctD8GccRJeVvg==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-hapi": { + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.41.0.tgz", + "integrity": "sha512-jKDrxPNXDByPlYcMdZjNPYCvw0SQJjN+B1A+QH+sx+sAHsKSAf9hwFiJSrI6C4XdOls43V/f/fkp9ITkHhKFbQ==", "dependencies": { - "abab": "^2.0.5", - "iconv-lite": "^0.6.3", - "source-map-js": "^1.0.1" + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">=14" }, "peerDependencies": { - "webpack": "^5.0.0" + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/next/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-hapi/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, "engines": { - "node": ">=8" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/next/node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-hapi/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">= 6" + "node": ">=10" } }, - "node_modules/@nx/next/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-ioredis": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.43.0.tgz", + "integrity": "sha512-i3Dke/LdhZbiUAEImmRG3i7Dimm/BD7t8pDDzwepSvIQ6s2X6FPia7561gw+64w+nx0+G9X14D7rEfaMEmmjig==", "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/redis-common": "^0.36.2", + "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { - "node": ">=12" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/node": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/node/-/node-19.2.0.tgz", - "integrity": "sha512-d4VnUY5i4nWw2dIkc3OJx4tiBNPsym9Xvq0XyyHjCn3DXTFOH9UiYpVR3kOL/22DeQs8hGOkb3jaSNdi2W8Dlg==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-ioredis/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@nrwl/node": "19.2.0", - "@nx/devkit": "19.2.0", - "@nx/eslint": "19.2.0", - "@nx/jest": "19.2.0", - "@nx/js": "19.2.0", - "tslib": "^2.3.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/node/node_modules/@nrwl/devkit": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.2.0.tgz", - "integrity": "sha512-Ew5AJZkLXJwt15HjaIbHve8FOXmZ3HK8KPqTXqwKHX8jQW+fDUCaSXKe/lCZMNg0RvY+jMNecuC86uGdiIbLMg==", - "dev": true, - "dependencies": { - "@nx/devkit": "19.2.0" + "node_modules/@opentelemetry/instrumentation-ioredis/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/@nx/node/node_modules/@nx/devkit": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.2.0.tgz", - "integrity": "sha512-fK3zRUE2SLp9BUomFiyCuAX2E1yfWYE/hKimniscsvM34/u/xLZYVmmZ0/jfpGPbyaonXKZr2KTb7RimX/hyqg==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-kafkajs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-kafkajs/-/instrumentation-kafkajs-0.3.0.tgz", + "integrity": "sha512-UnkZueYK1ise8FXQeKlpBd7YYUtC7mM8J0wzUSccEfc/G8UqHQqAzIyYCUOUPUKp8GsjLnWOOK/3hJc4owb7Jg==", "dependencies": { - "@nrwl/devkit": "19.2.0", - "ejs": "^3.1.7", - "enquirer": "~2.3.6", - "ignore": "^5.0.4", - "minimatch": "9.0.3", - "semver": "^7.5.3", - "tmp": "~0.2.1", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { - "nx": ">= 17 <= 20" + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/node/node_modules/@nx/eslint": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/eslint/-/eslint-19.2.0.tgz", - "integrity": "sha512-9OIMntrLDPrQNZjYxOncIX+65r4RhV2dJ3PrjJ9lwCVqJKZGxfCn6f8JK8ubeLoWFPVjKEtfLTHK529vvfXifQ==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-kafkajs/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@nx/devkit": "19.2.0", - "@nx/js": "19.2.0", - "@nx/linter": "19.2.0", - "semver": "^7.5.3", - "tslib": "^2.3.0", - "typescript": "~5.4.2" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, - "peerDependencies": { - "@zkochan/js-yaml": "0.0.7", - "eslint": "^8.0.0 || ^9.0.0" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@zkochan/js-yaml": { - "optional": true - } - } - }, - "node_modules/@nx/node/node_modules/@nx/jest": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/jest/-/jest-19.2.0.tgz", - "integrity": "sha512-iJMqfwkIB4T7NRYAQe3nZWFEAQGGblMGcxWczMKEixCIZWcAz4up74eb0H6Yv+tUVOQHrFTm6J1OnrW3BqvOZA==", - "dev": true, - "dependencies": { - "@jest/reporters": "^29.4.1", - "@jest/test-result": "^29.4.1", - "@nrwl/jest": "19.2.0", - "@nx/devkit": "19.2.0", - "@nx/js": "19.2.0", - "@phenomnomnominal/tsquery": "~5.0.1", - "chalk": "^4.1.0", - "identity-obj-proxy": "3.0.0", - "jest-config": "^29.4.1", - "jest-resolve": "^29.4.1", - "jest-util": "^29.4.1", - "minimatch": "9.0.3", - "resolve.exports": "1.1.0", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" - } - }, - "node_modules/@nx/node/node_modules/@nx/linter": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/linter/-/linter-19.2.0.tgz", - "integrity": "sha512-Rahjy3+OLc4aXT8VNXpwyMozeU4RB6HIQOh5NAdcA6PoOH8cG1VtbyjryIZE8l5HT1hrpI5EkONZt1UXiIGw3w==", - "dev": true, - "dependencies": { - "@nx/eslint": "19.2.0" + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/node/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-kafkajs/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -10608,251 +22024,236 @@ "node": ">=10" } }, - "node_modules/@nx/nx-darwin-arm64": { - "version": "19.4.4", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.4.4.tgz", - "integrity": "sha512-qmPz1PYsV1zlpSWBHLmy3J7Hw5H5pPWAps6ObcxwUuQwli6uySi4OKFKCLnmWgi1ICvB2NviChK45OIDtxJ2Iw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/nx-darwin-x64": { - "version": "19.4.4", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.4.4.tgz", - "integrity": "sha512-/M+KQrjaIovhTP81BGMQ3AezSy9ZYhubXg7G3ltcMfox07yw5Pj10Ip9ZwkE5zF6CuJXNAoLesmNhbqMXodsag==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], + "node_modules/@opentelemetry/instrumentation-knex": { + "version": "0.40.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-knex/-/instrumentation-knex-0.40.0.tgz", + "integrity": "sha512-6jka2jfX8+fqjEbCn6hKWHVWe++mHrIkLQtaJqUkBt3ZBs2xn1+y0khxiDS0v/mNb0bIKDJWwtpKFfsQDM1Geg==", + "dependencies": { + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/nx-freebsd-x64": { - "version": "19.4.4", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.4.4.tgz", - "integrity": "sha512-PegR8GgHn24/eXqVRme3iRPHVYmH94rSBNoKOrWHJ8RTA/Dw+ZoOmhdLssOSs6z7JQ0S63MKo8x/HILI3+WyXw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], + "node_modules/@opentelemetry/instrumentation-knex/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "19.4.4", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.4.4.tgz", - "integrity": "sha512-6Yz0aTR8XE/MXpjbQ5HRlGcngYXUv156tJeynO8lyiZ0HK1RkUq+MsbSLw0zvqBUljWQwQwK20rsAx9AUqM9kQ==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@opentelemetry/instrumentation-knex/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">= 10" + "node": ">=10" } }, - "node_modules/@nx/nx-linux-arm64-gnu": { - "version": "19.4.4", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.4.4.tgz", - "integrity": "sha512-33zZ+ytnRgXnx7Ls8hoEtXSRDJF8PuZaJBbGocrpfXku58fHj7+AJtQZWjQe3STGJuVUbmIZNfGJ/st+3Zeccg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@opentelemetry/instrumentation-koa": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.43.0.tgz", + "integrity": "sha512-lDAhSnmoTIN6ELKmLJBplXzT/Jqs5jGZehuG22EdSMaTwgjMpxMDI1YtlKEhiWPWkrz5LUsd0aOO0ZRc9vn3AQ==", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/nx-linux-arm64-musl": { - "version": "19.4.4", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.4.4.tgz", - "integrity": "sha512-00qPmFs0LGmeudYSwhcuMLNRb4/Eaaf6SMkqdbJU2iKEbq6rY7clORAJlOn3FQPmxi/j2uEfbkONMfO8pqsu3A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@opentelemetry/instrumentation-koa/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/nx-linux-x64-gnu": { - "version": "19.4.4", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.4.4.tgz", - "integrity": "sha512-R7wIdVzSVvKTsLPRBIo9eouEik4ZiYhR4eG2XybhdWNhv8vC+VzOdbWWUyxQzzxj2Lo5o7d4UlFxvblTftQJJw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@opentelemetry/instrumentation-koa/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">= 10" + "node": ">=10" } }, - "node_modules/@nx/nx-linux-x64-musl": { - "version": "19.4.4", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.4.4.tgz", - "integrity": "sha512-2Xu71Jwa0Ti2fwvvGXb21kpMaga4eZeS5+2MKMJnE2hzW6NWSx68xnw6TPJIdEKbkJUHWk32vF4vob79puunHQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@opentelemetry/instrumentation-lru-memoizer": { + "version": "0.40.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-lru-memoizer/-/instrumentation-lru-memoizer-0.40.0.tgz", + "integrity": "sha512-21xRwZsEdMPnROu/QsaOIODmzw59IYpGFmuC4aFWvMj6stA8+Ei1tX67nkarJttlNjoM94um0N4X26AD7ff54A==", + "dependencies": { + "@opentelemetry/instrumentation": "^0.53.0" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/nx-win32-arm64-msvc": { - "version": "19.4.4", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.4.4.tgz", - "integrity": "sha512-ztF1MhxB+IdLIqwx1DbAdqJvTHrFstUavinFTxTaGBTu9AtFwziRP567XB8TiyzyCSmY9H8JJHGByQ0Mr6cUbQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], + "node_modules/@opentelemetry/instrumentation-lru-memoizer/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/nx-win32-x64-msvc": { - "version": "19.4.4", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.4.4.tgz", - "integrity": "sha512-AdcjRiQ3MXlhpwCt5QprxtwAvG+VcYymF6ZI37aHZ9EkSEkD77iFgpkAhfhhHEgbTmnGBcMZMwJ5MENXjwdW8A==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], + "node_modules/@opentelemetry/instrumentation-lru-memoizer/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">= 10" + "node": ">=10" } }, - "node_modules/@nx/react": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/react/-/react-19.2.0.tgz", - "integrity": "sha512-G9PSRnX8X4lCaJ7808xwL+kfZ/LWLi/Rph6mGJFnSS+0Y89WyHNcQTIWdvzabQy2RwXgi/eDy1FToDx/5rTZbA==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-memcached": { + "version": "0.39.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-memcached/-/instrumentation-memcached-0.39.0.tgz", + "integrity": "sha512-WfwvKAZ9I1qILRP5EUd88HQjwAAL+trXpCpozjBi4U6a0A07gB3fZ5PFAxbXemSjF5tHk9KVoROnqHvQ+zzFSQ==", "dependencies": { - "@nrwl/react": "19.2.0", - "@nx/devkit": "19.2.0", - "@nx/eslint": "19.2.0", - "@nx/js": "19.2.0", - "@nx/web": "19.2.0", - "@phenomnomnominal/tsquery": "~5.0.1", - "@svgr/webpack": "^8.0.1", - "chalk": "^4.1.0", - "file-loader": "^6.2.0", - "minimatch": "9.0.3", - "tslib": "^2.3.0" + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/memcached": "^2.2.6" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/react/node_modules/@nrwl/devkit": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.2.0.tgz", - "integrity": "sha512-Ew5AJZkLXJwt15HjaIbHve8FOXmZ3HK8KPqTXqwKHX8jQW+fDUCaSXKe/lCZMNg0RvY+jMNecuC86uGdiIbLMg==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-memcached/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@nx/devkit": "19.2.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/react/node_modules/@nx/devkit": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.2.0.tgz", - "integrity": "sha512-fK3zRUE2SLp9BUomFiyCuAX2E1yfWYE/hKimniscsvM34/u/xLZYVmmZ0/jfpGPbyaonXKZr2KTb7RimX/hyqg==", - "dev": true, - "dependencies": { - "@nrwl/devkit": "19.2.0", - "ejs": "^3.1.7", - "enquirer": "~2.3.6", - "ignore": "^5.0.4", - "minimatch": "9.0.3", - "semver": "^7.5.3", - "tmp": "~0.2.1", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" + "node_modules/@opentelemetry/instrumentation-memcached/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, - "peerDependencies": { - "nx": ">= 17 <= 20" + "engines": { + "node": ">=10" } }, - "node_modules/@nx/react/node_modules/@nx/eslint": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/eslint/-/eslint-19.2.0.tgz", - "integrity": "sha512-9OIMntrLDPrQNZjYxOncIX+65r4RhV2dJ3PrjJ9lwCVqJKZGxfCn6f8JK8ubeLoWFPVjKEtfLTHK529vvfXifQ==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-mongodb": { + "version": "0.47.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.47.0.tgz", + "integrity": "sha512-yqyXRx2SulEURjgOQyJzhCECSh5i1uM49NUaq9TqLd6fA7g26OahyJfsr9NE38HFqGRHpi4loyrnfYGdrsoVjQ==", "dependencies": { - "@nx/devkit": "19.2.0", - "@nx/js": "19.2.0", - "@nx/linter": "19.2.0", - "semver": "^7.5.3", - "tslib": "^2.3.0", - "typescript": "~5.4.2" + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/sdk-metrics": "^1.9.1", + "@opentelemetry/semantic-conventions": "^1.27.0" }, - "peerDependencies": { - "@zkochan/js-yaml": "0.0.7", - "eslint": "^8.0.0 || ^9.0.0" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@zkochan/js-yaml": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/react/node_modules/@nx/linter": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/linter/-/linter-19.2.0.tgz", - "integrity": "sha512-Rahjy3+OLc4aXT8VNXpwyMozeU4RB6HIQOh5NAdcA6PoOH8cG1VtbyjryIZE8l5HT1hrpI5EkONZt1UXiIGw3w==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-mongodb/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@nx/eslint": "19.2.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/react/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-mongodb/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -10860,55 +22261,47 @@ "node": ">=10" } }, - "node_modules/@nx/web": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/web/-/web-19.2.0.tgz", - "integrity": "sha512-iMRwDjkU7GfJql4wT6pGCimFoHYV/2bQuI/N9b9T3NEL9sk5tlMqlik6bbSGtje8XoUAbxaQrTpr9pJeaUPYwg==", - "dev": true, - "dependencies": { - "@nrwl/web": "19.2.0", - "@nx/devkit": "19.2.0", - "@nx/js": "19.2.0", - "chalk": "^4.1.0", - "detect-port": "^1.5.1", - "http-server": "^14.1.0", - "tslib": "^2.3.0" - } - }, - "node_modules/@nx/web/node_modules/@nrwl/devkit": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.2.0.tgz", - "integrity": "sha512-Ew5AJZkLXJwt15HjaIbHve8FOXmZ3HK8KPqTXqwKHX8jQW+fDUCaSXKe/lCZMNg0RvY+jMNecuC86uGdiIbLMg==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-mongoose": { + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.42.0.tgz", + "integrity": "sha512-AnWv+RaR86uG3qNEMwt3plKX1ueRM7AspfszJYVkvkehiicC3bHQA6vWdb6Zvy5HAE14RyFbu9+2hUUjR2NSyg==", "dependencies": { - "@nx/devkit": "19.2.0" + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/web/node_modules/@nx/devkit": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.2.0.tgz", - "integrity": "sha512-fK3zRUE2SLp9BUomFiyCuAX2E1yfWYE/hKimniscsvM34/u/xLZYVmmZ0/jfpGPbyaonXKZr2KTb7RimX/hyqg==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-mongoose/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@nrwl/devkit": "19.2.0", - "ejs": "^3.1.7", - "enquirer": "~2.3.6", - "ignore": "^5.0.4", - "minimatch": "9.0.3", - "semver": "^7.5.3", - "tmp": "~0.2.1", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { - "nx": ">= 17 <= 20" + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/web/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-mongoose/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -10916,1314 +22309,1149 @@ "node": ">=10" } }, - "node_modules/@nx/webpack": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nx/webpack/-/webpack-19.6.3.tgz", - "integrity": "sha512-AUz4SPdD6LtIh+hB8AJX7GdzLHmlj5aU/yXp4UTKF5DZlha4NphN8YIP+NN56nCgEZMxM8txp7U0zytqhcFP1Q==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-mysql": { + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.41.0.tgz", + "integrity": "sha512-jnvrV6BsQWyHS2qb2fkfbfSb1R/lmYwqEZITwufuRl37apTopswu9izc0b1CYRp/34tUG/4k/V39PND6eyiNvw==", "dependencies": { - "@babel/core": "^7.23.2", - "@module-federation/enhanced": "^0.2.3", - "@module-federation/sdk": "^0.2.3", - "@nrwl/webpack": "19.6.3", - "@nx/devkit": "19.6.3", - "@nx/js": "19.6.3", - "@phenomnomnominal/tsquery": "~5.0.1", - "ajv": "^8.12.0", - "autoprefixer": "^10.4.9", - "babel-loader": "^9.1.2", - "browserslist": "^4.21.4", - "chalk": "^4.1.0", - "copy-webpack-plugin": "^10.2.4", - "css-loader": "^6.4.0", - "css-minimizer-webpack-plugin": "^5.0.0", - "express": "^4.19.2", - "fork-ts-checker-webpack-plugin": "7.2.13", - "http-proxy-middleware": "^3.0.0", - "less": "4.1.3", - "less-loader": "11.1.0", - "license-webpack-plugin": "^4.0.2", - "loader-utils": "^2.0.3", - "mini-css-extract-plugin": "~2.4.7", - "parse5": "4.0.0", - "postcss": "^8.4.38", - "postcss-import": "~14.1.0", - "postcss-loader": "^6.1.1", - "rxjs": "^7.8.0", - "sass": "^1.42.1", - "sass-loader": "^12.2.0", - "source-map-loader": "^5.0.0", - "style-loader": "^3.3.0", - "stylus": "^0.59.0", - "stylus-loader": "^7.1.0", - "terser-webpack-plugin": "^5.3.3", - "ts-loader": "^9.3.1", - "tsconfig-paths-webpack-plugin": "4.0.0", - "tslib": "^2.3.0", - "webpack": "^5.80.0", - "webpack-dev-server": "^5.0.4", - "webpack-node-externals": "^3.0.0", - "webpack-subresource-integrity": "^5.1.0" + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/mysql": "2.15.26" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/webpack/node_modules/@nrwl/devkit": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.6.3.tgz", - "integrity": "sha512-zrAboArNfrEMjimBl/0YeM08HfjqOEG/VHdCHKO+5QMDg65w7vDJ2flwyNhlmnMl8BMJSy9fNo6PNGhboOf3+w==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-mysql/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@nx/devkit": "19.6.3" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/webpack/node_modules/@nrwl/js": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nrwl/js/-/js-19.6.3.tgz", - "integrity": "sha512-Z5tYcUQNfgmNFMJpGmZd6fB0D1pCKNiS3aci2gxHAUIP0Z5cznTyCuzcJSIRx3uMHENhxXwzLwv2l/cqOqnD8A==", - "dev": true, - "dependencies": { - "@nx/js": "19.6.3" + "node_modules/@opentelemetry/instrumentation-mysql/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/@nx/webpack/node_modules/@nrwl/tao": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.6.3.tgz", - "integrity": "sha512-j4vPU87yBhTrdyPFSNhlUkN29w4BQ+M14khT8PFGe+Y26gHMxNRNXNFUCwtVARYAc6IwxS8Uvlwy7AwXG2ETPA==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-mysql2": { + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.41.0.tgz", + "integrity": "sha512-REQB0x+IzVTpoNgVmy5b+UnH1/mDByrneimP6sbDHkp1j8QOl1HyWOrBH/6YWR0nrbU3l825Em5PlybjT3232g==", "dependencies": { - "nx": "19.6.3", - "tslib": "^2.3.0" + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@opentelemetry/sql-common": "^0.40.1" }, - "bin": { - "tao": "index.js" + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/webpack/node_modules/@nrwl/workspace": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-19.6.3.tgz", - "integrity": "sha512-NGJ6Mxpw8U6tZRT4ijGzqthr1NMgT/22uteu4otetLEdlqkh1VvLqJC9tjzLkYXmXF9QuoUrkwQib/HafsZmkg==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-mysql2/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@nx/workspace": "19.6.3" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/webpack/node_modules/@nx/devkit": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.6.3.tgz", - "integrity": "sha512-/d8Z5/Cy/H/1rIHxW3VjeK5dlvHwRxRj8rCm8/sj5Pz3GmGX03uuEK+J/p+VlP3gP8dAYMgZu3ImeqTAu6rBtw==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-mysql2/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@opentelemetry/instrumentation-net": { + "version": "0.39.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-net/-/instrumentation-net-0.39.0.tgz", + "integrity": "sha512-rixHoODfI/Cx1B0mH1BpxCT0bRSxktuBDrt9IvpT2KSEutK5hR0RsRdgdz/GKk+BQ4u+IG6godgMSGwNQCueEA==", "dependencies": { - "@nrwl/devkit": "19.6.3", - "ejs": "^3.1.7", - "enquirer": "~2.3.6", - "ignore": "^5.0.4", - "minimatch": "9.0.3", - "semver": "^7.5.3", - "tmp": "~0.2.1", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { - "nx": ">= 17 <= 20" + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/webpack/node_modules/@nx/js": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nx/js/-/js-19.6.3.tgz", - "integrity": "sha512-Ip7DseodvJSRM2sKhUjNMlNLegBtsB1u6TuQUiYOJa2FnIGzXETT2HuDMxBcL+u23xDTNyNvifNZ92mFywa00Q==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-net/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@babel/core": "^7.23.2", - "@babel/plugin-proposal-decorators": "^7.22.7", - "@babel/plugin-transform-class-properties": "^7.22.5", - "@babel/plugin-transform-runtime": "^7.23.2", - "@babel/preset-env": "^7.23.2", - "@babel/preset-typescript": "^7.22.5", - "@babel/runtime": "^7.22.6", - "@nrwl/js": "19.6.3", - "@nx/devkit": "19.6.3", - "@nx/workspace": "19.6.3", - "babel-plugin-const-enum": "^1.0.1", - "babel-plugin-macros": "^2.8.0", - "babel-plugin-transform-typescript-metadata": "^0.3.1", - "chalk": "^4.1.0", - "columnify": "^1.6.0", - "detect-port": "^1.5.1", - "fast-glob": "3.2.7", - "fs-extra": "^11.1.0", - "ignore": "^5.0.4", - "js-tokens": "^4.0.0", - "jsonc-parser": "3.2.0", - "minimatch": "9.0.3", - "npm-package-arg": "11.0.1", - "npm-run-path": "^4.0.1", - "ora": "5.3.0", - "semver": "^7.5.3", - "source-map-support": "0.5.19", - "ts-node": "10.9.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { - "verdaccio": "^5.0.4" + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-net/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, - "peerDependenciesMeta": { - "verdaccio": { - "optional": true - } + "engines": { + "node": ">=10" } }, - "node_modules/@nx/webpack/node_modules/@nx/nx-darwin-arm64": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.6.3.tgz", - "integrity": "sha512-P7WlX5YDZOABAlyfpR6eObigQTNuUuy3iJVUuGwp1Nuo3VPMPkpK1GMWKWLwOR9+2jGnF5MzuqWHk7CdF33uqQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], + "node_modules/@opentelemetry/instrumentation-pg": { + "version": "0.46.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.46.0.tgz", + "integrity": "sha512-PLbYYC7EIoigh9uzhBrDjyL4yhH9akjV2Mln3ci9+lD7p9HE5nUUgYCgcUasyr4bz99c8xy9ErzKLt38Y7Kodg==", + "dependencies": { + "@opentelemetry/core": "^1.26.0", + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "1.27.0", + "@opentelemetry/sql-common": "^0.40.1", + "@types/pg": "8.6.1", + "@types/pg-pool": "2.0.6" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/webpack/node_modules/@nx/nx-darwin-x64": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.6.3.tgz", - "integrity": "sha512-HF28dPc7h0EmEGYJWJUPA3cBvjXyHbSbGQP5oP885gos9zcyVBjQ2kdJEUZDNMHB9KlZraeXbmV1umFkikjn6A==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], + "node_modules/@opentelemetry/instrumentation-pg/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/webpack/node_modules/@nx/nx-freebsd-x64": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.6.3.tgz", - "integrity": "sha512-y52dWxQ/x2ccyPqA4Vou4CnTqZX4gr/wV9myJX56G1CyEpWasmcqmPFeOKQd6dj7llGM/KJ/4Gz29RYxcWffcA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], + "node_modules/@opentelemetry/instrumentation-pg/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">= 10" + "node": ">=10" } }, - "node_modules/@nx/webpack/node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.6.3.tgz", - "integrity": "sha512-RneCg1tglLbP4cmGnGUs4FgZVT0aOA9wA53tO4IbyxLnlRXNY9OE452YLgqv3H7sLtNjsey2Lkq1seBHtr3p/Q==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@opentelemetry/instrumentation-pino": { + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pino/-/instrumentation-pino-0.42.0.tgz", + "integrity": "sha512-SoX6FzucBfTuFNMZjdurJhcYWq2ve8/LkhmyVLUW31HpIB45RF1JNum0u4MkGisosDmXlK4njomcgUovShI+WA==", + "dependencies": { + "@opentelemetry/api-logs": "^0.53.0", + "@opentelemetry/core": "^1.25.0", + "@opentelemetry/instrumentation": "^0.53.0" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/webpack/node_modules/@nx/nx-linux-arm64-gnu": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.6.3.tgz", - "integrity": "sha512-Y+vgqaxrPQUEtCzxK25QY4ahO90l0eWgVrvCALexGmq0lW41JrVpfTTsbH/BAPLsx+u8A/GPAQAgrmg7d5lSxw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@opentelemetry/instrumentation-pino/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/webpack/node_modules/@nx/nx-linux-arm64-musl": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.6.3.tgz", - "integrity": "sha512-o/99DBgafbjiJ4e9KFxaldvtlZta/FdzEiQQW+SQQ0JGSYlLCZZ8tIT6t3edV7cmG+gQLNMwolJzgpY53O9wjA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@opentelemetry/instrumentation-pino/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">= 10" + "node": ">=10" } }, - "node_modules/@nx/webpack/node_modules/@nx/nx-linux-x64-gnu": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.6.3.tgz", - "integrity": "sha512-ppp0NBOhwJ39U1vR7h8jhFSfiur6CZPSUYjXsV44BlaNGc1wHZ+7FDXhzOTokgTNWHavYgYOJuVan5LtTLKJkA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@opentelemetry/instrumentation-redis": { + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis/-/instrumentation-redis-0.42.0.tgz", + "integrity": "sha512-jZBoqve0rEC51q0HuhjtZVq1DtUvJHzEJ3YKGvzGar2MU1J4Yt5+pQAQYh1W4jSoDyKeaI4hyeUdWM5N0c2lqA==", + "dependencies": { + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/redis-common": "^0.36.2", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/webpack/node_modules/@nx/nx-linux-x64-musl": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.6.3.tgz", - "integrity": "sha512-H7xgsT5OTtVYCXjXBLZu28v+rIInhbUggrgVJ2iQJFGBT2A2qmvGmDJdcDz8+K90ku1f4VuWmm8i+TEyDEcBuQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@opentelemetry/instrumentation-redis-4": { + "version": "0.42.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis-4/-/instrumentation-redis-4-0.42.1.tgz", + "integrity": "sha512-xm17LJhDfQzQo4wkM/zFwh6wk3SNN/FBFGkscI9Kj4efrb/o5p8Z3yE6ldBPNdIZ6RAwg2p3DL7fvE3DuUDJWA==", + "dependencies": { + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/redis-common": "^0.36.2", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/webpack/node_modules/@nx/nx-win32-arm64-msvc": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.6.3.tgz", - "integrity": "sha512-o9O6lSmx67zUnqOtlDC4YpC++fiUkixgIsQEG8J/2jdNgAATqOtERcqCNra/uke/Q94Vht2tVXjXF3uj92APhw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], + "node_modules/@opentelemetry/instrumentation-redis-4/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/webpack/node_modules/@nx/nx-win32-x64-msvc": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.6.3.tgz", - "integrity": "sha512-6NQhc7jYQ/sqPt5fDy8C+br73kTd5jhb8ZkPtEy2Amr1aA1K9SAxZAYfyvxLHS2z1nBEelNFgXe6HBmDX92FkA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], + "node_modules/@opentelemetry/instrumentation-redis-4/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">= 10" + "node": ">=10" } }, - "node_modules/@nx/webpack/node_modules/@nx/workspace": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-19.6.3.tgz", - "integrity": "sha512-DTvVJZuXHQd+F4M9JkTHGjLQADQZfUTs/h+v9/NC+YQHml8eixaNXSSvoHQcvBqO8HntbJz5LAJfQuiJ4IGBKw==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-redis/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@nrwl/workspace": "19.6.3", - "@nx/devkit": "19.6.3", - "chalk": "^4.1.0", - "enquirer": "~2.3.6", - "nx": "19.6.3", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/webpack/node_modules/@types/retry": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", - "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", - "dev": true - }, - "node_modules/@nx/webpack/node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true + "node_modules/@opentelemetry/instrumentation-redis/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } }, - "node_modules/@nx/webpack/node_modules/array-union": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz", - "integrity": "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-restify": { + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-restify/-/instrumentation-restify-0.41.0.tgz", + "integrity": "sha512-gKEo+X/wVKUBuD2WDDlF7SlDNBHMWjSQoLxFCsGqeKgHR0MGtwMel8uaDGg9LJ83nKqYy+7Vl/cDFxjba6H+/w==", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, "engines": { - "node": ">=12" + "node": ">=14" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/webpack/node_modules/copy-webpack-plugin": { - "version": "10.2.4", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz", - "integrity": "sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-restify/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "fast-glob": "^3.2.7", - "glob-parent": "^6.0.1", - "globby": "^12.0.2", - "normalize-path": "^3.0.0", - "schema-utils": "^4.0.0", - "serialize-javascript": "^6.0.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, "engines": { - "node": ">= 12.20.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">=14" }, "peerDependencies": { - "webpack": "^5.1.0" + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/webpack/node_modules/cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", - "dev": true, - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" + "node_modules/@opentelemetry/instrumentation-restify/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, "engines": { "node": ">=10" } }, - "node_modules/@nx/webpack/node_modules/define-lazy-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-router": { + "version": "0.40.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-router/-/instrumentation-router-0.40.0.tgz", + "integrity": "sha512-bRo4RaclGFiKtmv/N1D0MuzO7DuxbeqMkMCbPPng6mDwzpHAMpHz/K/IxJmF+H1Hi/NYXVjCKvHGClageLe9eA==", + "dependencies": { + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, "engines": { - "node": ">=12" + "node": ">=14" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/webpack/node_modules/dotenv-expand": { - "version": "11.0.6", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.6.tgz", - "integrity": "sha512-8NHi73otpWsZGBSZwwknTXS5pqMOrk9+Ssrna8xCaxkzEpU9OTf9R5ArQGVw03//Zmk9MOwLPng9WwndvpAJ5g==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-router/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "dotenv": "^16.4.4" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, "engines": { - "node": ">=12" + "node": ">=14" }, - "funding": { - "url": "https://dotenvx.com" + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/webpack/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "node_modules/@opentelemetry/instrumentation-router/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } }, - "node_modules/@nx/webpack/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-socket.io": { + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-socket.io/-/instrumentation-socket.io-0.42.0.tgz", + "integrity": "sha512-xB5tdsBzuZyicQTO3hDzJIpHQ7V1BYJ6vWPWgl19gWZDBdjEGc3HOupjkd3BUJyDoDhbMEHGk2nNlkUU99EfkA==", "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0" }, - "bin": { - "glob": "dist/esm/bin.mjs" + "engines": { + "node": ">=14" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/webpack/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-socket.io/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "is-glob": "^4.0.3" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, "engines": { - "node": ">=10.13.0" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/webpack/node_modules/glob/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-socket.io/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@opentelemetry/instrumentation-tedious": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.14.0.tgz", + "integrity": "sha512-ofq7pPhSqvRDvD2FVx3RIWPj76wj4QubfrbqJtEx0A+fWoaYxJOCIQ92tYJh28elAmjMmgF/XaYuJuBhBv5J3A==", "dependencies": { - "brace-expansion": "^2.0.1" + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/tedious": "^4.0.14" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=14" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/webpack/node_modules/globby": { - "version": "12.2.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-12.2.0.tgz", - "integrity": "sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-tedious/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "array-union": "^3.0.1", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.7", - "ignore": "^5.1.9", - "merge2": "^1.4.1", - "slash": "^4.0.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=14" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/webpack/node_modules/http-proxy-middleware": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-3.0.0.tgz", - "integrity": "sha512-36AV1fIaI2cWRzHo+rbcxhe3M3jUDCNzc4D5zRl57sEWRAxdXYtw7FSQKYY6PDKssiAKjLYypbssHk+xs/kMXw==", - "dev": true, - "dependencies": { - "@types/http-proxy": "^1.17.10", - "debug": "^4.3.4", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.5" + "node_modules/@opentelemetry/instrumentation-tedious/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" } }, - "node_modules/@nx/webpack/node_modules/ipaddr.js": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", - "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-undici": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.6.0.tgz", + "integrity": "sha512-ABJBhm5OdhGmbh0S/fOTE4N69IZ00CsHC5ijMYfzbw3E5NwLgpQk5xsljaECrJ8wz1SfXbO03FiSuu5AyRAkvQ==", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.53.0" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.7.0" } }, - "node_modules/@nx/webpack/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-undici/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, "engines": { - "node": ">=8" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/webpack/node_modules/is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-undici/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@nx/webpack/node_modules/is-wsl": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", - "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-winston": { + "version": "0.40.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-winston/-/instrumentation-winston-0.40.0.tgz", + "integrity": "sha512-eMk2tKl86YJ8/yHvtDbyhrE35/R0InhO9zuHTflPx8T0+IvKVUhPV71MsJr32sImftqeOww92QHt4Jd+a5db4g==", "dependencies": { - "is-inside-container": "^1.0.0" + "@opentelemetry/api-logs": "^0.53.0", + "@opentelemetry/instrumentation": "^0.53.0" }, "engines": { - "node": ">=16" + "node": ">=14" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/webpack/node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, + "node_modules/@opentelemetry/instrumentation-winston/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@isaacs/cliui": "^8.0.2" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": ">=14" }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/webpack/node_modules/memfs": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.11.1.tgz", - "integrity": "sha512-LZcMTBAgqUUKNXZagcZxvXXfgF1bHX7Y7nQ0QyEiNbRJgE29GhgPd8Yna1VQcLlPiHt/5RFJMWYN9Uv/VPNvjQ==", - "dev": true, - "dependencies": { - "@jsonjoy.com/json-pack": "^1.0.3", - "@jsonjoy.com/util": "^1.3.0", - "tree-dump": "^1.0.1", - "tslib": "^2.0.0" + "node_modules/@opentelemetry/instrumentation-winston/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">= 4.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" + "node": ">=10" } }, - "node_modules/@nx/webpack/node_modules/mini-css-extract-plugin": { - "version": "2.4.7", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.4.7.tgz", - "integrity": "sha512-euWmddf0sk9Nv1O0gfeeUAvAkoSlWncNLF77C0TP2+WoPvy8mAHKOzMajcCz2dzvyt3CNgxb1obIEVFIRxaipg==", - "dev": true, + "node_modules/@opentelemetry/otlp-exporter-base": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.53.0.tgz", + "integrity": "sha512-UCWPreGQEhD6FjBaeDuXhiMf6kkBODF0ZQzrk/tuQcaVDJ+dDQ/xhJp192H9yWnKxVpEjFrSSLnpqmX4VwX+eA==", "dependencies": { - "schema-utils": "^4.0.0" + "@opentelemetry/core": "1.26.0", + "@opentelemetry/otlp-transformer": "0.53.0" }, "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">=14" }, "peerDependencies": { - "webpack": "^5.0.0" + "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@nx/webpack/node_modules/nx": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/nx/-/nx-19.6.3.tgz", - "integrity": "sha512-JbgrEKaIBvTfhw3mG3GeyyzJHBAMfuQkMNrxxIto1fn94gxdjXdMfqUnAzrW6xRAt5OEEU+rf7v2OA3vEXYc3A==", - "dev": true, - "hasInstallScript": true, + "node_modules/@opentelemetry/otlp-grpc-exporter-base": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.53.0.tgz", + "integrity": "sha512-F7RCN8VN+lzSa4fGjewit8Z5fEUpY/lmMVy5EWn2ZpbAabg3EE3sCLuTNfOiooNGnmvzimUPruoeqeko/5/TzQ==", "dependencies": { - "@napi-rs/wasm-runtime": "0.2.4", - "@nrwl/tao": "19.6.3", - "@yarnpkg/lockfile": "^1.1.0", - "@yarnpkg/parsers": "3.0.0-rc.46", - "@zkochan/js-yaml": "0.0.7", - "axios": "^1.7.4", - "chalk": "^4.1.0", - "cli-cursor": "3.1.0", - "cli-spinners": "2.6.1", - "cliui": "^8.0.1", - "dotenv": "~16.4.5", - "dotenv-expand": "~11.0.6", - "enquirer": "~2.3.6", - "figures": "3.2.0", - "flat": "^5.0.2", - "front-matter": "^4.0.2", - "fs-extra": "^11.1.0", - "ignore": "^5.0.4", - "jest-diff": "^29.4.1", - "jsonc-parser": "3.2.0", - "lines-and-columns": "~2.0.3", - "minimatch": "9.0.3", - "node-machine-id": "1.1.12", - "npm-run-path": "^4.0.1", - "open": "^8.4.0", - "ora": "5.3.0", - "semver": "^7.5.3", - "string-width": "^4.2.3", - "strong-log-transformer": "^2.1.0", - "tar-stream": "~2.2.0", - "tmp": "~0.2.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0", - "yargs": "^17.6.2", - "yargs-parser": "21.1.1" - }, - "bin": { - "nx": "bin/nx.js", - "nx-cloud": "bin/nx-cloud.js" + "@grpc/grpc-js": "^1.7.1", + "@opentelemetry/core": "1.26.0", + "@opentelemetry/otlp-exporter-base": "0.53.0", + "@opentelemetry/otlp-transformer": "0.53.0" }, - "optionalDependencies": { - "@nx/nx-darwin-arm64": "19.6.3", - "@nx/nx-darwin-x64": "19.6.3", - "@nx/nx-freebsd-x64": "19.6.3", - "@nx/nx-linux-arm-gnueabihf": "19.6.3", - "@nx/nx-linux-arm64-gnu": "19.6.3", - "@nx/nx-linux-arm64-musl": "19.6.3", - "@nx/nx-linux-x64-gnu": "19.6.3", - "@nx/nx-linux-x64-musl": "19.6.3", - "@nx/nx-win32-arm64-msvc": "19.6.3", - "@nx/nx-win32-x64-msvc": "19.6.3" + "engines": { + "node": ">=14" }, "peerDependencies": { - "@swc-node/register": "^1.8.0", - "@swc/core": "^1.3.85" - }, - "peerDependenciesMeta": { - "@swc-node/register": { - "optional": true - }, - "@swc/core": { - "optional": true - } + "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@nx/webpack/node_modules/p-retry": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.0.tgz", - "integrity": "sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==", - "dev": true, + "node_modules/@opentelemetry/otlp-transformer": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.53.0.tgz", + "integrity": "sha512-rM0sDA9HD8dluwuBxLetUmoqGJKSAbWenwD65KY9iZhUxdBHRLrIdrABfNDP7aiTjcgK8XFyTn5fhDz7N+W6DA==", "dependencies": { - "@types/retry": "0.12.2", - "is-network-error": "^1.0.0", - "retry": "^0.13.1" + "@opentelemetry/api-logs": "0.53.0", + "@opentelemetry/core": "1.26.0", + "@opentelemetry/resources": "1.26.0", + "@opentelemetry/sdk-logs": "0.53.0", + "@opentelemetry/sdk-metrics": "1.26.0", + "@opentelemetry/sdk-trace-base": "1.26.0", + "protobufjs": "^7.3.0" }, "engines": { - "node": ">=16.17" + "node": ">=14" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/webpack/node_modules/postcss-loader": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", - "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", - "dev": true, + "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/resources": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", + "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", + "license": "Apache-2.0", "dependencies": { - "cosmiconfig": "^7.0.0", - "klona": "^2.0.5", - "semver": "^7.3.5" + "@opentelemetry/core": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" }, "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">=14" }, "peerDependencies": { - "postcss": "^7.0.0 || ^8.0.1", - "webpack": "^5.0.0" + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@nx/webpack/node_modules/rimraf": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", - "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", - "dev": true, + "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/sdk-trace-base": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.26.0.tgz", + "integrity": "sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw==", + "license": "Apache-2.0", "dependencies": { - "glob": "^10.3.7" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@nx/webpack/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, - "bin": { - "semver": "bin/semver.js" + "@opentelemetry/core": "1.26.0", + "@opentelemetry/resources": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" }, "engines": { - "node": ">=10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@nx/webpack/node_modules/slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", - "dev": true, + "node_modules/@opentelemetry/propagation-utils": { + "version": "0.30.11", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagation-utils/-/propagation-utils-0.30.11.tgz", + "integrity": "sha512-rY4L/2LWNk5p/22zdunpqVmgz6uN419DsRTw5KFMa6u21tWhXS8devlMy4h8m8nnS20wM7r6yYweCNNKjgLYJw==", "engines": { - "node": ">=12" + "node": ">=14" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@nx/webpack/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, + "node_modules/@opentelemetry/propagator-aws-xray": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-aws-xray/-/propagator-aws-xray-1.26.0.tgz", + "integrity": "sha512-Sex+JyEZ/xX328TArBqQjh1NZSfNyw5NdASUIi9hnPsnMBMSBaDe7B9JRnXv0swz7niNyAnXa6MY7yOCV76EvA==", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "@opentelemetry/core": "1.26.0" }, "engines": { - "node": ">=8" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@nx/webpack/node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", - "dev": true, + "node_modules/@opentelemetry/propagator-b3": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-b3/-/propagator-b3-1.26.0.tgz", + "integrity": "sha512-vvVkQLQ/lGGyEy9GT8uFnI047pajSOVnZI2poJqVGD3nJ+B9sFGdlHNnQKophE3lHfnIH0pw2ubrCTjZCgIj+Q==", "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" + "@opentelemetry/core": "1.26.0" }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" + "engines": { + "node": ">=14" }, "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@nx/webpack/node_modules/webpack-dev-middleware": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.4.2.tgz", - "integrity": "sha512-xOO8n6eggxnwYpy1NlzUKpvrjfJTvae5/D6WOK0S2LSo7vjmo5gCM1DbLUmFqrMTJP+W/0YZNctm7jasWvLuBA==", - "dev": true, + "node_modules/@opentelemetry/propagator-jaeger": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-jaeger/-/propagator-jaeger-1.26.0.tgz", + "integrity": "sha512-DelFGkCdaxA1C/QA0Xilszfr0t4YbGd3DjxiCDPh34lfnFr+VkkrjV9S8ZTJvAzfdKERXhfOxIKBoGPJwoSz7Q==", "dependencies": { - "colorette": "^2.0.10", - "memfs": "^4.6.0", - "mime-types": "^2.1.31", - "on-finished": "^2.4.1", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" + "@opentelemetry/core": "1.26.0" }, "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">=14" }, "peerDependencies": { - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - } + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@nx/webpack/node_modules/webpack-dev-server": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.0.4.tgz", - "integrity": "sha512-dljXhUgx3HqKP2d8J/fUMvhxGhzjeNVarDLcbO/EWMSgRizDkxHQDZQaLFL5VJY9tRBj2Gz+rvCEYYvhbqPHNA==", - "dev": true, + "node_modules/@opentelemetry/redis-common": { + "version": "0.36.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/redis-common/-/redis-common-0.36.2.tgz", + "integrity": "sha512-faYX1N0gpLhej/6nyp6bgRjzAKXn5GOEMYY7YhciSfCoITAktLUtQ36d24QEWNA1/WA1y6qQunCe0OhHRkVl9g==", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/resource-detector-alibaba-cloud": { + "version": "0.29.3", + "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-alibaba-cloud/-/resource-detector-alibaba-cloud-0.29.3.tgz", + "integrity": "sha512-jdnG/cYItxwKGRj2n3YsJn1+j3QsMRUfaH/mQSj2b6yULo7bKO4turvASwxy3GuSDH55VwrK+F8oIbanJk69ng==", "dependencies": { - "@types/bonjour": "^3.5.13", - "@types/connect-history-api-fallback": "^1.5.4", - "@types/express": "^4.17.21", - "@types/serve-index": "^1.9.4", - "@types/serve-static": "^1.15.5", - "@types/sockjs": "^0.3.36", - "@types/ws": "^8.5.10", - "ansi-html-community": "^0.0.8", - "bonjour-service": "^1.2.1", - "chokidar": "^3.6.0", - "colorette": "^2.0.10", - "compression": "^1.7.4", - "connect-history-api-fallback": "^2.0.0", - "default-gateway": "^6.0.3", - "express": "^4.17.3", - "graceful-fs": "^4.2.6", - "html-entities": "^2.4.0", - "http-proxy-middleware": "^2.0.3", - "ipaddr.js": "^2.1.0", - "launch-editor": "^2.6.1", - "open": "^10.0.3", - "p-retry": "^6.2.0", - "rimraf": "^5.0.5", - "schema-utils": "^4.2.0", - "selfsigned": "^2.4.1", - "serve-index": "^1.9.1", - "sockjs": "^0.3.24", - "spdy": "^4.0.2", - "webpack-dev-middleware": "^7.1.0", - "ws": "^8.16.0" - }, - "bin": { - "webpack-dev-server": "bin/webpack-dev-server.js" + "@opentelemetry/core": "^1.26.0", + "@opentelemetry/resources": "^1.10.0", + "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">=14" }, "peerDependencies": { - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - }, - "webpack-cli": { - "optional": true - } + "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@nx/webpack/node_modules/webpack-dev-server/node_modules/http-proxy-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", - "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", - "dev": true, + "node_modules/@opentelemetry/resource-detector-aws": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-aws/-/resource-detector-aws-1.6.2.tgz", + "integrity": "sha512-xxT6PVmcBTtCo0rf4Bv/mnDMpVRITVt13bDX8mOqKVb0kr5EwIMabZS5EGJhXjP4nljrOIA7ZlOJgSX0Kehfkw==", "dependencies": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" + "@opentelemetry/core": "^1.0.0", + "@opentelemetry/resources": "^1.10.0", + "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { - "node": ">=12.0.0" + "node": ">=14" }, "peerDependencies": { - "@types/express": "^4.17.13" - }, - "peerDependenciesMeta": { - "@types/express": { - "optional": true - } + "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@nx/webpack/node_modules/webpack-dev-server/node_modules/open": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz", - "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==", - "dev": true, + "node_modules/@opentelemetry/resource-detector-azure": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-azure/-/resource-detector-azure-0.2.11.tgz", + "integrity": "sha512-XepvQfTXWyHAoAziCfXGwYbSZL0LHtFk5iuKKN2VE2vzcoiw5Tepi0Qafuwb7CCtpQRReao4H7E29MFbCmh47g==", "dependencies": { - "default-browser": "^5.2.1", - "define-lazy-prop": "^3.0.0", - "is-inside-container": "^1.0.0", - "is-wsl": "^3.1.0" + "@opentelemetry/core": "^1.25.1", + "@opentelemetry/resources": "^1.10.1", + "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { - "node": ">=18" + "node": ">=14" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@nx/webpack/node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">= 6" + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@nx/webpack/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, + "node_modules/@opentelemetry/resource-detector-container": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-container/-/resource-detector-container-0.4.4.tgz", + "integrity": "sha512-ZEN2mq7lIjQWJ8NTt1umtr6oT/Kb89856BOmESLSvgSHbIwOFYs7cSfSRH5bfiVw6dXTQAVbZA/wLgCHKrebJA==", "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" + "@opentelemetry/core": "^1.26.0", + "@opentelemetry/resources": "^1.10.0", + "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { - "node": ">=12" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@nx/workspace": { - "version": "19.7.3", - "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-19.7.3.tgz", - "integrity": "sha512-FUHeOLCXdHEB1b6FiNU9swCZIKXbsGWRDfgHpHGeiZHp7uhH41W/EKTVukRxnQ+HXhE7zfxhn8KkllfaXIifPg==", - "dev": true, + "node_modules/@opentelemetry/resource-detector-gcp": { + "version": "0.29.12", + "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-gcp/-/resource-detector-gcp-0.29.12.tgz", + "integrity": "sha512-liFG9XTaFVyY9YdFy4r2qVNa4a+Mg3k+XoWzzq2F+/xR0hFLfL0H4k7CsMW+T4Vl+1Cvc9W9WEVt5VCF4u/SYw==", "dependencies": { - "@nrwl/workspace": "19.7.3", - "@nx/devkit": "19.7.3", - "chalk": "^4.1.0", - "enquirer": "~2.3.6", - "nx": "19.7.3", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" + "@opentelemetry/core": "^1.0.0", + "@opentelemetry/resources": "^1.10.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "gcp-metadata": "^6.0.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@nx/workspace/node_modules/@nrwl/devkit": { - "version": "19.7.3", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.7.3.tgz", - "integrity": "sha512-g9vANTuxgHan6uAkI6M6tkfLjHECLmbZ4A80UqpxJNQJsCJFEHkzIC9oxhf8bWV3PjgCH6Xm4VyQ2GHwb3sgWw==", - "dev": true, + "node_modules/@opentelemetry/resources": { + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.27.0.tgz", + "integrity": "sha512-jOwt2VJ/lUD5BLc+PMNymDrUCpm5PKi1E9oSVYAvz01U/VdndGmrtV3DU1pG4AwlYhJRHbHfOUIlpBeXCPw6QQ==", + "license": "Apache-2.0", "dependencies": { - "@nx/devkit": "19.7.3" + "@opentelemetry/core": "1.27.0", + "@opentelemetry/semantic-conventions": "1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@nx/workspace/node_modules/@nrwl/tao": { - "version": "19.7.3", - "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.7.3.tgz", - "integrity": "sha512-cIGhnSFPZdVTp4bI0fqwFoE9i7ToPg5jXz+hNMl/MTwcOQfKQ1JJY/ZPLM3aBUPORFIZ/GECQEycUb6+xCB56g==", - "dev": true, + "node_modules/@opentelemetry/resources/node_modules/@opentelemetry/core": { + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.27.0.tgz", + "integrity": "sha512-yQPKnK5e+76XuiqUH/gKyS8wv/7qITd5ln56QkBTf3uggr0VkXOXfcaAuG330UfdYu83wsyoBwqwxigpIG+Jkg==", + "license": "Apache-2.0", "dependencies": { - "nx": "19.7.3", - "tslib": "^2.3.0" + "@opentelemetry/semantic-conventions": "1.27.0" }, - "bin": { - "tao": "index.js" + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@nx/workspace/node_modules/@nx/devkit": { - "version": "19.7.3", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.7.3.tgz", - "integrity": "sha512-dIavuzfcMLCTa5uhd4R7HsxcFO0w9fHwG4wDg76wyBAbPGJlrR+9zg359hZ/SkXdguO6bMVmmQg/EXIvo6g69A==", - "dev": true, + "node_modules/@opentelemetry/sdk-logs": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.53.0.tgz", + "integrity": "sha512-dhSisnEgIj/vJZXZV6f6KcTnyLDx/VuQ6l3ejuZpMpPlh9S1qMHiZU9NMmOkVkwwHkMy3G6mEBwdP23vUZVr4g==", "dependencies": { - "@nrwl/devkit": "19.7.3", - "ejs": "^3.1.7", - "enquirer": "~2.3.6", - "ignore": "^5.0.4", - "minimatch": "9.0.3", - "semver": "^7.5.3", - "tmp": "~0.2.1", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" + "@opentelemetry/api-logs": "0.53.0", + "@opentelemetry/core": "1.26.0", + "@opentelemetry/resources": "1.26.0" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { - "nx": ">= 17 <= 20" + "@opentelemetry/api": ">=1.4.0 <1.10.0" } }, - "node_modules/@nx/workspace/node_modules/@nx/nx-darwin-arm64": { - "version": "19.7.3", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.7.3.tgz", - "integrity": "sha512-0dDK0UkMR0vBv4AP/48Q9A+OC2dvpivdt8su/4W/CPADy69M9B5O3jPiK+jTRsLshQG/soC9JG0Rll1BNWymPg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], + "node_modules/@opentelemetry/sdk-logs/node_modules/@opentelemetry/resources": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", + "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@nx/workspace/node_modules/@nx/nx-darwin-x64": { - "version": "19.7.3", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.7.3.tgz", - "integrity": "sha512-hTdv5YY2GQTdT7GwVO7ST27ZzvCmAQvmkEapfnCdy74QsL4gapaXJFvtWLHVfG6qHNRHWXbpdegvR3VswRHZVQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], + "node_modules/@opentelemetry/sdk-metrics": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.26.0.tgz", + "integrity": "sha512-0SvDXmou/JjzSDOjUmetAAvcKQW6ZrvosU0rkbDGpXvvZN+pQF6JbK/Kd4hNdK4q/22yeruqvukXEJyySTzyTQ==", + "dependencies": { + "@opentelemetry/core": "1.26.0", + "@opentelemetry/resources": "1.26.0" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, - "node_modules/@nx/workspace/node_modules/@nx/nx-freebsd-x64": { - "version": "19.7.3", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.7.3.tgz", - "integrity": "sha512-dwuB/3eoV2RbD0b0LHnagQOXa9PKAjLi7g5vNxzw6LuNT1tdaLaUZZGv2tfG0hHjsV0cOaAX41rEyOIwJyE7zg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], + "node_modules/@opentelemetry/sdk-metrics/node_modules/@opentelemetry/resources": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", + "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@nx/workspace/node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "19.7.3", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.7.3.tgz", - "integrity": "sha512-X/eG3IqvIxlCfIOiCQKv7RKwra54I+SN9zj2TeSOtd/uK0paa3mYSlGUJqoP3wpzasW1+EPIGkTQqV283IA15w==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@opentelemetry/sdk-node": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-node/-/sdk-node-0.53.0.tgz", + "integrity": "sha512-0hsxfq3BKy05xGktwG8YdGdxV978++x40EAKyKr1CaHZRh8uqVlXnclnl7OMi9xLMJEcXUw7lGhiRlArFcovyg==", + "dependencies": { + "@opentelemetry/api-logs": "0.53.0", + "@opentelemetry/core": "1.26.0", + "@opentelemetry/exporter-logs-otlp-grpc": "0.53.0", + "@opentelemetry/exporter-logs-otlp-http": "0.53.0", + "@opentelemetry/exporter-logs-otlp-proto": "0.53.0", + "@opentelemetry/exporter-trace-otlp-grpc": "0.53.0", + "@opentelemetry/exporter-trace-otlp-http": "0.53.0", + "@opentelemetry/exporter-trace-otlp-proto": "0.53.0", + "@opentelemetry/exporter-zipkin": "1.26.0", + "@opentelemetry/instrumentation": "0.53.0", + "@opentelemetry/resources": "1.26.0", + "@opentelemetry/sdk-logs": "0.53.0", + "@opentelemetry/sdk-metrics": "1.26.0", + "@opentelemetry/sdk-trace-base": "1.26.0", + "@opentelemetry/sdk-trace-node": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, - "node_modules/@nx/workspace/node_modules/@nx/nx-linux-arm64-gnu": { - "version": "19.7.3", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.7.3.tgz", - "integrity": "sha512-LNaX8DVcPlFVJhMf1AAAR6j1DZF9BlVhWlilRM44tIfnmvPfKIahKJIJbuikHE7q+lkvMrQUUDXKiQJlmm/qDw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/exporter-trace-otlp-http": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.53.0.tgz", + "integrity": "sha512-m7F5ZTq+V9mKGWYpX8EnZ7NjoqAU7VemQ1E2HAG+W/u0wpY1x0OmbxAXfGKFHCspdJk8UKlwPGrpcB8nay3P8A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.26.0", + "@opentelemetry/otlp-exporter-base": "0.53.0", + "@opentelemetry/otlp-transformer": "0.53.0", + "@opentelemetry/resources": "1.26.0", + "@opentelemetry/sdk-trace-base": "1.26.0" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@nx/workspace/node_modules/@nx/nx-linux-arm64-musl": { - "version": "19.7.3", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.7.3.tgz", - "integrity": "sha512-TJ9PqSebhrn8NfrW+wqMXB9N65U0L0Kjt8FfahWffNKtSAEUvhurbNhqna2Rt5WJe2qaVf6zN2pOHKhF/5pL0w==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@nx/workspace/node_modules/@nx/nx-linux-x64-gnu": { - "version": "19.7.3", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.7.3.tgz", - "integrity": "sha512-YMb4WGGovwgxsP6VvAEnyWvLoUwsDrdE5CxFQ2yoThD2BixmSHUKLtx6dtPDHz25nOE3v1ZzM0xTwYXBhPaeRQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/resources": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", + "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@nx/workspace/node_modules/@nx/nx-linux-x64-musl": { - "version": "19.7.3", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.7.3.tgz", - "integrity": "sha512-zkjgDSvw2eDN+KuJBPPAPhU/lOdiMvJU0UMthJFw85dhQIYfAO8+UgiFg/qBsKo0kQ0MkhntnIPBPF8bH40qWg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/sdk-trace-base": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.26.0.tgz", + "integrity": "sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.26.0", + "@opentelemetry/resources": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@nx/workspace/node_modules/@nx/nx-win32-arm64-msvc": { - "version": "19.7.3", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.7.3.tgz", - "integrity": "sha512-qCTFG6VxNvEe5JfoAELGZsjWDL4G+2NVSoSS3tByJYwVX256qgALcVoUHMjpxBn9FeOvUW9w5PL4Am4PKDdXLw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], + "node_modules/@opentelemetry/sdk-node/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">= 10" + "node": ">=10" } }, - "node_modules/@nx/workspace/node_modules/@nx/nx-win32-x64-msvc": { - "version": "19.7.3", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.7.3.tgz", - "integrity": "sha512-ULNf73gLgB5cU/O4dlQe6tetbRIROTmaUNYTUUCCAC0BqVwZwPDxn4u9C5LgiErVyfPwwAhlserCGei5taLASQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], + "node_modules/@opentelemetry/sdk-trace-base": { + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.27.0.tgz", + "integrity": "sha512-btz6XTQzwsyJjombpeqCX6LhiMQYpzt2pIYNPnw0IPO/3AhT6yjnf8Mnv3ZC2A4eRYOjqrg+bfaXg9XHDRJDWQ==", + "dependencies": { + "@opentelemetry/core": "1.27.0", + "@opentelemetry/resources": "1.27.0", + "@opentelemetry/semantic-conventions": "1.27.0" + }, "engines": { - "node": ">= 10" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@nx/workspace/node_modules/dotenv-expand": { - "version": "11.0.6", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.6.tgz", - "integrity": "sha512-8NHi73otpWsZGBSZwwknTXS5pqMOrk9+Ssrna8xCaxkzEpU9OTf9R5ArQGVw03//Zmk9MOwLPng9WwndvpAJ5g==", - "dev": true, + "node_modules/@opentelemetry/sdk-trace-base/node_modules/@opentelemetry/core": { + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.27.0.tgz", + "integrity": "sha512-yQPKnK5e+76XuiqUH/gKyS8wv/7qITd5ln56QkBTf3uggr0VkXOXfcaAuG330UfdYu83wsyoBwqwxigpIG+Jkg==", "dependencies": { - "dotenv": "^16.4.4" + "@opentelemetry/semantic-conventions": "1.27.0" }, "engines": { - "node": ">=12" + "node": ">=14" }, - "funding": { - "url": "https://dotenvx.com" + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@nx/workspace/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/@nx/workspace/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, + "node_modules/@opentelemetry/sdk-trace-node": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-1.26.0.tgz", + "integrity": "sha512-Fj5IVKrj0yeUwlewCRwzOVcr5avTuNnMHWf7GPc1t6WaT78J6CJyF3saZ/0RkZfdeNO8IcBl/bNcWMVZBMRW8Q==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/context-async-hooks": "1.26.0", + "@opentelemetry/core": "1.26.0", + "@opentelemetry/propagator-b3": "1.26.0", + "@opentelemetry/propagator-jaeger": "1.26.0", + "@opentelemetry/sdk-trace-base": "1.26.0", + "semver": "^7.5.2" + }, "engines": { - "node": ">=8" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@nx/workspace/node_modules/lines-and-columns": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.3.tgz", - "integrity": "sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w==", - "dev": true, + "node_modules/@opentelemetry/sdk-trace-node/node_modules/@opentelemetry/resources": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", + "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" + }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@nx/workspace/node_modules/nx": { - "version": "19.7.3", - "resolved": "https://registry.npmjs.org/nx/-/nx-19.7.3.tgz", - "integrity": "sha512-8F4CzKavSuOFv+uKVwXHc00Px0q40CWAYCW6NC5IgU3AMaJVumyHzgB8Sn+yfkaVgfVnZVqznOsyrbZUWuj/VA==", - "dev": true, - "hasInstallScript": true, + "node_modules/@opentelemetry/sdk-trace-node/node_modules/@opentelemetry/sdk-trace-base": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.26.0.tgz", + "integrity": "sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw==", + "license": "Apache-2.0", "dependencies": { - "@napi-rs/wasm-runtime": "0.2.4", - "@nrwl/tao": "19.7.3", - "@yarnpkg/lockfile": "^1.1.0", - "@yarnpkg/parsers": "3.0.0-rc.46", - "@zkochan/js-yaml": "0.0.7", - "axios": "^1.7.4", - "chalk": "^4.1.0", - "cli-cursor": "3.1.0", - "cli-spinners": "2.6.1", - "cliui": "^8.0.1", - "dotenv": "~16.4.5", - "dotenv-expand": "~11.0.6", - "enquirer": "~2.3.6", - "figures": "3.2.0", - "flat": "^5.0.2", - "front-matter": "^4.0.2", - "fs-extra": "^11.1.0", - "ignore": "^5.0.4", - "jest-diff": "^29.4.1", - "jsonc-parser": "3.2.0", - "lines-and-columns": "2.0.3", - "minimatch": "9.0.3", - "node-machine-id": "1.1.12", - "npm-run-path": "^4.0.1", - "open": "^8.4.0", - "ora": "5.3.0", - "semver": "^7.5.3", - "string-width": "^4.2.3", - "strong-log-transformer": "^2.1.0", - "tar-stream": "~2.2.0", - "tmp": "~0.2.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0", - "yargs": "^17.6.2", - "yargs-parser": "21.1.1" - }, - "bin": { - "nx": "bin/nx.js", - "nx-cloud": "bin/nx-cloud.js" + "@opentelemetry/core": "1.26.0", + "@opentelemetry/resources": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" }, - "optionalDependencies": { - "@nx/nx-darwin-arm64": "19.7.3", - "@nx/nx-darwin-x64": "19.7.3", - "@nx/nx-freebsd-x64": "19.7.3", - "@nx/nx-linux-arm-gnueabihf": "19.7.3", - "@nx/nx-linux-arm64-gnu": "19.7.3", - "@nx/nx-linux-arm64-musl": "19.7.3", - "@nx/nx-linux-x64-gnu": "19.7.3", - "@nx/nx-linux-x64-musl": "19.7.3", - "@nx/nx-win32-arm64-msvc": "19.7.3", - "@nx/nx-win32-x64-msvc": "19.7.3" + "engines": { + "node": ">=14" }, "peerDependencies": { - "@swc-node/register": "^1.8.0", - "@swc/core": "^1.3.85" - }, - "peerDependenciesMeta": { - "@swc-node/register": { - "optional": true - }, - "@swc/core": { - "optional": true - } + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@nx/workspace/node_modules/semver": { + "node_modules/@opentelemetry/sdk-trace-node/node_modules/semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, "bin": { "semver": "bin/semver.js" }, @@ -12231,9799 +23459,9678 @@ "node": ">=10" } }, - "node_modules/@nx/workspace/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, + "node_modules/@opentelemetry/semantic-conventions": { + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.27.0.tgz", + "integrity": "sha512-sAay1RrB+ONOem0OZanAR1ZI/k7yDpnOQSQmTMuGImUQb2y8EbSaCJ94FQluM74xoU03vlb2d2U90hZluL6nQg==", + "license": "Apache-2.0", "engines": { - "node": ">=8" + "node": ">=14" } }, - "node_modules/@nx/workspace/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, + "node_modules/@opentelemetry/sql-common": { + "version": "0.40.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sql-common/-/sql-common-0.40.1.tgz", + "integrity": "sha512-nSDlnHSqzC3pXn/wZEZVLuAuJ1MYMXPBwtv2qAbCa3847SaHItdE7SzUq/Jtb0KZmh1zfAbNi3AAMjztTT4Ugg==", "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" + "@opentelemetry/core": "^1.1.0" }, "engines": { - "node": ">=12" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0" } }, - "node_modules/@open-draft/deferred-promise": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", - "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@open-draft/logger": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz", - "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", - "dev": true, - "license": "MIT", + "node_modules/@opentelemetry/winston-transport": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/winston-transport/-/winston-transport-0.7.0.tgz", + "integrity": "sha512-Q35p/glAOE6sl0ZgbddYsdjy23mzt89lFGhht4pJwrrJyInFIgdONFmMJb47kmXbFM3JHOcI0j+PL1BPPTPXBQ==", "dependencies": { - "is-node-process": "^1.2.0", - "outvariant": "^1.4.0" + "@opentelemetry/api-logs": "^0.54.0", + "winston-transport": "4.*" + }, + "engines": { + "node": ">=14" } }, - "node_modules/@open-draft/until": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz", - "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@open-policy-agent/opa-wasm": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@open-policy-agent/opa-wasm/-/opa-wasm-1.9.0.tgz", - "integrity": "sha512-wuxQYoqU80ulYdFtZ1BKaFs29IRZZV3hl48L4wMRxXFlEoLBDfl5rL8iBNIyp+DDymvDxGS4ZMRVaBBWXnPYLQ==", + "node_modules/@opentelemetry/winston-transport/node_modules/@opentelemetry/api-logs": { + "version": "0.54.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.54.0.tgz", + "integrity": "sha512-9HhEh5GqFrassUndqJsyW7a0PzfyWr2eV2xwzHLIS+wX3125+9HE9FMRAKmJRwxZhgZGwH3HNQQjoMGZqmOeVA==", "dependencies": { - "sprintf-js": "^1.1.2", - "yaml": "^1.10.2" + "@opentelemetry/api": "^1.3.0" + }, + "engines": { + "node": ">=14" } }, - "node_modules/@open-policy-agent/opa-wasm/node_modules/yaml": { + "node_modules/@oxc-resolver/binding-darwin-arm64": { "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "license": "ISC", - "engines": { - "node": ">= 6" - } + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-darwin-arm64/-/binding-darwin-arm64-1.10.2.tgz", + "integrity": "sha512-aOCZYXqmFL+2sXlaVkYbAOtICGGeTFtmdul8OimQfOXHJods6YHJ2nR6+rEeBcJzaXyXPP18ne1IsEc4AYL1IA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@openapitools/openapi-generator-cli": { - "version": "2.15.3", - "resolved": "https://registry.npmjs.org/@openapitools/openapi-generator-cli/-/openapi-generator-cli-2.15.3.tgz", - "integrity": "sha512-2UBnsDlMt36thhdXxisbA1qReVtbCaw+NCvXoslRXlaJBL4qkAmZUhNeDLNu3LCbwA2PASMWhJSqeLwgwMCitw==", + "node_modules/@oxc-resolver/binding-darwin-x64": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-darwin-x64/-/binding-darwin-x64-1.10.2.tgz", + "integrity": "sha512-6WD7lHGkoduFZfUgnC2suKOlqttQRKxWsiVXiiGPu3mfXvQAhMd/gekuH1t8vOhFlPJduaww15n5UB0bSjCK+w==", + "cpu": [ + "x64" + ], "dev": true, - "hasInstallScript": true, - "dependencies": { - "@nestjs/axios": "3.1.1", - "@nestjs/common": "10.4.6", - "@nestjs/core": "10.4.6", - "@nuxtjs/opencollective": "0.3.2", - "axios": "1.7.7", - "chalk": "4.1.2", - "commander": "8.3.0", - "compare-versions": "4.1.4", - "concurrently": "6.5.1", - "console.table": "0.10.0", - "fs-extra": "10.1.0", - "glob": "9.3.5", - "inquirer": "8.2.6", - "lodash": "4.17.21", - "proxy-agent": "6.4.0", - "reflect-metadata": "0.1.13", - "rxjs": "7.8.1", - "tslib": "2.8.1" - }, - "bin": { - "openapi-generator-cli": "main.js" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/openapi_generator" - } + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/axios": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-3.1.1.tgz", - "integrity": "sha512-ySoxrzqX80P1q6LKLKGcgyBd2utg4gbC+4FsJNpXYvILorMlxss/ECNogD9EXLCE4JS5exVFD5ez0nK5hXcNTQ==", + "node_modules/@oxc-resolver/binding-freebsd-x64": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-freebsd-x64/-/binding-freebsd-x64-1.10.2.tgz", + "integrity": "sha512-nEqHWx/Ot5p7Mafj8qH6vFlLSvHjECxAcZwhnAMqRuQu1NgXC/QM3emkdhVGy7QJgsxZbHpPaF6TERNf5/NL9Q==", + "cpu": [ + "x64" + ], "dev": true, - "peerDependencies": { - "@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0", - "axios": "^1.3.1", - "rxjs": "^6.0.0 || ^7.0.0" - } + "optional": true, + "os": [ + "freebsd" + ] }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/common": { - "version": "10.4.6", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.4.6.tgz", - "integrity": "sha512-KkezkZvU9poWaNq4L+lNvx+386hpOxPJkfXBBeSMrcqBOx8kVr36TGN2uYkF4Ta4zNu1KbCjmZbc0rhHSg296g==", + "node_modules/@oxc-resolver/binding-linux-arm-gnueabihf": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.10.2.tgz", + "integrity": "sha512-+AlZI0fPnpfArh8aC5k2295lmQrxa2p8gBLxC3buvCkz0ZpbVLxyyAXz3J2jGwJnmc5MUPLEqPYw6ZlAGH4XHA==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "iterare": "1.2.1", - "tslib": "2.7.0", - "uid": "2.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nest" - }, - "peerDependencies": { - "class-transformer": "*", - "class-validator": "*", - "reflect-metadata": "^0.1.12 || ^0.2.0", - "rxjs": "^7.1.0" - }, - "peerDependenciesMeta": { - "class-transformer": { - "optional": true - }, - "class-validator": { - "optional": true - } - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/common/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", - "dev": true + "node_modules/@oxc-resolver/binding-linux-arm64-gnu": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.10.2.tgz", + "integrity": "sha512-8fZ8NszFaUZaoA8eUwkF2lHjgUs76aFiewWgG/cjcZmwKp+ErZQLW8eOvIWZ4SohHQ+ScvhVsSaU2PU38c88gw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/core": { - "version": "10.4.6", - "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.4.6.tgz", - "integrity": "sha512-zXVPxCNRfO6gAy0yvEDjUxE/8gfZICJFpsl2lZAUH31bPb6m+tXuhUq2mVCTEltyMYQ+DYtRe+fEYM2v152N1g==", + "node_modules/@oxc-resolver/binding-linux-arm64-musl": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.10.2.tgz", + "integrity": "sha512-oPrLICrw96Ym9n04FWXWGkbkpF6qJtZ57JSnqI3oQ24xHTt4iWyjHKHQO46NbJAK9sFb3Qce4BzV8faDI5Rifg==", + "cpu": [ + "arm64" + ], "dev": true, - "hasInstallScript": true, - "dependencies": { - "@nuxtjs/opencollective": "0.3.2", - "fast-safe-stringify": "2.1.1", - "iterare": "1.2.1", - "path-to-regexp": "3.3.0", - "tslib": "2.7.0", - "uid": "2.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nest" - }, - "peerDependencies": { - "@nestjs/common": "^10.0.0", - "@nestjs/microservices": "^10.0.0", - "@nestjs/platform-express": "^10.0.0", - "@nestjs/websockets": "^10.0.0", - "reflect-metadata": "^0.1.12 || ^0.2.0", - "rxjs": "^7.1.0" - }, - "peerDependenciesMeta": { - "@nestjs/microservices": { - "optional": true - }, - "@nestjs/platform-express": { - "optional": true - }, - "@nestjs/websockets": { - "optional": true - } - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/core/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", - "dev": true + "node_modules/@oxc-resolver/binding-linux-x64-gnu": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.10.2.tgz", + "integrity": "sha512-eli74jTAUiIfqi8IPFqiPxQS69Alcr6w/IFRyf3XxrkxeFGgcgxJkRIxWNTKJ6T3EXxjuma+49LdZn6l9rEj7A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "node_modules/@oxc-resolver/binding-linux-x64-musl": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-musl/-/binding-linux-x64-musl-1.10.2.tgz", + "integrity": "sha512-HH9zmjNSQo3rkbqJH5nIjGrtjC+QPrUy0KGGMR/oRCSLuD0cNFJ/Uly1XAugwSm4oEw0+rv6PmeclXmVTKsxhw==", + "cpu": [ + "x64" + ], "dev": true, - "engines": { - "node": ">= 12" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/fs-extra": { - "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==", + "node_modules/@oxc-resolver/binding-wasm32-wasi": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-wasm32-wasi/-/binding-wasm32-wasi-1.10.2.tgz", + "integrity": "sha512-3ItX23q33sfVBtMMdMhVDSe0NX5zBHxHfmFiXhSJuwNaVIwGpLFU7WU2nmq9oNdnmTOvjL8vlhOqiGvumBLlRA==", + "cpu": [ + "wasm32" + ], "dev": true, + "optional": true, "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "@napi-rs/wasm-runtime": "^0.2.4" }, "engines": { - "node": ">=12" + "node": ">=14.0.0" } }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/glob": { - "version": "9.3.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", - "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", + "node_modules/@oxc-resolver/binding-win32-arm64-msvc": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.10.2.tgz", + "integrity": "sha512-aVoj2V+jmQ1N+lVy9AhaLmzssJM0lcKt8D0UL83aNLZJ5lSN7hgBuUXTVmL+VF268f167khjo38z+fbELDVm8Q==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "minimatch": "^8.0.2", - "minipass": "^4.2.4", - "path-scurry": "^1.6.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/minimatch": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", - "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", + "node_modules/@oxc-resolver/binding-win32-x64-msvc": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.10.2.tgz", + "integrity": "sha512-l8BDQWyP0Piw8hlmYPUqTRKLsq+ceG9h+9p6ZrjNzwW9AmJX7T7T2hgoVVHqS6f4WNA/CFkb3RyZP9QTzNkyyA==", + "cpu": [ + "x64" + ], "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@parcel/watcher": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.0.tgz", + "integrity": "sha512-i0GV1yJnm2n3Yq1qw6QrUrd/LI9bE8WEBOTtOkpCXHHdyN3TAGgqAK/DAT05z4fq2x04cARXt2pDmjWjL92iTQ==", + "hasInstallScript": true, "dependencies": { - "brace-expansion": "^2.0.1" + "detect-libc": "^1.0.3", + "is-glob": "^4.0.3", + "micromatch": "^4.0.5", + "node-addon-api": "^7.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">= 10.0.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/minipass": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", - "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", - "dev": true, - "engines": { - "node": ">=8" + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.0", + "@parcel/watcher-darwin-arm64": "2.5.0", + "@parcel/watcher-darwin-x64": "2.5.0", + "@parcel/watcher-freebsd-x64": "2.5.0", + "@parcel/watcher-linux-arm-glibc": "2.5.0", + "@parcel/watcher-linux-arm-musl": "2.5.0", + "@parcel/watcher-linux-arm64-glibc": "2.5.0", + "@parcel/watcher-linux-arm64-musl": "2.5.0", + "@parcel/watcher-linux-x64-glibc": "2.5.0", + "@parcel/watcher-linux-x64-musl": "2.5.0", + "@parcel/watcher-win32-arm64": "2.5.0", + "@parcel/watcher-win32-ia32": "2.5.0", + "@parcel/watcher-win32-x64": "2.5.0" } }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/path-to-regexp": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.3.0.tgz", - "integrity": "sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==", - "dev": true - }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/reflect-metadata": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", - "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", - "dev": true - }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true - }, - "node_modules/@opentelemetry/api": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", - "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.0.tgz", + "integrity": "sha512-qlX4eS28bUcQCdribHkg/herLe+0A9RyYC+mm2PXpncit8z5b3nSqGVzMNR3CmtAOgRutiZ02eIJJgP/b1iEFQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@opentelemetry/api-logs": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.53.0.tgz", - "integrity": "sha512-8HArjKx+RaAI8uEIgcORbZIPklyh1YLjPSBus8hjRmvLi6DeFzgOcdZ7KwPabKj8mXF8dX0hyfAyGfycz0DbFw==", - "dependencies": { - "@opentelemetry/api": "^1.0.0" + "node": ">= 10.0.0" }, - "engines": { - "node": ">=14" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@opentelemetry/auto-instrumentations-node": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/auto-instrumentations-node/-/auto-instrumentations-node-0.51.0.tgz", - "integrity": "sha512-xsgydgtJiToxvFsDcmLDrHiFfHOmdomqk4KCnr40YZdsfw7KO4RJEU0om2f7pFh6WUI5q8nSQ53QgZ+DAz6TzA==", - "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/instrumentation-amqplib": "^0.42.0", - "@opentelemetry/instrumentation-aws-lambda": "^0.45.0", - "@opentelemetry/instrumentation-aws-sdk": "^0.44.0", - "@opentelemetry/instrumentation-bunyan": "^0.41.0", - "@opentelemetry/instrumentation-cassandra-driver": "^0.41.0", - "@opentelemetry/instrumentation-connect": "^0.39.0", - "@opentelemetry/instrumentation-cucumber": "^0.9.0", - "@opentelemetry/instrumentation-dataloader": "^0.12.0", - "@opentelemetry/instrumentation-dns": "^0.39.0", - "@opentelemetry/instrumentation-express": "^0.43.0", - "@opentelemetry/instrumentation-fastify": "^0.40.0", - "@opentelemetry/instrumentation-fs": "^0.15.0", - "@opentelemetry/instrumentation-generic-pool": "^0.39.0", - "@opentelemetry/instrumentation-graphql": "^0.43.0", - "@opentelemetry/instrumentation-grpc": "^0.53.0", - "@opentelemetry/instrumentation-hapi": "^0.41.0", - "@opentelemetry/instrumentation-http": "^0.53.0", - "@opentelemetry/instrumentation-ioredis": "^0.43.0", - "@opentelemetry/instrumentation-kafkajs": "^0.3.0", - "@opentelemetry/instrumentation-knex": "^0.40.0", - "@opentelemetry/instrumentation-koa": "^0.43.0", - "@opentelemetry/instrumentation-lru-memoizer": "^0.40.0", - "@opentelemetry/instrumentation-memcached": "^0.39.0", - "@opentelemetry/instrumentation-mongodb": "^0.47.0", - "@opentelemetry/instrumentation-mongoose": "^0.42.0", - "@opentelemetry/instrumentation-mysql": "^0.41.0", - "@opentelemetry/instrumentation-mysql2": "^0.41.0", - "@opentelemetry/instrumentation-nestjs-core": "^0.40.0", - "@opentelemetry/instrumentation-net": "^0.39.0", - "@opentelemetry/instrumentation-pg": "^0.46.0", - "@opentelemetry/instrumentation-pino": "^0.42.0", - "@opentelemetry/instrumentation-redis": "^0.42.0", - "@opentelemetry/instrumentation-redis-4": "^0.42.1", - "@opentelemetry/instrumentation-restify": "^0.41.0", - "@opentelemetry/instrumentation-router": "^0.40.0", - "@opentelemetry/instrumentation-socket.io": "^0.42.0", - "@opentelemetry/instrumentation-tedious": "^0.14.0", - "@opentelemetry/instrumentation-undici": "^0.6.0", - "@opentelemetry/instrumentation-winston": "^0.40.0", - "@opentelemetry/resource-detector-alibaba-cloud": "^0.29.3", - "@opentelemetry/resource-detector-aws": "^1.6.2", - "@opentelemetry/resource-detector-azure": "^0.2.11", - "@opentelemetry/resource-detector-container": "^0.4.4", - "@opentelemetry/resource-detector-gcp": "^0.29.12", - "@opentelemetry/resources": "^1.24.0", - "@opentelemetry/sdk-node": "^0.53.0" - }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.0.tgz", + "integrity": "sha512-hyZ3TANnzGfLpRA2s/4U1kbw2ZI4qGxaRJbBH2DCSREFfubMswheh8TeiC1sGZ3z2jUf3s37P0BBlrD3sjVTUw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=14" + "node": ">= 10.0.0" }, - "peerDependencies": { - "@opentelemetry/api": "^1.4.1" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.0.tgz", + "integrity": "sha512-9rhlwd78saKf18fT869/poydQK8YqlU26TMiNg7AIu7eBp9adqbJZqmdFOsbZ5cnLp5XvRo9wcFmNHgHdWaGYA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=14" + "node": ">= 10.0.0" }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/instrumentation-express": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-express/-/instrumentation-express-0.43.0.tgz", - "integrity": "sha512-bxTIlzn9qPXJgrhz8/Do5Q3jIlqfpoJrSUtVGqH+90eM1v2PkPHc+SdE+zSqe4q9Y1UQJosmZ4N4bm7Zj/++MA==", - "dependencies": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.0.tgz", + "integrity": "sha512-syvfhZzyM8kErg3VF0xpV8dixJ+RzbUaaGaeb7uDuz0D3FK97/mZ5AJQ3XNnDsXX7KkFNtyQyFrXZzQIcN49Tw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=14" + "node": ">= 10.0.0" }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/instrumentation-http": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.53.0.tgz", - "integrity": "sha512-H74ErMeDuZfj7KgYCTOFGWF5W9AfaPnqLQQxeFq85+D29wwV2yqHbz2IKLYpkOh7EI6QwDEl7rZCIxjJLyc/CQ==", - "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/instrumentation": "0.53.0", - "@opentelemetry/semantic-conventions": "1.27.0", - "semver": "^7.5.2" - }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.0.tgz", + "integrity": "sha512-0VQY1K35DQET3dVYWpOaPFecqOT9dbuCfzjxoQyif1Wc574t3kOSkKevULddcR9znz1TcklCE7Ht6NIxjvTqLA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" + "node": ">= 10.0.0" }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/instrumentation-nestjs-core": { - "version": "0.40.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-nestjs-core/-/instrumentation-nestjs-core-0.40.0.tgz", - "integrity": "sha512-WF1hCUed07vKmf5BzEkL0wSPinqJgH7kGzOjjMAiTGacofNXjb/y4KQ8loj2sNsh5C/NN7s1zxQuCgbWbVTGKg==", - "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.0.tgz", + "integrity": "sha512-6uHywSIzz8+vi2lAzFeltnYbdHsDm3iIB57d4g5oaB9vKwjb6N6dRIgZMujw4nm5r6v9/BQH0noq6DzHrqr2pA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" + "node": ">= 10.0.0" }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "bin": { - "semver": "bin/semver.js" - }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.0.tgz", + "integrity": "sha512-BfNjXwZKxBy4WibDb/LDCriWSKLz+jJRL3cM/DllnHH5QUyoiUNEp3GmL80ZqxeumoADfCCP19+qiYiC8gUBjA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10" + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@opentelemetry/context-async-hooks": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-1.26.0.tgz", - "integrity": "sha512-HedpXXYzzbaoutw6DFLWLDket2FwLkLpil4hGCZ1xYEIMTcivdfwEOISgdbLEWyG3HW52gTq2V9mOVJrONgiwg==", + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.0.tgz", + "integrity": "sha512-S1qARKOphxfiBEkwLUbHjCY9BWPdWnW9j7f7Hb2jPplu8UZ3nes7zpPOW9bkLbHRvWM0WDTsjdOTUgW0xLBN1Q==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" + "node": ">= 10.0.0" }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@opentelemetry/core": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.26.0.tgz", - "integrity": "sha512-1iKxXXE8415Cdv0yjG3G6hQnB5eVEsJce3QaawX8SjDn0mAS0ZM8fAbZZJD4ajvhC15cePvosSCut404KrIIvQ==", - "dependencies": { - "@opentelemetry/semantic-conventions": "1.27.0" - }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.0.tgz", + "integrity": "sha512-d9AOkusyXARkFD66S6zlGXyzx5RvY+chTP9Jp0ypSTC9d4lzyRs9ovGf/80VCxjKddcUvnsGwCHWuF2EoPgWjw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" + "node": ">= 10.0.0" }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@opentelemetry/exporter-logs-otlp-grpc": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-grpc/-/exporter-logs-otlp-grpc-0.53.0.tgz", - "integrity": "sha512-x5ygAQgWAQOI+UOhyV3z9eW7QU2dCfnfOuIBiyYmC2AWr74f6x/3JBnP27IAcEx6aihpqBYWKnpoUTztkVPAZw==", - "dependencies": { - "@grpc/grpc-js": "^1.7.1", - "@opentelemetry/core": "1.26.0", - "@opentelemetry/otlp-grpc-exporter-base": "0.53.0", - "@opentelemetry/otlp-transformer": "0.53.0", - "@opentelemetry/sdk-logs": "0.53.0" - }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.0.tgz", + "integrity": "sha512-iqOC+GoTDoFyk/VYSFHwjHhYrk8bljW6zOhPuhi5t9ulqiYq1togGJB5e3PwYVFFfeVgc6pbz3JdQyDoBszVaA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" + "node": ">= 10.0.0" }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@opentelemetry/exporter-logs-otlp-http": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.53.0.tgz", - "integrity": "sha512-cSRKgD/n8rb+Yd+Cif6EnHEL/VZg1o8lEcEwFji1lwene6BdH51Zh3feAD9p2TyVoBKrl6Q9Zm2WltSp2k9gWQ==", + "node_modules/@parcel/watcher-wasm": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-wasm/-/watcher-wasm-2.5.0.tgz", + "integrity": "sha512-Z4ouuR8Pfggk1EYYbTaIoxc+Yv4o7cGQnH0Xy8+pQ+HbiW+ZnwhcD2LPf/prfq1nIWpAxjOkQ8uSMFWMtBLiVQ==", + "bundleDependencies": [ + "napi-wasm" + ], "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@opentelemetry/core": "1.26.0", - "@opentelemetry/otlp-exporter-base": "0.53.0", - "@opentelemetry/otlp-transformer": "0.53.0", - "@opentelemetry/sdk-logs": "0.53.0" + "is-glob": "^4.0.3", + "micromatch": "^4.0.5", + "napi-wasm": "^1.1.0" }, "engines": { - "node": ">=14" + "node": ">= 10.0.0" }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@opentelemetry/exporter-logs-otlp-proto": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.53.0.tgz", - "integrity": "sha512-jhEcVL1deeWNmTUP05UZMriZPSWUBcfg94ng7JuBb1q2NExgnADQFl1VQQ+xo62/JepK+MxQe4xAwlsDQFbISA==", - "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@opentelemetry/core": "1.26.0", - "@opentelemetry/otlp-exporter-base": "0.53.0", - "@opentelemetry/otlp-transformer": "0.53.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/sdk-logs": "0.53.0", - "@opentelemetry/sdk-trace-base": "1.26.0" - }, + "node_modules/@parcel/watcher-wasm/node_modules/napi-wasm": { + "version": "1.1.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.0.tgz", + "integrity": "sha512-twtft1d+JRNkM5YbmexfcH/N4znDtjgysFaV9zvZmmJezQsKpkfLYJ+JFV3uygugK6AtIM2oADPkB2AdhBrNig==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=14" + "node": ">= 10.0.0" }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@opentelemetry/exporter-logs-otlp-proto/node_modules/@opentelemetry/resources": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", - "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.0.tgz", + "integrity": "sha512-+rgpsNRKwo8A53elqbbHXdOMtY/tAtTzManTWShB5Kk54N8Q9mzNWV7tV+IbGueCbcj826MfWGU3mprWtuf1TA==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=14" + "node": ">= 10.0.0" }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@opentelemetry/exporter-logs-otlp-proto/node_modules/@opentelemetry/sdk-trace-base": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.26.0.tgz", - "integrity": "sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.0.tgz", + "integrity": "sha512-lPrxve92zEHdgeff3aiu4gDOIt4u7sJYha6wbdEZDCDUhtjTsOMiaJzG5lMY4GkWH8p0fMmO2Ppq5G5XXG+DQw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=14" + "node": ">= 10.0.0" }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@opentelemetry/exporter-metrics-otlp-http": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-http/-/exporter-metrics-otlp-http-0.53.0.tgz", - "integrity": "sha512-nvZtOk23pZOrTW10Za2WPd9pk4tWDvL6ALlHRFfInpcTjtOgCrv+fQDxpzosa5PeXvYeFFUO5aYCTnwiCX4Dzg==", - "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/otlp-exporter-base": "0.53.0", - "@opentelemetry/otlp-transformer": "0.53.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/sdk-metrics": "1.26.0" + "node_modules/@parcel/watcher/node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "bin": { + "detect-libc": "bin/detect-libc.js" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">=0.10" } }, - "node_modules/@opentelemetry/exporter-metrics-otlp-http/node_modules/@opentelemetry/resources": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", - "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", - "license": "Apache-2.0", + "node_modules/@parcel/watcher/node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==" + }, + "node_modules/@peculiar/asn1-schema": { + "version": "2.3.15", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.3.15.tgz", + "integrity": "sha512-QPeD8UA8axQREpgR5UTAfu2mqQmm97oUqahDtNdBcfj3qAnoXzFdQW+aNf/tD2WVXF8Fhmftxoj0eMIT++gX2w==", + "license": "MIT", "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "asn1js": "^3.0.5", + "pvtsutils": "^1.3.6", + "tslib": "^2.8.1" } }, - "node_modules/@opentelemetry/exporter-metrics-otlp-proto": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-proto/-/exporter-metrics-otlp-proto-0.53.0.tgz", - "integrity": "sha512-cO99cY04Oy+i8nfYoY0DOVRWVSb0unlerblvf4Fyt2Ls8CkUECLfgjfUXqdjOhBYOX/OZGOBSGetqqYFtKGdGA==", + "node_modules/@peculiar/asn1-schema/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@peculiar/json-schema": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@peculiar/json-schema/-/json-schema-1.1.12.tgz", + "integrity": "sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==", + "license": "MIT", "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/exporter-metrics-otlp-http": "0.53.0", - "@opentelemetry/otlp-exporter-base": "0.53.0", - "@opentelemetry/otlp-transformer": "0.53.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/sdk-metrics": "1.26.0" + "tslib": "^2.0.0" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">=8.0.0" } }, - "node_modules/@opentelemetry/exporter-metrics-otlp-proto/node_modules/@opentelemetry/resources": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", - "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", - "license": "Apache-2.0", + "node_modules/@peculiar/webcrypto": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.5.0.tgz", + "integrity": "sha512-BRs5XUAwiyCDQMsVA9IDvDa7UBR9gAvPHgugOeGng3YN6vJ9JYonyDc0lNczErgtCWtucjR5N7VtaonboD/ezg==", + "license": "MIT", "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" + "@peculiar/asn1-schema": "^2.3.8", + "@peculiar/json-schema": "^1.1.12", + "pvtsutils": "^1.3.5", + "tslib": "^2.6.2", + "webcrypto-core": "^1.8.0" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "node": ">=10.12.0" } }, - "node_modules/@opentelemetry/exporter-trace-otlp-grpc": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-grpc/-/exporter-trace-otlp-grpc-0.53.0.tgz", - "integrity": "sha512-m6KSh6OBDwfDjpzPVbuJbMgMbkoZfpxYH2r262KckgX9cMYvooWXEKzlJYsNDC6ADr28A1rtRoUVRwNfIN4tUg==", + "node_modules/@phenomnomnominal/tsquery": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@phenomnomnominal/tsquery/-/tsquery-5.0.1.tgz", + "integrity": "sha512-3nVv+e2FQwsW8Aw6qTU6f+1rfcJ3hrcnvH/mu9i8YhxO+9sqbOfpL8m6PbET5+xKOlz/VSbp0RoYWYCtIsnmuA==", + "dev": true, "dependencies": { - "@grpc/grpc-js": "^1.7.1", - "@opentelemetry/core": "1.26.0", - "@opentelemetry/otlp-grpc-exporter-base": "0.53.0", - "@opentelemetry/otlp-transformer": "0.53.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/sdk-trace-base": "1.26.0" + "esquery": "^1.4.0" }, + "peerDependencies": { + "typescript": "^3 || ^4 || ^5" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, "engines": { "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@opentelemetry/exporter-trace-otlp-grpc/node_modules/@opentelemetry/resources": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", - "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", - "license": "Apache-2.0", + "node_modules/@pnpm/config.env-replace": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", + "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", + "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" + "graceful-fs": "4.2.10" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "node": ">=12.22.0" } }, - "node_modules/@opentelemetry/exporter-trace-otlp-grpc/node_modules/@opentelemetry/sdk-trace-base": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.26.0.tgz", - "integrity": "sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw==", - "license": "Apache-2.0", + "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/@pnpm/npm-conf": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.2.2.tgz", + "integrity": "sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==", "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" + "@pnpm/config.env-replace": "^1.1.0", + "@pnpm/network.ca-file": "^1.0.1", + "config-chain": "^1.1.11" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "node": ">=12" } }, - "node_modules/@opentelemetry/exporter-trace-otlp-proto": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-proto/-/exporter-trace-otlp-proto-0.53.0.tgz", - "integrity": "sha512-T/bdXslwRKj23S96qbvGtaYOdfyew3TjPEKOk5mHjkCmkVl1O9C/YMdejwSsdLdOq2YW30KjR9kVi0YMxZushQ==", + "node_modules/@polka/url": { + "version": "1.0.0-next.25", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.25.tgz", + "integrity": "sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==" + }, + "node_modules/@polkadot-api/json-rpc-provider": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@polkadot-api/json-rpc-provider/-/json-rpc-provider-0.0.1.tgz", + "integrity": "sha512-/SMC/l7foRjpykLTUTacIH05H3mr9ip8b5xxfwXlVezXrNVLp3Cv0GX6uItkKd+ZjzVPf3PFrDF2B2/HLSNESA==", + "license": "MIT", + "optional": true + }, + "node_modules/@polkadot-api/json-rpc-provider-proxy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@polkadot-api/json-rpc-provider-proxy/-/json-rpc-provider-proxy-0.1.0.tgz", + "integrity": "sha512-8GSFE5+EF73MCuLQm8tjrbCqlgclcHBSRaswvXziJ0ZW7iw3UEMsKkkKvELayWyBuOPa2T5i1nj6gFOeIsqvrg==", + "license": "MIT", + "optional": true + }, + "node_modules/@polkadot-api/metadata-builders": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@polkadot-api/metadata-builders/-/metadata-builders-0.3.2.tgz", + "integrity": "sha512-TKpfoT6vTb+513KDzMBTfCb/ORdgRnsS3TDFpOhAhZ08ikvK+hjHMt5plPiAX/OWkm1Wc9I3+K6W0hX5Ab7MVg==", + "license": "MIT", + "optional": true, "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/otlp-exporter-base": "0.53.0", - "@opentelemetry/otlp-transformer": "0.53.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/sdk-trace-base": "1.26.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@polkadot-api/substrate-bindings": "0.6.0", + "@polkadot-api/utils": "0.1.0" } }, - "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/resources": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", - "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", - "license": "Apache-2.0", + "node_modules/@polkadot-api/observable-client": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@polkadot-api/observable-client/-/observable-client-0.3.2.tgz", + "integrity": "sha512-HGgqWgEutVyOBXoGOPp4+IAq6CNdK/3MfQJmhCJb8YaJiaK4W6aRGrdQuQSTPHfERHCARt9BrOmEvTXAT257Ug==", + "license": "MIT", + "optional": true, "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" + "@polkadot-api/metadata-builders": "0.3.2", + "@polkadot-api/substrate-bindings": "0.6.0", + "@polkadot-api/utils": "0.1.0" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "@polkadot-api/substrate-client": "0.1.4", + "rxjs": ">=7.8.0" } }, - "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/sdk-trace-base": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.26.0.tgz", - "integrity": "sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw==", - "license": "Apache-2.0", + "node_modules/@polkadot-api/substrate-bindings": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@polkadot-api/substrate-bindings/-/substrate-bindings-0.6.0.tgz", + "integrity": "sha512-lGuhE74NA1/PqdN7fKFdE5C1gNYX357j1tWzdlPXI0kQ7h3kN0zfxNOpPUN7dIrPcOFZ6C0tRRVrBylXkI6xPw==", + "license": "MIT", + "optional": true, "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "@noble/hashes": "^1.3.1", + "@polkadot-api/utils": "0.1.0", + "@scure/base": "^1.1.1", + "scale-ts": "^1.6.0" } }, - "node_modules/@opentelemetry/exporter-zipkin": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-zipkin/-/exporter-zipkin-1.26.0.tgz", - "integrity": "sha512-PW5R34n3SJHO4t0UetyHKiXL6LixIqWN6lWncg3eRXhKuT30x+b7m5sDJS0kEWRfHeS+kG7uCw2vBzmB2lk3Dw==", + "node_modules/@polkadot-api/substrate-client": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@polkadot-api/substrate-client/-/substrate-client-0.1.4.tgz", + "integrity": "sha512-MljrPobN0ZWTpn++da9vOvt+Ex+NlqTlr/XT7zi9sqPtDJiQcYl+d29hFAgpaeTqbeQKZwz3WDE9xcEfLE8c5A==", + "license": "MIT", + "optional": true, "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/sdk-trace-base": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@polkadot-api/json-rpc-provider": "0.0.1", + "@polkadot-api/utils": "0.1.0" } }, - "node_modules/@opentelemetry/exporter-zipkin/node_modules/@opentelemetry/resources": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", - "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", + "node_modules/@polkadot-api/utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@polkadot-api/utils/-/utils-0.1.0.tgz", + "integrity": "sha512-MXzWZeuGxKizPx2Xf/47wx9sr/uxKw39bVJUptTJdsaQn/TGq+z310mHzf1RCGvC1diHM8f593KrnDgc9oNbJA==", + "license": "MIT", + "optional": true + }, + "node_modules/@polkadot/api": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@polkadot/api/-/api-14.1.1.tgz", + "integrity": "sha512-3uSJUdaohKtAvj9fjqyOkYs0PthWBdWtkko2TcYGRxj9BikbZMmx+agdkty8VrOxvn3pPoTRKe/jMt2Txn2MaA==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" + "@polkadot/api-augment": "14.1.1", + "@polkadot/api-base": "14.1.1", + "@polkadot/api-derive": "14.1.1", + "@polkadot/keyring": "^13.2.1", + "@polkadot/rpc-augment": "14.1.1", + "@polkadot/rpc-core": "14.1.1", + "@polkadot/rpc-provider": "14.1.1", + "@polkadot/types": "14.1.1", + "@polkadot/types-augment": "14.1.1", + "@polkadot/types-codec": "14.1.1", + "@polkadot/types-create": "14.1.1", + "@polkadot/types-known": "14.1.1", + "@polkadot/util": "^13.2.1", + "@polkadot/util-crypto": "^13.2.1", + "eventemitter3": "^5.0.1", + "rxjs": "^7.8.1", + "tslib": "^2.8.0" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "node": ">=18" } }, - "node_modules/@opentelemetry/exporter-zipkin/node_modules/@opentelemetry/sdk-trace-base": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.26.0.tgz", - "integrity": "sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw==", + "node_modules/@polkadot/api-augment": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@polkadot/api-augment/-/api-augment-14.1.1.tgz", + "integrity": "sha512-n6aexVgdlHfh3d12qFYpooxzS9yjKq/oxLNXKvhpV3CMg36Hlq4ULDdtI6L3sB8I3nwdBEWaXyBvbpKvPZGUxQ==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" + "@polkadot/api-base": "14.1.1", + "@polkadot/rpc-augment": "14.1.1", + "@polkadot/types": "14.1.1", + "@polkadot/types-augment": "14.1.1", + "@polkadot/types-codec": "14.1.1", + "@polkadot/util": "^13.2.1", + "tslib": "^2.8.0" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "node": ">=18" } }, - "node_modules/@opentelemetry/instrumentation-amqplib": { - "version": "0.42.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-amqplib/-/instrumentation-amqplib-0.42.0.tgz", - "integrity": "sha512-fiuU6OKsqHJiydHWgTRQ7MnIrJ2lEqsdgFtNIH4LbAUJl/5XmrIeoDzDnox+hfkgWK65jsleFuQDtYb5hW1koQ==", - "dependencies": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } + "node_modules/@polkadot/api-augment/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" }, - "node_modules/@opentelemetry/instrumentation-amqplib/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "node_modules/@polkadot/api-base": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@polkadot/api-base/-/api-base-14.1.1.tgz", + "integrity": "sha512-gMj0uIlAv6RkRMzmhl61KU1/Pcadrarxn0lBdDTcVua3KEWLuncI+VbiN3cEd/aW6QUTgcDFpppm8nfwD9eVzQ==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" + "@polkadot/rpc-core": "14.1.1", + "@polkadot/types": "14.1.1", + "@polkadot/util": "^13.2.1", + "rxjs": "^7.8.1", + "tslib": "^2.8.0" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">=18" } }, - "node_modules/@opentelemetry/instrumentation-amqplib/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } + "node_modules/@polkadot/api-base/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" }, - "node_modules/@opentelemetry/instrumentation-aws-lambda": { - "version": "0.45.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-aws-lambda/-/instrumentation-aws-lambda-0.45.0.tgz", - "integrity": "sha512-22ZnmYftKjFoiqC1k3tu2AVKiXSZv+ohuHWk4V4MdJpPuNkadY624aDkv5BmwDeavDxVFgqE9nGgDM9s3Q94mg==", + "node_modules/@polkadot/api-derive": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@polkadot/api-derive/-/api-derive-14.1.1.tgz", + "integrity": "sha512-ZElYAr/euw2fR7RmGkgJgF88IK9iz3rqgesmdLtgQ2a85MEiR4UrVvhNKSjMr9PSn7EUM1mUixZhGp3jvuqrsA==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/propagator-aws-xray": "^1.3.1", - "@opentelemetry/resources": "^1.8.0", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@types/aws-lambda": "8.10.143" + "@polkadot/api": "14.1.1", + "@polkadot/api-augment": "14.1.1", + "@polkadot/api-base": "14.1.1", + "@polkadot/rpc-core": "14.1.1", + "@polkadot/types": "14.1.1", + "@polkadot/types-codec": "14.1.1", + "@polkadot/util": "^13.2.1", + "@polkadot/util-crypto": "^13.2.1", + "rxjs": "^7.8.1", + "tslib": "^2.8.0" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">=18" } }, - "node_modules/@opentelemetry/instrumentation-aws-lambda/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "node_modules/@polkadot/api-derive/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@polkadot/api/node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" + }, + "node_modules/@polkadot/api/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@polkadot/keyring": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/@polkadot/keyring/-/keyring-13.2.3.tgz", + "integrity": "sha512-pgTo6DXNXub0wGD+MnVHYhKxf80Jl+QMOCb818ioGdXz++Uw4mTueFAwtB+N7TGo0HafhChUiNJDxFdlDkcAng==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" + "@polkadot/util": "13.2.3", + "@polkadot/util-crypto": "13.2.3", + "tslib": "^2.8.0" }, "engines": { - "node": ">=14" + "node": ">=18" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@polkadot/util": "13.2.3", + "@polkadot/util-crypto": "13.2.3" } }, - "node_modules/@opentelemetry/instrumentation-aws-lambda/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } + "node_modules/@polkadot/keyring/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" }, - "node_modules/@opentelemetry/instrumentation-aws-sdk": { - "version": "0.44.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-aws-sdk/-/instrumentation-aws-sdk-0.44.0.tgz", - "integrity": "sha512-HIWFg4TDQsayceiikOnruMmyQ0SZYW6WiR+wknWwWVLHC3lHTCpAnqzp5V42ckArOdlwHZu2Jvq2GMSM4Myx3w==", + "node_modules/@polkadot/networks": { + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/@polkadot/networks/-/networks-13.3.1.tgz", + "integrity": "sha512-g/0OmCMUrbbW4RQ/xajTYd2SMJvFKY4kmMvpxtNN57hWQpY7c5oDXSz57jGH2uwvcBWeDfaNokcS+9hJL1RBcA==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/propagation-utils": "^0.30.11", - "@opentelemetry/semantic-conventions": "^1.27.0" + "@polkadot/util": "13.3.1", + "@substrate/ss58-registry": "^1.51.0", + "tslib": "^2.8.0" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">=18" } }, - "node_modules/@opentelemetry/instrumentation-aws-sdk/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "node_modules/@polkadot/networks/node_modules/@polkadot/util": { + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/@polkadot/util/-/util-13.3.1.tgz", + "integrity": "sha512-5crLP/rUZOJzuo/W8t73J8PxpibJ5vrxY57rR6V+mIpCZd1ORiw0wxeHcV5F9Adpn7yJyuGBwxPbueNR5Rr1Zw==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" + "@polkadot/x-bigint": "13.3.1", + "@polkadot/x-global": "13.3.1", + "@polkadot/x-textdecoder": "13.3.1", + "@polkadot/x-textencoder": "13.3.1", + "@types/bn.js": "^5.1.6", + "bn.js": "^5.2.1", + "tslib": "^2.8.0" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">=18" } }, - "node_modules/@opentelemetry/instrumentation-aws-sdk/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/@polkadot/networks/node_modules/@polkadot/x-textdecoder": { + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/@polkadot/x-textdecoder/-/x-textdecoder-13.3.1.tgz", + "integrity": "sha512-g2R9O1p0ZsNDhZ3uEBZh6fQaVLlo3yFr0YNqt15v7e9lBI4APvTJ202EINlo2jB5lz/R438/BdjEA3AL+0zUtQ==", + "license": "Apache-2.0", + "dependencies": { + "@polkadot/x-global": "13.3.1", + "tslib": "^2.8.0" }, "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/@opentelemetry/instrumentation-bunyan": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-bunyan/-/instrumentation-bunyan-0.41.0.tgz", - "integrity": "sha512-NoQS+gcwQ7pzb2PZFyra6bAxDAVXBMmpKxBblEuXJWirGrAksQllg9XTdmqhrwT/KxUYrbVca/lMams7e51ysg==", + "node_modules/@polkadot/networks/node_modules/@polkadot/x-textencoder": { + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/@polkadot/x-textencoder/-/x-textencoder-13.3.1.tgz", + "integrity": "sha512-DnHLUdoKDYxekfxopuUuPB+j5Mu7Jemejcduu5gz3/89GP/sYPAu0CAVbq9B+hK1yGjBBj31eA4wkAV1oktYmg==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "^0.53.0", - "@opentelemetry/instrumentation": "^0.53.0", - "@types/bunyan": "1.8.9" + "@polkadot/x-global": "13.3.1", + "tslib": "^2.8.0" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">=18" } }, - "node_modules/@opentelemetry/instrumentation-bunyan/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "node_modules/@polkadot/networks/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@polkadot/rpc-augment": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@polkadot/rpc-augment/-/rpc-augment-14.1.1.tgz", + "integrity": "sha512-jeDYDepe6IOzgUFD+vLEuLrWGqw/dJIcxb8uf/YpnsvzA8kbPZx3BcIhboIpI8HpdKdn6f5mflSTVgDUpUPmNg==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" + "@polkadot/rpc-core": "14.1.1", + "@polkadot/types": "14.1.1", + "@polkadot/types-codec": "14.1.1", + "@polkadot/util": "^13.2.1", + "tslib": "^2.8.0" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">=18" } }, - "node_modules/@opentelemetry/instrumentation-bunyan/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } + "node_modules/@polkadot/rpc-augment/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" }, - "node_modules/@opentelemetry/instrumentation-cassandra-driver": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-cassandra-driver/-/instrumentation-cassandra-driver-0.41.0.tgz", - "integrity": "sha512-hvTNcC8qjCQEHZTLAlTmDptjsEGqCKpN+90hHH8Nn/GwilGr5TMSwGrlfstdJuZWyw8HAnRUed6bcjvmHHk2Xw==", + "node_modules/@polkadot/rpc-core": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@polkadot/rpc-core/-/rpc-core-14.1.1.tgz", + "integrity": "sha512-rfV1ArJcAZQ3lzAM9P+yIaXN720yJysNGy14FxupLsFsvzowEnEPs4khS2HgnX6j1RqkElw6va/ZVhOsLPhy9w==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0" + "@polkadot/rpc-augment": "14.1.1", + "@polkadot/rpc-provider": "14.1.1", + "@polkadot/types": "14.1.1", + "@polkadot/util": "^13.2.1", + "rxjs": "^7.8.1", + "tslib": "^2.8.0" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">=18" } }, - "node_modules/@opentelemetry/instrumentation-cassandra-driver/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "node_modules/@polkadot/rpc-core/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@polkadot/rpc-provider": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@polkadot/rpc-provider/-/rpc-provider-14.1.1.tgz", + "integrity": "sha512-BY0H1CC7M360uHXU2IfFdgFmcdjmIz6NxPmXRhrT3QGFmJSHuFevjTbIFlPG7YBK5ivochLrcISelRr7HKXYOg==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" + "@polkadot/keyring": "^13.2.1", + "@polkadot/types": "14.1.1", + "@polkadot/types-support": "14.1.1", + "@polkadot/util": "^13.2.1", + "@polkadot/util-crypto": "^13.2.1", + "@polkadot/x-fetch": "^13.2.1", + "@polkadot/x-global": "^13.2.1", + "@polkadot/x-ws": "^13.2.1", + "eventemitter3": "^5.0.1", + "mock-socket": "^9.3.1", + "nock": "^13.5.5", + "tslib": "^2.8.0" }, "engines": { - "node": ">=14" + "node": ">=18" }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "optionalDependencies": { + "@substrate/connect": "0.8.11" } }, - "node_modules/@opentelemetry/instrumentation-cassandra-driver/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } + "node_modules/@polkadot/rpc-provider/node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" }, - "node_modules/@opentelemetry/instrumentation-connect": { - "version": "0.39.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.39.0.tgz", - "integrity": "sha512-pGBiKevLq7NNglMgqzmeKczF4XQMTOUOTkK8afRHMZMnrK3fcETyTH7lVaSozwiOM3Ws+SuEmXZT7DYrrhxGlg==", + "node_modules/@polkadot/rpc-provider/node_modules/nock": { + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/nock/-/nock-13.5.6.tgz", + "integrity": "sha512-o2zOYiCpzRqSzPj0Zt/dQ/DqZeYoaQ7TUonc/xUPjCGl9WeHpNbxgVvOquXYAaJzI0M9BXV3HTzG0p8IUAbBTQ==", + "license": "MIT", "dependencies": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@types/connect": "3.4.36" + "debug": "^4.1.0", + "json-stringify-safe": "^5.0.1", + "propagate": "^2.0.0" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">= 10.13" } }, - "node_modules/@opentelemetry/instrumentation-connect/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "node_modules/@polkadot/rpc-provider/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@polkadot/types": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-14.1.1.tgz", + "integrity": "sha512-bT1wxu2wZsKR8Ih1PHu4SqptOF+MQbh21e+NJVZkIsrjQz1DvKkdcW4G/s0i0vX/QIjnXTJFC84vMzr5cxJm8Q==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" + "@polkadot/keyring": "^13.2.1", + "@polkadot/types-augment": "14.1.1", + "@polkadot/types-codec": "14.1.1", + "@polkadot/types-create": "14.1.1", + "@polkadot/util": "^13.2.1", + "@polkadot/util-crypto": "^13.2.1", + "rxjs": "^7.8.1", + "tslib": "^2.8.0" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">=18" } }, - "node_modules/@opentelemetry/instrumentation-connect/node_modules/@types/connect": { - "version": "3.4.36", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.36.tgz", - "integrity": "sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==", + "node_modules/@polkadot/types-augment": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-augment/-/types-augment-14.1.1.tgz", + "integrity": "sha512-A73JCwmg5ZuYVHw1k7Lxx4MjjRwQd6Yw/VaRIPqjk3iyG5r9RyFJgsJ7xRafDlKFG0AJ5c6ixvlaHOnBrEAzpQ==", + "license": "Apache-2.0", "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@opentelemetry/instrumentation-connect/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "@polkadot/types": "14.1.1", + "@polkadot/types-codec": "14.1.1", + "@polkadot/util": "^13.2.1", + "tslib": "^2.8.0" }, "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/@opentelemetry/instrumentation-cucumber": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-cucumber/-/instrumentation-cucumber-0.9.0.tgz", - "integrity": "sha512-4PQNFnIqnA2WM3ZHpr0xhZpHSqJ5xJ6ppTIzZC7wPqe+ZBpj41vG8B6ieqiPfq+im4QdqbYnzLb3rj48GDEN9g==", + "node_modules/@polkadot/types-augment/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@polkadot/types-codec": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-codec/-/types-codec-14.1.1.tgz", + "integrity": "sha512-O6UyTjEAeZMf/uthF3NjCy4tiAeWjj4tfTEWTx2Z65fNTTbXx1Mq5YBBOWsvzBXGBFK35C8buYa4l8cgQS9MoA==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0" + "@polkadot/util": "^13.2.1", + "@polkadot/x-bigint": "^13.2.1", + "tslib": "^2.8.0" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "node": ">=18" } }, - "node_modules/@opentelemetry/instrumentation-cucumber/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "node_modules/@polkadot/types-codec/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@polkadot/types-create": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-create/-/types-create-14.1.1.tgz", + "integrity": "sha512-t4gr5NKU8zZetnDvoRnlioEZlkYybBSql+Ep3mQUiJosF5w/SCN6EKV0GPqs0fB1ovqhDQSnwe2xoRjHsiHObA==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" + "@polkadot/types-codec": "14.1.1", + "@polkadot/util": "^13.2.1", + "tslib": "^2.8.0" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">=18" } }, - "node_modules/@opentelemetry/instrumentation-cucumber/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } + "node_modules/@polkadot/types-create/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" }, - "node_modules/@opentelemetry/instrumentation-dataloader": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dataloader/-/instrumentation-dataloader-0.12.0.tgz", - "integrity": "sha512-pnPxatoFE0OXIZDQhL2okF//dmbiWFzcSc8pUg9TqofCLYZySSxDCgQc69CJBo5JnI3Gz1KP+mOjS4WAeRIH4g==", + "node_modules/@polkadot/types-known": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-known/-/types-known-14.1.1.tgz", + "integrity": "sha512-TvyqTsm1Wxw+tjN8UsB04+vZv5znZE5ETGunHLHnvv4WF/lkz4WpkRc/9iqduM5O/iOZh8mEb7n/uyz8LL4brA==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0" + "@polkadot/networks": "^13.2.1", + "@polkadot/types": "14.1.1", + "@polkadot/types-codec": "14.1.1", + "@polkadot/types-create": "14.1.1", + "@polkadot/util": "^13.2.1", + "tslib": "^2.8.0" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">=18" } }, - "node_modules/@opentelemetry/instrumentation-dataloader/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "node_modules/@polkadot/types-known/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@polkadot/types-support": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-support/-/types-support-14.1.1.tgz", + "integrity": "sha512-DJgJ/2n3eWFlgH1K/U7G4NSbgdsx4Lb1fK4yVlZ9t81lJWWiAeb/FodHJb8jlQ6Jezx5S71fRripXfg+FdyCDA==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" + "@polkadot/util": "^13.2.1", + "tslib": "^2.8.0" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">=18" } }, - "node_modules/@opentelemetry/instrumentation-dataloader/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/@polkadot/types-support/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@polkadot/types/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@polkadot/util": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/@polkadot/util/-/util-13.2.3.tgz", + "integrity": "sha512-pioNnsig3qHXrfOKMe4Yqos8B8N3/EZUpS+WfTpWnn1VjYban/0GrTXeavPlAwggnY27b8fS6rBzQBhnVYDw8g==", + "license": "Apache-2.0", + "dependencies": { + "@polkadot/x-bigint": "13.2.3", + "@polkadot/x-global": "13.2.3", + "@polkadot/x-textdecoder": "13.2.3", + "@polkadot/x-textencoder": "13.2.3", + "@types/bn.js": "^5.1.6", + "bn.js": "^5.2.1", + "tslib": "^2.8.0" }, "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/@opentelemetry/instrumentation-dns": { - "version": "0.39.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dns/-/instrumentation-dns-0.39.0.tgz", - "integrity": "sha512-+iPzvXqVdJa67QBuz2tuP0UI3LS1/cMMo6dS7360DDtOQX+sQzkiN+mo3Omn4T6ZRhkTDw6c7uwsHBcmL31+1g==", + "node_modules/@polkadot/util-crypto": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/@polkadot/util-crypto/-/util-crypto-13.2.3.tgz", + "integrity": "sha512-5sbggmLbn5eiuVMyPROPlT5roHRqdKHOfSpioNbGvGIZ1qIWVoC1RfsK0NWJOVGDzy6DpQe0KYT/kgcU5Xsrzw==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "semver": "^7.5.4" + "@noble/curves": "^1.3.0", + "@noble/hashes": "^1.3.3", + "@polkadot/networks": "13.2.3", + "@polkadot/util": "13.2.3", + "@polkadot/wasm-crypto": "^7.4.1", + "@polkadot/wasm-util": "^7.4.1", + "@polkadot/x-bigint": "13.2.3", + "@polkadot/x-randomvalues": "13.2.3", + "@scure/base": "^1.1.7", + "tslib": "^2.8.0" }, "engines": { - "node": ">=14" + "node": ">=18" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@polkadot/util": "13.2.3" } }, - "node_modules/@opentelemetry/instrumentation-dns/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "node_modules/@polkadot/util-crypto/node_modules/@polkadot/networks": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/@polkadot/networks/-/networks-13.2.3.tgz", + "integrity": "sha512-mG+zkXg/33AyPrkv2xBbAo3LBUwOwBn6qznBU/4jxiZPnVvCwMaxE7xHM22B5riItbNJ169FXv3wy0v6ZmkFbw==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" + "@polkadot/util": "13.2.3", + "@substrate/ss58-registry": "^1.51.0", + "tslib": "^2.8.0" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">=18" } }, - "node_modules/@opentelemetry/instrumentation-dns/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "bin": { - "semver": "bin/semver.js" + "node_modules/@polkadot/util-crypto/node_modules/@polkadot/x-bigint": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/@polkadot/x-bigint/-/x-bigint-13.2.3.tgz", + "integrity": "sha512-VKgEAh0LsxTd/Hg517Tt5ZU4CySjBwMpaojbkjgv3fOdg1cN7t4eFEUxpyj7mlO0cp22SzDh7nmy4TO98qhLQA==", + "license": "Apache-2.0", + "dependencies": { + "@polkadot/x-global": "13.2.3", + "tslib": "^2.8.0" }, "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/@opentelemetry/instrumentation-fastify": { - "version": "0.40.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fastify/-/instrumentation-fastify-0.40.0.tgz", - "integrity": "sha512-74qj4nG3zPtU7g2x4sm2T4R3/pBMyrYstTsqSZwdlhQk1SD4l8OSY9sPRX1qkhfxOuW3U4KZQAV/Cymb3fB6hg==", + "node_modules/@polkadot/util-crypto/node_modules/@polkadot/x-global": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/@polkadot/x-global/-/x-global-13.2.3.tgz", + "integrity": "sha512-7MYQIAEwBkRcNrgqac5PbB0kNPlI6ISJEy6/Nb+crj8BFjQ8rf11PF49fq0QsvDeuYM1aNLigrvYZNptQs4lbw==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0" + "tslib": "^2.8.0" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">=18" } }, - "node_modules/@opentelemetry/instrumentation-fastify/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "node_modules/@polkadot/util-crypto/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@polkadot/util/node_modules/@polkadot/x-bigint": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/@polkadot/x-bigint/-/x-bigint-13.2.3.tgz", + "integrity": "sha512-VKgEAh0LsxTd/Hg517Tt5ZU4CySjBwMpaojbkjgv3fOdg1cN7t4eFEUxpyj7mlO0cp22SzDh7nmy4TO98qhLQA==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" + "@polkadot/x-global": "13.2.3", + "tslib": "^2.8.0" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">=18" } }, - "node_modules/@opentelemetry/instrumentation-fastify/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/@polkadot/util/node_modules/@polkadot/x-global": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/@polkadot/x-global/-/x-global-13.2.3.tgz", + "integrity": "sha512-7MYQIAEwBkRcNrgqac5PbB0kNPlI6ISJEy6/Nb+crj8BFjQ8rf11PF49fq0QsvDeuYM1aNLigrvYZNptQs4lbw==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" }, "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/@opentelemetry/instrumentation-fs": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fs/-/instrumentation-fs-0.15.0.tgz", - "integrity": "sha512-JWVKdNLpu1skqZQA//jKOcKdJC66TWKqa2FUFq70rKohvaSq47pmXlnabNO+B/BvLfmidfiaN35XakT5RyMl2Q==", + "node_modules/@polkadot/util/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@polkadot/wasm-bridge": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-bridge/-/wasm-bridge-7.4.1.tgz", + "integrity": "sha512-tdkJaV453tezBxhF39r4oeG0A39sPKGDJmN81LYLf+Fihb7astzwju+u75BRmDrHZjZIv00un3razJEWCxze6g==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.53.0" + "@polkadot/wasm-util": "7.4.1", + "tslib": "^2.7.0" }, "engines": { - "node": ">=14" + "node": ">=18" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@polkadot/util": "*", + "@polkadot/x-randomvalues": "*" } }, - "node_modules/@opentelemetry/instrumentation-fs/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "node_modules/@polkadot/wasm-bridge/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@polkadot/wasm-crypto": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto/-/wasm-crypto-7.4.1.tgz", + "integrity": "sha512-kHN/kF7hYxm1y0WeFLWeWir6oTzvcFmR4N8fJJokR+ajYbdmrafPN+6iLgQVbhZnDdxyv9jWDuRRsDnBx8tPMQ==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" + "@polkadot/wasm-bridge": "7.4.1", + "@polkadot/wasm-crypto-asmjs": "7.4.1", + "@polkadot/wasm-crypto-init": "7.4.1", + "@polkadot/wasm-crypto-wasm": "7.4.1", + "@polkadot/wasm-util": "7.4.1", + "tslib": "^2.7.0" }, "engines": { - "node": ">=14" + "node": ">=18" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@polkadot/util": "*", + "@polkadot/x-randomvalues": "*" } }, - "node_modules/@opentelemetry/instrumentation-fs/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/@polkadot/wasm-crypto-asmjs": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-asmjs/-/wasm-crypto-asmjs-7.4.1.tgz", + "integrity": "sha512-pwU8QXhUW7IberyHJIQr37IhbB6DPkCG5FhozCiNTq4vFBsFPjm9q8aZh7oX1QHQaiAZa2m2/VjIVE+FHGbvHQ==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.7.0" }, "engines": { - "node": ">=10" + "node": ">=18" + }, + "peerDependencies": { + "@polkadot/util": "*" } }, - "node_modules/@opentelemetry/instrumentation-generic-pool": { - "version": "0.39.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.39.0.tgz", - "integrity": "sha512-y4v8Y+tSfRB3NNBvHjbjrn7rX/7sdARG7FuK6zR8PGb28CTa0kHpEGCJqvL9L8xkTNvTXo+lM36ajFGUaK1aNw==", + "node_modules/@polkadot/wasm-crypto-asmjs/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@polkadot/wasm-crypto-init": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-init/-/wasm-crypto-init-7.4.1.tgz", + "integrity": "sha512-AVka33+f7MvXEEIGq5U0dhaA2SaXMXnxVCQyhJTaCnJ5bRDj0Xlm3ijwDEQUiaDql7EikbkkRtmlvs95eSUWYQ==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0" + "@polkadot/wasm-bridge": "7.4.1", + "@polkadot/wasm-crypto-asmjs": "7.4.1", + "@polkadot/wasm-crypto-wasm": "7.4.1", + "@polkadot/wasm-util": "7.4.1", + "tslib": "^2.7.0" }, "engines": { - "node": ">=14" + "node": ">=18" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@polkadot/util": "*", + "@polkadot/x-randomvalues": "*" } }, - "node_modules/@opentelemetry/instrumentation-generic-pool/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "node_modules/@polkadot/wasm-crypto-init/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@polkadot/wasm-crypto-wasm": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-wasm/-/wasm-crypto-wasm-7.4.1.tgz", + "integrity": "sha512-PE1OAoupFR0ZOV2O8tr7D1FEUAwaggzxtfs3Aa5gr+yxlSOaWUKeqsOYe1KdrcjmZVV3iINEAXxgrbzCmiuONg==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" + "@polkadot/wasm-util": "7.4.1", + "tslib": "^2.7.0" }, "engines": { - "node": ">=14" + "node": ">=18" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@polkadot/util": "*" } }, - "node_modules/@opentelemetry/instrumentation-generic-pool/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } + "node_modules/@polkadot/wasm-crypto-wasm/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" }, - "node_modules/@opentelemetry/instrumentation-graphql": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.43.0.tgz", - "integrity": "sha512-aI3YMmC2McGd8KW5du1a2gBA0iOMOGLqg4s9YjzwbjFwjlmMNFSK1P3AIg374GWg823RPUGfVTIgZ/juk9CVOA==", + "node_modules/@polkadot/wasm-crypto/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@polkadot/wasm-util": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-util/-/wasm-util-7.4.1.tgz", + "integrity": "sha512-RAcxNFf3zzpkr+LX/ItAsvj+QyM56TomJ0xjUMo4wKkHjwsxkz4dWJtx5knIgQz/OthqSDMR59VNEycQeNuXzA==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0" + "tslib": "^2.7.0" }, "engines": { - "node": ">=14" + "node": ">=18" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@polkadot/util": "*" } }, - "node_modules/@opentelemetry/instrumentation-graphql/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "node_modules/@polkadot/wasm-util/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@polkadot/x-bigint": { + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/@polkadot/x-bigint/-/x-bigint-13.3.1.tgz", + "integrity": "sha512-ewc708a7LUdrT92v9DsSAIbcJQBn3aR9/LavF/iyMOq5lZJyPXDSjAnskfMs818R3RLCrKVKfs+aKkxt2eqo8g==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" + "@polkadot/x-global": "13.3.1", + "tslib": "^2.8.0" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">=18" } }, - "node_modules/@opentelemetry/instrumentation-graphql/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/@polkadot/x-bigint/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@polkadot/x-fetch": { + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/@polkadot/x-fetch/-/x-fetch-13.3.1.tgz", + "integrity": "sha512-J+HM42j0KGqdC/eo7vmsdLPz74MR7+0My4km6TG9HGjKqqztwygtenpopPod2SbRnL4nHiEG0wZzpVOW6HN2gw==", + "license": "Apache-2.0", + "dependencies": { + "@polkadot/x-global": "13.3.1", + "node-fetch": "^3.3.2", + "tslib": "^2.8.0" }, "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/@opentelemetry/instrumentation-grpc": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-grpc/-/instrumentation-grpc-0.53.0.tgz", - "integrity": "sha512-Ss338T92yE1UCgr9zXSY3cPuaAy27uQw+wAC5IwsQKCXL5wwkiOgkd+2Ngksa9EGsgUEMwGeHi76bDdHFJ5Rrw==", + "node_modules/@polkadot/x-fetch/node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/@polkadot/x-fetch/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", "dependencies": { - "@opentelemetry/instrumentation": "0.53.0", - "@opentelemetry/semantic-conventions": "1.27.0" + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" }, "engines": { - "node": ">=14" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" } }, - "node_modules/@opentelemetry/instrumentation-grpc/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "node_modules/@polkadot/x-fetch/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@polkadot/x-global": { + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/@polkadot/x-global/-/x-global-13.3.1.tgz", + "integrity": "sha512-861TeIw49a3JvkwlUWrddfG+JaUqtFZDsemYxxZIjjcRJLrKOsoKNqHbiHi2OPrwlX8PwAA/wc5I9Q4XRQ7KEg==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" + "tslib": "^2.8.0" }, "engines": { - "node": ">=14" + "node": ">=18" + } + }, + "node_modules/@polkadot/x-global/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@polkadot/x-randomvalues": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/@polkadot/x-randomvalues/-/x-randomvalues-13.2.3.tgz", + "integrity": "sha512-Zf0GTfLmVk+VzPUmcQSpXjjmFzMTjPhXoLuIoE7xIu73T+vQ+TX9j7DvorN6bIRsnZ9l1SyTZsSf/NTjNZKIZg==", + "license": "Apache-2.0", + "dependencies": { + "@polkadot/x-global": "13.2.3", + "tslib": "^2.8.0" + }, + "engines": { + "node": ">=18" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@polkadot/util": "13.2.3", + "@polkadot/wasm-util": "*" } }, - "node_modules/@opentelemetry/instrumentation-grpc/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/@polkadot/x-randomvalues/node_modules/@polkadot/x-global": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/@polkadot/x-global/-/x-global-13.2.3.tgz", + "integrity": "sha512-7MYQIAEwBkRcNrgqac5PbB0kNPlI6ISJEy6/Nb+crj8BFjQ8rf11PF49fq0QsvDeuYM1aNLigrvYZNptQs4lbw==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" }, "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/@opentelemetry/instrumentation-hapi": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.41.0.tgz", - "integrity": "sha512-jKDrxPNXDByPlYcMdZjNPYCvw0SQJjN+B1A+QH+sx+sAHsKSAf9hwFiJSrI6C4XdOls43V/f/fkp9ITkHhKFbQ==", + "node_modules/@polkadot/x-randomvalues/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@polkadot/x-textdecoder": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/@polkadot/x-textdecoder/-/x-textdecoder-13.2.3.tgz", + "integrity": "sha512-i8hRXPtGknmdm3FYv6/94I52VXHJZa5sgYNw1+Hqb4Jqmq4awUjea35CKXd/+aw70Qn8Ngg31l2GoiH494fa+Q==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0" + "@polkadot/x-global": "13.2.3", + "tslib": "^2.8.0" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">=18" } }, - "node_modules/@opentelemetry/instrumentation-hapi/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "node_modules/@polkadot/x-textdecoder/node_modules/@polkadot/x-global": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/@polkadot/x-global/-/x-global-13.2.3.tgz", + "integrity": "sha512-7MYQIAEwBkRcNrgqac5PbB0kNPlI6ISJEy6/Nb+crj8BFjQ8rf11PF49fq0QsvDeuYM1aNLigrvYZNptQs4lbw==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" + "tslib": "^2.8.0" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">=18" } }, - "node_modules/@opentelemetry/instrumentation-hapi/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/@polkadot/x-textdecoder/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@polkadot/x-textencoder": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/@polkadot/x-textencoder/-/x-textencoder-13.2.3.tgz", + "integrity": "sha512-wJI3Bb/dC4zyBXJFm5+ZhyBXWoI5wvP8k8qX0/ZC0PQsgSAqs7LVhiofk4Wd94n0P41W5re58LrGXLyziSAshw==", + "license": "Apache-2.0", + "dependencies": { + "@polkadot/x-global": "13.2.3", + "tslib": "^2.8.0" }, "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/@opentelemetry/instrumentation-ioredis": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.43.0.tgz", - "integrity": "sha512-i3Dke/LdhZbiUAEImmRG3i7Dimm/BD7t8pDDzwepSvIQ6s2X6FPia7561gw+64w+nx0+G9X14D7rEfaMEmmjig==", + "node_modules/@polkadot/x-textencoder/node_modules/@polkadot/x-global": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/@polkadot/x-global/-/x-global-13.2.3.tgz", + "integrity": "sha512-7MYQIAEwBkRcNrgqac5PbB0kNPlI6ISJEy6/Nb+crj8BFjQ8rf11PF49fq0QsvDeuYM1aNLigrvYZNptQs4lbw==", + "license": "Apache-2.0", "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/redis-common": "^0.36.2", - "@opentelemetry/semantic-conventions": "^1.27.0" + "tslib": "^2.8.0" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">=18" } }, - "node_modules/@opentelemetry/instrumentation-ioredis/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "node_modules/@polkadot/x-textencoder/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@polkadot/x-ws": { + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/@polkadot/x-ws/-/x-ws-13.3.1.tgz", + "integrity": "sha512-ytqkC7FwVs4BlzNFAmPMFp+xD1KIdMMP/mvCSOrnxjlsyM5DVGop4x4c2ZgDUBmrFqmIiVkWDfMIZeOxui2OLQ==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" + "@polkadot/x-global": "13.3.1", + "tslib": "^2.8.0", + "ws": "^8.18.0" }, "engines": { - "node": ">=14" + "node": ">=18" + } + }, + "node_modules/@polkadot/x-ws/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@prisma/client": { + "version": "5.8.1", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.8.1.tgz", + "integrity": "sha512-xQtMPfbIwLlbm0VVIVQY2yqQVOxPwRQhvIp7Z3m2900g1bu/zRHKhYZJQWELqmjl6d8YwBy0K2NvMqh47v1ubw==", + "hasInstallScript": true, + "engines": { + "node": ">=16.13" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "prisma": "*" + }, + "peerDependenciesMeta": { + "prisma": { + "optional": true + } + } + }, + "node_modules/@prisma/debug": { + "version": "5.16.2", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.16.2.tgz", + "integrity": "sha512-ItzB4nR4O8eLzuJiuP3WwUJfoIvewMHqpGCad+64gvThcKEVOtaUza9AEJo2DPqAOa/AWkFyK54oM4WwHeew+A==", + "devOptional": true + }, + "node_modules/@prisma/engines": { + "version": "5.16.2", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.16.2.tgz", + "integrity": "sha512-qUxwMtrwoG3byd4PbX6T7EjHJ8AUhzTuwniOGkh/hIznBfcE2QQnGakyEq4VnwNuttMqvh/GgPFapHQ3lCuRHg==", + "devOptional": true, + "hasInstallScript": true, + "dependencies": { + "@prisma/debug": "5.16.2", + "@prisma/engines-version": "5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303", + "@prisma/fetch-engine": "5.16.2", + "@prisma/get-platform": "5.16.2" + } + }, + "node_modules/@prisma/engines-version": { + "version": "5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303.tgz", + "integrity": "sha512-HkT2WbfmFZ9WUPyuJHhkiADxazHg8Y4gByrTSVeb3OikP6tjQ7txtSUGu9OBOBH0C13dPKN2qqH12xKtHu/Hiw==", + "devOptional": true + }, + "node_modules/@prisma/fetch-engine": { + "version": "5.16.2", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.16.2.tgz", + "integrity": "sha512-sq51lfHKfH2jjYSjBtMjP+AznFqOJzXpqmq6B9auWrlTJrMgZ7lPyhWUW7VU7LsQU48/TJ+DZeIz8s9bMYvcHg==", + "devOptional": true, + "dependencies": { + "@prisma/debug": "5.16.2", + "@prisma/engines-version": "5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303", + "@prisma/get-platform": "5.16.2" + } + }, + "node_modules/@prisma/get-platform": { + "version": "5.16.2", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.16.2.tgz", + "integrity": "sha512-cXiHPgNLNyj22vLouPVNegklpRL/iX2jxTeap5GRO3DmCoVyIHmJAV1CgUMUJhHlcol9yYy7EHvsnXTDJ/PKEA==", + "devOptional": true, + "dependencies": { + "@prisma/debug": "5.16.2" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, + "node_modules/@radix-ui/primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.1.tgz", + "integrity": "sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==", + "dependencies": { + "@babel/runtime": "^7.13.10" + } + }, + "node_modules/@radix-ui/react-arrow": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz", + "integrity": "sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw==", + "dependencies": { + "@radix-ui/react-primitive": "2.0.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-ioredis/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/@radix-ui/react-arrow/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", + "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-kafkajs": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-kafkajs/-/instrumentation-kafkajs-0.3.0.tgz", - "integrity": "sha512-UnkZueYK1ise8FXQeKlpBd7YYUtC7mM8J0wzUSccEfc/G8UqHQqAzIyYCUOUPUKp8GsjLnWOOK/3hJc4owb7Jg==", + "node_modules/@radix-ui/react-arrow/node_modules/@radix-ui/react-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz", + "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==", "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-slot": "1.1.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-kafkajs/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-arrow/node_modules/@radix-ui/react-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", + "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-compose-refs": "1.1.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-kafkajs/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-knex": { - "version": "0.40.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-knex/-/instrumentation-knex-0.40.0.tgz", - "integrity": "sha512-6jka2jfX8+fqjEbCn6hKWHVWe++mHrIkLQtaJqUkBt3ZBs2xn1+y0khxiDS0v/mNb0bIKDJWwtpKFfsQDM1Geg==", + "node_modules/@radix-ui/react-checkbox": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.1.1.tgz", + "integrity": "sha512-0i/EKJ222Afa1FE0C6pNJxDq1itzcl3HChE9DwskA4th4KRse8ojx8a1nVcOjwJdbpDLcz7uol77yYnQNMHdKw==", "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-presence": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-controllable-state": "1.1.0", + "@radix-ui/react-use-previous": "1.1.0", + "@radix-ui/react-use-size": "1.1.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-knex/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" - }, + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz", + "integrity": "sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==" + }, + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", + "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-knex/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-context": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz", + "integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-koa": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.43.0.tgz", - "integrity": "sha512-lDAhSnmoTIN6ELKmLJBplXzT/Jqs5jGZehuG22EdSMaTwgjMpxMDI1YtlKEhiWPWkrz5LUsd0aOO0ZRc9vn3AQ==", + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-presence": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.0.tgz", + "integrity": "sha512-Gq6wuRN/asf9H/E/VzdKoUtT8GC9PQc9z40/vEr0VCJ4u5XvvhWIrSsCB6vD2/cH7ugTdSfYq9fLJCcM00acrQ==", "dependencies": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-koa/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz", + "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-slot": "1.1.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-koa/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-lru-memoizer": { - "version": "0.40.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-lru-memoizer/-/instrumentation-lru-memoizer-0.40.0.tgz", - "integrity": "sha512-21xRwZsEdMPnROu/QsaOIODmzw59IYpGFmuC4aFWvMj6stA8+Ei1tX67nkarJttlNjoM94um0N4X26AD7ff54A==", + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", + "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0" + "@radix-ui/react-compose-refs": "1.1.0" }, - "engines": { - "node": ">=14" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", + "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-lru-memoizer/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz", + "integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-use-callback-ref": "1.1.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-lru-memoizer/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", + "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-memcached": { - "version": "0.39.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-memcached/-/instrumentation-memcached-0.39.0.tgz", - "integrity": "sha512-WfwvKAZ9I1qILRP5EUd88HQjwAAL+trXpCpozjBi4U6a0A07gB3fZ5PFAxbXemSjF5tHk9KVoROnqHvQ+zzFSQ==", + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-use-size": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz", + "integrity": "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==", "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@types/memcached": "^2.2.6" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-memcached/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-collapsible": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.0.3.tgz", + "integrity": "sha512-UBmVDkmR6IvDsloHVN+3rtx4Mi5TFvylYXpluuv0f37dtaz3H99bp8No0LGXRigVpl3UAT4l9j6bIchh42S/Gg==", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-controllable-state": "1.0.1", + "@radix-ui/react-use-layout-effect": "1.0.1" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-memcached/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-mongodb": { - "version": "0.47.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.47.0.tgz", - "integrity": "sha512-yqyXRx2SulEURjgOQyJzhCECSh5i1uM49NUaq9TqLd6fA7g26OahyJfsr9NE38HFqGRHpi4loyrnfYGdrsoVjQ==", + "node_modules/@radix-ui/react-collection": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.3.tgz", + "integrity": "sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==", "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/sdk-metrics": "^1.9.1", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-slot": "1.0.2" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-mongodb/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz", + "integrity": "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" + "@babel/runtime": "^7.13.10" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-mongodb/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-mongoose": { - "version": "0.42.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.42.0.tgz", - "integrity": "sha512-AnWv+RaR86uG3qNEMwt3plKX1ueRM7AspfszJYVkvkehiicC3bHQA6vWdb6Zvy5HAE14RyFbu9+2hUUjR2NSyg==", + "node_modules/@radix-ui/react-context": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.0.1.tgz", + "integrity": "sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==", "dependencies": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@babel/runtime": "^7.13.10" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-mongoose/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-dialog": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.2.tgz", + "integrity": "sha512-Yj4dZtqa2o+kG61fzB0H2qUvmwBA2oyQroGLyNtBj1beo1khoQ3q1a2AO8rrQYjd8256CO9+N8L9tvsS+bnIyA==", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.1", + "@radix-ui/react-focus-guards": "1.1.1", + "@radix-ui/react-focus-scope": "1.1.0", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-portal": "1.1.2", + "@radix-ui/react-presence": "1.1.1", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-slot": "1.1.0", + "@radix-ui/react-use-controllable-state": "1.1.0", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.6.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-mongoose/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz", + "integrity": "sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==" + }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", + "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-mysql": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.41.0.tgz", - "integrity": "sha512-jnvrV6BsQWyHS2qb2fkfbfSb1R/lmYwqEZITwufuRl37apTopswu9izc0b1CYRp/34tUG/4k/V39PND6eyiNvw==", - "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@types/mysql": "2.15.26" - }, - "engines": { - "node": ">=14" - }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-context": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", + "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-mysql/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.1.tgz", + "integrity": "sha512-QSxg29lfr/xcev6kSz7MAlmDnzbP1eI/Dwn3Tp1ip0KT5CUELsxkekFEMVBEoykI3oV39hKT4TKZzBNMbcTZYQ==", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-escape-keydown": "1.1.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-mysql/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-focus-guards": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz", + "integrity": "sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-mysql2": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.41.0.tgz", - "integrity": "sha512-REQB0x+IzVTpoNgVmy5b+UnH1/mDByrneimP6sbDHkp1j8QOl1HyWOrBH/6YWR0nrbU3l825Em5PlybjT3232g==", + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-focus-scope": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.0.tgz", + "integrity": "sha512-200UD8zylvEyL8Bx+z76RJnASR2gRMuxlgFCPAe/Q/679a/r0eK3MBVYMb7vZODZcffZBdob1EGnky78xmVvcA==", "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@opentelemetry/sql-common": "^0.40.1" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-mysql2/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-id": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz", + "integrity": "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-mysql2/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-net": { - "version": "0.39.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-net/-/instrumentation-net-0.39.0.tgz", - "integrity": "sha512-rixHoODfI/Cx1B0mH1BpxCT0bRSxktuBDrt9IvpT2KSEutK5hR0RsRdgdz/GKk+BQ4u+IG6godgMSGwNQCueEA==", + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-portal": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.2.tgz", + "integrity": "sha512-WeDYLGPxJb/5EGBoedyJbT0MpoULmwnIPMJMSldkuiMsBAv7N1cRdsTWZWht9vpPOiN3qyiGAtbK2is47/uMFg==", "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-net/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-presence": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.1.tgz", + "integrity": "sha512-IeFXVi4YS1K0wVZzXNrbaaUvIJ3qdY+/Ih4eHFhWA9SwGR9UDX7Ck8abvL57C4cv3wwMvUE0OG69Qc3NCcTe/A==", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-net/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-pg": { - "version": "0.46.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.46.0.tgz", - "integrity": "sha512-PLbYYC7EIoigh9uzhBrDjyL4yhH9akjV2Mln3ci9+lD7p9HE5nUUgYCgcUasyr4bz99c8xy9ErzKLt38Y7Kodg==", + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz", + "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==", "dependencies": { - "@opentelemetry/core": "^1.26.0", - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "1.27.0", - "@opentelemetry/sql-common": "^0.40.1", - "@types/pg": "8.6.1", - "@types/pg-pool": "2.0.6" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-slot": "1.1.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-pg/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", + "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-compose-refs": "1.1.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-pg/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", + "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-pino": { - "version": "0.42.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pino/-/instrumentation-pino-0.42.0.tgz", - "integrity": "sha512-SoX6FzucBfTuFNMZjdurJhcYWq2ve8/LkhmyVLUW31HpIB45RF1JNum0u4MkGisosDmXlK4njomcgUovShI+WA==", + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz", + "integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==", "dependencies": { - "@opentelemetry/api-logs": "^0.53.0", - "@opentelemetry/core": "^1.25.0", - "@opentelemetry/instrumentation": "^0.53.0" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-use-callback-ref": "1.1.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-pino/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-use-escape-keydown": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz", + "integrity": "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-use-callback-ref": "1.1.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-pino/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-redis": { - "version": "0.42.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis/-/instrumentation-redis-0.42.0.tgz", - "integrity": "sha512-jZBoqve0rEC51q0HuhjtZVq1DtUvJHzEJ3YKGvzGar2MU1J4Yt5+pQAQYh1W4jSoDyKeaI4hyeUdWM5N0c2lqA==", - "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/redis-common": "^0.36.2", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" - }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", + "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-redis-4": { - "version": "0.42.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis-4/-/instrumentation-redis-4-0.42.1.tgz", - "integrity": "sha512-xm17LJhDfQzQo4wkM/zFwh6wk3SNN/FBFGkscI9Kj4efrb/o5p8Z3yE6ldBPNdIZ6RAwg2p3DL7fvE3DuUDJWA==", + "node_modules/@radix-ui/react-dialog/node_modules/react-remove-scroll": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.0.tgz", + "integrity": "sha512-I2U4JVEsQenxDAKaVa3VZ/JeJZe0/2DxPWL8Tj8yLKctQJQiZM52pn/GWFpSp8dftjM3pSAHVJZscAnC/y+ySQ==", "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/redis-common": "^0.36.2", - "@opentelemetry/semantic-conventions": "^1.27.0" + "react-remove-scroll-bar": "^2.3.6", + "react-style-singleton": "^2.2.1", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.0", + "use-sidecar": "^1.1.2" }, "engines": { - "node": ">=14" + "node": ">=10" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-redis-4/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-direction": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.0.1.tgz", + "integrity": "sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" + "@babel/runtime": "^7.13.10" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-redis-4/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-redis/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.5.tgz", + "integrity": "sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g==", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-escape-keydown": "1.0.3" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-redis/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-restify": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-restify/-/instrumentation-restify-0.41.0.tgz", - "integrity": "sha512-gKEo+X/wVKUBuD2WDDlF7SlDNBHMWjSQoLxFCsGqeKgHR0MGtwMel8uaDGg9LJ83nKqYy+7Vl/cDFxjba6H+/w==", + "node_modules/@radix-ui/react-dropdown-menu": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.0.6.tgz", + "integrity": "sha512-i6TuFOoWmLWq+M/eCLGd/bQ2HfAX1RJgvrBQ6AQLmzfvsLdefxbWu8G9zczcPFfcSPehz9GcpF6K9QYreFV8hA==", "dependencies": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-menu": "2.0.6", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-controllable-state": "1.0.1" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-restify/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-focus-guards": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.1.tgz", + "integrity": "sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" + "@babel/runtime": "^7.13.10" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-restify/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-router": { - "version": "0.40.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-router/-/instrumentation-router-0.40.0.tgz", - "integrity": "sha512-bRo4RaclGFiKtmv/N1D0MuzO7DuxbeqMkMCbPPng6mDwzpHAMpHz/K/IxJmF+H1Hi/NYXVjCKvHGClageLe9eA==", + "node_modules/@radix-ui/react-focus-scope": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.4.tgz", + "integrity": "sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA==", "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-router/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-id": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.0.1.tgz", + "integrity": "sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-layout-effect": "1.0.1" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-router/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-socket.io": { - "version": "0.42.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-socket.io/-/instrumentation-socket.io-0.42.0.tgz", - "integrity": "sha512-xB5tdsBzuZyicQTO3hDzJIpHQ7V1BYJ6vWPWgl19gWZDBdjEGc3HOupjkd3BUJyDoDhbMEHGk2nNlkUU99EfkA==", + "node_modules/@radix-ui/react-menu": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.0.6.tgz", + "integrity": "sha512-BVkFLS+bUC8HcImkRKPSiVumA1VPOOEC5WBMiT+QAVsPzW1FJzI9KnqgGxVDPBcql5xXrHkD3JOVoXWEXD8SYA==", "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-collection": "1.0.3", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-direction": "1.0.1", + "@radix-ui/react-dismissable-layer": "1.0.5", + "@radix-ui/react-focus-guards": "1.0.1", + "@radix-ui/react-focus-scope": "1.0.4", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-popper": "1.1.3", + "@radix-ui/react-portal": "1.0.4", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-roving-focus": "1.0.4", + "@radix-ui/react-slot": "1.0.2", + "@radix-ui/react-use-callback-ref": "1.0.1", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.5.5" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-socket.io/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-arrow": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz", + "integrity": "sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA==", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-socket.io/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-tedious": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.14.0.tgz", - "integrity": "sha512-ofq7pPhSqvRDvD2FVx3RIWPj76wj4QubfrbqJtEx0A+fWoaYxJOCIQ92tYJh28elAmjMmgF/XaYuJuBhBv5J3A==", + "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-popper": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.1.3.tgz", + "integrity": "sha512-cKpopj/5RHZWjrbF2846jBNacjQVwkP068DfmgrNJXpvVWrOvlAmE9xSiy5OqeE+Gi8D9fP+oDhUnPqNMY8/5w==", "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@types/tedious": "^4.0.14" - }, - "engines": { - "node": ">=14" + "@babel/runtime": "^7.13.10", + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.0.3", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-layout-effect": "1.0.1", + "@radix-ui/react-use-rect": "1.0.1", + "@radix-ui/react-use-size": "1.0.1", + "@radix-ui/rect": "1.0.1" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-tedious/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-use-rect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.0.1.tgz", + "integrity": "sha512-Cq5DLuSiuYVKNU8orzJMbl15TXilTnJKUCltMVQg53BQOF1/C5toAaGrowkgksdBQ9H+SRL23g0HDmg9tvmxXw==", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" + "@babel/runtime": "^7.13.10", + "@radix-ui/rect": "1.0.1" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-tedious/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-undici": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.6.0.tgz", - "integrity": "sha512-ABJBhm5OdhGmbh0S/fOTE4N69IZ00CsHC5ijMYfzbw3E5NwLgpQk5xsljaECrJ8wz1SfXbO03FiSuu5AyRAkvQ==", + "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/rect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.0.1.tgz", + "integrity": "sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ==", "dependencies": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.53.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.7.0" + "@babel/runtime": "^7.13.10" } }, - "node_modules/@opentelemetry/instrumentation-undici/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-popper": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.0.tgz", + "integrity": "sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg==", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0", + "@radix-ui/react-use-rect": "1.1.0", + "@radix-ui/react-use-size": "1.1.0", + "@radix-ui/rect": "1.1.0" }, - "engines": { - "node": ">=14" + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", + "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-undici/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-context": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz", + "integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-winston": { - "version": "0.40.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-winston/-/instrumentation-winston-0.40.0.tgz", - "integrity": "sha512-eMk2tKl86YJ8/yHvtDbyhrE35/R0InhO9zuHTflPx8T0+IvKVUhPV71MsJr32sImftqeOww92QHt4Jd+a5db4g==", + "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz", + "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==", "dependencies": { - "@opentelemetry/api-logs": "^0.53.0", - "@opentelemetry/instrumentation": "^0.53.0" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-slot": "1.1.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-winston/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", + "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-compose-refs": "1.1.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-winston/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", + "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/otlp-exporter-base": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.53.0.tgz", - "integrity": "sha512-UCWPreGQEhD6FjBaeDuXhiMf6kkBODF0ZQzrk/tuQcaVDJ+dDQ/xhJp192H9yWnKxVpEjFrSSLnpqmX4VwX+eA==", - "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/otlp-transformer": "0.53.0" - }, - "engines": { - "node": ">=14" - }, + "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", + "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/otlp-grpc-exporter-base": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.53.0.tgz", - "integrity": "sha512-F7RCN8VN+lzSa4fGjewit8Z5fEUpY/lmMVy5EWn2ZpbAabg3EE3sCLuTNfOiooNGnmvzimUPruoeqeko/5/TzQ==", + "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-use-size": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz", + "integrity": "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==", "dependencies": { - "@grpc/grpc-js": "^1.7.1", - "@opentelemetry/core": "1.26.0", - "@opentelemetry/otlp-exporter-base": "0.53.0", - "@opentelemetry/otlp-transformer": "0.53.0" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/otlp-transformer": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.53.0.tgz", - "integrity": "sha512-rM0sDA9HD8dluwuBxLetUmoqGJKSAbWenwD65KY9iZhUxdBHRLrIdrABfNDP7aiTjcgK8XFyTn5fhDz7N+W6DA==", + "node_modules/@radix-ui/react-portal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.4.tgz", + "integrity": "sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@opentelemetry/core": "1.26.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/sdk-logs": "0.53.0", - "@opentelemetry/sdk-metrics": "1.26.0", - "@opentelemetry/sdk-trace-base": "1.26.0", - "protobufjs": "^7.3.0" - }, - "engines": { - "node": ">=14" + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/resources": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", - "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-presence": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.0.1.tgz", + "integrity": "sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==", "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-use-layout-effect": "1.0.1" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/sdk-trace-base": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.26.0.tgz", - "integrity": "sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-primitive": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz", + "integrity": "sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==", "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" + "@babel/runtime": "^7.13.10", + "@radix-ui/react-slot": "1.0.2" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/propagation-utils": { - "version": "0.30.11", - "resolved": "https://registry.npmjs.org/@opentelemetry/propagation-utils/-/propagation-utils-0.30.11.tgz", - "integrity": "sha512-rY4L/2LWNk5p/22zdunpqVmgz6uN419DsRTw5KFMa6u21tWhXS8devlMy4h8m8nnS20wM7r6yYweCNNKjgLYJw==", - "engines": { - "node": ">=14" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/propagator-aws-xray": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-aws-xray/-/propagator-aws-xray-1.26.0.tgz", - "integrity": "sha512-Sex+JyEZ/xX328TArBqQjh1NZSfNyw5NdASUIi9hnPsnMBMSBaDe7B9JRnXv0swz7niNyAnXa6MY7yOCV76EvA==", + "node_modules/@radix-ui/react-radio-group": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.2.0.tgz", + "integrity": "sha512-yv+oiLaicYMBpqgfpSPw6q+RyXlLdIpQWDHZbUKURxe+nEh53hFXPPlfhfQQtYkS5MMK/5IWIa76SksleQZSzw==", "dependencies": { - "@opentelemetry/core": "1.26.0" - }, - "engines": { - "node": ">=14" + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-direction": "1.1.0", + "@radix-ui/react-presence": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-roving-focus": "1.1.0", + "@radix-ui/react-use-controllable-state": "1.1.0", + "@radix-ui/react-use-previous": "1.1.0", + "@radix-ui/react-use-size": "1.1.0" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/propagator-b3": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-b3/-/propagator-b3-1.26.0.tgz", - "integrity": "sha512-vvVkQLQ/lGGyEy9GT8uFnI047pajSOVnZI2poJqVGD3nJ+B9sFGdlHNnQKophE3lHfnIH0pw2ubrCTjZCgIj+Q==", + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz", + "integrity": "sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==" + }, + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-collection": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.0.tgz", + "integrity": "sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw==", "dependencies": { - "@opentelemetry/core": "1.26.0" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-slot": "1.1.0" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/propagator-jaeger": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-jaeger/-/propagator-jaeger-1.26.0.tgz", - "integrity": "sha512-DelFGkCdaxA1C/QA0Xilszfr0t4YbGd3DjxiCDPh34lfnFr+VkkrjV9S8ZTJvAzfdKERXhfOxIKBoGPJwoSz7Q==", - "dependencies": { - "@opentelemetry/core": "1.26.0" - }, - "engines": { - "node": ">=14" - }, + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", + "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/redis-common": { - "version": "0.36.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/redis-common/-/redis-common-0.36.2.tgz", - "integrity": "sha512-faYX1N0gpLhej/6nyp6bgRjzAKXn5GOEMYY7YhciSfCoITAktLUtQ36d24QEWNA1/WA1y6qQunCe0OhHRkVl9g==", - "engines": { - "node": ">=14" + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-context": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz", + "integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/resource-detector-alibaba-cloud": { - "version": "0.29.3", - "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-alibaba-cloud/-/resource-detector-alibaba-cloud-0.29.3.tgz", - "integrity": "sha512-jdnG/cYItxwKGRj2n3YsJn1+j3QsMRUfaH/mQSj2b6yULo7bKO4turvASwxy3GuSDH55VwrK+F8oIbanJk69ng==", - "dependencies": { - "@opentelemetry/core": "^1.26.0", - "@opentelemetry/resources": "^1.10.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" - }, + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-direction": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz", + "integrity": "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==", "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/resource-detector-aws": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-aws/-/resource-detector-aws-1.6.2.tgz", - "integrity": "sha512-xxT6PVmcBTtCo0rf4Bv/mnDMpVRITVt13bDX8mOqKVb0kr5EwIMabZS5EGJhXjP4nljrOIA7ZlOJgSX0Kehfkw==", + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-id": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz", + "integrity": "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==", "dependencies": { - "@opentelemetry/core": "^1.0.0", - "@opentelemetry/resources": "^1.10.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/resource-detector-azure": { - "version": "0.2.11", - "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-azure/-/resource-detector-azure-0.2.11.tgz", - "integrity": "sha512-XepvQfTXWyHAoAziCfXGwYbSZL0LHtFk5iuKKN2VE2vzcoiw5Tepi0Qafuwb7CCtpQRReao4H7E29MFbCmh47g==", + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-presence": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.0.tgz", + "integrity": "sha512-Gq6wuRN/asf9H/E/VzdKoUtT8GC9PQc9z40/vEr0VCJ4u5XvvhWIrSsCB6vD2/cH7ugTdSfYq9fLJCcM00acrQ==", "dependencies": { - "@opentelemetry/core": "^1.25.1", - "@opentelemetry/resources": "^1.10.1", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/resource-detector-container": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-container/-/resource-detector-container-0.4.4.tgz", - "integrity": "sha512-ZEN2mq7lIjQWJ8NTt1umtr6oT/Kb89856BOmESLSvgSHbIwOFYs7cSfSRH5bfiVw6dXTQAVbZA/wLgCHKrebJA==", + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz", + "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==", "dependencies": { - "@opentelemetry/core": "^1.26.0", - "@opentelemetry/resources": "^1.10.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-slot": "1.1.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/resource-detector-gcp": { - "version": "0.29.12", - "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-gcp/-/resource-detector-gcp-0.29.12.tgz", - "integrity": "sha512-liFG9XTaFVyY9YdFy4r2qVNa4a+Mg3k+XoWzzq2F+/xR0hFLfL0H4k7CsMW+T4Vl+1Cvc9W9WEVt5VCF4u/SYw==", + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-roving-focus": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.0.tgz", + "integrity": "sha512-EA6AMGeq9AEeQDeSH0aZgG198qkfHSbvWTf1HvoDmOB5bBG/qTxjYMWUKMnYiV6J/iP/J8MEFSuB2zRU2n7ODA==", "dependencies": { - "@opentelemetry/core": "^1.0.0", - "@opentelemetry/resources": "^1.10.0", - "@opentelemetry/semantic-conventions": "^1.27.0", - "gcp-metadata": "^6.0.0" - }, - "engines": { - "node": ">=14" + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-collection": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-direction": "1.1.0", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-controllable-state": "1.1.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/resources": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.27.0.tgz", - "integrity": "sha512-jOwt2VJ/lUD5BLc+PMNymDrUCpm5PKi1E9oSVYAvz01U/VdndGmrtV3DU1pG4AwlYhJRHbHfOUIlpBeXCPw6QQ==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", + "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", "dependencies": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-compose-refs": "1.1.0" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/resources/node_modules/@opentelemetry/core": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.27.0.tgz", - "integrity": "sha512-yQPKnK5e+76XuiqUH/gKyS8wv/7qITd5ln56QkBTf3uggr0VkXOXfcaAuG330UfdYu83wsyoBwqwxigpIG+Jkg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" - }, + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", + "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/sdk-logs": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.53.0.tgz", - "integrity": "sha512-dhSisnEgIj/vJZXZV6f6KcTnyLDx/VuQ6l3ejuZpMpPlh9S1qMHiZU9NMmOkVkwwHkMy3G6mEBwdP23vUZVr4g==", + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz", + "integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@opentelemetry/core": "1.26.0", - "@opentelemetry/resources": "1.26.0" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-use-callback-ref": "1.1.0" }, "peerDependencies": { - "@opentelemetry/api": ">=1.4.0 <1.10.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/sdk-logs/node_modules/@opentelemetry/resources": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", - "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" - }, + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", + "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/sdk-metrics": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.26.0.tgz", - "integrity": "sha512-0SvDXmou/JjzSDOjUmetAAvcKQW6ZrvosU0rkbDGpXvvZN+pQF6JbK/Kd4hNdK4q/22yeruqvukXEJyySTzyTQ==", + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-use-size": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz", + "integrity": "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==", "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/resources": "1.26.0" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/sdk-metrics/node_modules/@opentelemetry/resources": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", - "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-roving-focus": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.4.tgz", + "integrity": "sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==", "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-collection": "1.0.3", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-direction": "1.0.1", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-controllable-state": "1.0.1" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/sdk-node": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-node/-/sdk-node-0.53.0.tgz", - "integrity": "sha512-0hsxfq3BKy05xGktwG8YdGdxV978++x40EAKyKr1CaHZRh8uqVlXnclnl7OMi9xLMJEcXUw7lGhiRlArFcovyg==", + "node_modules/@radix-ui/react-slot": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz", + "integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@opentelemetry/core": "1.26.0", - "@opentelemetry/exporter-logs-otlp-grpc": "0.53.0", - "@opentelemetry/exporter-logs-otlp-http": "0.53.0", - "@opentelemetry/exporter-logs-otlp-proto": "0.53.0", - "@opentelemetry/exporter-trace-otlp-grpc": "0.53.0", - "@opentelemetry/exporter-trace-otlp-http": "0.53.0", - "@opentelemetry/exporter-trace-otlp-proto": "0.53.0", - "@opentelemetry/exporter-zipkin": "1.26.0", - "@opentelemetry/instrumentation": "0.53.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/sdk-logs": "0.53.0", - "@opentelemetry/sdk-metrics": "1.26.0", - "@opentelemetry/sdk-trace-base": "1.26.0", - "@opentelemetry/sdk-trace-node": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1" }, "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/exporter-trace-otlp-http": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.53.0.tgz", - "integrity": "sha512-m7F5ZTq+V9mKGWYpX8EnZ7NjoqAU7VemQ1E2HAG+W/u0wpY1x0OmbxAXfGKFHCspdJk8UKlwPGrpcB8nay3P8A==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-tooltip": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.0.7.tgz", + "integrity": "sha512-lPh5iKNFVQ/jav/j6ZrWq3blfDJ0OH9R6FlNUHPMqdLuQ9vwDgFsRxvl8b7Asuy5c8xmoojHUxKHQSOAvMHxyw==", "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/otlp-exporter-base": "0.53.0", - "@opentelemetry/otlp-transformer": "0.53.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/sdk-trace-base": "1.26.0" - }, - "engines": { - "node": ">=14" + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-dismissable-layer": "1.0.5", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-popper": "1.1.3", + "@radix-ui/react-portal": "1.0.4", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-slot": "1.0.2", + "@radix-ui/react-use-controllable-state": "1.0.1", + "@radix-ui/react-visually-hidden": "1.0.3" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-arrow": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz", + "integrity": "sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA==", "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/resources": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", - "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-popper": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.1.3.tgz", + "integrity": "sha512-cKpopj/5RHZWjrbF2846jBNacjQVwkP068DfmgrNJXpvVWrOvlAmE9xSiy5OqeE+Gi8D9fP+oDhUnPqNMY8/5w==", "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" + "@babel/runtime": "^7.13.10", + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.0.3", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-layout-effect": "1.0.1", + "@radix-ui/react-use-rect": "1.0.1", + "@radix-ui/react-use-size": "1.0.1", + "@radix-ui/rect": "1.0.1" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/sdk-trace-base": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.26.0.tgz", - "integrity": "sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-use-rect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.0.1.tgz", + "integrity": "sha512-Cq5DLuSiuYVKNU8orzJMbl15TXilTnJKUCltMVQg53BQOF1/C5toAaGrowkgksdBQ9H+SRL23g0HDmg9tvmxXw==", "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" + "@babel/runtime": "^7.13.10", + "@radix-ui/rect": "1.0.1" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-node/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/sdk-trace-base": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.27.0.tgz", - "integrity": "sha512-btz6XTQzwsyJjombpeqCX6LhiMQYpzt2pIYNPnw0IPO/3AhT6yjnf8Mnv3ZC2A4eRYOjqrg+bfaXg9XHDRJDWQ==", + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/rect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.0.1.tgz", + "integrity": "sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ==", "dependencies": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/resources": "1.27.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "@babel/runtime": "^7.13.10" } }, - "node_modules/@opentelemetry/sdk-trace-base/node_modules/@opentelemetry/core": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.27.0.tgz", - "integrity": "sha512-yQPKnK5e+76XuiqUH/gKyS8wv/7qITd5ln56QkBTf3uggr0VkXOXfcaAuG330UfdYu83wsyoBwqwxigpIG+Jkg==", + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz", + "integrity": "sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==", "dependencies": { - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" + "@babel/runtime": "^7.13.10" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/sdk-trace-node": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-1.26.0.tgz", - "integrity": "sha512-Fj5IVKrj0yeUwlewCRwzOVcr5avTuNnMHWf7GPc1t6WaT78J6CJyF3saZ/0RkZfdeNO8IcBl/bNcWMVZBMRW8Q==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.1.tgz", + "integrity": "sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==", "dependencies": { - "@opentelemetry/context-async-hooks": "1.26.0", - "@opentelemetry/core": "1.26.0", - "@opentelemetry/propagator-b3": "1.26.0", - "@opentelemetry/propagator-jaeger": "1.26.0", - "@opentelemetry/sdk-trace-base": "1.26.0", - "semver": "^7.5.2" - }, - "engines": { - "node": ">=14" + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-callback-ref": "1.0.1" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/sdk-trace-node/node_modules/@opentelemetry/resources": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", - "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-use-escape-keydown": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.3.tgz", + "integrity": "sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==", "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-callback-ref": "1.0.1" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/sdk-trace-node/node_modules/@opentelemetry/sdk-trace-base": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.26.0.tgz", - "integrity": "sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.1.tgz", + "integrity": "sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==", "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" + "@babel/runtime": "^7.13.10" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-trace-node/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "bin": { - "semver": "bin/semver.js" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/semantic-conventions": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.27.0.tgz", - "integrity": "sha512-sAay1RrB+ONOem0OZanAR1ZI/k7yDpnOQSQmTMuGImUQb2y8EbSaCJ94FQluM74xoU03vlb2d2U90hZluL6nQg==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" + "node_modules/@radix-ui/react-use-previous": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.0.tgz", + "integrity": "sha512-Z/e78qg2YFnnXcW88A4JmTtm4ADckLno6F7OXotmkQfeuCVaKuYzqAATPhVzl3delXE7CxIV8shofPn3jPc5Og==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/sql-common": { - "version": "0.40.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/sql-common/-/sql-common-0.40.1.tgz", - "integrity": "sha512-nSDlnHSqzC3pXn/wZEZVLuAuJ1MYMXPBwtv2qAbCa3847SaHItdE7SzUq/Jtb0KZmh1zfAbNi3AAMjztTT4Ugg==", + "node_modules/@radix-ui/react-use-rect": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz", + "integrity": "sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==", "dependencies": { - "@opentelemetry/core": "^1.1.0" - }, - "engines": { - "node": ">=14" + "@radix-ui/rect": "1.1.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.1.0" - } - }, - "node_modules/@opentelemetry/winston-transport": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/winston-transport/-/winston-transport-0.7.0.tgz", - "integrity": "sha512-Q35p/glAOE6sl0ZgbddYsdjy23mzt89lFGhht4pJwrrJyInFIgdONFmMJb47kmXbFM3JHOcI0j+PL1BPPTPXBQ==", - "dependencies": { - "@opentelemetry/api-logs": "^0.54.0", - "winston-transport": "4.*" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "engines": { - "node": ">=14" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/winston-transport/node_modules/@opentelemetry/api-logs": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.54.0.tgz", - "integrity": "sha512-9HhEh5GqFrassUndqJsyW7a0PzfyWr2eV2xwzHLIS+wX3125+9HE9FMRAKmJRwxZhgZGwH3HNQQjoMGZqmOeVA==", + "node_modules/@radix-ui/react-use-size": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.0.1.tgz", + "integrity": "sha512-ibay+VqrgcaI6veAojjofPATwledXiSmX+C0KrBk/xgpX9rBzPV3OsfwlhQdUOFbh+LKQorLYT+xTXW9V8yd0g==", "dependencies": { - "@opentelemetry/api": "^1.3.0" + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-layout-effect": "1.0.1" }, - "engines": { - "node": ">=14" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@oxc-resolver/binding-darwin-arm64": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-darwin-arm64/-/binding-darwin-arm64-1.10.2.tgz", - "integrity": "sha512-aOCZYXqmFL+2sXlaVkYbAOtICGGeTFtmdul8OimQfOXHJods6YHJ2nR6+rEeBcJzaXyXPP18ne1IsEc4AYL1IA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@oxc-resolver/binding-darwin-x64": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-darwin-x64/-/binding-darwin-x64-1.10.2.tgz", - "integrity": "sha512-6WD7lHGkoduFZfUgnC2suKOlqttQRKxWsiVXiiGPu3mfXvQAhMd/gekuH1t8vOhFlPJduaww15n5UB0bSjCK+w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@oxc-resolver/binding-freebsd-x64": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-freebsd-x64/-/binding-freebsd-x64-1.10.2.tgz", - "integrity": "sha512-nEqHWx/Ot5p7Mafj8qH6vFlLSvHjECxAcZwhnAMqRuQu1NgXC/QM3emkdhVGy7QJgsxZbHpPaF6TERNf5/NL9Q==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@oxc-resolver/binding-linux-arm-gnueabihf": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.10.2.tgz", - "integrity": "sha512-+AlZI0fPnpfArh8aC5k2295lmQrxa2p8gBLxC3buvCkz0ZpbVLxyyAXz3J2jGwJnmc5MUPLEqPYw6ZlAGH4XHA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@oxc-resolver/binding-linux-arm64-gnu": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.10.2.tgz", - "integrity": "sha512-8fZ8NszFaUZaoA8eUwkF2lHjgUs76aFiewWgG/cjcZmwKp+ErZQLW8eOvIWZ4SohHQ+ScvhVsSaU2PU38c88gw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@oxc-resolver/binding-linux-arm64-musl": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.10.2.tgz", - "integrity": "sha512-oPrLICrw96Ym9n04FWXWGkbkpF6qJtZ57JSnqI3oQ24xHTt4iWyjHKHQO46NbJAK9sFb3Qce4BzV8faDI5Rifg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@oxc-resolver/binding-linux-x64-gnu": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.10.2.tgz", - "integrity": "sha512-eli74jTAUiIfqi8IPFqiPxQS69Alcr6w/IFRyf3XxrkxeFGgcgxJkRIxWNTKJ6T3EXxjuma+49LdZn6l9rEj7A==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@oxc-resolver/binding-linux-x64-musl": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-musl/-/binding-linux-x64-musl-1.10.2.tgz", - "integrity": "sha512-HH9zmjNSQo3rkbqJH5nIjGrtjC+QPrUy0KGGMR/oRCSLuD0cNFJ/Uly1XAugwSm4oEw0+rv6PmeclXmVTKsxhw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@oxc-resolver/binding-wasm32-wasi": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-wasm32-wasi/-/binding-wasm32-wasi-1.10.2.tgz", - "integrity": "sha512-3ItX23q33sfVBtMMdMhVDSe0NX5zBHxHfmFiXhSJuwNaVIwGpLFU7WU2nmq9oNdnmTOvjL8vlhOqiGvumBLlRA==", - "cpu": [ - "wasm32" - ], - "dev": true, - "optional": true, + "node_modules/@radix-ui/react-visually-hidden": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.0.3.tgz", + "integrity": "sha512-D4w41yN5YRKtu464TLnByKzMDG/JlMPHtfZgQAu9v6mNakUqGUI9vUrfQKz8NK41VMm/xbZbh76NUTVtIYqOMA==", "dependencies": { - "@napi-rs/wasm-runtime": "^0.2.4" + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" }, - "engines": { - "node": ">=14.0.0" + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@oxc-resolver/binding-win32-arm64-msvc": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.10.2.tgz", - "integrity": "sha512-aVoj2V+jmQ1N+lVy9AhaLmzssJM0lcKt8D0UL83aNLZJ5lSN7hgBuUXTVmL+VF268f167khjo38z+fbELDVm8Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] + "node_modules/@radix-ui/rect": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.0.tgz", + "integrity": "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==" }, - "node_modules/@oxc-resolver/binding-win32-x64-msvc": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.10.2.tgz", - "integrity": "sha512-l8BDQWyP0Piw8hlmYPUqTRKLsq+ceG9h+9p6ZrjNzwW9AmJX7T7T2hgoVVHqS6f4WNA/CFkb3RyZP9QTzNkyyA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] + "node_modules/@react-native/assets-registry": { + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.77.0.tgz", + "integrity": "sha512-Ms4tYYAMScgINAXIhE4riCFJPPL/yltughHS950l0VP5sm5glbimn9n7RFn9Tc8cipX74/ddbk19+ydK2iDMmA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + } }, - "node_modules/@parcel/watcher": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.0.tgz", - "integrity": "sha512-i0GV1yJnm2n3Yq1qw6QrUrd/LI9bE8WEBOTtOkpCXHHdyN3TAGgqAK/DAT05z4fq2x04cARXt2pDmjWjL92iTQ==", - "hasInstallScript": true, + "node_modules/@react-native/babel-plugin-codegen": { + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.77.0.tgz", + "integrity": "sha512-5TYPn1k+jdDOZJU4EVb1kZ0p9TCVICXK3uplRev5Gul57oWesAaiWGZOzfRS3lonWeuR4ij8v8PFfIHOaq0vmA==", + "license": "MIT", + "peer": true, "dependencies": { - "detect-libc": "^1.0.3", - "is-glob": "^4.0.3", - "micromatch": "^4.0.5", - "node-addon-api": "^7.0.0" + "@babel/traverse": "^7.25.3", + "@react-native/codegen": "0.77.0" }, "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "@parcel/watcher-android-arm64": "2.5.0", - "@parcel/watcher-darwin-arm64": "2.5.0", - "@parcel/watcher-darwin-x64": "2.5.0", - "@parcel/watcher-freebsd-x64": "2.5.0", - "@parcel/watcher-linux-arm-glibc": "2.5.0", - "@parcel/watcher-linux-arm-musl": "2.5.0", - "@parcel/watcher-linux-arm64-glibc": "2.5.0", - "@parcel/watcher-linux-arm64-musl": "2.5.0", - "@parcel/watcher-linux-x64-glibc": "2.5.0", - "@parcel/watcher-linux-x64-musl": "2.5.0", - "@parcel/watcher-win32-arm64": "2.5.0", - "@parcel/watcher-win32-ia32": "2.5.0", - "@parcel/watcher-win32-x64": "2.5.0" + "node": ">=18" } }, - "node_modules/@parcel/watcher-android-arm64": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.0.tgz", - "integrity": "sha512-qlX4eS28bUcQCdribHkg/herLe+0A9RyYC+mm2PXpncit8z5b3nSqGVzMNR3CmtAOgRutiZ02eIJJgP/b1iEFQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "android" - ], + "node_modules/@react-native/babel-preset": { + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.77.0.tgz", + "integrity": "sha512-Z4yxE66OvPyQ/iAlaETI1ptRLcDm7Tk6ZLqtCPuUX3AMg+JNgIA86979T4RSk486/JrBUBH5WZe2xjj7eEHXsA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/core": "^7.25.2", + "@babel/plugin-proposal-export-default-from": "^7.24.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-default-from": "^7.24.7", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-transform-arrow-functions": "^7.24.7", + "@babel/plugin-transform-async-generator-functions": "^7.25.4", + "@babel/plugin-transform-async-to-generator": "^7.24.7", + "@babel/plugin-transform-block-scoping": "^7.25.0", + "@babel/plugin-transform-class-properties": "^7.25.4", + "@babel/plugin-transform-classes": "^7.25.4", + "@babel/plugin-transform-computed-properties": "^7.24.7", + "@babel/plugin-transform-destructuring": "^7.24.8", + "@babel/plugin-transform-flow-strip-types": "^7.25.2", + "@babel/plugin-transform-for-of": "^7.24.7", + "@babel/plugin-transform-function-name": "^7.25.1", + "@babel/plugin-transform-literals": "^7.25.2", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.8", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-numeric-separator": "^7.24.7", + "@babel/plugin-transform-object-rest-spread": "^7.24.7", + "@babel/plugin-transform-optional-catch-binding": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.8", + "@babel/plugin-transform-parameters": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.24.7", + "@babel/plugin-transform-private-property-in-object": "^7.24.7", + "@babel/plugin-transform-react-display-name": "^7.24.7", + "@babel/plugin-transform-react-jsx": "^7.25.2", + "@babel/plugin-transform-react-jsx-self": "^7.24.7", + "@babel/plugin-transform-react-jsx-source": "^7.24.7", + "@babel/plugin-transform-regenerator": "^7.24.7", + "@babel/plugin-transform-runtime": "^7.24.7", + "@babel/plugin-transform-shorthand-properties": "^7.24.7", + "@babel/plugin-transform-spread": "^7.24.7", + "@babel/plugin-transform-sticky-regex": "^7.24.7", + "@babel/plugin-transform-typescript": "^7.25.2", + "@babel/plugin-transform-unicode-regex": "^7.24.7", + "@babel/template": "^7.25.0", + "@react-native/babel-plugin-codegen": "0.77.0", + "babel-plugin-syntax-hermes-parser": "0.25.1", + "babel-plugin-transform-flow-enums": "^0.0.2", + "react-refresh": "^0.14.0" + }, "engines": { - "node": ">= 10.0.0" + "node": ">=18" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "peerDependencies": { + "@babel/core": "*" } }, - "node_modules/@parcel/watcher-darwin-arm64": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.0.tgz", - "integrity": "sha512-hyZ3TANnzGfLpRA2s/4U1kbw2ZI4qGxaRJbBH2DCSREFfubMswheh8TeiC1sGZ3z2jUf3s37P0BBlrD3sjVTUw==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], + "node_modules/@react-native/codegen": { + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.77.0.tgz", + "integrity": "sha512-rE9lXx41ZjvE8cG7e62y/yGqzUpxnSvJ6me6axiX+aDewmI4ZrddvRGYyxCnawxy5dIBHSnrpZse3P87/4Lm7w==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/parser": "^7.25.3", + "glob": "^7.1.1", + "hermes-parser": "0.25.1", + "invariant": "^2.2.4", + "jscodeshift": "^17.0.0", + "nullthrows": "^1.1.1", + "yargs": "^17.6.2" + }, "engines": { - "node": ">= 10.0.0" + "node": ">=18" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "peerDependencies": { + "@babel/preset-env": "^7.1.6" } }, - "node_modules/@parcel/watcher-darwin-x64": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.0.tgz", - "integrity": "sha512-9rhlwd78saKf18fT869/poydQK8YqlU26TMiNg7AIu7eBp9adqbJZqmdFOsbZ5cnLp5XvRo9wcFmNHgHdWaGYA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], + "node_modules/@react-native/codegen/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT", + "peer": true + }, + "node_modules/@react-native/codegen/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "peer": true, "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">=8" } }, - "node_modules/@parcel/watcher-freebsd-x64": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.0.tgz", - "integrity": "sha512-syvfhZzyM8kErg3VF0xpV8dixJ+RzbUaaGaeb7uDuz0D3FK97/mZ5AJQ3XNnDsXX7KkFNtyQyFrXZzQIcN49Tw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10.0.0" + "node_modules/@react-native/codegen/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "peer": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "engines": { + "node": ">=8" } }, - "node_modules/@parcel/watcher-linux-arm-glibc": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.0.tgz", - "integrity": "sha512-0VQY1K35DQET3dVYWpOaPFecqOT9dbuCfzjxoQyif1Wc574t3kOSkKevULddcR9znz1TcklCE7Ht6NIxjvTqLA==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" + "node_modules/@react-native/codegen/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "peer": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "engines": { + "node": ">=12" } }, - "node_modules/@parcel/watcher-linux-arm-musl": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.0.tgz", - "integrity": "sha512-6uHywSIzz8+vi2lAzFeltnYbdHsDm3iIB57d4g5oaB9vKwjb6N6dRIgZMujw4nm5r6v9/BQH0noq6DzHrqr2pA==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/@react-native/community-cli-plugin": { + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.77.0.tgz", + "integrity": "sha512-GRshwhCHhtupa3yyCbel14SlQligV8ffNYN5L1f8HCo2SeGPsBDNjhj2U+JTrMPnoqpwowPGvkCwyqwqYff4MQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@react-native/dev-middleware": "0.77.0", + "@react-native/metro-babel-transformer": "0.77.0", + "chalk": "^4.0.0", + "debug": "^2.2.0", + "invariant": "^2.2.4", + "metro": "^0.81.0", + "metro-config": "^0.81.0", + "metro-core": "^0.81.0", + "readline": "^1.3.0", + "semver": "^7.1.3" + }, "engines": { - "node": ">= 10.0.0" + "node": ">=18" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "peerDependencies": { + "@react-native-community/cli-server-api": "*" + }, + "peerDependenciesMeta": { + "@react-native-community/cli-server-api": { + "optional": true + } } }, - "node_modules/@parcel/watcher-linux-arm64-glibc": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.0.tgz", - "integrity": "sha512-BfNjXwZKxBy4WibDb/LDCriWSKLz+jJRL3cM/DllnHH5QUyoiUNEp3GmL80ZqxeumoADfCCP19+qiYiC8gUBjA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node_modules/@react-native/community-cli-plugin/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "2.0.0" } }, - "node_modules/@parcel/watcher-linux-arm64-musl": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.0.tgz", - "integrity": "sha512-S1qARKOphxfiBEkwLUbHjCY9BWPdWnW9j7f7Hb2jPplu8UZ3nes7zpPOW9bkLbHRvWM0WDTsjdOTUgW0xLBN1Q==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" + "node_modules/@react-native/community-cli-plugin/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT", + "peer": true + }, + "node_modules/@react-native/community-cli-plugin/node_modules/semver": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.0.tgz", + "integrity": "sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ==", + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "engines": { + "node": ">=10" } }, - "node_modules/@parcel/watcher-linux-x64-glibc": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.0.tgz", - "integrity": "sha512-d9AOkusyXARkFD66S6zlGXyzx5RvY+chTP9Jp0ypSTC9d4lzyRs9ovGf/80VCxjKddcUvnsGwCHWuF2EoPgWjw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/@react-native/debugger-frontend": { + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.77.0.tgz", + "integrity": "sha512-glOvSEjCbVXw+KtfiOAmrq21FuLE1VsmBsyT7qud4KWbXP43aUEhzn70mWyFuiIdxnzVPKe2u8iWTQTdJksR1w==", + "license": "BSD-3-Clause", + "peer": true, "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">=18" } }, - "node_modules/@parcel/watcher-linux-x64-musl": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.0.tgz", - "integrity": "sha512-iqOC+GoTDoFyk/VYSFHwjHhYrk8bljW6zOhPuhi5t9ulqiYq1togGJB5e3PwYVFFfeVgc6pbz3JdQyDoBszVaA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" + "node_modules/@react-native/dev-middleware": { + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.77.0.tgz", + "integrity": "sha512-DAlEYujm43O+Dq98KP2XfLSX5c/TEGtt+JBDEIOQewk374uYY52HzRb1+Gj6tNaEj/b33no4GibtdxbO5zmPhg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@isaacs/ttlcache": "^1.4.1", + "@react-native/debugger-frontend": "0.77.0", + "chrome-launcher": "^0.15.2", + "chromium-edge-launcher": "^0.2.0", + "connect": "^3.6.5", + "debug": "^2.2.0", + "nullthrows": "^1.1.1", + "open": "^7.0.3", + "selfsigned": "^2.4.1", + "serve-static": "^1.16.2", + "ws": "^6.2.3" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "engines": { + "node": ">=18" } }, - "node_modules/@parcel/watcher-wasm": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-wasm/-/watcher-wasm-2.5.0.tgz", - "integrity": "sha512-Z4ouuR8Pfggk1EYYbTaIoxc+Yv4o7cGQnH0Xy8+pQ+HbiW+ZnwhcD2LPf/prfq1nIWpAxjOkQ8uSMFWMtBLiVQ==", - "bundleDependencies": [ - "napi-wasm" - ], + "node_modules/@react-native/dev-middleware/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "peer": true, "dependencies": { - "is-glob": "^4.0.3", - "micromatch": "^4.0.5", - "napi-wasm": "^1.1.0" - }, + "ms": "2.0.0" + } + }, + "node_modules/@react-native/dev-middleware/node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "peer": true, "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">= 0.8" } }, - "node_modules/@parcel/watcher-wasm/node_modules/napi-wasm": { - "version": "1.1.0", - "inBundle": true, - "license": "MIT" + "node_modules/@react-native/dev-middleware/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT", + "peer": true }, - "node_modules/@parcel/watcher-win32-arm64": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.0.tgz", - "integrity": "sha512-twtft1d+JRNkM5YbmexfcH/N4znDtjgysFaV9zvZmmJezQsKpkfLYJ+JFV3uygugK6AtIM2oADPkB2AdhBrNig==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], + "node_modules/@react-native/dev-middleware/node_modules/open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + }, "engines": { - "node": ">= 10.0.0" + "node": ">=8" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@parcel/watcher-win32-ia32": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.0.tgz", - "integrity": "sha512-+rgpsNRKwo8A53elqbbHXdOMtY/tAtTzManTWShB5Kk54N8Q9mzNWV7tV+IbGueCbcj826MfWGU3mprWtuf1TA==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" + "node_modules/@react-native/dev-middleware/node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", + "peer": true, + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/@parcel/watcher-win32-x64": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.0.tgz", - "integrity": "sha512-lPrxve92zEHdgeff3aiu4gDOIt4u7sJYha6wbdEZDCDUhtjTsOMiaJzG5lMY4GkWH8p0fMmO2Ppq5G5XXG+DQw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], + "node_modules/@react-native/dev-middleware/node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "peer": true, "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">= 0.8" } }, - "node_modules/@parcel/watcher/node_modules/detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", - "bin": { - "detect-libc": "bin/detect-libc.js" + "node_modules/@react-native/dev-middleware/node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT", + "peer": true + }, + "node_modules/@react-native/dev-middleware/node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", + "peer": true, + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" }, "engines": { - "node": ">=0.10" + "node": ">= 0.8.0" } }, - "node_modules/@parcel/watcher/node_modules/node-addon-api": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", - "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==" - }, - "node_modules/@phenomnomnominal/tsquery": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@phenomnomnominal/tsquery/-/tsquery-5.0.1.tgz", - "integrity": "sha512-3nVv+e2FQwsW8Aw6qTU6f+1rfcJ3hrcnvH/mu9i8YhxO+9sqbOfpL8m6PbET5+xKOlz/VSbp0RoYWYCtIsnmuA==", - "dev": true, + "node_modules/@react-native/dev-middleware/node_modules/ws": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", + "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", + "license": "MIT", + "peer": true, "dependencies": { - "esquery": "^1.4.0" - }, - "peerDependencies": { - "typescript": "^3 || ^4 || ^5" + "async-limiter": "~1.0.0" } }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "optional": true, + "node_modules/@react-native/gradle-plugin": { + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.77.0.tgz", + "integrity": "sha512-rmfh93jzbndSq7kihYHUQ/EGHTP8CCd3GDCmg5SbxSOHAaAYx2HZ28ZG7AVcGUsWeXp+e/90zGIyfOzDRx0Zaw==", + "license": "MIT", + "peer": true, "engines": { - "node": ">=14" + "node": ">=18" } }, - "node_modules/@pnpm/config.env-replace": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", - "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", + "node_modules/@react-native/js-polyfills": { + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.77.0.tgz", + "integrity": "sha512-kHFcMJVkGb3ptj3yg1soUsMHATqal4dh0QTGAbYihngJ6zy+TnP65J3GJq4UlwqFE9K1RZkeCmTwlmyPFHOGvA==", + "license": "MIT", + "peer": true, "engines": { - "node": ">=12.22.0" + "node": ">=18" } }, - "node_modules/@pnpm/network.ca-file": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", - "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", + "node_modules/@react-native/metro-babel-transformer": { + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.77.0.tgz", + "integrity": "sha512-19GfvhBRKCU3UDWwCnDR4QjIzz3B2ZuwhnxMRwfAgPxz7QY9uKour9RGmBAVUk1Wxi/SP7dLEvWnmnuBO39e2A==", + "license": "MIT", + "peer": true, "dependencies": { - "graceful-fs": "4.2.10" + "@babel/core": "^7.25.2", + "@react-native/babel-preset": "0.77.0", + "hermes-parser": "0.25.1", + "nullthrows": "^1.1.1" }, "engines": { - "node": ">=12.22.0" + "node": ">=18" + }, + "peerDependencies": { + "@babel/core": "*" } }, - "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + "node_modules/@react-native/normalize-color": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@react-native/normalize-color/-/normalize-color-2.1.0.tgz", + "integrity": "sha512-Z1jQI2NpdFJCVgpY+8Dq/Bt3d+YUi1928Q+/CZm/oh66fzM0RUl54vvuXlPJKybH4pdCZey1eDTPaLHkMPNgWA==", + "license": "MIT", + "peer": true }, - "node_modules/@pnpm/npm-conf": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.2.2.tgz", - "integrity": "sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==", + "node_modules/@react-native/normalize-colors": { + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.77.0.tgz", + "integrity": "sha512-qjmxW3xRZe4T0ZBEaXZNHtuUbRgyfybWijf1yUuQwjBt24tSapmIslwhCjpKidA0p93ssPcepquhY0ykH25mew==", + "license": "MIT", + "peer": true + }, + "node_modules/@react-native/virtualized-lists": { + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.77.0.tgz", + "integrity": "sha512-ppPtEu9ISO9iuzpA2HBqrfmDpDAnGGduNDVaegadOzbMCPAB3tC9Blxdu9W68LyYlNQILIsP6/FYtLwf7kfNew==", + "license": "MIT", + "peer": true, "dependencies": { - "@pnpm/config.env-replace": "^1.1.0", - "@pnpm/network.ca-file": "^1.0.1", - "config-chain": "^1.1.11" + "invariant": "^2.2.4", + "nullthrows": "^1.1.1" }, "engines": { - "node": ">=12" - } - }, - "node_modules/@polka/url": { - "version": "1.0.0-next.25", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.25.tgz", - "integrity": "sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==" - }, - "node_modules/@prisma/client": { - "version": "5.8.1", - "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.8.1.tgz", - "integrity": "sha512-xQtMPfbIwLlbm0VVIVQY2yqQVOxPwRQhvIp7Z3m2900g1bu/zRHKhYZJQWELqmjl6d8YwBy0K2NvMqh47v1ubw==", - "hasInstallScript": true, - "engines": { - "node": ">=16.13" + "node": ">=18" }, "peerDependencies": { - "prisma": "*" + "@types/react": "^18.2.6", + "react": "*", + "react-native": "*" }, "peerDependenciesMeta": { - "prisma": { + "@types/react": { "optional": true } } }, - "node_modules/@prisma/debug": { - "version": "5.16.2", - "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.16.2.tgz", - "integrity": "sha512-ItzB4nR4O8eLzuJiuP3WwUJfoIvewMHqpGCad+64gvThcKEVOtaUza9AEJo2DPqAOa/AWkFyK54oM4WwHeew+A==", - "devOptional": true + "node_modules/@rushstack/eslint-patch": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.3.tgz", + "integrity": "sha512-qC/xYId4NMebE6w/V33Fh9gWxLgURiNYgVNObbJl2LZv0GUUItCcCqC5axQSwRaAgaxl2mELq1rMzlswaQ0Zxg==", + "dev": true }, - "node_modules/@prisma/engines": { - "version": "5.16.2", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.16.2.tgz", - "integrity": "sha512-qUxwMtrwoG3byd4PbX6T7EjHJ8AUhzTuwniOGkh/hIznBfcE2QQnGakyEq4VnwNuttMqvh/GgPFapHQ3lCuRHg==", - "devOptional": true, - "hasInstallScript": true, + "node_modules/@safe-global/safe-apps-provider": { + "version": "0.18.4", + "resolved": "https://registry.npmjs.org/@safe-global/safe-apps-provider/-/safe-apps-provider-0.18.4.tgz", + "integrity": "sha512-SWYeG3gyTO6wGHMSokfHakZ9isByn2mHsM0VohIorYFFEyGGmJ89btnTm+DqDUSoQtvWAatZB7XNy6CaYMvqtg==", "dependencies": { - "@prisma/debug": "5.16.2", - "@prisma/engines-version": "5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303", - "@prisma/fetch-engine": "5.16.2", - "@prisma/get-platform": "5.16.2" + "@safe-global/safe-apps-sdk": "^9.1.0", + "events": "^3.3.0" } }, - "node_modules/@prisma/engines-version": { - "version": "5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303.tgz", - "integrity": "sha512-HkT2WbfmFZ9WUPyuJHhkiADxazHg8Y4gByrTSVeb3OikP6tjQ7txtSUGu9OBOBH0C13dPKN2qqH12xKtHu/Hiw==", - "devOptional": true - }, - "node_modules/@prisma/fetch-engine": { - "version": "5.16.2", - "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.16.2.tgz", - "integrity": "sha512-sq51lfHKfH2jjYSjBtMjP+AznFqOJzXpqmq6B9auWrlTJrMgZ7lPyhWUW7VU7LsQU48/TJ+DZeIz8s9bMYvcHg==", - "devOptional": true, + "node_modules/@safe-global/safe-apps-sdk": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@safe-global/safe-apps-sdk/-/safe-apps-sdk-9.1.0.tgz", + "integrity": "sha512-N5p/ulfnnA2Pi2M3YeWjULeWbjo7ei22JwU/IXnhoHzKq3pYCN6ynL9mJBOlvDVv892EgLPCWCOwQk/uBT2v0Q==", "dependencies": { - "@prisma/debug": "5.16.2", - "@prisma/engines-version": "5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303", - "@prisma/get-platform": "5.16.2" + "@safe-global/safe-gateway-typescript-sdk": "^3.5.3", + "viem": "^2.1.1" } }, - "node_modules/@prisma/get-platform": { - "version": "5.16.2", - "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.16.2.tgz", - "integrity": "sha512-cXiHPgNLNyj22vLouPVNegklpRL/iX2jxTeap5GRO3DmCoVyIHmJAV1CgUMUJhHlcol9yYy7EHvsnXTDJ/PKEA==", - "devOptional": true, + "node_modules/@safe-global/safe-gateway-typescript-sdk": { + "version": "3.22.2", + "resolved": "https://registry.npmjs.org/@safe-global/safe-gateway-typescript-sdk/-/safe-gateway-typescript-sdk-3.22.2.tgz", + "integrity": "sha512-Y0yAxRaB98LFp2Dm+ACZqBSdAmI3FlpH/LjxOZ94g/ouuDJecSq0iR26XZ5QDuEL8Rf+L4jBJaoDC08CD0KkJw==", + "engines": { + "node": ">=16" + } + }, + "node_modules/@scure/base": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.7.tgz", + "integrity": "sha512-PPNYBslrLNNUQ/Yad37MHYsNQtK67EhWb6WtSvNLLPo7SdVZgkUjD6Dg+5On7zNwmskf8OX7I7Nx5oN+MIWE0g==", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.5.0.tgz", + "integrity": "sha512-8EnFYkqEQdnkuGBVpCzKxyIwDCBLDVj3oiX0EKUFre/tOjL/Hqba1D6n/8RcmaQy4f95qQFrO2A8Sr6ybh4NRw==", "dependencies": { - "@prisma/debug": "5.16.2" + "@noble/curves": "~1.6.0", + "@noble/hashes": "~1.5.0", + "@scure/base": "~1.1.7" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + "node_modules/@scure/bip32/node_modules/@noble/hashes": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.5.0.tgz", + "integrity": "sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + "node_modules/@scure/bip39": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", + "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", + "dependencies": { + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + "node_modules/@segment/loosely-validate-event": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@segment/loosely-validate-event/-/loosely-validate-event-2.0.0.tgz", + "integrity": "sha512-ZMCSfztDBqwotkl848ODgVcAmN4OItEWDCkshcKz0/W6gGSQayuuCtWV/MlodFivAZD793d6UgANd6wCXUfrIw==", + "optional": true, + "peer": true, + "dependencies": { + "component-type": "^1.2.1", + "join-component": "^1.1.0" + } }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + "node_modules/@sepior/tsmsdkv2": { + "version": "63.0.0", + "resolved": "https://nexus.sepior.net/repository/sepior-nodejs-tsm-sdk-group/@sepior/tsmsdkv2/-/tsmsdkv2-63.0.0.tgz", + "integrity": "sha512-SERPces5/gCumUzZK8fE0oGWG6+zlRohz1VWLjEzncWEAWeC65RNhIQvCrCUSosirpoSSflxx5Kf7OHU19M8UA==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "bindings": "^1.5.0", + "elliptic": "^6.5.4", + "node-addon-api": "^7.1.0" + } }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "node_modules/@sepior/tsmsdkv2/node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "optional": true + }, + "node_modules/@sideway/address": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", + "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", "dependencies": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" + "@hapi/hoek": "^9.0.0" } }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + "node_modules/@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" }, - "node_modules/@protobufjs/path": { + "node_modules/@silencelaboratories/dkls-wasm-ll-node": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + "resolved": "https://registry.npmjs.org/@silencelaboratories/dkls-wasm-ll-node/-/dkls-wasm-ll-node-1.1.2.tgz", + "integrity": "sha512-ZGnE0p/GQRIMHJzbPtSy/3deUmD340NbWrBwpU0NyqJW4EKvh9xxv5ZFnJApq1YboHxHTaz2aP03eu+ZPZShpQ==", + "license": "SLL" }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + "node_modules/@silencelaboratories/dkls-wasm-ll-web": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@silencelaboratories/dkls-wasm-ll-web/-/dkls-wasm-ll-web-1.1.2.tgz", + "integrity": "sha512-GFdQdeTAK5RQ6SP+RVenjm/cSAXYek8+hMOL6Uw6uqsoGhJzveJHMEKEEbitGDpBjoN/admwxIKcv0wpIo022Q==", + "license": "SLL" }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" }, - "node_modules/@radix-ui/primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.1.tgz", - "integrity": "sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==", + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", "dependencies": { - "@babel/runtime": "^7.13.10" + "type-detect": "4.0.8" } }, - "node_modules/@radix-ui/react-arrow": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz", - "integrity": "sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw==", + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", "dependencies": { - "@radix-ui/react-primitive": "2.0.0" + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@slorber/remark-comment": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@slorber/remark-comment/-/remark-comment-1.0.0.tgz", + "integrity": "sha512-RCE24n7jsOj1M0UPvIQCHTe7fI0sFL4S2nwKVWwHyVr/wI/H8GosgsJGyhnsZoGFnD/P2hLf1mSbrrgSLN93NA==", + "dependencies": { + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.1.0", + "micromark-util-symbol": "^1.0.1" + } + }, + "node_modules/@smithy/abort-controller": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.1.4.tgz", + "integrity": "sha512-VupaALAQlXViW3/enTf/f5l5JZYSAxoJL7f0nanhNNKnww6DGCg1oYIuNP78KDugnkwthBO6iEcym16HhWV8RQ==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/config-resolver": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-3.0.8.tgz", + "integrity": "sha512-Tv1obAC18XOd2OnDAjSWmmthzx6Pdeh63FbLin8MlPiuJ2ATpKkq0NcNOJFr0dO+JmZXnwu8FQxKJ3TKJ3Hulw==", + "dependencies": { + "@smithy/node-config-provider": "^3.1.7", + "@smithy/types": "^3.4.2", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.6", + "tslib": "^2.6.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/core": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.4.5.tgz", + "integrity": "sha512-Z0qlPXgZ0pouYgnu/cZTEYeRAvniiKZmVl4wIbZHX/nEMHkMDV9ao6KFArsU9KndE0TuhL149xcRx45wfw1YCA==", + "dependencies": { + "@smithy/middleware-endpoint": "^3.1.3", + "@smithy/middleware-retry": "^3.0.20", + "@smithy/middleware-serde": "^3.0.6", + "@smithy/protocol-http": "^4.1.3", + "@smithy/smithy-client": "^3.3.4", + "@smithy/types": "^3.4.2", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-middleware": "^3.0.6", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/credential-provider-imds": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.3.tgz", + "integrity": "sha512-VoxMzSzdvkkjMJNE38yQgx4CfnmT+Z+5EUXkg4x7yag93eQkVQgZvN3XBSHC/ylfBbLbAtdu7flTCChX9I+mVg==", + "dependencies": { + "@smithy/node-config-provider": "^3.1.7", + "@smithy/property-provider": "^3.1.6", + "@smithy/types": "^3.4.2", + "@smithy/url-parser": "^3.0.6", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/fetch-http-handler": { + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.8.tgz", + "integrity": "sha512-Lqe0B8F5RM7zkw//6avq1SJ8AfaRd3ubFUS1eVp5WszV7p6Ne5hQ4dSuMHDpNRPhgTvj4va9Kd/pcVigHEHRow==", + "dependencies": { + "@smithy/protocol-http": "^4.1.3", + "@smithy/querystring-builder": "^3.0.6", + "@smithy/types": "^3.4.2", + "@smithy/util-base64": "^3.0.0", + "tslib": "^2.6.2" } }, - "node_modules/@radix-ui/react-arrow/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", - "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "node_modules/@smithy/hash-node": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-3.0.6.tgz", + "integrity": "sha512-c/FHEdKK/7DU2z6ZE91L36ahyXWayR3B+FzELjnYq7wH5YqIseM24V+pWCS9kFn1Ln8OFGTf+pyYPiHZuX0s/Q==", + "dependencies": { + "@smithy/types": "^3.4.2", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@radix-ui/react-arrow/node_modules/@radix-ui/react-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz", - "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==", + "node_modules/@smithy/invalid-dependency": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-3.0.6.tgz", + "integrity": "sha512-czM7Ioq3s8pIXht7oD+vmgy4Wfb4XavU/k/irO8NdXFFOx7YAlsCCcKOh/lJD1mJSYQqiR7NmpZ9JviryD/7AQ==", "dependencies": { - "@radix-ui/react-slot": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" } }, - "node_modules/@radix-ui/react-arrow/node_modules/@radix-ui/react-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", - "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", + "node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "tslib": "^2.6.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@radix-ui/react-checkbox": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.1.1.tgz", - "integrity": "sha512-0i/EKJ222Afa1FE0C6pNJxDq1itzcl3HChE9DwskA4th4KRse8ojx8a1nVcOjwJdbpDLcz7uol77yYnQNMHdKw==", + "node_modules/@smithy/middleware-content-length": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-3.0.8.tgz", + "integrity": "sha512-VuyszlSO49WKh3H9/kIO2kf07VUwGV80QRiaDxUfP8P8UKlokz381ETJvwLhwuypBYhLymCYyNhB3fLAGBX2og==", "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-presence": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-controllable-state": "1.1.0", - "@radix-ui/react-use-previous": "1.1.0", - "@radix-ui/react-use-size": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@smithy/protocol-http": "^4.1.3", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/primitive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz", - "integrity": "sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==" - }, - "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", - "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "node_modules/@smithy/middleware-endpoint": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.1.3.tgz", + "integrity": "sha512-KeM/OrK8MVFUsoJsmCN0MZMVPjKKLudn13xpgwIMpGTYpA8QZB2Xq5tJ+RE6iu3A6NhOI4VajDTwBsm8pwwrhg==", + "dependencies": { + "@smithy/middleware-serde": "^3.0.6", + "@smithy/node-config-provider": "^3.1.7", + "@smithy/shared-ini-file-loader": "^3.1.7", + "@smithy/types": "^3.4.2", + "@smithy/url-parser": "^3.0.6", + "@smithy/util-middleware": "^3.0.6", + "tslib": "^2.6.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-context": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz", - "integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "node_modules/@smithy/middleware-retry": { + "version": "3.0.20", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.20.tgz", + "integrity": "sha512-HELCOVwYw5hFDBm69d+LmmGjBCjWnwp/t7SJiHmp+c4u9vgfIaCjdSeIdnlOsLrr5ic5jGTJXvJFUQnd987b/g==", + "dependencies": { + "@smithy/node-config-provider": "^3.1.7", + "@smithy/protocol-http": "^4.1.3", + "@smithy/service-error-classification": "^3.0.6", + "@smithy/smithy-client": "^3.3.4", + "@smithy/types": "^3.4.2", + "@smithy/util-middleware": "^3.0.6", + "@smithy/util-retry": "^3.0.6", + "tslib": "^2.6.2", + "uuid": "^9.0.1" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-presence": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.0.tgz", - "integrity": "sha512-Gq6wuRN/asf9H/E/VzdKoUtT8GC9PQc9z40/vEr0VCJ4u5XvvhWIrSsCB6vD2/cH7ugTdSfYq9fLJCcM00acrQ==", + "node_modules/@smithy/middleware-serde": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.6.tgz", + "integrity": "sha512-KKTUSl1MzOM0MAjGbudeaVNtIDo+PpekTBkCNwvfZlKndodrnvRo+00USatiyLOc0ujjO9UydMRu3O9dYML7ag==", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz", - "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==", + "node_modules/@smithy/middleware-stack": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.6.tgz", + "integrity": "sha512-2c0eSYhTQ8xQqHMcRxLMpadFbTXg6Zla5l0mwNftFCZMQmuhI7EbAJMx6R5eqfuV3YbJ3QGyS3d5uSmrHV8Khg==", "dependencies": { - "@radix-ui/react-slot": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", - "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", + "node_modules/@smithy/node-config-provider": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.7.tgz", + "integrity": "sha512-g3mfnC3Oo8pOI0dYuPXLtdW1WGVb3bR2tkV21GNkm0ZvQjLTtamXAwCWt/FCb0HGvKt3gHHmF1XerG0ICfalOg==", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@smithy/property-provider": "^3.1.6", + "@smithy/shared-ini-file-loader": "^3.1.7", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-use-callback-ref": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", - "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "node_modules/@smithy/node-http-handler": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.2.3.tgz", + "integrity": "sha512-/gcm5DJ3k1b1zEInzBGAZC8ntJ+jwrz1NcSIu+9dSXd1FfG0G6QgkDI40tt8/WYUbHtLyo8fEqtm2v29koWo/w==", + "dependencies": { + "@smithy/abort-controller": "^3.1.4", + "@smithy/protocol-http": "^4.1.3", + "@smithy/querystring-builder": "^3.0.6", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-use-controllable-state": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz", - "integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==", + "node_modules/@smithy/property-provider": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.6.tgz", + "integrity": "sha512-NK3y/T7Q/Bw+Z8vsVs9MYIQ5v7gOX7clyrXcwhhIBQhbPgRl6JDrZbusO9qWDhcEus75Tg+VCxtIRfo3H76fpw==", "dependencies": { - "@radix-ui/react-use-callback-ref": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", - "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "node_modules/@smithy/protocol-http": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.3.tgz", + "integrity": "sha512-GcbMmOYpH9iRqtC05RbRnc/0FssxSTHlmaNhYBTgSgNCYpdR3Kt88u5GAZTBmouzv+Zlj/VRv92J9ruuDeJuEw==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-use-size": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz", - "integrity": "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==", + "node_modules/@smithy/querystring-builder": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.6.tgz", + "integrity": "sha512-sQe08RunoObe+Usujn9+R2zrLuQERi3CWvRO3BvnoWSYUaIrLKuAIeY7cMeDax6xGyfIP3x/yFWbEKSXvOnvVg==", "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@smithy/types": "^3.4.2", + "@smithy/util-uri-escape": "^3.0.0", + "tslib": "^2.6.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@radix-ui/react-collapsible": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.0.3.tgz", - "integrity": "sha512-UBmVDkmR6IvDsloHVN+3rtx4Mi5TFvylYXpluuv0f37dtaz3H99bp8No0LGXRigVpl3UAT4l9j6bIchh42S/Gg==", + "node_modules/@smithy/querystring-parser": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.6.tgz", + "integrity": "sha512-UJKw4LlEkytzz2Wq+uIdHf6qOtFfee/o7ruH0jF5I6UAuU+19r9QV7nU3P/uI0l6+oElRHmG/5cBBcGJrD7Ozg==", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-id": "1.0.1", - "@radix-ui/react-presence": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-controllable-state": "1.0.1", - "@radix-ui/react-use-layout-effect": "1.0.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@radix-ui/react-collection": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.3.tgz", - "integrity": "sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==", + "node_modules/@smithy/service-error-classification": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-3.0.6.tgz", + "integrity": "sha512-53SpchU3+DUZrN7J6sBx9tBiCVGzsib2e4sc512Q7K9fpC5zkJKs6Z9s+qbMxSYrkEkle6hnMtrts7XNkMJJMg==", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-slot": "1.0.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" + "@smithy/types": "^3.4.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@radix-ui/react-compose-refs": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz", - "integrity": "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==", + "node_modules/@smithy/shared-ini-file-loader": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.7.tgz", + "integrity": "sha512-IA4K2qTJYXkF5OfVN4vsY1hfnUZjaslEE8Fsr/gGFza4TAC2A9NfnZuSY2srQIbt9bwtjHiAayrRVgKse4Q7fA==", "dependencies": { - "@babel/runtime": "^7.13.10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@radix-ui/react-context": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.0.1.tgz", - "integrity": "sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==", + "node_modules/@smithy/signature-v4": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-4.1.4.tgz", + "integrity": "sha512-72MiK7xYukNsnLJI9NqvUHqTu0ziEsfMsYNlWpiJfuGQnCTFKpckThlEatirvcA/LmT1h7rRO+pJD06PYsPu9Q==", "dependencies": { - "@babel/runtime": "^7.13.10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" + "@smithy/is-array-buffer": "^3.0.0", + "@smithy/protocol-http": "^4.1.3", + "@smithy/types": "^3.4.2", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-middleware": "^3.0.6", + "@smithy/util-uri-escape": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@radix-ui/react-dialog": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.2.tgz", - "integrity": "sha512-Yj4dZtqa2o+kG61fzB0H2qUvmwBA2oyQroGLyNtBj1beo1khoQ3q1a2AO8rrQYjd8256CO9+N8L9tvsS+bnIyA==", + "node_modules/@smithy/smithy-client": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.3.4.tgz", + "integrity": "sha512-NKw/2XxOW/Rg3rzB90HxsmGok5oS6vRzJgMh/JN4BHaOQQ4q5OuX999GmOGxEp730wbpIXIowfKZmIMXkG4v0Q==", "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-dismissable-layer": "1.1.1", - "@radix-ui/react-focus-guards": "1.1.1", - "@radix-ui/react-focus-scope": "1.1.0", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-portal": "1.1.2", - "@radix-ui/react-presence": "1.1.1", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-slot": "1.1.0", - "@radix-ui/react-use-controllable-state": "1.1.0", - "aria-hidden": "^1.1.1", - "react-remove-scroll": "2.6.0" + "@smithy/middleware-endpoint": "^3.1.3", + "@smithy/middleware-stack": "^3.0.6", + "@smithy/protocol-http": "^4.1.3", + "@smithy/types": "^3.4.2", + "@smithy/util-stream": "^3.1.8", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/types": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.4.2.tgz", + "integrity": "sha512-tHiFcfcVedVBHpmHUEUHOCCih8iZbIAYn9NvPsNzaPm/237I3imdDdZoOC8c87H5HBAVEa06tTgb+OcSWV9g5w==", + "dependencies": { + "tslib": "^2.6.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/primitive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz", - "integrity": "sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==" + "node_modules/@smithy/url-parser": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.6.tgz", + "integrity": "sha512-47Op/NU8Opt49KyGpHtVdnmmJMsp2hEwBdyjuFB9M2V5QVOwA7pBhhxKN5z6ztKGrMw76gd8MlbPuzzvaAncuQ==", + "dependencies": { + "@smithy/querystring-parser": "^3.0.6", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", - "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "node_modules/@smithy/util-base64": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-3.0.0.tgz", + "integrity": "sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-context": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", - "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "node_modules/@smithy/util-body-length-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz", + "integrity": "sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ==", + "dependencies": { + "tslib": "^2.6.2" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-dismissable-layer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.1.tgz", - "integrity": "sha512-QSxg29lfr/xcev6kSz7MAlmDnzbP1eI/Dwn3Tp1ip0KT5CUELsxkekFEMVBEoykI3oV39hKT4TKZzBNMbcTZYQ==", + "node_modules/@smithy/util-body-length-node": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-3.0.0.tgz", + "integrity": "sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA==", "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-escape-keydown": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "tslib": "^2.6.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-focus-guards": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz", - "integrity": "sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-focus-scope": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.0.tgz", - "integrity": "sha512-200UD8zylvEyL8Bx+z76RJnASR2gRMuxlgFCPAe/Q/679a/r0eK3MBVYMb7vZODZcffZBdob1EGnky78xmVvcA==", + "node_modules/@smithy/util-config-provider": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz", + "integrity": "sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-callback-ref": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "tslib": "^2.6.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-id": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz", - "integrity": "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==", + "node_modules/@smithy/util-defaults-mode-browser": { + "version": "3.0.20", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.20.tgz", + "integrity": "sha512-HpYmCpEThQJpCKzwzrGrklhdegRfuXI9keHRrHidbyEMliCdgic6t38MikJeZEkdIcEMhO1g95HIYMzjUzB+xg==", "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@smithy/property-provider": "^3.1.6", + "@smithy/smithy-client": "^3.3.4", + "@smithy/types": "^3.4.2", + "bowser": "^2.11.0", + "tslib": "^2.6.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">= 10.0.0" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-portal": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.2.tgz", - "integrity": "sha512-WeDYLGPxJb/5EGBoedyJbT0MpoULmwnIPMJMSldkuiMsBAv7N1cRdsTWZWht9vpPOiN3qyiGAtbK2is47/uMFg==", + "node_modules/@smithy/util-defaults-mode-node": { + "version": "3.0.20", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.20.tgz", + "integrity": "sha512-atdsHNtAX0rwTvRRGsrONU0C0XzapH6tI8T1y/OReOvWN7uBwXqqWRft6m8egU2DgeReU0xqT3PHdGCe5VRaaQ==", "dependencies": { - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-layout-effect": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@smithy/config-resolver": "^3.0.8", + "@smithy/credential-provider-imds": "^3.2.3", + "@smithy/node-config-provider": "^3.1.7", + "@smithy/property-provider": "^3.1.6", + "@smithy/smithy-client": "^3.3.4", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "engines": { + "node": ">= 10.0.0" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-presence": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.1.tgz", - "integrity": "sha512-IeFXVi4YS1K0wVZzXNrbaaUvIJ3qdY+/Ih4eHFhWA9SwGR9UDX7Ck8abvL57C4cv3wwMvUE0OG69Qc3NCcTe/A==", + "node_modules/@smithy/util-endpoints": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-2.1.2.tgz", + "integrity": "sha512-FEISzffb4H8DLzGq1g4MuDpcv6CIG15fXoQzDH9SjpRJv6h7J++1STFWWinilG0tQh9H1v2UKWG19Jjr2B16zQ==", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@smithy/node-config-provider": "^3.1.7", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz", - "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==", + "node_modules/@smithy/util-hex-encoding": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz", + "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==", "dependencies": { - "@radix-ui/react-slot": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "tslib": "^2.6.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", - "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", + "node_modules/@smithy/util-middleware": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.6.tgz", + "integrity": "sha512-BxbX4aBhI1O9p87/xM+zWy0GzT3CEVcXFPBRDoHAM+pV0eSW156pR+PSYEz0DQHDMYDsYAflC2bQNz2uaDBUZQ==", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-use-callback-ref": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", - "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "node_modules/@smithy/util-retry": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.6.tgz", + "integrity": "sha512-BRZiuF7IwDntAbevqMco67an0Sr9oLQJqqRCsSPZZHYRnehS0LHDAkJk/pSmI7Z8c/1Vet294H7fY2fWUgB+Rg==", + "dependencies": { + "@smithy/service-error-classification": "^3.0.6", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-use-controllable-state": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz", - "integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==", + "node_modules/@smithy/util-stream": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.1.8.tgz", + "integrity": "sha512-hoKOqSmb8FD3WLObuB5hwbM7bNIWgcnvkThokTvVq7J5PKjlLUK5qQQcB9zWLHIoSaIlf3VIv2OxZY2wtQjcRQ==", "dependencies": { - "@radix-ui/react-use-callback-ref": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@smithy/fetch-http-handler": "^3.2.8", + "@smithy/node-http-handler": "^3.2.3", + "@smithy/types": "^3.4.2", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-use-escape-keydown": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz", - "integrity": "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==", + "node_modules/@smithy/util-uri-escape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", + "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", "dependencies": { - "@radix-ui/react-use-callback-ref": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "tslib": "^2.6.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", - "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@radix-ui/react-dialog/node_modules/react-remove-scroll": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.0.tgz", - "integrity": "sha512-I2U4JVEsQenxDAKaVa3VZ/JeJZe0/2DxPWL8Tj8yLKctQJQiZM52pn/GWFpSp8dftjM3pSAHVJZscAnC/y+ySQ==", + "node_modules/@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" + }, + "node_modules/@solana/buffer-layout": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz", + "integrity": "sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA==", + "license": "MIT", "dependencies": { - "react-remove-scroll-bar": "^2.3.6", - "react-style-singleton": "^2.2.1", - "tslib": "^2.1.0", - "use-callback-ref": "^1.3.0", - "use-sidecar": "^1.1.2" + "buffer": "~6.0.3" }, "engines": { - "node": ">=10" - }, - "peerDependencies": { - "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "node": ">=5.10" } }, - "node_modules/@radix-ui/react-direction": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.0.1.tgz", - "integrity": "sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==", + "node_modules/@solana/buffer-layout-utils": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@solana/buffer-layout-utils/-/buffer-layout-utils-0.2.0.tgz", + "integrity": "sha512-szG4sxgJGktbuZYDg2FfNmkMi0DYQoVjN2h7ta1W1hPrwzarcFLBq9UpX1UjNXsNpT9dn+chgprtWGioUAr4/g==", + "license": "Apache-2.0", "dependencies": { - "@babel/runtime": "^7.13.10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" + "@solana/buffer-layout": "^4.0.0", + "@solana/web3.js": "^1.32.0", + "bigint-buffer": "^1.1.5", + "bignumber.js": "^9.0.1" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">= 10" } }, - "node_modules/@radix-ui/react-dismissable-layer": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.5.tgz", - "integrity": "sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g==", - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-callback-ref": "1.0.1", - "@radix-ui/react-use-escape-keydown": "1.0.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true + "node_modules/@solana/buffer-layout/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" }, - "@types/react-dom": { - "optional": true + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" } }, - "node_modules/@radix-ui/react-dropdown-menu": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.0.6.tgz", - "integrity": "sha512-i6TuFOoWmLWq+M/eCLGd/bQ2HfAX1RJgvrBQ6AQLmzfvsLdefxbWu8G9zczcPFfcSPehz9GcpF6K9QYreFV8hA==", + "node_modules/@solana/spl-token": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@solana/spl-token/-/spl-token-0.3.1.tgz", + "integrity": "sha512-26/0XlW5Lyeu3CUlBGt+0o3l4H6AJtRtMMtsxhcKj+DwfGg+QMnPl/exTmZLEsymsn03PFhogd97v5fJXhYeow==", + "license": "Apache-2.0", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-id": "1.0.1", - "@radix-ui/react-menu": "2.0.6", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-controllable-state": "1.0.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true + "@solana/buffer-layout": "^4.0.0", + "@solana/buffer-layout-utils": "^0.2.0", + "@solana/web3.js": "^1.41.0" + } + }, + "node_modules/@solana/web3.js": { + "version": "1.92.1", + "resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.92.1.tgz", + "integrity": "sha512-72hytgOHfJLbvKT0+HRuFUhxxZpCnlo4zFDt37UHPel1DJbgqGOWo3xUf3VEPRWBvSRv0EH15g8MGatdj1PO9g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.6", + "@noble/curves": "^1.4.0", + "@noble/hashes": "^1.4.0", + "@solana/buffer-layout": "^4.0.1", + "agentkeepalive": "^4.5.0", + "bigint-buffer": "^1.1.5", + "bn.js": "^5.2.1", + "borsh": "^0.7.0", + "bs58": "^4.0.1", + "buffer": "6.0.3", + "fast-stable-stringify": "^1.0.0", + "jayson": "^4.1.0", + "node-fetch": "^2.7.0", + "rpc-websockets": "^7.11.1", + "superstruct": "^1.0.4" + } + }, + "node_modules/@solana/web3.js/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" }, - "@types/react-dom": { - "optional": true + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" } }, - "node_modules/@radix-ui/react-focus-guards": { + "node_modules/@stablelib/aead": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.1.tgz", - "integrity": "sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==", + "resolved": "https://registry.npmjs.org/@stablelib/aead/-/aead-1.0.1.tgz", + "integrity": "sha512-q39ik6sxGHewqtO0nP4BuSe3db5G1fEJE8ukvngS2gLkBXyy6E7pLubhbYgnkDFv6V8cWaxcE4Xn0t6LWcJkyg==" + }, + "node_modules/@stablelib/binary": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/binary/-/binary-1.0.1.tgz", + "integrity": "sha512-ClJWvmL6UBM/wjkvv/7m5VP3GMr9t0osr4yVgLZsLCOz4hGN9gIAFEqnJ0TsSMAN+n840nf2cHZnA5/KFqHC7Q==", "dependencies": { - "@babel/runtime": "^7.13.10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "@stablelib/int": "^1.0.1" } }, - "node_modules/@radix-ui/react-focus-scope": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.4.tgz", - "integrity": "sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA==", + "node_modules/@stablelib/bytes": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/bytes/-/bytes-1.0.1.tgz", + "integrity": "sha512-Kre4Y4kdwuqL8BR2E9hV/R5sOrUj6NanZaZis0V6lX5yzqC3hBuVSDXUIBqQv/sCpmuWRiHLwqiT1pqqjuBXoQ==" + }, + "node_modules/@stablelib/chacha": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/chacha/-/chacha-1.0.1.tgz", + "integrity": "sha512-Pmlrswzr0pBzDofdFuVe1q7KdsHKhhU24e8gkEwnTGOmlC7PADzLVxGdn2PoNVBBabdg0l/IfLKg6sHAbTQugg==", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-callback-ref": "1.0.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "@stablelib/binary": "^1.0.1", + "@stablelib/wipe": "^1.0.1" } }, - "node_modules/@radix-ui/react-id": { + "node_modules/@stablelib/chacha20poly1305": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.0.1.tgz", - "integrity": "sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==", + "resolved": "https://registry.npmjs.org/@stablelib/chacha20poly1305/-/chacha20poly1305-1.0.1.tgz", + "integrity": "sha512-MmViqnqHd1ymwjOQfghRKw2R/jMIGT3wySN7cthjXCBdO+qErNPUBnRzqNpnvIwg7JBCg3LdeCZZO4de/yEhVA==", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-use-layout-effect": "1.0.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "@stablelib/aead": "^1.0.1", + "@stablelib/binary": "^1.0.1", + "@stablelib/chacha": "^1.0.1", + "@stablelib/constant-time": "^1.0.1", + "@stablelib/poly1305": "^1.0.1", + "@stablelib/wipe": "^1.0.1" } }, - "node_modules/@radix-ui/react-menu": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.0.6.tgz", - "integrity": "sha512-BVkFLS+bUC8HcImkRKPSiVumA1VPOOEC5WBMiT+QAVsPzW1FJzI9KnqgGxVDPBcql5xXrHkD3JOVoXWEXD8SYA==", + "node_modules/@stablelib/constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/constant-time/-/constant-time-1.0.1.tgz", + "integrity": "sha512-tNOs3uD0vSJcK6z1fvef4Y+buN7DXhzHDPqRLSXUel1UfqMB1PWNsnnAezrKfEwTLpN0cGH2p9NNjs6IqeD0eg==" + }, + "node_modules/@stablelib/ed25519": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@stablelib/ed25519/-/ed25519-1.0.3.tgz", + "integrity": "sha512-puIMWaX9QlRsbhxfDc5i+mNPMY+0TmQEskunY1rZEBPi1acBCVQAhnsk/1Hk50DGPtVsZtAWQg4NHGlVaO9Hqg==", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-collection": "1.0.3", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-direction": "1.0.1", - "@radix-ui/react-dismissable-layer": "1.0.5", - "@radix-ui/react-focus-guards": "1.0.1", - "@radix-ui/react-focus-scope": "1.0.4", - "@radix-ui/react-id": "1.0.1", - "@radix-ui/react-popper": "1.1.3", - "@radix-ui/react-portal": "1.0.4", - "@radix-ui/react-presence": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-roving-focus": "1.0.4", - "@radix-ui/react-slot": "1.0.2", - "@radix-ui/react-use-callback-ref": "1.0.1", - "aria-hidden": "^1.1.1", - "react-remove-scroll": "2.5.5" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "@stablelib/random": "^1.0.2", + "@stablelib/sha512": "^1.0.1", + "@stablelib/wipe": "^1.0.1" } }, - "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-arrow": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz", - "integrity": "sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA==", + "node_modules/@stablelib/hash": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/hash/-/hash-1.0.1.tgz", + "integrity": "sha512-eTPJc/stDkdtOcrNMZ6mcMK1e6yBbqRBaNW55XA1jU8w/7QdnCF0CmMmOD1m7VSkBR44PWrMHU2l6r8YEQHMgg==" + }, + "node_modules/@stablelib/hex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/hex/-/hex-1.0.1.tgz", + "integrity": "sha512-PQOEChVBjhYGgAD+ehO2ow1gSj1slre3jW4oMD4kV8VrhYhzmtsQDWDZej3BQO8qkVezdczDvISxVSF24PuYNA==", + "license": "MIT" + }, + "node_modules/@stablelib/hkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/hkdf/-/hkdf-1.0.1.tgz", + "integrity": "sha512-SBEHYE16ZXlHuaW5RcGk533YlBj4grMeg5TooN80W3NpcHRtLZLLXvKyX0qcRFxf+BGDobJLnwkvgEwHIDBR6g==", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-primitive": "1.0.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "@stablelib/hash": "^1.0.1", + "@stablelib/hmac": "^1.0.1", + "@stablelib/wipe": "^1.0.1" } }, - "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-popper": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.1.3.tgz", - "integrity": "sha512-cKpopj/5RHZWjrbF2846jBNacjQVwkP068DfmgrNJXpvVWrOvlAmE9xSiy5OqeE+Gi8D9fP+oDhUnPqNMY8/5w==", + "node_modules/@stablelib/hmac": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/hmac/-/hmac-1.0.1.tgz", + "integrity": "sha512-V2APD9NSnhVpV/QMYgCVMIYKiYG6LSqw1S65wxVoirhU/51ACio6D4yDVSwMzuTJXWZoVHbDdINioBwKy5kVmA==", "dependencies": { - "@babel/runtime": "^7.13.10", - "@floating-ui/react-dom": "^2.0.0", - "@radix-ui/react-arrow": "1.0.3", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-callback-ref": "1.0.1", - "@radix-ui/react-use-layout-effect": "1.0.1", - "@radix-ui/react-use-rect": "1.0.1", - "@radix-ui/react-use-size": "1.0.1", - "@radix-ui/rect": "1.0.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "@stablelib/constant-time": "^1.0.1", + "@stablelib/hash": "^1.0.1", + "@stablelib/wipe": "^1.0.1" } }, - "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-use-rect": { + "node_modules/@stablelib/int": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.0.1.tgz", - "integrity": "sha512-Cq5DLuSiuYVKNU8orzJMbl15TXilTnJKUCltMVQg53BQOF1/C5toAaGrowkgksdBQ9H+SRL23g0HDmg9tvmxXw==", + "resolved": "https://registry.npmjs.org/@stablelib/int/-/int-1.0.1.tgz", + "integrity": "sha512-byr69X/sDtDiIjIV6m4roLVWnNNlRGzsvxw+agj8CIEazqWGOQp2dTYgQhtyVXV9wpO6WyXRQUzLV/JRNumT2w==" + }, + "node_modules/@stablelib/keyagreement": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/keyagreement/-/keyagreement-1.0.1.tgz", + "integrity": "sha512-VKL6xBwgJnI6l1jKrBAfn265cspaWBPAPEc62VBQrWHLqVgNRE09gQ/AnOEyKUWrrqfD+xSQ3u42gJjLDdMDQg==", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/rect": "1.0.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "@stablelib/bytes": "^1.0.1" } }, - "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/rect": { + "node_modules/@stablelib/poly1305": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.0.1.tgz", - "integrity": "sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ==", + "resolved": "https://registry.npmjs.org/@stablelib/poly1305/-/poly1305-1.0.1.tgz", + "integrity": "sha512-1HlG3oTSuQDOhSnLwJRKeTRSAdFNVB/1djy2ZbS35rBSJ/PFqx9cf9qatinWghC2UbfOYD8AcrtbUQl8WoxabA==", "dependencies": { - "@babel/runtime": "^7.13.10" + "@stablelib/constant-time": "^1.0.1", + "@stablelib/wipe": "^1.0.1" } }, - "node_modules/@radix-ui/react-popper": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.0.tgz", - "integrity": "sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg==", + "node_modules/@stablelib/random": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@stablelib/random/-/random-1.0.2.tgz", + "integrity": "sha512-rIsE83Xpb7clHPVRlBj8qNe5L8ISQOzjghYQm/dZ7VaM2KHYwMW5adjQjrzTZCchFnNCNhkwtnOBa9HTMJCI8w==", "dependencies": { - "@floating-ui/react-dom": "^2.0.0", - "@radix-ui/react-arrow": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0", - "@radix-ui/react-use-rect": "1.1.0", - "@radix-ui/react-use-size": "1.1.0", - "@radix-ui/rect": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "@stablelib/binary": "^1.0.1", + "@stablelib/wipe": "^1.0.1" } }, - "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", - "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "node_modules/@stablelib/sha256": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/sha256/-/sha256-1.0.1.tgz", + "integrity": "sha512-GIIH3e6KH+91FqGV42Kcj71Uefd/QEe7Dy42sBTeqppXV95ggCcxLTk39bEr+lZfJmp+ghsR07J++ORkRELsBQ==", + "dependencies": { + "@stablelib/binary": "^1.0.1", + "@stablelib/hash": "^1.0.1", + "@stablelib/wipe": "^1.0.1" } }, - "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-context": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz", - "integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "node_modules/@stablelib/sha384": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/sha384/-/sha384-1.0.1.tgz", + "integrity": "sha512-LkhNw9E/9JJzPFxVVBw70yXp2l90XZOm6yPiqh9id+AFscDk2OZ0UkTddUKpPuvjdVtc+7ENvtkSNFJmMncLQg==", + "license": "MIT", + "dependencies": { + "@stablelib/sha512": "^1.0.1" } }, - "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz", - "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==", + "node_modules/@stablelib/sha512": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/sha512/-/sha512-1.0.1.tgz", + "integrity": "sha512-13gl/iawHV9zvDKciLo1fQ8Bgn2Pvf7OV6amaRVKiq3pjQ3UmEpXxWiAfV8tYjUpeZroBxtyrwtdooQT/i3hzw==", "dependencies": { - "@radix-ui/react-slot": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "@stablelib/binary": "^1.0.1", + "@stablelib/hash": "^1.0.1", + "@stablelib/wipe": "^1.0.1" } }, - "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", - "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", + "node_modules/@stablelib/wipe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/wipe/-/wipe-1.0.1.tgz", + "integrity": "sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg==" + }, + "node_modules/@stablelib/x25519": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@stablelib/x25519/-/x25519-1.0.3.tgz", + "integrity": "sha512-KnTbKmUhPhHavzobclVJQG5kuivH+qDLpe84iRqX3CLrKp881cF160JvXJ+hjn1aMyCwYOKeIZefIH/P5cJoRw==", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "@stablelib/keyagreement": "^1.0.1", + "@stablelib/random": "^1.0.2", + "@stablelib/wipe": "^1.0.1" } }, - "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-use-callback-ref": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", - "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "node_modules/@stacks/common": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@stacks/common/-/common-4.3.5.tgz", + "integrity": "sha512-UuViiQ7fn3vdtTe3739aRzbl+wbukekeQuXgqt8d7nB2HC2HodD7GcHhpUga165cO35CD6lQUtj3vXxJb5Ga+A==", + "license": "MIT", + "dependencies": { + "@types/bn.js": "^5.1.0", + "@types/node": "^18.0.4", + "buffer": "^6.0.3" } }, - "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", - "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true + "node_modules/@stacks/common/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" } }, - "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-use-size": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz", - "integrity": "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==", + "node_modules/@stacks/network": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@stacks/network/-/network-4.3.5.tgz", + "integrity": "sha512-TC4+AkuT6qi3MoEGxTftA+4BNp99QvGnI+qtKQkoA1m0KDr8b9hSBUhugJHRhQbWuo7D6q0+JagYEGxLID29Kw==", + "license": "MIT", "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "@stacks/common": "^4.3.5", + "cross-fetch": "^3.1.5" } }, - "node_modules/@radix-ui/react-portal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.4.tgz", - "integrity": "sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==", + "node_modules/@stacks/network/node_modules/cross-fetch": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", + "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-primitive": "1.0.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "node-fetch": "^2.7.0" } }, - "node_modules/@radix-ui/react-presence": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.0.1.tgz", - "integrity": "sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==", - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-use-layout-effect": "1.0.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "node_modules/@stacks/transactions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-2.0.1.tgz", + "integrity": "sha512-q+8nCbn+0m1T8NbGG2sfMcBcCxdaH/F+vgBEHkhMIFHFLYXVYBGYbTX2llGS9StLp/tQq6p2Bfb1kzKFSw8FRQ==", + "license": "GPL-3.0-or-later", + "dependencies": { + "@stacks/common": "^2.0.1", + "@stacks/network": "^1.2.2", + "@types/bn.js": "^4.11.6", + "@types/elliptic": "^6.4.12", + "@types/node": "^14.14.43", + "@types/randombytes": "^2.0.0", + "@types/sha.js": "^2.4.0", + "bn.js": "^4.12.0", + "c32check": "^1.1.2", + "cross-fetch": "^3.1.4", + "elliptic": "^6.5.4", + "lodash": "^4.17.20", + "randombytes": "^2.1.0", + "ripemd160-min": "^0.0.6", + "sha.js": "^2.4.11", + "smart-buffer": "^4.1.0" } }, - "node_modules/@radix-ui/react-primitive": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz", - "integrity": "sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==", + "node_modules/@stacks/transactions/node_modules/@stacks/common": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@stacks/common/-/common-2.0.2.tgz", + "integrity": "sha512-RpuNIqf+XmcHlMjXeVZE4fS3yIUlCvOYmxyBKOarh010Kx3Gs/LhAeejn/329lYcIE6VwNPoeXPSE9deq7Yjcw==", + "license": "GPL-3.0-or-later", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-slot": "1.0.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "@types/node": "^14.14.43", + "bn.js": "^4.12.0", + "buffer": "^6.0.3", + "cross-fetch": "^3.1.4" } }, - "node_modules/@radix-ui/react-radio-group": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.2.0.tgz", - "integrity": "sha512-yv+oiLaicYMBpqgfpSPw6q+RyXlLdIpQWDHZbUKURxe+nEh53hFXPPlfhfQQtYkS5MMK/5IWIa76SksleQZSzw==", + "node_modules/@stacks/transactions/node_modules/@stacks/network": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@stacks/network/-/network-1.2.2.tgz", + "integrity": "sha512-xcWwuRrLJn9qqi3PEBcP2UPZHQztTZd31C0aVlzYHttNMir/sY9SrUqSnw45z2Jo4O9pIYYPIiPRtdV91Ho3fw==", + "license": "GPL-3.0-or-later", "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-direction": "1.1.0", - "@radix-ui/react-presence": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-roving-focus": "1.1.0", - "@radix-ui/react-use-controllable-state": "1.1.0", - "@radix-ui/react-use-previous": "1.1.0", - "@radix-ui/react-use-size": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "@stacks/common": "^1.2.2" } }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/primitive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz", - "integrity": "sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==" + "node_modules/@stacks/transactions/node_modules/@stacks/network/node_modules/@stacks/common": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@stacks/common/-/common-1.2.2.tgz", + "integrity": "sha512-knCqq88EBRCN8AhS7+Sx2PJuRv0EFNChEpqLqCAchCHCQfp5bWad/47Zw+fLP9ccBwFXh4pl1wDtbQLBfDo0+A==", + "license": "GPL-3.0-or-later", + "dependencies": { + "cross-fetch": "^3.0.6" + } }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-collection": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.0.tgz", - "integrity": "sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw==", + "node_modules/@stacks/transactions/node_modules/@types/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", + "license": "MIT", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-slot": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "@types/node": "*" } }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", - "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true + "node_modules/@stacks/transactions/node_modules/@types/node": { + "version": "14.18.63", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.63.tgz", + "integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==", + "license": "MIT" + }, + "node_modules/@stacks/transactions/node_modules/bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "license": "MIT" + }, + "node_modules/@stacks/transactions/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" } }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-context": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz", - "integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "node_modules/@stacks/transactions/node_modules/cross-fetch": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", + "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", + "license": "MIT", + "dependencies": { + "node-fetch": "^2.7.0" } }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-direction": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz", - "integrity": "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "node_modules/@substrate/connect": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/@substrate/connect/-/connect-0.8.11.tgz", + "integrity": "sha512-ofLs1PAO9AtDdPbdyTYj217Pe+lBfTLltdHDs3ds8no0BseoLeAGxpz1mHfi7zB4IxI3YyAiLjH6U8cw4pj4Nw==", + "deprecated": "versions below 1.x are no longer maintained", + "license": "GPL-3.0-only", + "optional": true, + "dependencies": { + "@substrate/connect-extension-protocol": "^2.0.0", + "@substrate/connect-known-chains": "^1.1.5", + "@substrate/light-client-extension-helpers": "^1.0.0", + "smoldot": "2.0.26" } }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-id": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz", - "integrity": "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==", + "node_modules/@substrate/connect-extension-protocol": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@substrate/connect-extension-protocol/-/connect-extension-protocol-2.2.1.tgz", + "integrity": "sha512-GoafTgm/Jey9E4Xlj4Z5ZBt/H4drH2CNq8VrAro80rtoznrXnFDNVivLQzZN0Xaj2g8YXSn9pC9Oc9IovYZJXw==", + "license": "GPL-3.0-only", + "optional": true + }, + "node_modules/@substrate/connect-known-chains": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@substrate/connect-known-chains/-/connect-known-chains-1.9.0.tgz", + "integrity": "sha512-R7yE0kIRUnvNlMiYramQ+dQwSY0ZpqRJ1mK8hLKlvCbEMqjSFa0n/WYYG6/bst9nNA1O6OZLWpvMso6yhENe3A==", + "license": "GPL-3.0-only", + "optional": true + }, + "node_modules/@substrate/light-client-extension-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@substrate/light-client-extension-helpers/-/light-client-extension-helpers-1.0.0.tgz", + "integrity": "sha512-TdKlni1mBBZptOaeVrKnusMg/UBpWUORNDv5fdCaJklP4RJiFOzBCrzC+CyVI5kQzsXBisZ+2pXm+rIjS38kHg==", + "license": "MIT", + "optional": true, "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.0" + "@polkadot-api/json-rpc-provider": "^0.0.1", + "@polkadot-api/json-rpc-provider-proxy": "^0.1.0", + "@polkadot-api/observable-client": "^0.3.0", + "@polkadot-api/substrate-client": "^0.1.2", + "@substrate/connect-extension-protocol": "^2.0.0", + "@substrate/connect-known-chains": "^1.1.5", + "rxjs": "^7.8.1" }, "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "smoldot": "2.x" } }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-presence": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.0.tgz", - "integrity": "sha512-Gq6wuRN/asf9H/E/VzdKoUtT8GC9PQc9z40/vEr0VCJ4u5XvvhWIrSsCB6vD2/cH7ugTdSfYq9fLJCcM00acrQ==", + "node_modules/@substrate/ss58-registry": { + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/@substrate/ss58-registry/-/ss58-registry-1.51.0.tgz", + "integrity": "sha512-TWDurLiPxndFgKjVavCniytBIw+t4ViOi7TYp9h/D0NMmkEc9klFTo+827eyEJ0lELpqO207Ey7uGxUa+BS1jQ==", + "license": "Apache-2.0" + }, + "node_modules/@substrate/txwrapper-core": { + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/@substrate/txwrapper-core/-/txwrapper-core-7.5.2.tgz", + "integrity": "sha512-QbWNA8teVYS2YfrZ5JWtl6nmX11UIS7k4ZF5ukKe/oqaCSifoNhTYkTDnN/AWImOPQ0N0QeVge1XlF1TUtfFDA==", + "license": "Apache-2.0", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "@polkadot/api": "^14.0.1", + "@polkadot/keyring": "^13.1.1", + "memoizee": "0.4.15" } }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz", - "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==", + "node_modules/@substrate/txwrapper-polkadot": { + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/@substrate/txwrapper-polkadot/-/txwrapper-polkadot-7.5.2.tgz", + "integrity": "sha512-ekTnEOdyuwjHj2HIjh2NK7Rqu5QadKVMsTadU/bAfAoKJEEFXy/WMnsmCahGg09eFx77MX/rPuqv6IRQxl+8VA==", + "license": "Apache-2.0", "dependencies": { - "@radix-ui/react-slot": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "@substrate/txwrapper-core": "^7.5.2", + "@substrate/txwrapper-substrate": "^7.5.2" } }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-roving-focus": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.0.tgz", - "integrity": "sha512-EA6AMGeq9AEeQDeSH0aZgG198qkfHSbvWTf1HvoDmOB5bBG/qTxjYMWUKMnYiV6J/iP/J8MEFSuB2zRU2n7ODA==", + "node_modules/@substrate/txwrapper-substrate": { + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/@substrate/txwrapper-substrate/-/txwrapper-substrate-7.5.3.tgz", + "integrity": "sha512-hAZTcZzB7uGLwm62JFCmxM9M0lm+5Id1tROqdKkuukesAAt06UcTTiaopq2w/B9syWamMor63aQEFugEIK2PLQ==", + "license": "Apache-2.0", "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-collection": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-direction": "1.1.0", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-controllable-state": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "@substrate/txwrapper-core": "^7.5.3" } }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", - "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", + "node_modules/@substrate/txwrapper-substrate/node_modules/@substrate/txwrapper-core": { + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/@substrate/txwrapper-core/-/txwrapper-core-7.5.3.tgz", + "integrity": "sha512-vcb9GaAY8ex330yjJoDCa2w32R2u/KUmEKsD/5DRgTbPEUF1OYiKmmuOJWcD0jHu9HZ8HWlniiV8wxxwo3PVCA==", + "license": "Apache-2.0", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "@polkadot/api": "^14.0.1", + "@polkadot/keyring": "^13.1.1", + "memoizee": "0.4.17" } }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-use-callback-ref": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", - "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "node_modules/@substrate/txwrapper-substrate/node_modules/memoizee": { + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.17.tgz", + "integrity": "sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA==", + "license": "ISC", + "dependencies": { + "d": "^1.0.2", + "es5-ext": "^0.10.64", + "es6-weak-map": "^2.0.3", + "event-emitter": "^0.3.5", + "is-promise": "^2.2.2", + "lru-queue": "^0.1.0", + "next-tick": "^1.1.0", + "timers-ext": "^0.1.7" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=0.12" } }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-use-controllable-state": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz", - "integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==", - "dependencies": { - "@radix-ui/react-use-callback-ref": "1.1.0" + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", + "engines": { + "node": ">=14" }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", - "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-use-size": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz", - "integrity": "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==", - "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.0" + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", + "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "engines": { + "node": ">=14" }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@radix-ui/react-roving-focus": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.4.tgz", - "integrity": "sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==", - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-collection": "1.0.3", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-direction": "1.0.1", - "@radix-ui/react-id": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-callback-ref": "1.0.1", - "@radix-ui/react-use-controllable-state": "1.0.1" + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", + "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", + "engines": { + "node": ">=14" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@radix-ui/react-slot": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz", - "integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==", - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-compose-refs": "1.0.1" + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", + "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" }, "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", + "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@radix-ui/react-tooltip": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.0.7.tgz", - "integrity": "sha512-lPh5iKNFVQ/jav/j6ZrWq3blfDJ0OH9R6FlNUHPMqdLuQ9vwDgFsRxvl8b7Asuy5c8xmoojHUxKHQSOAvMHxyw==", - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-dismissable-layer": "1.0.5", - "@radix-ui/react-id": "1.0.1", - "@radix-ui/react-popper": "1.1.3", - "@radix-ui/react-portal": "1.0.4", - "@radix-ui/react-presence": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-slot": "1.0.2", - "@radix-ui/react-use-controllable-state": "1.0.1", - "@radix-ui/react-visually-hidden": "1.0.3" + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", + "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" }, "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", + "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", + "engines": { + "node": ">=12" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-arrow": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz", - "integrity": "sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA==", + "node_modules/@svgr/babel-preset": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", + "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-primitive": "1.0.3" + "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", + "@svgr/babel-plugin-transform-svg-component": "8.0.0" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-popper": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.1.3.tgz", - "integrity": "sha512-cKpopj/5RHZWjrbF2846jBNacjQVwkP068DfmgrNJXpvVWrOvlAmE9xSiy5OqeE+Gi8D9fP+oDhUnPqNMY8/5w==", + "node_modules/@svgr/core": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", + "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", "dependencies": { - "@babel/runtime": "^7.13.10", - "@floating-ui/react-dom": "^2.0.0", - "@radix-ui/react-arrow": "1.0.3", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-callback-ref": "1.0.1", - "@radix-ui/react-use-layout-effect": "1.0.1", - "@radix-ui/react-use-rect": "1.0.1", - "@radix-ui/react-use-size": "1.0.1", - "@radix-ui/rect": "1.0.1" + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^8.1.3", + "snake-case": "^3.0.4" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-use-rect": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.0.1.tgz", - "integrity": "sha512-Cq5DLuSiuYVKNU8orzJMbl15TXilTnJKUCltMVQg53BQOF1/C5toAaGrowkgksdBQ9H+SRL23g0HDmg9tvmxXw==", + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", + "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/rect": "1.0.1" + "@babel/types": "^7.21.3", + "entities": "^4.4.0" }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/rect": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.0.1.tgz", - "integrity": "sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ==", + "node_modules/@svgr/plugin-jsx": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", + "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", "dependencies": { - "@babel/runtime": "^7.13.10" + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "@svgr/hast-util-to-babel-ast": "8.0.0", + "svg-parser": "^2.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" } }, - "node_modules/@radix-ui/react-use-callback-ref": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz", - "integrity": "sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==", + "node_modules/@svgr/plugin-svgo": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-8.1.0.tgz", + "integrity": "sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA==", "dependencies": { - "@babel/runtime": "^7.13.10" + "cosmiconfig": "^8.1.3", + "deepmerge": "^4.3.1", + "svgo": "^3.0.2" }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "peerDependencies": { + "@svgr/core": "*" } }, - "node_modules/@radix-ui/react-use-controllable-state": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.1.tgz", - "integrity": "sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==", + "node_modules/@svgr/webpack": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.1.0.tgz", + "integrity": "sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-use-callback-ref": "1.0.1" + "@babel/core": "^7.21.3", + "@babel/plugin-transform-react-constant-elements": "^7.21.3", + "@babel/preset-env": "^7.20.2", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.21.0", + "@svgr/core": "8.1.0", + "@svgr/plugin-jsx": "8.1.0", + "@svgr/plugin-svgo": "8.1.0" }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/@radix-ui/react-use-escape-keydown": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.3.tgz", - "integrity": "sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==", - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-use-callback-ref": "1.0.1" + "node_modules/@swc-node/core": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/@swc-node/core/-/core-1.13.3.tgz", + "integrity": "sha512-OGsvXIid2Go21kiNqeTIn79jcaX4l0G93X2rAnas4LFoDyA9wAwVK7xZdm+QsKoMn5Mus2yFLCc4OtX2dD/PWA==", + "dev": true, + "engines": { + "node": ">= 10" }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "peerDependencies": { + "@swc/core": ">= 1.4.13", + "@swc/types": ">= 0.1" } }, - "node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.1.tgz", - "integrity": "sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==", + "node_modules/@swc-node/register": { + "version": "1.10.9", + "resolved": "https://registry.npmjs.org/@swc-node/register/-/register-1.10.9.tgz", + "integrity": "sha512-iXy2sjP0phPEpK2yivjRC3PAgoLaT4sjSk0LDWCTdcTBJmR4waEog0E6eJbvoOkLkOtWw37SB8vCkl/bbh4+8A==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.13.10" + "@swc-node/core": "^1.13.3", + "@swc-node/sourcemap-support": "^0.5.1", + "colorette": "^2.0.20", + "debug": "^4.3.5", + "oxc-resolver": "^1.10.2", + "pirates": "^4.0.6", + "tslib": "^2.6.3" }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-previous": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.0.tgz", - "integrity": "sha512-Z/e78qg2YFnnXcW88A4JmTtm4ADckLno6F7OXotmkQfeuCVaKuYzqAATPhVzl3delXE7CxIV8shofPn3jPc5Og==", "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "@swc/core": ">= 1.4.13", + "typescript": ">= 4.3" } }, - "node_modules/@radix-ui/react-use-rect": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz", - "integrity": "sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==", + "node_modules/@swc-node/sourcemap-support": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@swc-node/sourcemap-support/-/sourcemap-support-0.5.1.tgz", + "integrity": "sha512-JxIvIo/Hrpv0JCHSyRpetAdQ6lB27oFYhv0PKCNf1g2gUXOjpeR1exrXccRxLMuAV5WAmGFBwRnNOJqN38+qtg==", + "dev": true, "dependencies": { - "@radix-ui/rect": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "source-map-support": "^0.5.21", + "tslib": "^2.6.3" } }, - "node_modules/@radix-ui/react-use-size": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.0.1.tgz", - "integrity": "sha512-ibay+VqrgcaI6veAojjofPATwledXiSmX+C0KrBk/xgpX9rBzPV3OsfwlhQdUOFbh+LKQorLYT+xTXW9V8yd0g==", + "node_modules/@swc-node/sourcemap-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@swc-node/sourcemap-support/node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-use-layout-effect": "1.0.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } }, - "node_modules/@radix-ui/react-visually-hidden": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.0.3.tgz", - "integrity": "sha512-D4w41yN5YRKtu464TLnByKzMDG/JlMPHtfZgQAu9v6mNakUqGUI9vUrfQKz8NK41VMm/xbZbh76NUTVtIYqOMA==", + "node_modules/@swc/core": { + "version": "1.7.26", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.7.26.tgz", + "integrity": "sha512-f5uYFf+TmMQyYIoxkn/evWhNGuUzC730dFwAKGwBVHHVoPyak1/GvJUm6i1SKl+2Hrj9oN0i3WSoWWZ4pgI8lw==", + "dev": true, + "hasInstallScript": true, "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-primitive": "1.0.3" + "@swc/counter": "^0.1.3", + "@swc/types": "^0.1.12" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.7.26", + "@swc/core-darwin-x64": "1.7.26", + "@swc/core-linux-arm-gnueabihf": "1.7.26", + "@swc/core-linux-arm64-gnu": "1.7.26", + "@swc/core-linux-arm64-musl": "1.7.26", + "@swc/core-linux-x64-gnu": "1.7.26", + "@swc/core-linux-x64-musl": "1.7.26", + "@swc/core-win32-arm64-msvc": "1.7.26", + "@swc/core-win32-ia32-msvc": "1.7.26", + "@swc/core-win32-x64-msvc": "1.7.26" }, "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" + "@swc/helpers": "*" }, "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { + "@swc/helpers": { "optional": true } } }, - "node_modules/@radix-ui/rect": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.0.tgz", - "integrity": "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==" - }, - "node_modules/@react-native/assets-registry": { - "version": "0.77.0", - "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.77.0.tgz", - "integrity": "sha512-Ms4tYYAMScgINAXIhE4riCFJPPL/yltughHS950l0VP5sm5glbimn9n7RFn9Tc8cipX74/ddbk19+ydK2iDMmA==", - "license": "MIT", - "peer": true, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.7.26", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.26.tgz", + "integrity": "sha512-FF3CRYTg6a7ZVW4yT9mesxoVVZTrcSWtmZhxKCYJX9brH4CS/7PRPjAKNk6kzWgWuRoglP7hkjQcd6EpMcZEAw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=18" + "node": ">=10" } }, - "node_modules/@react-native/babel-plugin-codegen": { - "version": "0.77.0", - "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.77.0.tgz", - "integrity": "sha512-5TYPn1k+jdDOZJU4EVb1kZ0p9TCVICXK3uplRev5Gul57oWesAaiWGZOzfRS3lonWeuR4ij8v8PFfIHOaq0vmA==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/traverse": "^7.25.3", - "@react-native/codegen": "0.77.0" - }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.7.26", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.7.26.tgz", + "integrity": "sha512-az3cibZdsay2HNKmc4bjf62QVukuiMRh5sfM5kHR/JMTrLyS6vSw7Ihs3UTkZjUxkLTT8ro54LI6sV6sUQUbLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=18" + "node": ">=10" } }, - "node_modules/@react-native/babel-preset": { - "version": "0.77.0", - "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.77.0.tgz", - "integrity": "sha512-Z4yxE66OvPyQ/iAlaETI1ptRLcDm7Tk6ZLqtCPuUX3AMg+JNgIA86979T4RSk486/JrBUBH5WZe2xjj7eEHXsA==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/core": "^7.25.2", - "@babel/plugin-proposal-export-default-from": "^7.24.7", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-default-from": "^7.24.7", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-transform-arrow-functions": "^7.24.7", - "@babel/plugin-transform-async-generator-functions": "^7.25.4", - "@babel/plugin-transform-async-to-generator": "^7.24.7", - "@babel/plugin-transform-block-scoping": "^7.25.0", - "@babel/plugin-transform-class-properties": "^7.25.4", - "@babel/plugin-transform-classes": "^7.25.4", - "@babel/plugin-transform-computed-properties": "^7.24.7", - "@babel/plugin-transform-destructuring": "^7.24.8", - "@babel/plugin-transform-flow-strip-types": "^7.25.2", - "@babel/plugin-transform-for-of": "^7.24.7", - "@babel/plugin-transform-function-name": "^7.25.1", - "@babel/plugin-transform-literals": "^7.25.2", - "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", - "@babel/plugin-transform-modules-commonjs": "^7.24.8", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", - "@babel/plugin-transform-numeric-separator": "^7.24.7", - "@babel/plugin-transform-object-rest-spread": "^7.24.7", - "@babel/plugin-transform-optional-catch-binding": "^7.24.7", - "@babel/plugin-transform-optional-chaining": "^7.24.8", - "@babel/plugin-transform-parameters": "^7.24.7", - "@babel/plugin-transform-private-methods": "^7.24.7", - "@babel/plugin-transform-private-property-in-object": "^7.24.7", - "@babel/plugin-transform-react-display-name": "^7.24.7", - "@babel/plugin-transform-react-jsx": "^7.25.2", - "@babel/plugin-transform-react-jsx-self": "^7.24.7", - "@babel/plugin-transform-react-jsx-source": "^7.24.7", - "@babel/plugin-transform-regenerator": "^7.24.7", - "@babel/plugin-transform-runtime": "^7.24.7", - "@babel/plugin-transform-shorthand-properties": "^7.24.7", - "@babel/plugin-transform-spread": "^7.24.7", - "@babel/plugin-transform-sticky-regex": "^7.24.7", - "@babel/plugin-transform-typescript": "^7.25.2", - "@babel/plugin-transform-unicode-regex": "^7.24.7", - "@babel/template": "^7.25.0", - "@react-native/babel-plugin-codegen": "0.77.0", - "babel-plugin-syntax-hermes-parser": "0.25.1", - "babel-plugin-transform-flow-enums": "^0.0.2", - "react-refresh": "^0.14.0" - }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.7.26", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.7.26.tgz", + "integrity": "sha512-VYPFVJDO5zT5U3RpCdHE5v1gz4mmR8BfHecUZTmD2v1JeFY6fv9KArJUpjrHEEsjK/ucXkQFmJ0jaiWXmpOV9Q==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@babel/core": "*" + "node": ">=10" } }, - "node_modules/@react-native/codegen": { - "version": "0.77.0", - "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.77.0.tgz", - "integrity": "sha512-rE9lXx41ZjvE8cG7e62y/yGqzUpxnSvJ6me6axiX+aDewmI4ZrddvRGYyxCnawxy5dIBHSnrpZse3P87/4Lm7w==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/parser": "^7.25.3", - "glob": "^7.1.1", - "hermes-parser": "0.25.1", - "invariant": "^2.2.4", - "jscodeshift": "^17.0.0", - "nullthrows": "^1.1.1", - "yargs": "^17.6.2" - }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.7.26", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.7.26.tgz", + "integrity": "sha512-YKevOV7abpjcAzXrhsl+W48Z9mZvgoVs2eP5nY+uoMAdP2b3GxC0Df1Co0I90o2lkzO4jYBpTMcZlmUXLdXn+Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@babel/preset-env": "^7.1.6" + "node": ">=10" } }, - "node_modules/@react-native/codegen/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT", - "peer": true - }, - "node_modules/@react-native/codegen/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "license": "MIT", - "peer": true, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.7.26", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.7.26.tgz", + "integrity": "sha512-3w8iZICMkQQON0uIcvz7+Q1MPOW6hJ4O5ETjA0LSP/tuKqx30hIniCGOgPDnv3UTMruLUnQbtBwVCZTBKR3Rkg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/@react-native/codegen/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "peer": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.7.26", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.26.tgz", + "integrity": "sha512-c+pp9Zkk2lqb06bNGkR2Looxrs7FtGDMA4/aHjZcCqATgp348hOKH5WPvNLBl+yPrISuWjbKDVn3NgAvfvpH4w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/@react-native/codegen/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "license": "MIT", - "peer": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.7.26", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.7.26.tgz", + "integrity": "sha512-PgtyfHBF6xG87dUSSdTJHwZ3/8vWZfNIXQV2GlwEpslrOkGqy+WaiiyE7Of7z9AvDILfBBBcJvJ/r8u980wAfQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12" + "node": ">=10" } }, - "node_modules/@react-native/community-cli-plugin": { - "version": "0.77.0", - "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.77.0.tgz", - "integrity": "sha512-GRshwhCHhtupa3yyCbel14SlQligV8ffNYN5L1f8HCo2SeGPsBDNjhj2U+JTrMPnoqpwowPGvkCwyqwqYff4MQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "@react-native/dev-middleware": "0.77.0", - "@react-native/metro-babel-transformer": "0.77.0", - "chalk": "^4.0.0", - "debug": "^2.2.0", - "invariant": "^2.2.4", - "metro": "^0.81.0", - "metro-config": "^0.81.0", - "metro-core": "^0.81.0", - "readline": "^1.3.0", - "semver": "^7.1.3" - }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.7.26", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.7.26.tgz", + "integrity": "sha512-9TNXPIJqFynlAOrRD6tUQjMq7KApSklK3R/tXgIxc7Qx+lWu8hlDQ/kVPLpU7PWvMMwC/3hKBW+p5f+Tms1hmA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@react-native-community/cli-server-api": "*" - }, - "peerDependenciesMeta": { - "@react-native-community/cli-server-api": { - "optional": true - } + "node": ">=10" } }, - "node_modules/@react-native/community-cli-plugin/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "peer": true, - "dependencies": { - "ms": "2.0.0" + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.7.26", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.7.26.tgz", + "integrity": "sha512-9YngxNcG3177GYdsTum4V98Re+TlCeJEP4kEwEg9EagT5s3YejYdKwVAkAsJszzkXuyRDdnHUpYbTrPG6FiXrQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" } }, - "node_modules/@react-native/community-cli-plugin/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT", - "peer": true - }, - "node_modules/@react-native/community-cli-plugin/node_modules/semver": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.0.tgz", - "integrity": "sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ==", - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver.js" - }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.7.26", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.26.tgz", + "integrity": "sha512-VR+hzg9XqucgLjXxA13MtV5O3C0bK0ywtLIBw/+a+O+Oc6mxFWHtdUeXDbIi5AiPbn0fjgVJMqYnyjGyyX8u0w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], "engines": { "node": ">=10" } }, - "node_modules/@react-native/debugger-frontend": { - "version": "0.77.0", - "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.77.0.tgz", - "integrity": "sha512-glOvSEjCbVXw+KtfiOAmrq21FuLE1VsmBsyT7qud4KWbXP43aUEhzn70mWyFuiIdxnzVPKe2u8iWTQTdJksR1w==", - "license": "BSD-3-Clause", - "peer": true, - "engines": { - "node": ">=18" - } + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" }, - "node_modules/@react-native/dev-middleware": { - "version": "0.77.0", - "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.77.0.tgz", - "integrity": "sha512-DAlEYujm43O+Dq98KP2XfLSX5c/TEGtt+JBDEIOQewk374uYY52HzRb1+Gj6tNaEj/b33no4GibtdxbO5zmPhg==", - "license": "MIT", - "peer": true, + "node_modules/@swc/helpers": { + "version": "0.5.11", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.11.tgz", + "integrity": "sha512-YNlnKRWF2sVojTpIyzwou9XoTNbzbzONwRhOoniEioF1AtaitTvVZblaQRrAzChWQ1bLYyYSWzM18y4WwgzJ+A==", + "dev": true, "dependencies": { - "@isaacs/ttlcache": "^1.4.1", - "@react-native/debugger-frontend": "0.77.0", - "chrome-launcher": "^0.15.2", - "chromium-edge-launcher": "^0.2.0", - "connect": "^3.6.5", - "debug": "^2.2.0", - "nullthrows": "^1.1.1", - "open": "^7.0.3", - "selfsigned": "^2.4.1", - "serve-static": "^1.16.2", - "ws": "^6.2.3" - }, - "engines": { - "node": ">=18" + "tslib": "^2.4.0" } }, - "node_modules/@react-native/dev-middleware/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "peer": true, + "node_modules/@swc/types": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.12.tgz", + "integrity": "sha512-wBJA+SdtkbFhHjTMYH+dEH1y4VpfGdAc2Kw/LK09i9bXd/K6j6PkDcFCEzb6iVfZMkPRrl/q0e3toqTAJdkIVA==", + "dev": true, "dependencies": { - "ms": "2.0.0" + "@swc/counter": "^0.1.3" } }, - "node_modules/@react-native/dev-middleware/node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "license": "MIT", - "peer": true, + "node_modules/@szmarczak/http-timer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", + "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", + "dependencies": { + "defer-to-connect": "^2.0.1" + }, "engines": { - "node": ">= 0.8" + "node": ">=14.16" } }, - "node_modules/@react-native/dev-middleware/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT", - "peer": true + "node_modules/@tanstack/query-core": { + "version": "5.51.9", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.51.9.tgz", + "integrity": "sha512-HsAwaY5J19MD18ykZDS3aVVh+bAt0i7m6uQlFC2b77DLV9djo+xEN7MWQAQQTR8IM+7r/zbozTQ7P0xr0bHuew==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } }, - "node_modules/@react-native/dev-middleware/node_modules/open": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", - "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", - "license": "MIT", - "peer": true, + "node_modules/@tanstack/react-query": { + "version": "5.51.11", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.51.11.tgz", + "integrity": "sha512-4Kq2x0XpDlpvSnaLG+8pHNH60zEc3mBvb3B2tOMDjcPCi/o+Du3p/9qpPLwJOTliVxxPJAP27fuIhLrsRdCr7A==", "dependencies": { - "is-docker": "^2.0.0", - "is-wsl": "^2.1.1" - }, - "engines": { - "node": ">=8" + "@tanstack/query-core": "5.51.9" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18.0.0" } }, - "node_modules/@react-native/dev-middleware/node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "node_modules/@taquito/local-forging": { + "version": "6.3.5-beta.0", + "resolved": "https://registry.npmjs.org/@taquito/local-forging/-/local-forging-6.3.5-beta.0.tgz", + "integrity": "sha512-p0E3Ww3kg+YQYPmp/XK4YKZpWdKqtIg1ZlDtptLn66nbDA3ivzbiFHe3LxceJsYnaCcoWTXl/sRf34VKTkMK3Q==", "license": "MIT", - "peer": true, "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" + "@taquito/utils": "^6.3.5-beta.0", + "bignumber.js": "^9.0.0" }, "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/@react-native/dev-middleware/node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.8" + "node": ">=6.0.0" } }, - "node_modules/@react-native/dev-middleware/node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT", - "peer": true - }, - "node_modules/@react-native/dev-middleware/node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "node_modules/@taquito/signer": { + "version": "6.3.5-beta.0", + "resolved": "https://registry.npmjs.org/@taquito/signer/-/signer-6.3.5-beta.0.tgz", + "integrity": "sha512-8f2XPXw8XveGuJGCiqj9vyAiATBepz+s/J6asYil4HGwjgAXZ2unBemuqNk7oQ9xSz9fCCbFxc4ZER1GtJ8Auw==", "license": "MIT", - "peer": true, "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" + "@taquito/utils": "^6.3.5-beta.0", + "bignumber.js": "^9.0.0", + "bip39": "^3.0.2", + "elliptic": "^6.5.2", + "libsodium-wrappers": "^0.7.6", + "pbkdf2": "^3.0.17", + "typedarray-to-buffer": "^3.1.5" }, "engines": { - "node": ">= 0.8.0" + "node": ">=6.0.0" } }, - "node_modules/@react-native/dev-middleware/node_modules/ws": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", - "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", + "node_modules/@taquito/utils": { + "version": "6.3.5-beta.0", + "resolved": "https://registry.npmjs.org/@taquito/utils/-/utils-6.3.5-beta.0.tgz", + "integrity": "sha512-EFzDnTXMctbIEnt3yfgqPmogwxR2jTYnAZqxGOgfycYlZQWGNAfvgW5KFMlhYPAfYEAU/2euvE5BYMgnexBIOA==", "license": "MIT", - "peer": true, "dependencies": { - "async-limiter": "~1.0.0" - } - }, - "node_modules/@react-native/gradle-plugin": { - "version": "0.77.0", - "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.77.0.tgz", - "integrity": "sha512-rmfh93jzbndSq7kihYHUQ/EGHTP8CCd3GDCmg5SbxSOHAaAYx2HZ28ZG7AVcGUsWeXp+e/90zGIyfOzDRx0Zaw==", - "license": "MIT", - "peer": true, + "blakejs": "^1.1.0", + "bs58check": "^2.1.2", + "buffer": "^5.6.0" + }, "engines": { - "node": ">=18" + "node": ">=6.0.0" } }, - "node_modules/@react-native/js-polyfills": { - "version": "0.77.0", - "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.77.0.tgz", - "integrity": "sha512-kHFcMJVkGb3ptj3yg1soUsMHATqal4dh0QTGAbYihngJ6zy+TnP65J3GJq4UlwqFE9K1RZkeCmTwlmyPFHOGvA==", - "license": "MIT", - "peer": true, + "node_modules/@testing-library/dom": { + "version": "9.3.4", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.4.tgz", + "integrity": "sha512-FlS4ZWlp97iiNWig0Muq8p+3rVDjRiYE+YKGbAqXOu9nwJFFOdL00kFpz42M+4huzYi86vAK1sOOfyOG45muIQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.1.3", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, "engines": { - "node": ">=18" + "node": ">=14" } }, - "node_modules/@react-native/metro-babel-transformer": { - "version": "0.77.0", - "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.77.0.tgz", - "integrity": "sha512-19GfvhBRKCU3UDWwCnDR4QjIzz3B2ZuwhnxMRwfAgPxz7QY9uKour9RGmBAVUk1Wxi/SP7dLEvWnmnuBO39e2A==", - "license": "MIT", - "peer": true, + "node_modules/@testing-library/react": { + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-14.1.2.tgz", + "integrity": "sha512-z4p7DVBTPjKM5qDZ0t5ZjzkpSNb+fZy1u6bzO7kk8oeGagpPCAtgh4cx1syrfp7a+QWkM021jGqjJaxJJnXAZg==", + "dev": true, "dependencies": { - "@babel/core": "^7.25.2", - "@react-native/babel-preset": "0.77.0", - "hermes-parser": "0.25.1", - "nullthrows": "^1.1.1" + "@babel/runtime": "^7.12.5", + "@testing-library/dom": "^9.0.0", + "@types/react-dom": "^18.0.0" }, "engines": { - "node": ">=18" + "node": ">=14" }, "peerDependencies": { - "@babel/core": "*" + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "node_modules/@react-native/normalize-colors": { - "version": "0.77.0", - "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.77.0.tgz", - "integrity": "sha512-qjmxW3xRZe4T0ZBEaXZNHtuUbRgyfybWijf1yUuQwjBt24tSapmIslwhCjpKidA0p93ssPcepquhY0ykH25mew==", - "license": "MIT", - "peer": true + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true, + "engines": { + "node": ">= 10" + } }, - "node_modules/@react-native/virtualized-lists": { - "version": "0.77.0", - "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.77.0.tgz", - "integrity": "sha512-ppPtEu9ISO9iuzpA2HBqrfmDpDAnGGduNDVaegadOzbMCPAB3tC9Blxdu9W68LyYlNQILIsP6/FYtLwf7kfNew==", - "license": "MIT", - "peer": true, - "dependencies": { - "invariant": "^2.2.4", - "nullthrows": "^1.1.1" - }, + "node_modules/@tootallnate/quickjs-emscripten": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==" + }, + "node_modules/@tronweb3/google-protobuf": { + "version": "3.21.4", + "resolved": "https://registry.npmjs.org/@tronweb3/google-protobuf/-/google-protobuf-3.21.4.tgz", + "integrity": "sha512-joxgV4esCdyZ921AprMIG1T7HjkypquhbJ5qJti/priCBJhRE1z9GOxIEMvayxSVSRbMGIoJNE0Knrg3vpwM1w==", + "license": "(BSD-3-Clause AND Apache-2.0)" + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/react": "^18.2.6", - "react": "*", - "react-native": "*" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "node": ">=10.13.0" } }, - "node_modules/@rushstack/eslint-patch": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.3.tgz", - "integrity": "sha512-qC/xYId4NMebE6w/V33Fh9gWxLgURiNYgVNObbJl2LZv0GUUItCcCqC5axQSwRaAgaxl2mELq1rMzlswaQ0Zxg==", + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", "dev": true }, - "node_modules/@safe-global/safe-apps-provider": { - "version": "0.18.4", - "resolved": "https://registry.npmjs.org/@safe-global/safe-apps-provider/-/safe-apps-provider-0.18.4.tgz", - "integrity": "sha512-SWYeG3gyTO6wGHMSokfHakZ9isByn2mHsM0VohIorYFFEyGGmJ89btnTm+DqDUSoQtvWAatZB7XNy6CaYMvqtg==", + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true + }, + "node_modules/@tybys/wasm-util": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", + "integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==", + "dev": true, "dependencies": { - "@safe-global/safe-apps-sdk": "^9.1.0", - "events": "^3.3.0" + "tslib": "^2.4.0" } }, - "node_modules/@safe-global/safe-apps-sdk": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/@safe-global/safe-apps-sdk/-/safe-apps-sdk-9.1.0.tgz", - "integrity": "sha512-N5p/ulfnnA2Pi2M3YeWjULeWbjo7ei22JwU/IXnhoHzKq3pYCN6ynL9mJBOlvDVv892EgLPCWCOwQk/uBT2v0Q==", + "node_modules/@types/acorn": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz", + "integrity": "sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==", "dependencies": { - "@safe-global/safe-gateway-typescript-sdk": "^3.5.3", - "viem": "^2.1.1" + "@types/estree": "*" } }, - "node_modules/@safe-global/safe-gateway-typescript-sdk": { - "version": "3.22.2", - "resolved": "https://registry.npmjs.org/@safe-global/safe-gateway-typescript-sdk/-/safe-gateway-typescript-sdk-3.22.2.tgz", - "integrity": "sha512-Y0yAxRaB98LFp2Dm+ACZqBSdAmI3FlpH/LjxOZ94g/ouuDJecSq0iR26XZ5QDuEL8Rf+L4jBJaoDC08CD0KkJw==", - "engines": { - "node": ">=16" - } + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true }, - "node_modules/@scure/base": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.7.tgz", - "integrity": "sha512-PPNYBslrLNNUQ/Yad37MHYsNQtK67EhWb6WtSvNLLPo7SdVZgkUjD6Dg+5On7zNwmskf8OX7I7Nx5oN+MIWE0g==", - "funding": { - "url": "https://paulmillr.com/funding/" - } + "node_modules/@types/aws-lambda": { + "version": "8.10.143", + "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.143.tgz", + "integrity": "sha512-u5vzlcR14ge/4pMTTMDQr3MF0wEe38B2F9o84uC4F43vN5DGTy63npRrB6jQhyt+C0lGv4ZfiRcRkqJoZuPnmg==" }, - "node_modules/@scure/bip32": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.5.0.tgz", - "integrity": "sha512-8EnFYkqEQdnkuGBVpCzKxyIwDCBLDVj3oiX0EKUFre/tOjL/Hqba1D6n/8RcmaQy4f95qQFrO2A8Sr6ybh4NRw==", + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dependencies": { - "@noble/curves": "~1.6.0", - "@noble/hashes": "~1.5.0", - "@scure/base": "~1.1.7" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" } }, - "node_modules/@scure/bip32/node_modules/@noble/hashes": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.5.0.tgz", - "integrity": "sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==", - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dependencies": { + "@babel/types": "^7.0.0" } }, - "node_modules/@scure/bip39": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", - "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", "dependencies": { - "@noble/hashes": "~1.4.0", - "@scure/base": "~1.1.6" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" } }, - "node_modules/@sepior/tsmsdkv2": { - "version": "63.0.0", - "resolved": "https://nexus.sepior.net/repository/sepior-nodejs-tsm-sdk-group/@sepior/tsmsdkv2/-/tsmsdkv2-63.0.0.tgz", - "integrity": "sha512-SERPces5/gCumUzZK8fE0oGWG6+zlRohz1VWLjEzncWEAWeC65RNhIQvCrCUSosirpoSSflxx5Kf7OHU19M8UA==", - "hasInstallScript": true, - "optional": true, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", "dependencies": { - "bindings": "^1.5.0", - "elliptic": "^6.5.4", - "node-addon-api": "^7.1.0" + "@babel/types": "^7.20.7" } }, - "node_modules/@sepior/tsmsdkv2/node_modules/node-addon-api": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", - "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", - "optional": true + "node_modules/@types/bluebird": { + "version": "3.5.42", + "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.42.tgz", + "integrity": "sha512-Jhy+MWRlro6UjVi578V/4ZGNfeCOcNCp0YaFNIUGFKlImowqwb1O/22wDVk3FDGMLqxdpOV3qQHD5fPEH4hK6A==", + "license": "MIT" }, - "node_modules/@sideway/address": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", - "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", + "node_modules/@types/bn.js": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.6.tgz", + "integrity": "sha512-Xh8vSwUeMKeYYrj3cX4lGQgFSF/N03r+tv4AiLl1SucqV+uTQpxRcnM8AkXKHwYP9ZPXOYXRr2KPXpVlIvqh9w==", + "license": "MIT", "dependencies": { - "@hapi/hoek": "^9.0.0" + "@types/node": "*" } }, - "node_modules/@sideway/formula": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", - "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" - }, - "node_modules/@sideway/pinpoint": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", - "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" - }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" - }, - "node_modules/@sindresorhus/is": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" } }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "node_modules/@types/bonjour": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", "dependencies": { - "type-detect": "4.0.8" + "@types/node": "*" } }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "node_modules/@types/bunyan": { + "version": "1.8.9", + "resolved": "https://registry.npmjs.org/@types/bunyan/-/bunyan-1.8.9.tgz", + "integrity": "sha512-ZqS9JGpBxVOvsawzmVt30sP++gSQMTejCkIAQ3VdadOcRE8izTyW66hufvwLeH+YEGP6Js2AW7Gz+RMyvrEbmw==", "dependencies": { - "@sinonjs/commons": "^3.0.0" + "@types/node": "*" } }, - "node_modules/@slorber/remark-comment": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@slorber/remark-comment/-/remark-comment-1.0.0.tgz", - "integrity": "sha512-RCE24n7jsOj1M0UPvIQCHTe7fI0sFL4S2nwKVWwHyVr/wI/H8GosgsJGyhnsZoGFnD/P2hLf1mSbrrgSLN93NA==", + "node_modules/@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "license": "MIT", "dependencies": { - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.1.0", - "micromark-util-symbol": "^1.0.1" + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" } }, - "node_modules/@smithy/abort-controller": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.1.4.tgz", - "integrity": "sha512-VupaALAQlXViW3/enTf/f5l5JZYSAxoJL7f0nanhNNKnww6DGCg1oYIuNP78KDugnkwthBO6iEcym16HhWV8RQ==", + "node_modules/@types/compression": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@types/compression/-/compression-1.7.5.tgz", + "integrity": "sha512-AAQvK5pxMpaT+nDvhHrsBhLSYG5yQdtkaJE1WYieSNY2mVFKAgmU4ks65rkZD5oqnGCFLyQpUr1CqI4DmUMyDg==", + "dev": true, "dependencies": { - "@smithy/types": "^3.4.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "@types/express": "*" } }, - "node_modules/@smithy/config-resolver": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-3.0.8.tgz", - "integrity": "sha512-Tv1obAC18XOd2OnDAjSWmmthzx6Pdeh63FbLin8MlPiuJ2ATpKkq0NcNOJFr0dO+JmZXnwu8FQxKJ3TKJ3Hulw==", + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", "dependencies": { - "@smithy/node-config-provider": "^3.1.7", - "@smithy/types": "^3.4.2", - "@smithy/util-config-provider": "^3.0.0", - "@smithy/util-middleware": "^3.0.6", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "@types/node": "*" } }, - "node_modules/@smithy/core": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.4.5.tgz", - "integrity": "sha512-Z0qlPXgZ0pouYgnu/cZTEYeRAvniiKZmVl4wIbZHX/nEMHkMDV9ao6KFArsU9KndE0TuhL149xcRx45wfw1YCA==", + "node_modules/@types/connect-history-api-fallback": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", + "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", "dependencies": { - "@smithy/middleware-endpoint": "^3.1.3", - "@smithy/middleware-retry": "^3.0.20", - "@smithy/middleware-serde": "^3.0.6", - "@smithy/protocol-http": "^4.1.3", - "@smithy/smithy-client": "^3.3.4", - "@smithy/types": "^3.4.2", - "@smithy/util-body-length-browser": "^3.0.0", - "@smithy/util-middleware": "^3.0.6", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "@types/express-serve-static-core": "*", + "@types/node": "*" } }, - "node_modules/@smithy/credential-provider-imds": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.3.tgz", - "integrity": "sha512-VoxMzSzdvkkjMJNE38yQgx4CfnmT+Z+5EUXkg4x7yag93eQkVQgZvN3XBSHC/ylfBbLbAtdu7flTCChX9I+mVg==", + "node_modules/@types/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/cookiejar": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.5.tgz", + "integrity": "sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==" + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", "dependencies": { - "@smithy/node-config-provider": "^3.1.7", - "@smithy/property-provider": "^3.1.6", - "@smithy/types": "^3.4.2", - "@smithy/url-parser": "^3.0.6", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "@types/ms": "*" } }, - "node_modules/@smithy/fetch-http-handler": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.8.tgz", - "integrity": "sha512-Lqe0B8F5RM7zkw//6avq1SJ8AfaRd3ubFUS1eVp5WszV7p6Ne5hQ4dSuMHDpNRPhgTvj4va9Kd/pcVigHEHRow==", + "node_modules/@types/duplexify": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/@types/duplexify/-/duplexify-3.6.4.tgz", + "integrity": "sha512-2eahVPsd+dy3CL6FugAzJcxoraWhUghZGEQJns1kTKfCXWKJ5iG/VkaB05wRVrDKHfOFKqb0X0kXh91eE99RZg==", "dependencies": { - "@smithy/protocol-http": "^4.1.3", - "@smithy/querystring-builder": "^3.0.6", - "@smithy/types": "^3.4.2", - "@smithy/util-base64": "^3.0.0", - "tslib": "^2.6.2" + "@types/node": "*" } }, - "node_modules/@smithy/hash-node": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-3.0.6.tgz", - "integrity": "sha512-c/FHEdKK/7DU2z6ZE91L36ahyXWayR3B+FzELjnYq7wH5YqIseM24V+pWCS9kFn1Ln8OFGTf+pyYPiHZuX0s/Q==", + "node_modules/@types/eccrypto": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@types/eccrypto/-/eccrypto-1.1.6.tgz", + "integrity": "sha512-rsmcX5LdDZ3xN2W3al6+YR+XNmiQWlXSwVhsU184QOwNQNJ83YpwvAt8a7cT7y3RpVWkKWmXoIFdanI/z38rNQ==", + "license": "MIT", "dependencies": { - "@smithy/types": "^3.4.2", - "@smithy/util-buffer-from": "^3.0.0", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "@types/expect": "^1.20.4", + "@types/node": "*" } }, - "node_modules/@smithy/invalid-dependency": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-3.0.6.tgz", - "integrity": "sha512-czM7Ioq3s8pIXht7oD+vmgy4Wfb4XavU/k/irO8NdXFFOx7YAlsCCcKOh/lJD1mJSYQqiR7NmpZ9JviryD/7AQ==", + "node_modules/@types/elliptic": { + "version": "6.4.18", + "resolved": "https://registry.npmjs.org/@types/elliptic/-/elliptic-6.4.18.tgz", + "integrity": "sha512-UseG6H5vjRiNpQvrhy4VF/JXdA3V/Fp5amvveaL+fs28BZ6xIKJBPnUPRlEaZpysD9MbpfaLi8lbl7PGUAkpWw==", + "license": "MIT", "dependencies": { - "@smithy/types": "^3.4.2", - "tslib": "^2.6.2" + "@types/bn.js": "*" } }, - "node_modules/@smithy/is-array-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", - "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "node_modules/@types/eslint": { + "version": "8.56.10", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", + "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==", "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "@types/estree": "*", + "@types/json-schema": "*" } }, - "node_modules/@smithy/middleware-content-length": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-3.0.8.tgz", - "integrity": "sha512-VuyszlSO49WKh3H9/kIO2kf07VUwGV80QRiaDxUfP8P8UKlokz381ETJvwLhwuypBYhLymCYyNhB3fLAGBX2og==", + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", "dependencies": { - "@smithy/protocol-http": "^4.1.3", - "@smithy/types": "^3.4.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "@types/eslint": "*", + "@types/estree": "*" } }, - "node_modules/@smithy/middleware-endpoint": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.1.3.tgz", - "integrity": "sha512-KeM/OrK8MVFUsoJsmCN0MZMVPjKKLudn13xpgwIMpGTYpA8QZB2Xq5tJ+RE6iu3A6NhOI4VajDTwBsm8pwwrhg==", + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", "dependencies": { - "@smithy/middleware-serde": "^3.0.6", - "@smithy/node-config-provider": "^3.1.7", - "@smithy/shared-ini-file-loader": "^3.1.7", - "@smithy/types": "^3.4.2", - "@smithy/url-parser": "^3.0.6", - "@smithy/util-middleware": "^3.0.6", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "@types/estree": "*" } }, - "node_modules/@smithy/middleware-retry": { - "version": "3.0.20", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.20.tgz", - "integrity": "sha512-HELCOVwYw5hFDBm69d+LmmGjBCjWnwp/t7SJiHmp+c4u9vgfIaCjdSeIdnlOsLrr5ic5jGTJXvJFUQnd987b/g==", + "node_modules/@types/ethereumjs-util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@types/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", + "integrity": "sha512-qwQgQqXXTRv2h2AlJef+tMEszLFkCB9dWnrJYIdAwqjubERXEc/geB+S3apRw0yQyTVnsBf8r6BhlrE8vx+3WQ==", + "license": "MIT", "dependencies": { - "@smithy/node-config-provider": "^3.1.7", - "@smithy/protocol-http": "^4.1.3", - "@smithy/service-error-classification": "^3.0.6", - "@smithy/smithy-client": "^3.3.4", - "@smithy/types": "^3.4.2", - "@smithy/util-middleware": "^3.0.6", - "@smithy/util-retry": "^3.0.6", - "tslib": "^2.6.2", - "uuid": "^9.0.1" - }, - "engines": { - "node": ">=16.0.0" + "@types/bn.js": "*", + "@types/node": "*" } }, - "node_modules/@smithy/middleware-serde": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.6.tgz", - "integrity": "sha512-KKTUSl1MzOM0MAjGbudeaVNtIDo+PpekTBkCNwvfZlKndodrnvRo+00USatiyLOc0ujjO9UydMRu3O9dYML7ag==", + "node_modules/@types/eventsource": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@types/eventsource/-/eventsource-1.1.15.tgz", + "integrity": "sha512-XQmGcbnxUNa06HR3VBVkc9+A2Vpi9ZyLJcdS5dwaQQ/4ZMWFO+5c90FnMUpbtMZwB/FChoYHwuVg8TvkECacTA==", + "license": "MIT" + }, + "node_modules/@types/expect": { + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/@types/expect/-/expect-1.20.4.tgz", + "integrity": "sha512-Q5Vn3yjTDyCMV50TB6VRIbQNxSE4OmZR86VSbGaNpfUolm0iePBB4KdEEHmxoY5sT2+2DIvXW0rvMDP2nHZ4Mg==", + "license": "MIT" + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", "dependencies": { - "@smithy/types": "^3.4.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" } }, - "node_modules/@smithy/middleware-stack": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.6.tgz", - "integrity": "sha512-2c0eSYhTQ8xQqHMcRxLMpadFbTXg6Zla5l0mwNftFCZMQmuhI7EbAJMx6R5eqfuV3YbJ3QGyS3d5uSmrHV8Khg==", + "node_modules/@types/express-serve-static-core": { + "version": "4.19.5", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz", + "integrity": "sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==", "dependencies": { - "@smithy/types": "^3.4.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" } }, - "node_modules/@smithy/node-config-provider": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.7.tgz", - "integrity": "sha512-g3mfnC3Oo8pOI0dYuPXLtdW1WGVb3bR2tkV21GNkm0ZvQjLTtamXAwCWt/FCb0HGvKt3gHHmF1XerG0ICfalOg==", + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", "dependencies": { - "@smithy/property-provider": "^3.1.6", - "@smithy/shared-ini-file-loader": "^3.1.7", - "@smithy/types": "^3.4.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "@types/node": "*" } }, - "node_modules/@smithy/node-http-handler": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.2.3.tgz", - "integrity": "sha512-/gcm5DJ3k1b1zEInzBGAZC8ntJ+jwrz1NcSIu+9dSXd1FfG0G6QgkDI40tt8/WYUbHtLyo8fEqtm2v29koWo/w==", + "node_modules/@types/gtag.js": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/@types/gtag.js/-/gtag.js-0.0.12.tgz", + "integrity": "sha512-YQV9bUsemkzG81Ea295/nF/5GijnD2Af7QhEofh7xu+kvCN6RdodgNwwGWXB5GMI3NoyvQo0odNctoH/qLMIpg==" + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", "dependencies": { - "@smithy/abort-controller": "^3.1.4", - "@smithy/protocol-http": "^4.1.3", - "@smithy/querystring-builder": "^3.0.6", - "@smithy/types": "^3.4.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "@types/unist": "*" } }, - "node_modules/@smithy/property-provider": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.6.tgz", - "integrity": "sha512-NK3y/T7Q/Bw+Z8vsVs9MYIQ5v7gOX7clyrXcwhhIBQhbPgRl6JDrZbusO9qWDhcEus75Tg+VCxtIRfo3H76fpw==", + "node_modules/@types/history": { + "version": "4.7.11", + "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", + "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==" + }, + "node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==" + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==" + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==" + }, + "node_modules/@types/http-proxy": { + "version": "1.17.14", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", + "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", "dependencies": { - "@smithy/types": "^3.4.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "@types/node": "*" } }, - "node_modules/@smithy/protocol-http": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.3.tgz", - "integrity": "sha512-GcbMmOYpH9iRqtC05RbRnc/0FssxSTHlmaNhYBTgSgNCYpdR3Kt88u5GAZTBmouzv+Zlj/VRv92J9ruuDeJuEw==", + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", "dependencies": { - "@smithy/types": "^3.4.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "@types/istanbul-lib-coverage": "*" } }, - "node_modules/@smithy/querystring-builder": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.6.tgz", - "integrity": "sha512-sQe08RunoObe+Usujn9+R2zrLuQERi3CWvRO3BvnoWSYUaIrLKuAIeY7cMeDax6xGyfIP3x/yFWbEKSXvOnvVg==", + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", "dependencies": { - "@smithy/types": "^3.4.2", - "@smithy/util-uri-escape": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "@types/istanbul-lib-report": "*" } }, - "node_modules/@smithy/querystring-parser": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.6.tgz", - "integrity": "sha512-UJKw4LlEkytzz2Wq+uIdHf6qOtFfee/o7ruH0jF5I6UAuU+19r9QV7nU3P/uI0l6+oElRHmG/5cBBcGJrD7Ozg==", + "node_modules/@types/jest": { + "version": "29.5.12", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", + "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", + "dev": true, "dependencies": { - "@smithy/types": "^3.4.2", - "tslib": "^2.6.2" - }, + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "node_modules/@types/jest/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, "engines": { - "node": ">=16.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@smithy/service-error-classification": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-3.0.6.tgz", - "integrity": "sha512-53SpchU3+DUZrN7J6sBx9tBiCVGzsib2e4sc512Q7K9fpC5zkJKs6Z9s+qbMxSYrkEkle6hnMtrts7XNkMJJMg==", + "node_modules/@types/jest/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, "dependencies": { - "@smithy/types": "^3.4.2" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "engines": { - "node": ">=16.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@smithy/shared-ini-file-loader": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.7.tgz", - "integrity": "sha512-IA4K2qTJYXkF5OfVN4vsY1hfnUZjaslEE8Fsr/gGFza4TAC2A9NfnZuSY2srQIbt9bwtjHiAayrRVgKse4Q7fA==", + "node_modules/@types/jest/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, + "node_modules/@types/jsdom": { + "version": "20.0.1", + "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz", + "integrity": "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==", + "dev": true, "dependencies": { - "@smithy/types": "^3.4.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "@types/node": "*", + "@types/tough-cookie": "*", + "parse5": "^7.0.0" } }, - "node_modules/@smithy/signature-v4": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-4.1.4.tgz", - "integrity": "sha512-72MiK7xYukNsnLJI9NqvUHqTu0ziEsfMsYNlWpiJfuGQnCTFKpckThlEatirvcA/LmT1h7rRO+pJD06PYsPu9Q==", + "node_modules/@types/jsdom/node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dev": true, "dependencies": { - "@smithy/is-array-buffer": "^3.0.0", - "@smithy/protocol-http": "^4.1.3", - "@smithy/types": "^3.4.2", - "@smithy/util-hex-encoding": "^3.0.0", - "@smithy/util-middleware": "^3.0.6", - "@smithy/util-uri-escape": "^3.0.0", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" + "entities": "^4.4.0" }, - "engines": { - "node": ">=16.0.0" + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/@smithy/smithy-client": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.3.4.tgz", - "integrity": "sha512-NKw/2XxOW/Rg3rzB90HxsmGok5oS6vRzJgMh/JN4BHaOQQ4q5OuX999GmOGxEp730wbpIXIowfKZmIMXkG4v0Q==", + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "license": "MIT", "dependencies": { - "@smithy/middleware-endpoint": "^3.1.3", - "@smithy/middleware-stack": "^3.0.6", - "@smithy/protocol-http": "^4.1.3", - "@smithy/types": "^3.4.2", - "@smithy/util-stream": "^3.1.8", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "@types/node": "*" } }, - "node_modules/@smithy/types": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.4.2.tgz", - "integrity": "sha512-tHiFcfcVedVBHpmHUEUHOCCih8iZbIAYn9NvPsNzaPm/237I3imdDdZoOC8c87H5HBAVEa06tTgb+OcSWV9g5w==", + "node_modules/@types/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "license": "MIT" + }, + "node_modules/@types/lodash": { + "version": "4.17.7", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.7.tgz", + "integrity": "sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==" + }, + "node_modules/@types/long": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==", + "license": "MIT" + }, + "node_modules/@types/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==" + }, + "node_modules/@types/markdown-it": { + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", + "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", + "license": "MIT", "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "@types/linkify-it": "^5", + "@types/mdurl": "^2" } }, - "node_modules/@smithy/url-parser": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.6.tgz", - "integrity": "sha512-47Op/NU8Opt49KyGpHtVdnmmJMsp2hEwBdyjuFB9M2V5QVOwA7pBhhxKN5z6ztKGrMw76gd8MlbPuzzvaAncuQ==", + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", "dependencies": { - "@smithy/querystring-parser": "^3.0.6", - "@smithy/types": "^3.4.2", - "tslib": "^2.6.2" + "@types/unist": "*" } }, - "node_modules/@smithy/util-base64": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-3.0.0.tgz", - "integrity": "sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==", + "node_modules/@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", + "license": "MIT" + }, + "node_modules/@types/mdx": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", + "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==" + }, + "node_modules/@types/memcached": { + "version": "2.2.10", + "resolved": "https://registry.npmjs.org/@types/memcached/-/memcached-2.2.10.tgz", + "integrity": "sha512-AM9smvZN55Gzs2wRrqeMHVP7KE8KWgCJO/XL5yCly2xF6EKa4YlbpK+cLSAH4NG/Ah64HrlegmGqW8kYws7Vxg==", "dependencies": { - "@smithy/util-buffer-from": "^3.0.0", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "@types/node": "*" } }, - "node_modules/@smithy/util-body-length-browser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz", - "integrity": "sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ==", + "node_modules/@types/methods": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@types/methods/-/methods-1.1.4.tgz", + "integrity": "sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==", + "dev": true + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==" + }, + "node_modules/@types/ms": { + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" + }, + "node_modules/@types/mysql": { + "version": "2.15.26", + "resolved": "https://registry.npmjs.org/@types/mysql/-/mysql-2.15.26.tgz", + "integrity": "sha512-DSLCOXhkvfS5WNNPbfn2KdICAmk8lLc+/PNvnPnF7gOdMZCxopXduqv0OQ13y/yA/zXTSikZZqVgybUxOEg6YQ==", "dependencies": { - "tslib": "^2.6.2" + "@types/node": "*" } }, - "node_modules/@smithy/util-body-length-node": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-3.0.0.tgz", - "integrity": "sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA==", + "node_modules/@types/nock": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@types/nock/-/nock-11.1.0.tgz", + "integrity": "sha512-jI/ewavBQ7X5178262JQR0ewicPAcJhXS/iFaNJl0VHLfyosZ/kwSrsa6VNQNSO8i9d8SqdRgOtZSOKJ/+iNMw==", + "deprecated": "This is a stub types definition. nock provides its own type definitions, so you do not need this installed.", + "dev": true, "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "nock": "*" } }, - "node_modules/@smithy/util-buffer-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", - "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "node_modules/@types/node": { + "version": "18.16.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.9.tgz", + "integrity": "sha512-IeB32oIV4oGArLrd7znD2rkHQ6EDCM+2Sr76dJnrHwv9OHBTTM6nuDLK9bmikXzPa0ZlWMWtRGo/Uw4mrzQedA==" + }, + "node_modules/@types/node-forge": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", + "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", "dependencies": { - "@smithy/is-array-buffer": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "@types/node": "*" } }, - "node_modules/@smithy/util-config-provider": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz", - "integrity": "sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==", + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" + }, + "node_modules/@types/pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew==", + "license": "MIT", "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "@types/node": "*" } }, - "node_modules/@smithy/util-defaults-mode-browser": { - "version": "3.0.20", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.20.tgz", - "integrity": "sha512-HpYmCpEThQJpCKzwzrGrklhdegRfuXI9keHRrHidbyEMliCdgic6t38MikJeZEkdIcEMhO1g95HIYMzjUzB+xg==", + "node_modules/@types/pg": { + "version": "8.6.1", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.6.1.tgz", + "integrity": "sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w==", "dependencies": { - "@smithy/property-provider": "^3.1.6", - "@smithy/smithy-client": "^3.3.4", - "@smithy/types": "^3.4.2", - "bowser": "^2.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">= 10.0.0" + "@types/node": "*", + "pg-protocol": "*", + "pg-types": "^2.2.0" } }, - "node_modules/@smithy/util-defaults-mode-node": { - "version": "3.0.20", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.20.tgz", - "integrity": "sha512-atdsHNtAX0rwTvRRGsrONU0C0XzapH6tI8T1y/OReOvWN7uBwXqqWRft6m8egU2DgeReU0xqT3PHdGCe5VRaaQ==", + "node_modules/@types/pg-pool": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/pg-pool/-/pg-pool-2.0.6.tgz", + "integrity": "sha512-TaAUE5rq2VQYxab5Ts7WZhKNmuN78Q6PiFonTDdpbx8a1H0M1vhy3rhiMjl+e2iHmogyMw7jZF4FrE6eJUy5HQ==", "dependencies": { - "@smithy/config-resolver": "^3.0.8", - "@smithy/credential-provider-imds": "^3.2.3", - "@smithy/node-config-provider": "^3.1.7", - "@smithy/property-provider": "^3.1.6", - "@smithy/smithy-client": "^3.3.4", - "@smithy/types": "^3.4.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">= 10.0.0" + "@types/pg": "*" } }, - "node_modules/@smithy/util-endpoints": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-2.1.2.tgz", - "integrity": "sha512-FEISzffb4H8DLzGq1g4MuDpcv6CIG15fXoQzDH9SjpRJv6h7J++1STFWWinilG0tQh9H1v2UKWG19Jjr2B16zQ==", + "node_modules/@types/prismjs": { + "version": "1.26.4", + "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.4.tgz", + "integrity": "sha512-rlAnzkW2sZOjbqZ743IHUhFcvzaGbqijwOu8QZnZCjfQzBqFE3s4lOTJEsxikImav9uzz/42I+O7YUs1mWgMlg==" + }, + "node_modules/@types/prop-types": { + "version": "15.7.12", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==" + }, + "node_modules/@types/qs": { + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", + "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==" + }, + "node_modules/@types/randombytes": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/randombytes/-/randombytes-2.0.3.tgz", + "integrity": "sha512-+NRgihTfuURllWCiIAhm1wsJqzsocnqXM77V/CalsdJIYSRGEHMnritxh+6EsBklshC+clo1KgnN14qgSGeQdw==", + "license": "MIT", "dependencies": { - "@smithy/node-config-provider": "^3.1.7", - "@smithy/types": "^3.4.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "@types/node": "*" } }, - "node_modules/@smithy/util-hex-encoding": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz", - "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==", + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==" + }, + "node_modules/@types/react": { + "version": "18.2.62", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.62.tgz", + "integrity": "sha512-l3f57BbaEKP0xcFzf+5qRG8/PXykZiuVM6eEoPtqBPCp6dxO3HhDkLIgIyXPhPKNAeXn3KO2pEaNgzaEo/asaw==", "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" } }, - "node_modules/@smithy/util-middleware": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.6.tgz", - "integrity": "sha512-BxbX4aBhI1O9p87/xM+zWy0GzT3CEVcXFPBRDoHAM+pV0eSW156pR+PSYEz0DQHDMYDsYAflC2bQNz2uaDBUZQ==", + "node_modules/@types/react-dom": { + "version": "18.2.14", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.14.tgz", + "integrity": "sha512-V835xgdSVmyQmI1KLV2BEIUgqEuinxp9O4G6g3FqO/SqLac049E53aysv0oEFD2kHfejeKU+ZqL2bcFWj9gLAQ==", + "devOptional": true, "dependencies": { - "@smithy/types": "^3.4.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "@types/react": "*" } }, - "node_modules/@smithy/util-retry": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.6.tgz", - "integrity": "sha512-BRZiuF7IwDntAbevqMco67an0Sr9oLQJqqRCsSPZZHYRnehS0LHDAkJk/pSmI7Z8c/1Vet294H7fY2fWUgB+Rg==", + "node_modules/@types/react-router": { + "version": "5.1.20", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz", + "integrity": "sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==", "dependencies": { - "@smithy/service-error-classification": "^3.0.6", - "@smithy/types": "^3.4.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "@types/history": "^4.7.11", + "@types/react": "*" } }, - "node_modules/@smithy/util-stream": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.1.8.tgz", - "integrity": "sha512-hoKOqSmb8FD3WLObuB5hwbM7bNIWgcnvkThokTvVq7J5PKjlLUK5qQQcB9zWLHIoSaIlf3VIv2OxZY2wtQjcRQ==", + "node_modules/@types/react-router-config": { + "version": "5.0.11", + "resolved": "https://registry.npmjs.org/@types/react-router-config/-/react-router-config-5.0.11.tgz", + "integrity": "sha512-WmSAg7WgqW7m4x8Mt4N6ZyKz0BubSj/2tVUMsAHp+Yd2AMwcSbeFq9WympT19p5heCFmF97R9eD5uUR/t4HEqw==", "dependencies": { - "@smithy/fetch-http-handler": "^3.2.8", - "@smithy/node-http-handler": "^3.2.3", - "@smithy/types": "^3.4.2", - "@smithy/util-base64": "^3.0.0", - "@smithy/util-buffer-from": "^3.0.0", - "@smithy/util-hex-encoding": "^3.0.0", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router": "^5.1.0" } }, - "node_modules/@smithy/util-uri-escape": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", - "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", + "node_modules/@types/react-router-dom": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz", + "integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==", "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router": "*" } }, - "node_modules/@smithy/util-utf8": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", - "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "node_modules/@types/responselike": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", + "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", + "license": "MIT", "dependencies": { - "@smithy/util-buffer-from": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "@types/node": "*" } }, - "node_modules/@socket.io/component-emitter": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", - "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" - }, - "node_modules/@stablelib/aead": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/aead/-/aead-1.0.1.tgz", - "integrity": "sha512-q39ik6sxGHewqtO0nP4BuSe3db5G1fEJE8ukvngS2gLkBXyy6E7pLubhbYgnkDFv6V8cWaxcE4Xn0t6LWcJkyg==" + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" }, - "node_modules/@stablelib/binary": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/binary/-/binary-1.0.1.tgz", - "integrity": "sha512-ClJWvmL6UBM/wjkvv/7m5VP3GMr9t0osr4yVgLZsLCOz4hGN9gIAFEqnJ0TsSMAN+n840nf2cHZnA5/KFqHC7Q==", + "node_modules/@types/sax": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.7.tgz", + "integrity": "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==", "dependencies": { - "@stablelib/int": "^1.0.1" + "@types/node": "*" } }, - "node_modules/@stablelib/bytes": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/bytes/-/bytes-1.0.1.tgz", - "integrity": "sha512-Kre4Y4kdwuqL8BR2E9hV/R5sOrUj6NanZaZis0V6lX5yzqC3hBuVSDXUIBqQv/sCpmuWRiHLwqiT1pqqjuBXoQ==" + "node_modules/@types/scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-YIoDCTH3Af6XM5VuwGG/QL/CJqga1Zm3NkU3HZ4ZHK2fRMPYP1VczsTUqtsf43PH/iJNVlPHAo2oWX7BSdB2Hw==" }, - "node_modules/@stablelib/chacha": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/chacha/-/chacha-1.0.1.tgz", - "integrity": "sha512-Pmlrswzr0pBzDofdFuVe1q7KdsHKhhU24e8gkEwnTGOmlC7PADzLVxGdn2PoNVBBabdg0l/IfLKg6sHAbTQugg==", + "node_modules/@types/secp256k1": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.6.tgz", + "integrity": "sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==", + "license": "MIT", "dependencies": { - "@stablelib/binary": "^1.0.1", - "@stablelib/wipe": "^1.0.1" + "@types/node": "*" } }, - "node_modules/@stablelib/chacha20poly1305": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/chacha20poly1305/-/chacha20poly1305-1.0.1.tgz", - "integrity": "sha512-MmViqnqHd1ymwjOQfghRKw2R/jMIGT3wySN7cthjXCBdO+qErNPUBnRzqNpnvIwg7JBCg3LdeCZZO4de/yEhVA==", + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", "dependencies": { - "@stablelib/aead": "^1.0.1", - "@stablelib/binary": "^1.0.1", - "@stablelib/chacha": "^1.0.1", - "@stablelib/constant-time": "^1.0.1", - "@stablelib/poly1305": "^1.0.1", - "@stablelib/wipe": "^1.0.1" + "@types/mime": "^1", + "@types/node": "*" } }, - "node_modules/@stablelib/constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/constant-time/-/constant-time-1.0.1.tgz", - "integrity": "sha512-tNOs3uD0vSJcK6z1fvef4Y+buN7DXhzHDPqRLSXUel1UfqMB1PWNsnnAezrKfEwTLpN0cGH2p9NNjs6IqeD0eg==" - }, - "node_modules/@stablelib/ed25519": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@stablelib/ed25519/-/ed25519-1.0.3.tgz", - "integrity": "sha512-puIMWaX9QlRsbhxfDc5i+mNPMY+0TmQEskunY1rZEBPi1acBCVQAhnsk/1Hk50DGPtVsZtAWQg4NHGlVaO9Hqg==", + "node_modules/@types/serve-index": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", "dependencies": { - "@stablelib/random": "^1.0.2", - "@stablelib/sha512": "^1.0.1", - "@stablelib/wipe": "^1.0.1" + "@types/express": "*" } }, - "node_modules/@stablelib/hash": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/hash/-/hash-1.0.1.tgz", - "integrity": "sha512-eTPJc/stDkdtOcrNMZ6mcMK1e6yBbqRBaNW55XA1jU8w/7QdnCF0CmMmOD1m7VSkBR44PWrMHU2l6r8YEQHMgg==" - }, - "node_modules/@stablelib/hkdf": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/hkdf/-/hkdf-1.0.1.tgz", - "integrity": "sha512-SBEHYE16ZXlHuaW5RcGk533YlBj4grMeg5TooN80W3NpcHRtLZLLXvKyX0qcRFxf+BGDobJLnwkvgEwHIDBR6g==", + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", "dependencies": { - "@stablelib/hash": "^1.0.1", - "@stablelib/hmac": "^1.0.1", - "@stablelib/wipe": "^1.0.1" + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" } }, - "node_modules/@stablelib/hmac": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/hmac/-/hmac-1.0.1.tgz", - "integrity": "sha512-V2APD9NSnhVpV/QMYgCVMIYKiYG6LSqw1S65wxVoirhU/51ACio6D4yDVSwMzuTJXWZoVHbDdINioBwKy5kVmA==", + "node_modules/@types/sha.js": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/sha.js/-/sha.js-2.4.4.tgz", + "integrity": "sha512-Qukd+D6S2Hm0wLVt2Vh+/eWBIoUt+wF8jWjBsG4F8EFQRwKtYvtXCPcNl2OEUQ1R+eTr3xuSaBYUyM3WD1x/Qw==", + "license": "MIT", "dependencies": { - "@stablelib/constant-time": "^1.0.1", - "@stablelib/hash": "^1.0.1", - "@stablelib/wipe": "^1.0.1" + "@types/node": "*" } }, - "node_modules/@stablelib/int": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/int/-/int-1.0.1.tgz", - "integrity": "sha512-byr69X/sDtDiIjIV6m4roLVWnNNlRGzsvxw+agj8CIEazqWGOQp2dTYgQhtyVXV9wpO6WyXRQUzLV/JRNumT2w==" + "node_modules/@types/shimmer": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.2.0.tgz", + "integrity": "sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==" }, - "node_modules/@stablelib/keyagreement": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/keyagreement/-/keyagreement-1.0.1.tgz", - "integrity": "sha512-VKL6xBwgJnI6l1jKrBAfn265cspaWBPAPEc62VBQrWHLqVgNRE09gQ/AnOEyKUWrrqfD+xSQ3u42gJjLDdMDQg==", + "node_modules/@types/sockjs": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", "dependencies": { - "@stablelib/bytes": "^1.0.1" + "@types/node": "*" } }, - "node_modules/@stablelib/poly1305": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/poly1305/-/poly1305-1.0.1.tgz", - "integrity": "sha512-1HlG3oTSuQDOhSnLwJRKeTRSAdFNVB/1djy2ZbS35rBSJ/PFqx9cf9qatinWghC2UbfOYD8AcrtbUQl8WoxabA==", - "dependencies": { - "@stablelib/constant-time": "^1.0.1", - "@stablelib/wipe": "^1.0.1" - } + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==" }, - "node_modules/@stablelib/random": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@stablelib/random/-/random-1.0.2.tgz", - "integrity": "sha512-rIsE83Xpb7clHPVRlBj8qNe5L8ISQOzjghYQm/dZ7VaM2KHYwMW5adjQjrzTZCchFnNCNhkwtnOBa9HTMJCI8w==", + "node_modules/@types/statuses": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.5.tgz", + "integrity": "sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/superagent": { + "version": "8.1.7", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.7.tgz", + "integrity": "sha512-NmIsd0Yj4DDhftfWvvAku482PZum4DBW7U51OvS8gvOkDDY0WT1jsVyDV3hK+vplrsYw8oDwi9QxOM7U68iwww==", + "dev": true, "dependencies": { - "@stablelib/binary": "^1.0.1", - "@stablelib/wipe": "^1.0.1" + "@types/cookiejar": "^2.1.5", + "@types/methods": "^1.1.4", + "@types/node": "*" } }, - "node_modules/@stablelib/sha256": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/sha256/-/sha256-1.0.1.tgz", - "integrity": "sha512-GIIH3e6KH+91FqGV42Kcj71Uefd/QEe7Dy42sBTeqppXV95ggCcxLTk39bEr+lZfJmp+ghsR07J++ORkRELsBQ==", + "node_modules/@types/supertest": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-6.0.2.tgz", + "integrity": "sha512-137ypx2lk/wTQbW6An6safu9hXmajAifU/s7szAHLN/FeIm5w7yR0Wkl9fdJMRSHwOn4HLAI0DaB2TOORuhPDg==", + "dev": true, "dependencies": { - "@stablelib/binary": "^1.0.1", - "@stablelib/hash": "^1.0.1", - "@stablelib/wipe": "^1.0.1" + "@types/methods": "^1.1.4", + "@types/superagent": "^8.1.0" } }, - "node_modules/@stablelib/sha512": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/sha512/-/sha512-1.0.1.tgz", - "integrity": "sha512-13gl/iawHV9zvDKciLo1fQ8Bgn2Pvf7OV6amaRVKiq3pjQ3UmEpXxWiAfV8tYjUpeZroBxtyrwtdooQT/i3hzw==", + "node_modules/@types/tedious": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/@types/tedious/-/tedious-4.0.14.tgz", + "integrity": "sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==", "dependencies": { - "@stablelib/binary": "^1.0.1", - "@stablelib/hash": "^1.0.1", - "@stablelib/wipe": "^1.0.1" + "@types/node": "*" } }, - "node_modules/@stablelib/wipe": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/wipe/-/wipe-1.0.1.tgz", - "integrity": "sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg==" + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "dev": true }, - "node_modules/@stablelib/x25519": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@stablelib/x25519/-/x25519-1.0.3.tgz", - "integrity": "sha512-KnTbKmUhPhHavzobclVJQG5kuivH+qDLpe84iRqX3CLrKp881cF160JvXJ+hjn1aMyCwYOKeIZefIH/P5cJoRw==", - "dependencies": { - "@stablelib/keyagreement": "^1.0.1", - "@stablelib/random": "^1.0.2", - "@stablelib/wipe": "^1.0.1" - } + "node_modules/@types/traverse": { + "version": "0.6.37", + "resolved": "https://registry.npmjs.org/@types/traverse/-/traverse-0.6.37.tgz", + "integrity": "sha512-c90MVeDiUI1FhOZ6rLQ3kDWr50YE8+paDpM+5zbHjbmsqEp2DlMYkqnZnwbK9oI+NvDe8yRajup4jFwnVX6xsA==", + "dev": true }, - "node_modules/@svgr/babel-plugin-add-jsx-attribute": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", - "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "node_modules/@types/triple-beam": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", + "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==" }, - "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", - "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==" }, - "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", - "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" }, - "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", - "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "node_modules/@types/urijs": { + "version": "1.19.25", + "resolved": "https://registry.npmjs.org/@types/urijs/-/urijs-1.19.25.tgz", + "integrity": "sha512-XOfUup9r3Y06nFAZh3WvO0rBU4OtlfPB/vgxpjg+NRdGU6CN6djdc6OEiH+PcqHCY6eFLo9Ista73uarf4gnBg==", + "license": "MIT" }, - "node_modules/@svgr/babel-plugin-svg-dynamic-title": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", - "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "node_modules/@types/utf8": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@types/utf8/-/utf8-2.1.6.tgz", + "integrity": "sha512-pRs2gYF5yoKYrgSaira0DJqVg2tFuF+Qjp838xS7K+mJyY2jJzjsrl6y17GbIa4uMRogMbxs+ghNCvKg6XyNrA==", + "license": "MIT" }, - "node_modules/@svgr/babel-plugin-svg-em-dimensions": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", - "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "node_modules/@types/uuid": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.7.tgz", + "integrity": "sha512-WUtIVRUZ9i5dYXefDEAI7sh9/O7jGvHg7Df/5O/gtH3Yabe5odI3UWopVR1qbPXQtvOxWu3mM4XxlYeZtMWF4g==", + "dev": true }, - "node_modules/@svgr/babel-plugin-transform-react-native-svg": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", - "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node_modules/@types/validator": { + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.12.0.tgz", + "integrity": "sha512-nH45Lk7oPIJ1RVOF6JgFI6Dy0QpHEzq4QecZhvguxYPDwT8c93prCMqAtiIttm39voZ+DDR+qkNnMpJmMBRqag==" + }, + "node_modules/@types/ws": { + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", + "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", + "dependencies": { + "@types/node": "*" } }, - "node_modules/@svgr/babel-plugin-transform-svg-component": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", - "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", - "engines": { - "node": ">=12" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node_modules/@types/yargs": { + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", + "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", + "dependencies": { + "@types/yargs-parser": "*" } }, - "node_modules/@svgr/babel-preset": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", - "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.0.tgz", + "integrity": "sha512-py1miT6iQpJcs1BiJjm54AMzeuMPBSPuKPlnT8HlfudbcS5rYeX5jajpLf3mrdRh9dA/Ec2FVUY0ifeVNDIhZw==", + "dev": true, "dependencies": { - "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", - "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", - "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", - "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", - "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", - "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", - "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", - "@svgr/babel-plugin-transform-svg-component": "8.0.0" + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.16.0", + "@typescript-eslint/type-utils": "7.16.0", + "@typescript-eslint/utils": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": ">=14" + "node": "^18.18.0 || >=20.0.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@svgr/core": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", - "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", + "node_modules/@typescript-eslint/parser": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.9.0.tgz", + "integrity": "sha512-qHMJfkL5qvgQB2aLvhUSXxbK7OLnDkwPzFalg458pxQgfxKDfT1ZDbHQM/I6mDIf/svlMkj21kzKuQ2ixJlatQ==", + "dev": true, "dependencies": { - "@babel/core": "^7.21.3", - "@svgr/babel-preset": "8.1.0", - "camelcase": "^6.2.0", - "cosmiconfig": "^8.1.3", - "snake-case": "^3.0.4" + "@typescript-eslint/scope-manager": "7.9.0", + "@typescript-eslint/types": "7.9.0", + "@typescript-eslint/typescript-estree": "7.9.0", + "@typescript-eslint/visitor-keys": "7.9.0", + "debug": "^4.3.4" }, "engines": { - "node": ">=14" + "node": "^18.18.0 || >=20.0.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/hast-util-to-babel-ast": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", - "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", - "dependencies": { - "@babel/types": "^7.21.3", - "entities": "^4.4.0" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, - "engines": { - "node": ">=14" + "peerDependencies": { + "eslint": "^8.56.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@svgr/plugin-jsx": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", - "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.9.0.tgz", + "integrity": "sha512-ZwPK4DeCDxr3GJltRz5iZejPFAAr4Wk3+2WIBaj1L5PYK5RgxExu/Y68FFVclN0y6GGwH8q+KgKRCvaTmFBbgQ==", + "dev": true, "dependencies": { - "@babel/core": "^7.21.3", - "@svgr/babel-preset": "8.1.0", - "@svgr/hast-util-to-babel-ast": "8.0.0", - "svg-parser": "^2.0.4" + "@typescript-eslint/types": "7.9.0", + "@typescript-eslint/visitor-keys": "7.9.0" }, "engines": { - "node": ">=14" + "node": "^18.18.0 || >=20.0.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@svgr/core": "*" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@svgr/plugin-svgo": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-8.1.0.tgz", - "integrity": "sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA==", + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.9.0.tgz", + "integrity": "sha512-iESPx2TNLDNGQLyjKhUvIKprlP49XNEK+MvIf9nIO7ZZaZdbnfWKHnXAgufpxqfA0YryH8XToi4+CjBgVnFTSQ==", + "dev": true, "dependencies": { - "cosmiconfig": "^8.1.3", - "deepmerge": "^4.3.1", - "svgo": "^3.0.2" + "@typescript-eslint/types": "7.9.0", + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": ">=14" + "node": "^18.18.0 || >=20.0.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@svgr/core": "*" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@svgr/webpack": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.1.0.tgz", - "integrity": "sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.16.0.tgz", + "integrity": "sha512-8gVv3kW6n01Q6TrI1cmTZ9YMFi3ucDT7i7aI5lEikk2ebk1AEjrwX8MDTdaX5D7fPXMBLvnsaa0IFTAu+jcfOw==", + "dev": true, "dependencies": { - "@babel/core": "^7.21.3", - "@babel/plugin-transform-react-constant-elements": "^7.21.3", - "@babel/preset-env": "^7.20.2", - "@babel/preset-react": "^7.18.6", - "@babel/preset-typescript": "^7.21.0", - "@svgr/core": "8.1.0", - "@svgr/plugin-jsx": "8.1.0", - "@svgr/plugin-svgo": "8.1.0" + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0" }, "engines": { - "node": ">=14" + "node": "^18.18.0 || >=20.0.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@swc-node/core": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/@swc-node/core/-/core-1.13.3.tgz", - "integrity": "sha512-OGsvXIid2Go21kiNqeTIn79jcaX4l0G93X2rAnas4LFoDyA9wAwVK7xZdm+QsKoMn5Mus2yFLCc4OtX2dD/PWA==", + "node_modules/@typescript-eslint/scope-manager/node_modules/@typescript-eslint/types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", + "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", "dev": true, "engines": { - "node": ">= 10" + "node": "^18.18.0 || >=20.0.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - }, - "peerDependencies": { - "@swc/core": ">= 1.4.13", - "@swc/types": ">= 0.1" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@swc-node/register": { - "version": "1.10.9", - "resolved": "https://registry.npmjs.org/@swc-node/register/-/register-1.10.9.tgz", - "integrity": "sha512-iXy2sjP0phPEpK2yivjRC3PAgoLaT4sjSk0LDWCTdcTBJmR4waEog0E6eJbvoOkLkOtWw37SB8vCkl/bbh4+8A==", + "node_modules/@typescript-eslint/type-utils": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.0.tgz", + "integrity": "sha512-j0fuUswUjDHfqV/UdW6mLtOQQseORqfdmoBNDFOqs9rvNVR2e+cmu6zJu/Ku4SDuqiJko6YnhwcL8x45r8Oqxg==", "dev": true, "dependencies": { - "@swc-node/core": "^1.13.3", - "@swc-node/sourcemap-support": "^0.5.1", - "colorette": "^2.0.20", - "debug": "^4.3.5", - "oxc-resolver": "^1.10.2", - "pirates": "^4.0.6", - "tslib": "^2.6.3" + "@typescript-eslint/typescript-estree": "7.16.0", + "@typescript-eslint/utils": "7.16.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@swc/core": ">= 1.4.13", - "typescript": ">= 4.3" - } - }, - "node_modules/@swc-node/sourcemap-support": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@swc-node/sourcemap-support/-/sourcemap-support-0.5.1.tgz", - "integrity": "sha512-JxIvIo/Hrpv0JCHSyRpetAdQ6lB27oFYhv0PKCNf1g2gUXOjpeR1exrXccRxLMuAV5WAmGFBwRnNOJqN38+qtg==", - "dev": true, - "dependencies": { - "source-map-support": "^0.5.21", - "tslib": "^2.6.3" + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@swc-node/sourcemap-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", + "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", "dev": true, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@swc-node/sourcemap-support/node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@swc/core": { - "version": "1.7.26", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.7.26.tgz", - "integrity": "sha512-f5uYFf+TmMQyYIoxkn/evWhNGuUzC730dFwAKGwBVHHVoPyak1/GvJUm6i1SKl+2Hrj9oN0i3WSoWWZ4pgI8lw==", + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.0.tgz", + "integrity": "sha512-a5NTvk51ZndFuOLCh5OaJBELYc2O3Zqxfl3Js78VFE1zE46J2AaVuW+rEbVkQznjkmlzWsUI15BG5tQMixzZLw==", "dev": true, - "hasInstallScript": true, "dependencies": { - "@swc/counter": "^0.1.3", - "@swc/types": "^0.1.12" + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": ">=10" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/swc" - }, - "optionalDependencies": { - "@swc/core-darwin-arm64": "1.7.26", - "@swc/core-darwin-x64": "1.7.26", - "@swc/core-linux-arm-gnueabihf": "1.7.26", - "@swc/core-linux-arm64-gnu": "1.7.26", - "@swc/core-linux-arm64-musl": "1.7.26", - "@swc/core-linux-x64-gnu": "1.7.26", - "@swc/core-linux-x64-musl": "1.7.26", - "@swc/core-win32-arm64-msvc": "1.7.26", - "@swc/core-win32-ia32-msvc": "1.7.26", - "@swc/core-win32-x64-msvc": "1.7.26" - }, - "peerDependencies": { - "@swc/helpers": "*" + "url": "https://opencollective.com/typescript-eslint" }, "peerDependenciesMeta": { - "@swc/helpers": { + "typescript": { "optional": true } } }, - "node_modules/@swc/core-darwin-arm64": { - "version": "1.7.26", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.26.tgz", - "integrity": "sha512-FF3CRYTg6a7ZVW4yT9mesxoVVZTrcSWtmZhxKCYJX9brH4CS/7PRPjAKNk6kzWgWuRoglP7hkjQcd6EpMcZEAw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-darwin-x64": { - "version": "1.7.26", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.7.26.tgz", - "integrity": "sha512-az3cibZdsay2HNKmc4bjf62QVukuiMRh5sfM5kHR/JMTrLyS6vSw7Ihs3UTkZjUxkLTT8ro54LI6sV6sUQUbLQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.7.26", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.7.26.tgz", - "integrity": "sha512-VYPFVJDO5zT5U3RpCdHE5v1gz4mmR8BfHecUZTmD2v1JeFY6fv9KArJUpjrHEEsjK/ucXkQFmJ0jaiWXmpOV9Q==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.7.26", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.7.26.tgz", - "integrity": "sha512-YKevOV7abpjcAzXrhsl+W48Z9mZvgoVs2eP5nY+uoMAdP2b3GxC0Df1Co0I90o2lkzO4jYBpTMcZlmUXLdXn+Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.7.26", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.7.26.tgz", - "integrity": "sha512-3w8iZICMkQQON0uIcvz7+Q1MPOW6hJ4O5ETjA0LSP/tuKqx30hIniCGOgPDnv3UTMruLUnQbtBwVCZTBKR3Rkg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.7.26", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.26.tgz", - "integrity": "sha512-c+pp9Zkk2lqb06bNGkR2Looxrs7FtGDMA4/aHjZcCqATgp348hOKH5WPvNLBl+yPrISuWjbKDVn3NgAvfvpH4w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-x64-musl": { - "version": "1.7.26", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.7.26.tgz", - "integrity": "sha512-PgtyfHBF6xG87dUSSdTJHwZ3/8vWZfNIXQV2GlwEpslrOkGqy+WaiiyE7Of7z9AvDILfBBBcJvJ/r8u980wAfQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.7.26", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.7.26.tgz", - "integrity": "sha512-9TNXPIJqFynlAOrRD6tUQjMq7KApSklK3R/tXgIxc7Qx+lWu8hlDQ/kVPLpU7PWvMMwC/3hKBW+p5f+Tms1hmA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.7.26", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.7.26.tgz", - "integrity": "sha512-9YngxNcG3177GYdsTum4V98Re+TlCeJEP4kEwEg9EagT5s3YejYdKwVAkAsJszzkXuyRDdnHUpYbTrPG6FiXrQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.7.26", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.26.tgz", - "integrity": "sha512-VR+hzg9XqucgLjXxA13MtV5O3C0bK0ywtLIBw/+a+O+Oc6mxFWHtdUeXDbIi5AiPbn0fjgVJMqYnyjGyyX8u0w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/counter": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", - "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" - }, - "node_modules/@swc/helpers": { - "version": "0.5.11", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.11.tgz", - "integrity": "sha512-YNlnKRWF2sVojTpIyzwou9XoTNbzbzONwRhOoniEioF1AtaitTvVZblaQRrAzChWQ1bLYyYSWzM18y4WwgzJ+A==", - "dev": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@swc/types": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.12.tgz", - "integrity": "sha512-wBJA+SdtkbFhHjTMYH+dEH1y4VpfGdAc2Kw/LK09i9bXd/K6j6PkDcFCEzb6iVfZMkPRrl/q0e3toqTAJdkIVA==", + "node_modules/@typescript-eslint/type-utils/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "dependencies": { - "@swc/counter": "^0.1.3" + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@szmarczak/http-timer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", - "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", - "dependencies": { - "defer-to-connect": "^2.0.1" + "node_modules/@typescript-eslint/type-utils/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=14.16" + "node": ">=10" } }, - "node_modules/@tanstack/query-core": { - "version": "5.51.9", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.51.9.tgz", - "integrity": "sha512-HsAwaY5J19MD18ykZDS3aVVh+bAt0i7m6uQlFC2b77DLV9djo+xEN7MWQAQQTR8IM+7r/zbozTQ7P0xr0bHuew==", + "node_modules/@typescript-eslint/types": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.9.0.tgz", + "integrity": "sha512-oZQD9HEWQanl9UfsbGVcZ2cGaR0YT5476xfWE0oE5kQa2sNK2frxOlkeacLOTh9po4AlUT5rtkGyYM5kew0z5w==", + "dev": true, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@tanstack/react-query": { - "version": "5.51.11", - "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.51.11.tgz", - "integrity": "sha512-4Kq2x0XpDlpvSnaLG+8pHNH60zEc3mBvb3B2tOMDjcPCi/o+Du3p/9qpPLwJOTliVxxPJAP27fuIhLrsRdCr7A==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.9.0.tgz", + "integrity": "sha512-zBCMCkrb2YjpKV3LA0ZJubtKCDxLttxfdGmwZvTqqWevUPN0FZvSI26FalGFFUZU/9YQK/A4xcQF9o/VVaCKAg==", + "dev": true, "dependencies": { - "@tanstack/query-core": "5.51.9" + "@typescript-eslint/types": "7.9.0", + "@typescript-eslint/visitor-keys": "7.9.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, - "peerDependencies": { - "react": "^18.0.0" + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@testing-library/dom": { - "version": "9.3.4", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.4.tgz", - "integrity": "sha512-FlS4ZWlp97iiNWig0Muq8p+3rVDjRiYE+YKGbAqXOu9nwJFFOdL00kFpz42M+4huzYi86vAK1sOOfyOG45muIQ==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/visitor-keys": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.9.0.tgz", + "integrity": "sha512-iESPx2TNLDNGQLyjKhUvIKprlP49XNEK+MvIf9nIO7ZZaZdbnfWKHnXAgufpxqfA0YryH8XToi4+CjBgVnFTSQ==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^5.0.1", - "aria-query": "5.1.3", - "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.5.0", - "pretty-format": "^27.0.2" + "@typescript-eslint/types": "7.9.0", + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": ">=14" + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@testing-library/react": { - "version": "14.1.2", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-14.1.2.tgz", - "integrity": "sha512-z4p7DVBTPjKM5qDZ0t5ZjzkpSNb+fZy1u6bzO7kk8oeGagpPCAtgh4cx1syrfp7a+QWkM021jGqjJaxJJnXAZg==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "dependencies": { - "@babel/runtime": "^7.12.5", - "@testing-library/dom": "^9.0.0", - "@types/react-dom": "^18.0.0" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=14" + "node": ">=16 || 14 >=14.17" }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", "dev": true, + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">= 10" - } - }, - "node_modules/@tootallnate/quickjs-emscripten": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", - "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", - "dev": true - }, - "node_modules/@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "engines": { - "node": ">=10.13.0" + "node": ">=10" } }, - "node_modules/@tsconfig/node10": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", - "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", - "dev": true - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true - }, - "node_modules/@tybys/wasm-util": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", - "integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==", + "node_modules/@typescript-eslint/utils": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz", + "integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==", "dev": true, "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@types/acorn": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz", - "integrity": "sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==", - "dependencies": { - "@types/estree": "*" - } - }, - "node_modules/@types/aria-query": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", - "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", - "dev": true - }, - "node_modules/@types/aws-lambda": { - "version": "8.10.143", - "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.143.tgz", - "integrity": "sha512-u5vzlcR14ge/4pMTTMDQr3MF0wEe38B2F9o84uC4F43vN5DGTy63npRrB6jQhyt+C0lGv4ZfiRcRkqJoZuPnmg==" - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", - "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", - "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", - "dependencies": { - "@babel/types": "^7.20.7" - } - }, - "node_modules/@types/body-parser": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", - "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/bonjour": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", - "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/bunyan": { - "version": "1.8.9", - "resolved": "https://registry.npmjs.org/@types/bunyan/-/bunyan-1.8.9.tgz", - "integrity": "sha512-ZqS9JGpBxVOvsawzmVt30sP++gSQMTejCkIAQ3VdadOcRE8izTyW66hufvwLeH+YEGP6Js2AW7Gz+RMyvrEbmw==", - "dependencies": { - "@types/node": "*" + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.16.0", + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/typescript-estree": "7.16.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" } }, - "node_modules/@types/compression": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@types/compression/-/compression-1.7.5.tgz", - "integrity": "sha512-AAQvK5pxMpaT+nDvhHrsBhLSYG5yQdtkaJE1WYieSNY2mVFKAgmU4ks65rkZD5oqnGCFLyQpUr1CqI4DmUMyDg==", + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", + "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", "dev": true, - "dependencies": { - "@types/express": "*" - } - }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dependencies": { - "@types/node": "*" + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@types/connect-history-api-fallback": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", - "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.0.tgz", + "integrity": "sha512-a5NTvk51ZndFuOLCh5OaJBELYc2O3Zqxfl3Js78VFE1zE46J2AaVuW+rEbVkQznjkmlzWsUI15BG5tQMixzZLw==", + "dev": true, "dependencies": { - "@types/express-serve-static-core": "*", - "@types/node": "*" + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@types/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", + "node_modules/@typescript-eslint/utils/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, - "license": "MIT" - }, - "node_modules/@types/cookiejar": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.5.tgz", - "integrity": "sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==", - "dev": true - }, - "node_modules/@types/debug": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", - "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", "dependencies": { - "@types/ms": "*" + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@types/duplexify": { - "version": "3.6.4", - "resolved": "https://registry.npmjs.org/@types/duplexify/-/duplexify-3.6.4.tgz", - "integrity": "sha512-2eahVPsd+dy3CL6FugAzJcxoraWhUghZGEQJns1kTKfCXWKJ5iG/VkaB05wRVrDKHfOFKqb0X0kXh91eE99RZg==", - "dependencies": { - "@types/node": "*" + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/@types/eslint": { - "version": "8.56.10", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", - "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.0.tgz", + "integrity": "sha512-rMo01uPy9C7XxG7AFsxa8zLnWXTF8N3PYclekWSrurvhwiw1eW88mrKiAYe6s53AUY57nTRz8dJsuuXdkAhzCg==", + "dev": true, "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" + "@typescript-eslint/types": "7.16.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" + "node_modules/@typescript-eslint/visitor-keys/node_modules/@typescript-eslint/types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", + "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", + "dev": true, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" - }, - "node_modules/@types/estree-jsx": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", - "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", - "dependencies": { - "@types/estree": "*" - } + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" }, - "node_modules/@types/express": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", - "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "node_modules/@unimodules/core": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@unimodules/core/-/core-7.2.0.tgz", + "integrity": "sha512-Nu+bAd/xG4B2xyYMrmV3LnDr8czUQgV1XhoL3sOOMwGydDJtfpWNodGhPhEMyKq2CXo4X7DDIo8qG6W2fk6XAQ==", + "deprecated": "replaced by the 'expo' package, learn more: https://blog.expo.dev/whats-new-in-expo-modules-infrastructure-7a7cdda81ebc", + "license": "MIT", + "optional": true, "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" + "expo-modules-core": "~0.4.0" } }, - "node_modules/@types/express-serve-static-core": { - "version": "4.19.5", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz", - "integrity": "sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==", - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } + "node_modules/@unimodules/core/node_modules/compare-versions": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", + "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", + "license": "MIT", + "optional": true }, - "node_modules/@types/graceful-fs": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", - "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "node_modules/@unimodules/core/node_modules/expo-modules-core": { + "version": "0.4.10", + "resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-0.4.10.tgz", + "integrity": "sha512-uCZA3QzF0syRaHwYY99iaNhnye4vSQGsJ/y6IAiesXdbeVahWibX4G1KoKNPUyNsKXIM4tqA+4yByUSvJe4AAw==", + "license": "MIT", + "optional": true, "dependencies": { - "@types/node": "*" + "compare-versions": "^3.4.0", + "invariant": "^2.2.4" } }, - "node_modules/@types/gtag.js": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/@types/gtag.js/-/gtag.js-0.0.12.tgz", - "integrity": "sha512-YQV9bUsemkzG81Ea295/nF/5GijnD2Af7QhEofh7xu+kvCN6RdodgNwwGWXB5GMI3NoyvQo0odNctoH/qLMIpg==" - }, - "node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "node_modules/@unimodules/react-native-adapter": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@unimodules/react-native-adapter/-/react-native-adapter-6.5.0.tgz", + "integrity": "sha512-F2J6gVw9a57DTVTQQunp64fqD4HVBkltOpUz1L5lEccNbQlZEA7SjnqKJzXakI7uPhhN76/n+SGb7ihzHw2swQ==", + "deprecated": "replaced by the 'expo' package, learn more: https://blog.expo.dev/whats-new-in-expo-modules-infrastructure-7a7cdda81ebc", + "license": "MIT", + "optional": true, "dependencies": { - "@types/unist": "*" + "expo-modules-autolinking": "^0.3.2", + "expo-modules-core": "~0.4.0" } }, - "node_modules/@types/history": { - "version": "4.7.11", - "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", - "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==" - }, - "node_modules/@types/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==" - }, - "node_modules/@types/http-cache-semantics": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", - "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==" - }, - "node_modules/@types/http-errors": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==" - }, - "node_modules/@types/http-proxy": { - "version": "1.17.14", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", - "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", - "dependencies": { - "@types/node": "*" + "node_modules/@unimodules/react-native-adapter/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 10" } }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==" - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", - "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } + "node_modules/@unimodules/react-native-adapter/node_modules/compare-versions": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", + "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", + "license": "MIT", + "optional": true }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", - "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "node_modules/@unimodules/react-native-adapter/node_modules/expo-modules-autolinking": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-0.3.4.tgz", + "integrity": "sha512-Mu3CIMqEAI8aNM18U/l+7CCi+afU8dERrKjDDEx/Hu7XX3v3FcnnP+NuWDLY/e9/ETzwTJaqoRoBuzhawsuLWw==", + "license": "MIT", + "optional": true, "dependencies": { - "@types/istanbul-lib-report": "*" + "chalk": "^4.1.0", + "commander": "^7.2.0", + "fast-glob": "^3.2.5", + "find-up": "~5.0.0", + "fs-extra": "^9.1.0" + }, + "bin": { + "expo-modules-autolinking": "bin/expo-modules-autolinking.js" } }, - "node_modules/@types/jest": { - "version": "29.5.12", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", - "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", - "dev": true, + "node_modules/@unimodules/react-native-adapter/node_modules/expo-modules-core": { + "version": "0.4.10", + "resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-0.4.10.tgz", + "integrity": "sha512-uCZA3QzF0syRaHwYY99iaNhnye4vSQGsJ/y6IAiesXdbeVahWibX4G1KoKNPUyNsKXIM4tqA+4yByUSvJe4AAw==", + "license": "MIT", + "optional": true, "dependencies": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" + "compare-versions": "^3.4.0", + "invariant": "^2.2.4" } }, - "node_modules/@types/jest/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, + "node_modules/@unimodules/react-native-adapter/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "license": "MIT", + "optional": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@types/jest/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, + "node_modules/@unimodules/react-native-adapter/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "license": "MIT", + "optional": true, "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" } }, - "node_modules/@types/jest/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true - }, - "node_modules/@types/jsdom": { - "version": "20.0.1", - "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz", - "integrity": "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==", - "dev": true, + "node_modules/@unimodules/react-native-adapter/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "license": "MIT", + "optional": true, "dependencies": { - "@types/node": "*", - "@types/tough-cookie": "*", - "parse5": "^7.0.0" + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@types/jsdom/node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dev": true, + "node_modules/@unimodules/react-native-adapter/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "license": "MIT", + "optional": true, "dependencies": { - "entities": "^4.4.0" + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" }, "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true - }, - "node_modules/@types/lodash": { - "version": "4.17.7", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.7.tgz", - "integrity": "sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==", - "dev": true - }, - "node_modules/@types/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==" - }, - "node_modules/@types/mdast": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", - "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "node_modules/@urql/core": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@urql/core/-/core-2.3.6.tgz", + "integrity": "sha512-PUxhtBh7/8167HJK6WqBv6Z0piuiaZHQGYbhwpNL9aIQmLROPEdaUYkY4wh45wPQXcTpnd11l0q3Pw+TI11pdw==", + "license": "MIT", + "optional": true, + "peer": true, "dependencies": { - "@types/unist": "*" + "@graphql-typed-document-node/core": "^3.1.0", + "wonka": "^4.0.14" + }, + "peerDependencies": { + "graphql": "^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } }, - "node_modules/@types/mdx": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", - "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==" - }, - "node_modules/@types/memcached": { - "version": "2.2.10", - "resolved": "https://registry.npmjs.org/@types/memcached/-/memcached-2.2.10.tgz", - "integrity": "sha512-AM9smvZN55Gzs2wRrqeMHVP7KE8KWgCJO/XL5yCly2xF6EKa4YlbpK+cLSAH4NG/Ah64HrlegmGqW8kYws7Vxg==", + "node_modules/@wagmi/connectors": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/@wagmi/connectors/-/connectors-5.3.9.tgz", + "integrity": "sha512-TS1nJRfQbwPpeW28fPWkanuMuUJSoAAS0+zEthStq/PmwIDV4VKvOWycERgbl5pVeNtvdtHAstd7QtfhVADBXQ==", "dependencies": { - "@types/node": "*" + "@coinbase/wallet-sdk": "4.2.3", + "@metamask/sdk": "0.30.1", + "@safe-global/safe-apps-provider": "0.18.4", + "@safe-global/safe-apps-sdk": "9.1.0", + "@walletconnect/ethereum-provider": "2.17.0", + "cbw-sdk": "npm:@coinbase/wallet-sdk@3.9.3" + }, + "funding": { + "url": "https://github.com/sponsors/wevm" + }, + "peerDependencies": { + "@wagmi/core": "2.14.5", + "typescript": ">=5.0.4", + "viem": "2.x" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@types/methods": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@types/methods/-/methods-1.1.4.tgz", - "integrity": "sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==", - "dev": true - }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==" - }, - "node_modules/@types/ms": { - "version": "0.7.34", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", - "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" - }, - "node_modules/@types/mysql": { - "version": "2.15.26", - "resolved": "https://registry.npmjs.org/@types/mysql/-/mysql-2.15.26.tgz", - "integrity": "sha512-DSLCOXhkvfS5WNNPbfn2KdICAmk8lLc+/PNvnPnF7gOdMZCxopXduqv0OQ13y/yA/zXTSikZZqVgybUxOEg6YQ==", + "node_modules/@wagmi/core": { + "version": "2.14.5", + "resolved": "https://registry.npmjs.org/@wagmi/core/-/core-2.14.5.tgz", + "integrity": "sha512-tkeZYWtBiITQhvKspX4diEEs44rVu+d+dd2DAL5lAeTGS9d/Iu2VAT1G04frnVv49DUPS6zUu6PkCcUpSwS8Xw==", "dependencies": { - "@types/node": "*" + "eventemitter3": "5.0.1", + "mipd": "0.0.7", + "zustand": "5.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/wevm" + }, + "peerDependencies": { + "@tanstack/query-core": ">=5.0.0", + "typescript": ">=5.0.4", + "viem": "2.x" + }, + "peerDependenciesMeta": { + "@tanstack/query-core": { + "optional": true + }, + "typescript": { + "optional": true + } } }, - "node_modules/@types/nock": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/@types/nock/-/nock-11.1.0.tgz", - "integrity": "sha512-jI/ewavBQ7X5178262JQR0ewicPAcJhXS/iFaNJl0VHLfyosZ/kwSrsa6VNQNSO8i9d8SqdRgOtZSOKJ/+iNMw==", - "deprecated": "This is a stub types definition. nock provides its own type definitions, so you do not need this installed.", - "dev": true, + "node_modules/@wagmi/core/node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" + }, + "node_modules/@walletconnect/core": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/@walletconnect/core/-/core-2.17.0.tgz", + "integrity": "sha512-On+uSaCfWdsMIQsECwWHZBmUXfrnqmv6B8SXRRuTJgd8tUpEvBkLQH4X7XkSm3zW6ozEkQTCagZ2ox2YPn3kbw==", "dependencies": { - "nock": "*" + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-provider": "1.0.14", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/jsonrpc-ws-connection": "1.0.14", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "2.1.2", + "@walletconnect/relay-api": "1.0.11", + "@walletconnect/relay-auth": "1.0.4", + "@walletconnect/safe-json": "1.0.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.17.0", + "@walletconnect/utils": "2.17.0", + "events": "3.3.0", + "lodash.isequal": "4.5.0", + "uint8arrays": "3.1.0" + }, + "engines": { + "node": ">=18" } }, - "node_modules/@types/node": { - "version": "18.16.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.9.tgz", - "integrity": "sha512-IeB32oIV4oGArLrd7znD2rkHQ6EDCM+2Sr76dJnrHwv9OHBTTM6nuDLK9bmikXzPa0ZlWMWtRGo/Uw4mrzQedA==" - }, - "node_modules/@types/node-forge": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", - "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "node_modules/@walletconnect/environment": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@walletconnect/environment/-/environment-1.0.1.tgz", + "integrity": "sha512-T426LLZtHj8e8rYnKfzsw1aG6+M0BT1ZxayMdv/p8yM0MU+eJDISqNY3/bccxRr4LrF9csq02Rhqt08Ibl0VRg==", "dependencies": { - "@types/node": "*" + "tslib": "1.14.1" } }, - "node_modules/@types/parse-json": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", - "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" + "node_modules/@walletconnect/environment/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, - "node_modules/@types/pg": { - "version": "8.6.1", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.6.1.tgz", - "integrity": "sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w==", + "node_modules/@walletconnect/ethereum-provider": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/@walletconnect/ethereum-provider/-/ethereum-provider-2.17.0.tgz", + "integrity": "sha512-b+KTAXOb6JjoxkwpgYQQKPUcTwENGmdEdZoIDLeRicUmZTn/IQKfkMoC2frClB4YxkyoVMtj1oMV2JAax+yu9A==", "dependencies": { - "@types/node": "*", - "pg-protocol": "*", - "pg-types": "^2.2.0" + "@walletconnect/jsonrpc-http-connection": "1.0.8", + "@walletconnect/jsonrpc-provider": "1.0.14", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/modal": "2.7.0", + "@walletconnect/sign-client": "2.17.0", + "@walletconnect/types": "2.17.0", + "@walletconnect/universal-provider": "2.17.0", + "@walletconnect/utils": "2.17.0", + "events": "3.3.0" } }, - "node_modules/@types/pg-pool": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/pg-pool/-/pg-pool-2.0.6.tgz", - "integrity": "sha512-TaAUE5rq2VQYxab5Ts7WZhKNmuN78Q6PiFonTDdpbx8a1H0M1vhy3rhiMjl+e2iHmogyMw7jZF4FrE6eJUy5HQ==", + "node_modules/@walletconnect/events": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@walletconnect/events/-/events-1.0.1.tgz", + "integrity": "sha512-NPTqaoi0oPBVNuLv7qPaJazmGHs5JGyO8eEAk5VGKmJzDR7AHzD4k6ilox5kxk1iwiOnFopBOOMLs86Oa76HpQ==", "dependencies": { - "@types/pg": "*" + "keyvaluestorage-interface": "^1.0.0", + "tslib": "1.14.1" } }, - "node_modules/@types/prismjs": { - "version": "1.26.4", - "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.4.tgz", - "integrity": "sha512-rlAnzkW2sZOjbqZ743IHUhFcvzaGbqijwOu8QZnZCjfQzBqFE3s4lOTJEsxikImav9uzz/42I+O7YUs1mWgMlg==" - }, - "node_modules/@types/prop-types": { - "version": "15.7.12", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", - "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==" - }, - "node_modules/@types/qs": { - "version": "6.9.15", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", - "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==" - }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==" + "node_modules/@walletconnect/events/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, - "node_modules/@types/react": { - "version": "18.2.62", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.62.tgz", - "integrity": "sha512-l3f57BbaEKP0xcFzf+5qRG8/PXykZiuVM6eEoPtqBPCp6dxO3HhDkLIgIyXPhPKNAeXn3KO2pEaNgzaEo/asaw==", + "node_modules/@walletconnect/heartbeat": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@walletconnect/heartbeat/-/heartbeat-1.2.2.tgz", + "integrity": "sha512-uASiRmC5MwhuRuf05vq4AT48Pq8RMi876zV8rr8cV969uTOzWdB/k+Lj5yI2PBtB1bGQisGen7MM1GcZlQTBXw==", "dependencies": { - "@types/prop-types": "*", - "@types/scheduler": "*", - "csstype": "^3.0.2" + "@walletconnect/events": "^1.0.1", + "@walletconnect/time": "^1.0.2", + "events": "^3.3.0" } }, - "node_modules/@types/react-dom": { - "version": "18.2.14", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.14.tgz", - "integrity": "sha512-V835xgdSVmyQmI1KLV2BEIUgqEuinxp9O4G6g3FqO/SqLac049E53aysv0oEFD2kHfejeKU+ZqL2bcFWj9gLAQ==", - "devOptional": true, + "node_modules/@walletconnect/jsonrpc-http-connection": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-http-connection/-/jsonrpc-http-connection-1.0.8.tgz", + "integrity": "sha512-+B7cRuaxijLeFDJUq5hAzNyef3e3tBDIxyaCNmFtjwnod5AGis3RToNqzFU33vpVcxFhofkpE7Cx+5MYejbMGw==", "dependencies": { - "@types/react": "*" + "@walletconnect/jsonrpc-utils": "^1.0.6", + "@walletconnect/safe-json": "^1.0.1", + "cross-fetch": "^3.1.4", + "events": "^3.3.0" } }, - "node_modules/@types/react-router": { - "version": "5.1.20", - "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz", - "integrity": "sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==", + "node_modules/@walletconnect/jsonrpc-http-connection/node_modules/cross-fetch": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz", + "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==", "dependencies": { - "@types/history": "^4.7.11", - "@types/react": "*" + "node-fetch": "^2.6.12" } }, - "node_modules/@types/react-router-config": { - "version": "5.0.11", - "resolved": "https://registry.npmjs.org/@types/react-router-config/-/react-router-config-5.0.11.tgz", - "integrity": "sha512-WmSAg7WgqW7m4x8Mt4N6ZyKz0BubSj/2tVUMsAHp+Yd2AMwcSbeFq9WympT19p5heCFmF97R9eD5uUR/t4HEqw==", + "node_modules/@walletconnect/jsonrpc-provider": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-provider/-/jsonrpc-provider-1.0.14.tgz", + "integrity": "sha512-rtsNY1XqHvWj0EtITNeuf8PHMvlCLiS3EjQL+WOkxEOA4KPxsohFnBDeyPYiNm4ZvkQdLnece36opYidmtbmow==", "dependencies": { - "@types/history": "^4.7.11", - "@types/react": "*", - "@types/react-router": "^5.1.0" + "@walletconnect/jsonrpc-utils": "^1.0.8", + "@walletconnect/safe-json": "^1.0.2", + "events": "^3.3.0" } }, - "node_modules/@types/react-router-dom": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz", - "integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==", + "node_modules/@walletconnect/jsonrpc-types": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-types/-/jsonrpc-types-1.0.4.tgz", + "integrity": "sha512-P6679fG/M+wuWg9TY8mh6xFSdYnFyFjwFelxyISxMDrlbXokorEVXYOxiqEbrU3x1BmBoCAJJ+vtEaEoMlpCBQ==", "dependencies": { - "@types/history": "^4.7.11", - "@types/react": "*", - "@types/react-router": "*" + "events": "^3.3.0", + "keyvaluestorage-interface": "^1.0.0" } }, - "node_modules/@types/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" - }, - "node_modules/@types/sax": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.7.tgz", - "integrity": "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==", + "node_modules/@walletconnect/jsonrpc-utils": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-utils/-/jsonrpc-utils-1.0.8.tgz", + "integrity": "sha512-vdeb03bD8VzJUL6ZtzRYsFMq1eZQcM3EAzT0a3st59dyLfJ0wq+tKMpmGH7HlB7waD858UWgfIcudbPFsbzVdw==", "dependencies": { - "@types/node": "*" + "@walletconnect/environment": "^1.0.1", + "@walletconnect/jsonrpc-types": "^1.0.3", + "tslib": "1.14.1" } }, - "node_modules/@types/scheduler": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.23.0.tgz", - "integrity": "sha512-YIoDCTH3Af6XM5VuwGG/QL/CJqga1Zm3NkU3HZ4ZHK2fRMPYP1VczsTUqtsf43PH/iJNVlPHAo2oWX7BSdB2Hw==" + "node_modules/@walletconnect/jsonrpc-utils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, - "node_modules/@types/send": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", - "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "node_modules/@walletconnect/jsonrpc-ws-connection": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-ws-connection/-/jsonrpc-ws-connection-1.0.14.tgz", + "integrity": "sha512-Jsl6fC55AYcbkNVkwNM6Jo+ufsuCQRqViOQ8ZBPH9pRREHH9welbBiszuTLqEJiQcO/6XfFDl6bzCJIkrEi8XA==", "dependencies": { - "@types/mime": "^1", - "@types/node": "*" + "@walletconnect/jsonrpc-utils": "^1.0.6", + "@walletconnect/safe-json": "^1.0.2", + "events": "^3.3.0", + "ws": "^7.5.1" } }, - "node_modules/@types/serve-index": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", - "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", - "dependencies": { - "@types/express": "*" + "node_modules/@walletconnect/jsonrpc-ws-connection/node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, - "node_modules/@types/serve-static": { - "version": "1.15.7", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", - "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "node_modules/@walletconnect/keyvaluestorage": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@walletconnect/keyvaluestorage/-/keyvaluestorage-1.1.1.tgz", + "integrity": "sha512-V7ZQq2+mSxAq7MrRqDxanTzu2RcElfK1PfNYiaVnJgJ7Q7G7hTVwF8voIBx92qsRyGHZihrwNPHuZd1aKkd0rA==", "dependencies": { - "@types/http-errors": "*", - "@types/node": "*", - "@types/send": "*" + "@walletconnect/safe-json": "^1.0.1", + "idb-keyval": "^6.2.1", + "unstorage": "^1.9.0" + }, + "peerDependencies": { + "@react-native-async-storage/async-storage": "1.x" + }, + "peerDependenciesMeta": { + "@react-native-async-storage/async-storage": { + "optional": true + } } }, - "node_modules/@types/shimmer": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.2.0.tgz", - "integrity": "sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==" - }, - "node_modules/@types/sockjs": { - "version": "0.3.36", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", - "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", + "node_modules/@walletconnect/logger": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@walletconnect/logger/-/logger-2.1.2.tgz", + "integrity": "sha512-aAb28I3S6pYXZHQm5ESB+V6rDqIYfsnHaQyzFbwUUBFY4H0OXx/YtTl8lvhUNhMMfb9UxbwEBS253TlXUYJWSw==", "dependencies": { - "@types/node": "*" + "@walletconnect/safe-json": "^1.0.2", + "pino": "7.11.0" } }, - "node_modules/@types/stack-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", - "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==" - }, - "node_modules/@types/statuses": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.5.tgz", - "integrity": "sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/superagent": { - "version": "8.1.7", - "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.7.tgz", - "integrity": "sha512-NmIsd0Yj4DDhftfWvvAku482PZum4DBW7U51OvS8gvOkDDY0WT1jsVyDV3hK+vplrsYw8oDwi9QxOM7U68iwww==", - "dev": true, + "node_modules/@walletconnect/modal": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@walletconnect/modal/-/modal-2.7.0.tgz", + "integrity": "sha512-RQVt58oJ+rwqnPcIvRFeMGKuXb9qkgSmwz4noF8JZGUym3gUAzVs+uW2NQ1Owm9XOJAV+sANrtJ+VoVq1ftElw==", "dependencies": { - "@types/cookiejar": "^2.1.5", - "@types/methods": "^1.1.4", - "@types/node": "*" + "@walletconnect/modal-core": "2.7.0", + "@walletconnect/modal-ui": "2.7.0" } }, - "node_modules/@types/supertest": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-6.0.2.tgz", - "integrity": "sha512-137ypx2lk/wTQbW6An6safu9hXmajAifU/s7szAHLN/FeIm5w7yR0Wkl9fdJMRSHwOn4HLAI0DaB2TOORuhPDg==", - "dev": true, + "node_modules/@walletconnect/modal-core": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@walletconnect/modal-core/-/modal-core-2.7.0.tgz", + "integrity": "sha512-oyMIfdlNdpyKF2kTJowTixZSo0PGlCJRdssUN/EZdA6H6v03hZnf09JnwpljZNfir2M65Dvjm/15nGrDQnlxSA==", "dependencies": { - "@types/methods": "^1.1.4", - "@types/superagent": "^8.1.0" + "valtio": "1.11.2" } }, - "node_modules/@types/tedious": { - "version": "4.0.14", - "resolved": "https://registry.npmjs.org/@types/tedious/-/tedious-4.0.14.tgz", - "integrity": "sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==", + "node_modules/@walletconnect/modal-ui": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@walletconnect/modal-ui/-/modal-ui-2.7.0.tgz", + "integrity": "sha512-gERYvU7D7K1ANCN/8vUgsE0d2hnRemfAFZ2novm9aZBg7TEd/4EgB+AqbJ+1dc7GhOL6dazckVq78TgccHb7mQ==", "dependencies": { - "@types/node": "*" + "@walletconnect/modal-core": "2.7.0", + "lit": "2.8.0", + "motion": "10.16.2", + "qrcode": "1.5.3" } }, - "node_modules/@types/tough-cookie": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", - "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", - "dev": true - }, - "node_modules/@types/traverse": { - "version": "0.6.37", - "resolved": "https://registry.npmjs.org/@types/traverse/-/traverse-0.6.37.tgz", - "integrity": "sha512-c90MVeDiUI1FhOZ6rLQ3kDWr50YE8+paDpM+5zbHjbmsqEp2DlMYkqnZnwbK9oI+NvDe8yRajup4jFwnVX6xsA==", - "dev": true - }, - "node_modules/@types/triple-beam": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", - "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==" + "node_modules/@walletconnect/relay-api": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@walletconnect/relay-api/-/relay-api-1.0.11.tgz", + "integrity": "sha512-tLPErkze/HmC9aCmdZOhtVmYZq1wKfWTJtygQHoWtgg722Jd4homo54Cs4ak2RUFUZIGO2RsOpIcWipaua5D5Q==", + "dependencies": { + "@walletconnect/jsonrpc-types": "^1.0.2" + } }, - "node_modules/@types/trusted-types": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", - "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==" + "node_modules/@walletconnect/relay-auth": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@walletconnect/relay-auth/-/relay-auth-1.0.4.tgz", + "integrity": "sha512-kKJcS6+WxYq5kshpPaxGHdwf5y98ZwbfuS4EE/NkQzqrDFm5Cj+dP8LofzWvjrrLkZq7Afy7WrQMXdLy8Sx7HQ==", + "dependencies": { + "@stablelib/ed25519": "^1.0.2", + "@stablelib/random": "^1.0.1", + "@walletconnect/safe-json": "^1.0.1", + "@walletconnect/time": "^1.0.2", + "tslib": "1.14.1", + "uint8arrays": "^3.0.0" + } }, - "node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + "node_modules/@walletconnect/relay-auth/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, - "node_modules/@types/uuid": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.7.tgz", - "integrity": "sha512-WUtIVRUZ9i5dYXefDEAI7sh9/O7jGvHg7Df/5O/gtH3Yabe5odI3UWopVR1qbPXQtvOxWu3mM4XxlYeZtMWF4g==", - "dev": true + "node_modules/@walletconnect/safe-json": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@walletconnect/safe-json/-/safe-json-1.0.2.tgz", + "integrity": "sha512-Ogb7I27kZ3LPC3ibn8ldyUr5544t3/STow9+lzz7Sfo808YD7SBWk7SAsdBFlYgP2zDRy2hS3sKRcuSRM0OTmA==", + "dependencies": { + "tslib": "1.14.1" + } }, - "node_modules/@types/validator": { - "version": "13.12.0", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.12.0.tgz", - "integrity": "sha512-nH45Lk7oPIJ1RVOF6JgFI6Dy0QpHEzq4QecZhvguxYPDwT8c93prCMqAtiIttm39voZ+DDR+qkNnMpJmMBRqag==" + "node_modules/@walletconnect/safe-json/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, - "node_modules/@types/ws": { - "version": "8.5.10", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", - "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", + "node_modules/@walletconnect/sign-client": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/@walletconnect/sign-client/-/sign-client-2.17.0.tgz", + "integrity": "sha512-sErYwvSSHQolNXni47L3Bm10ptJc1s1YoJvJd34s5E9h9+d3rj7PrhbiW9X82deN+Dm5oA8X9tC4xty1yIBrVg==", "dependencies": { - "@types/node": "*" + "@walletconnect/core": "2.17.0", + "@walletconnect/events": "1.0.1", + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/logger": "2.1.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.17.0", + "@walletconnect/utils": "2.17.0", + "events": "3.3.0" } }, - "node_modules/@types/yargs": { - "version": "17.0.32", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", - "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", + "node_modules/@walletconnect/time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@walletconnect/time/-/time-1.0.2.tgz", + "integrity": "sha512-uzdd9woDcJ1AaBZRhqy5rNC9laqWGErfc4dxA9a87mPdKOgWMD85mcFo9dIYIts/Jwocfwn07EC6EzclKubk/g==", "dependencies": { - "@types/yargs-parser": "*" + "tslib": "1.14.1" } }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", - "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==" + "node_modules/@walletconnect/time/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.0.tgz", - "integrity": "sha512-py1miT6iQpJcs1BiJjm54AMzeuMPBSPuKPlnT8HlfudbcS5rYeX5jajpLf3mrdRh9dA/Ec2FVUY0ifeVNDIhZw==", - "dev": true, + "node_modules/@walletconnect/types": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/@walletconnect/types/-/types-2.17.0.tgz", + "integrity": "sha512-i1pn9URpvt9bcjRDkabuAmpA9K7mzyKoLJlbsAujRVX7pfaG7wur7u9Jz0bk1HxvuABL5LHNncTnVKSXKQ5jZA==", "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/type-utils": "7.16.0", - "@typescript-eslint/utils": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "@walletconnect/events": "1.0.1", + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "2.1.2", + "events": "3.3.0" } }, - "node_modules/@typescript-eslint/parser": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.9.0.tgz", - "integrity": "sha512-qHMJfkL5qvgQB2aLvhUSXxbK7OLnDkwPzFalg458pxQgfxKDfT1ZDbHQM/I6mDIf/svlMkj21kzKuQ2ixJlatQ==", - "dev": true, + "node_modules/@walletconnect/universal-provider": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/@walletconnect/universal-provider/-/universal-provider-2.17.0.tgz", + "integrity": "sha512-d3V5Be7AqLrvzcdMZSBS8DmGDRdqnyLk1DWmRKAGgR6ieUWykhhUKlvfeoZtvJrIXrY7rUGYpH1X41UtFkW5Pw==", "dependencies": { - "@typescript-eslint/scope-manager": "7.9.0", - "@typescript-eslint/types": "7.9.0", - "@typescript-eslint/typescript-estree": "7.9.0", - "@typescript-eslint/visitor-keys": "7.9.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "@walletconnect/jsonrpc-http-connection": "1.0.8", + "@walletconnect/jsonrpc-provider": "1.0.14", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/logger": "2.1.2", + "@walletconnect/sign-client": "2.17.0", + "@walletconnect/types": "2.17.0", + "@walletconnect/utils": "2.17.0", + "events": "3.3.0" } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.9.0.tgz", - "integrity": "sha512-ZwPK4DeCDxr3GJltRz5iZejPFAAr4Wk3+2WIBaj1L5PYK5RgxExu/Y68FFVclN0y6GGwH8q+KgKRCvaTmFBbgQ==", - "dev": true, + "node_modules/@walletconnect/utils": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/@walletconnect/utils/-/utils-2.17.0.tgz", + "integrity": "sha512-1aeQvjwsXy4Yh9G6g2eGmXrEl+BzkNjHRdCrGdMYqFTFa8ROEJfTGsSH3pLsNDlOY94CoBUvJvM55q/PMoN/FQ==", "dependencies": { - "@typescript-eslint/types": "7.9.0", - "@typescript-eslint/visitor-keys": "7.9.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "@stablelib/chacha20poly1305": "1.0.1", + "@stablelib/hkdf": "1.0.1", + "@stablelib/random": "1.0.2", + "@stablelib/sha256": "1.0.1", + "@stablelib/x25519": "1.0.3", + "@walletconnect/relay-api": "1.0.11", + "@walletconnect/relay-auth": "1.0.4", + "@walletconnect/safe-json": "1.0.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.17.0", + "@walletconnect/window-getters": "1.0.1", + "@walletconnect/window-metadata": "1.0.1", + "detect-browser": "5.3.0", + "elliptic": "^6.5.7", + "query-string": "7.1.3", + "uint8arrays": "3.1.0" } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.9.0.tgz", - "integrity": "sha512-iESPx2TNLDNGQLyjKhUvIKprlP49XNEK+MvIf9nIO7ZZaZdbnfWKHnXAgufpxqfA0YryH8XToi4+CjBgVnFTSQ==", - "dev": true, + "node_modules/@walletconnect/window-getters": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@walletconnect/window-getters/-/window-getters-1.0.1.tgz", + "integrity": "sha512-vHp+HqzGxORPAN8gY03qnbTMnhqIwjeRJNOMOAzePRg4xVEEE2WvYsI9G2NMjOknA8hnuYbU3/hwLcKbjhc8+Q==", "dependencies": { - "@typescript-eslint/types": "7.9.0", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "tslib": "1.14.1" } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.16.0.tgz", - "integrity": "sha512-8gVv3kW6n01Q6TrI1cmTZ9YMFi3ucDT7i7aI5lEikk2ebk1AEjrwX8MDTdaX5D7fPXMBLvnsaa0IFTAu+jcfOw==", - "dev": true, + "node_modules/@walletconnect/window-getters/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@walletconnect/window-metadata": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@walletconnect/window-metadata/-/window-metadata-1.0.1.tgz", + "integrity": "sha512-9koTqyGrM2cqFRW517BPY/iEtUDx2r1+Pwwu5m7sJ7ka79wi3EyqhqcICk/yDmv6jAS1rjKgTKXlEhanYjijcA==", "dependencies": { - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "@walletconnect/window-getters": "^1.0.1", + "tslib": "1.14.1" } }, - "node_modules/@typescript-eslint/scope-manager/node_modules/@typescript-eslint/types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", - "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", - "dev": true, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node_modules/@walletconnect/window-metadata/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@wasmer/wasi": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@wasmer/wasi/-/wasi-1.2.2.tgz", + "integrity": "sha512-39ZB3gefOVhBmkhf7Ta79RRSV/emIV8LhdvcWhP/MOZEjMmtzoZWMzt7phdKj8CUXOze+AwbvGK60lKaKldn1w==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", + "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" } }, - "node_modules/@typescript-eslint/type-utils": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.0.tgz", - "integrity": "sha512-j0fuUswUjDHfqV/UdW6mLtOQQseORqfdmoBNDFOqs9rvNVR2e+cmu6zJu/Ku4SDuqiJko6YnhwcL8x45r8Oqxg==", - "dev": true, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==" + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", "dependencies": { - "@typescript-eslint/typescript-estree": "7.16.0", - "@typescript-eslint/utils": "7.16.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", - "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", - "dev": true, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", + "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.12.1" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.0.tgz", - "integrity": "sha512-a5NTvk51ZndFuOLCh5OaJBELYc2O3Zqxfl3Js78VFE1zE46J2AaVuW+rEbVkQznjkmlzWsUI15BG5tQMixzZLw==", - "dev": true, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", "dependencies": { - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "@xtuc/ieee754": "^1.2.0" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "@xtuc/long": "4.2.2" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", + "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-opt": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1", + "@webassemblyjs/wast-printer": "1.12.1" } }, - "node_modules/@typescript-eslint/types": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.9.0.tgz", - "integrity": "sha512-oZQD9HEWQanl9UfsbGVcZ2cGaR0YT5476xfWE0oE5kQa2sNK2frxOlkeacLOTh9po4AlUT5rtkGyYM5kew0z5w==", - "dev": true, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", + "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.9.0.tgz", - "integrity": "sha512-zBCMCkrb2YjpKV3LA0ZJubtKCDxLttxfdGmwZvTqqWevUPN0FZvSI26FalGFFUZU/9YQK/A4xcQF9o/VVaCKAg==", - "dev": true, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", + "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", "dependencies": { - "@typescript-eslint/types": "7.9.0", - "@typescript-eslint/visitor-keys": "7.9.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.9.0.tgz", - "integrity": "sha512-iESPx2TNLDNGQLyjKhUvIKprlP49XNEK+MvIf9nIO7ZZaZdbnfWKHnXAgufpxqfA0YryH8XToi4+CjBgVnFTSQ==", - "dev": true, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", + "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", "dependencies": { - "@typescript-eslint/types": "7.9.0", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", + "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "@webassemblyjs/ast": "1.12.1", + "@xtuc/long": "4.2.2" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, + "node_modules/@xmldom/xmldom": { + "version": "0.7.13", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.13.tgz", + "integrity": "sha512-lm2GW5PkosIzccsaZIz7tp8cPADSIlIHWDFTR1N0SzfinhhYgeIQjFMz4rYzanCScr3DqQLeomUDArp6MWKm+g==", + "deprecated": "this version is no longer supported, please update to at least 0.8.*", + "license": "MIT", + "peer": true, "engines": { - "node": ">=10" + "node": ">=10.0.0" } }, - "node_modules/@typescript-eslint/utils": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz", - "integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==", - "dev": true, + "node_modules/@xrplf/isomorphic": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@xrplf/isomorphic/-/isomorphic-1.0.1.tgz", + "integrity": "sha512-0bIpgx8PDjYdrLFeC3csF305QQ1L7sxaWnL5y71mCvhenZzJgku9QsA+9QCXBC1eNYtxWO/xR91zrXJy2T/ixg==", + "license": "ISC", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/typescript-estree": "7.16.0" + "@noble/hashes": "^1.0.0", + "eventemitter3": "5.0.1", + "ws": "^8.13.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" + "node": ">=16.0.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", - "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", - "dev": true, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } + "node_modules/@xrplf/isomorphic/node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.0.tgz", - "integrity": "sha512-a5NTvk51ZndFuOLCh5OaJBELYc2O3Zqxfl3Js78VFE1zE46J2AaVuW+rEbVkQznjkmlzWsUI15BG5tQMixzZLw==", - "dev": true, + "node_modules/@xrplf/secret-numbers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@xrplf/secret-numbers/-/secret-numbers-1.0.0.tgz", + "integrity": "sha512-qsCLGyqe1zaq9j7PZJopK+iGTGRbk6akkg6iZXJJgxKwck0C5x5Gnwlb1HKYGOwPKyrXWpV6a2YmcpNpUFctGg==", + "license": "ISC", "dependencies": { - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "@xrplf/isomorphic": "^1.0.0", + "ripple-keypairs": "^2.0.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + }, + "node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true + }, + "node_modules/@yarnpkg/parsers": { + "version": "3.0.0-rc.46", + "resolved": "https://registry.npmjs.org/@yarnpkg/parsers/-/parsers-3.0.0-rc.46.tgz", + "integrity": "sha512-aiATs7pSutzda/rq8fnuPwTglyVwjM22bNnK2ZgjrpAjQHSSl3lztd2f9evst1W/qnC58DRz7T7QndUDumAR4Q==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "js-yaml": "^3.10.0", + "tslib": "^2.4.0" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=14.15.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "node_modules/@yarnpkg/parsers/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "dependencies": { + "sprintf-js": "~1.0.2" } }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.0.tgz", - "integrity": "sha512-rMo01uPy9C7XxG7AFsxa8zLnWXTF8N3PYclekWSrurvhwiw1eW88mrKiAYe6s53AUY57nTRz8dJsuuXdkAhzCg==", + "node_modules/@yarnpkg/parsers/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.16.0", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" + "argparse": "^1.0.7", + "esprima": "^4.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@typescript-eslint/visitor-keys/node_modules/@typescript-eslint/types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", - "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", + "node_modules/@yarnpkg/parsers/node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/@zkochan/js-yaml": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.7.tgz", + "integrity": "sha512-nrUSn7hzt7J6JWgWGz78ZYI8wj+gdIJdk0Ynjpp8l+trkn58Uqsf6RYrYkEK+3X18EX+TNdtJI0WxAtc+L84SQ==", "dev": true, - "engines": { - "node": "^18.18.0 || >=20.0.0" + "dependencies": { + "argparse": "^2.0.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" + "node_modules/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "deprecated": "Use your platform's native atob() and btoa() methods instead", + "dev": true }, - "node_modules/@wagmi/connectors": { - "version": "5.3.9", - "resolved": "https://registry.npmjs.org/@wagmi/connectors/-/connectors-5.3.9.tgz", - "integrity": "sha512-TS1nJRfQbwPpeW28fPWkanuMuUJSoAAS0+zEthStq/PmwIDV4VKvOWycERgbl5pVeNtvdtHAstd7QtfhVADBXQ==", - "dependencies": { - "@coinbase/wallet-sdk": "4.2.3", - "@metamask/sdk": "0.30.1", - "@safe-global/safe-apps-provider": "0.18.4", - "@safe-global/safe-apps-sdk": "9.1.0", - "@walletconnect/ethereum-provider": "2.17.0", - "cbw-sdk": "npm:@coinbase/wallet-sdk@3.9.3" - }, + "node_modules/abitype": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.4.tgz", + "integrity": "sha512-UivtYZOGJGE8rsrM/N5vdRkUpqEZVmuTumfTuolm7m/6O09wprd958rx8kUBwVAAAhQDveGAgD0GJdBuR8s6tw==", "funding": { "url": "https://github.com/sponsors/wevm" }, "peerDependencies": { - "@wagmi/core": "2.14.5", "typescript": ">=5.0.4", - "viem": "2.x" + "zod": "^3 >=3.22.0" }, "peerDependenciesMeta": { "typescript": { "optional": true - } - } - }, - "node_modules/@wagmi/core": { - "version": "2.14.5", - "resolved": "https://registry.npmjs.org/@wagmi/core/-/core-2.14.5.tgz", - "integrity": "sha512-tkeZYWtBiITQhvKspX4diEEs44rVu+d+dd2DAL5lAeTGS9d/Iu2VAT1G04frnVv49DUPS6zUu6PkCcUpSwS8Xw==", - "dependencies": { - "eventemitter3": "5.0.1", - "mipd": "0.0.7", - "zustand": "5.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/wevm" - }, - "peerDependencies": { - "@tanstack/query-core": ">=5.0.0", - "typescript": ">=5.0.4", - "viem": "2.x" - }, - "peerDependenciesMeta": { - "@tanstack/query-core": { - "optional": true }, - "typescript": { + "zod": { "optional": true } } }, - "node_modules/@wagmi/core/node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" - }, - "node_modules/@walletconnect/core": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/@walletconnect/core/-/core-2.17.0.tgz", - "integrity": "sha512-On+uSaCfWdsMIQsECwWHZBmUXfrnqmv6B8SXRRuTJgd8tUpEvBkLQH4X7XkSm3zW6ozEkQTCagZ2ox2YPn3kbw==", + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", "dependencies": { - "@walletconnect/heartbeat": "1.2.2", - "@walletconnect/jsonrpc-provider": "1.0.14", - "@walletconnect/jsonrpc-types": "1.0.4", - "@walletconnect/jsonrpc-utils": "1.0.8", - "@walletconnect/jsonrpc-ws-connection": "1.0.14", - "@walletconnect/keyvaluestorage": "1.1.1", - "@walletconnect/logger": "2.1.2", - "@walletconnect/relay-api": "1.0.11", - "@walletconnect/relay-auth": "1.0.4", - "@walletconnect/safe-json": "1.0.2", - "@walletconnect/time": "1.0.2", - "@walletconnect/types": "2.17.0", - "@walletconnect/utils": "2.17.0", - "events": "3.3.0", - "lodash.isequal": "4.5.0", - "uint8arrays": "3.1.0" + "event-target-shim": "^5.0.0" }, "engines": { - "node": ">=18" + "node": ">=6.5" } }, - "node_modules/@walletconnect/environment": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@walletconnect/environment/-/environment-1.0.1.tgz", - "integrity": "sha512-T426LLZtHj8e8rYnKfzsw1aG6+M0BT1ZxayMdv/p8yM0MU+eJDISqNY3/bccxRr4LrF9csq02Rhqt08Ibl0VRg==", + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "dependencies": { - "tslib": "1.14.1" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" } }, - "node_modules/@walletconnect/environment/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "node_modules/acorn": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } }, - "node_modules/@walletconnect/ethereum-provider": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/@walletconnect/ethereum-provider/-/ethereum-provider-2.17.0.tgz", - "integrity": "sha512-b+KTAXOb6JjoxkwpgYQQKPUcTwENGmdEdZoIDLeRicUmZTn/IQKfkMoC2frClB4YxkyoVMtj1oMV2JAax+yu9A==", + "node_modules/acorn-globals": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", + "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", + "dev": true, "dependencies": { - "@walletconnect/jsonrpc-http-connection": "1.0.8", - "@walletconnect/jsonrpc-provider": "1.0.14", - "@walletconnect/jsonrpc-types": "1.0.4", - "@walletconnect/jsonrpc-utils": "1.0.8", - "@walletconnect/modal": "2.7.0", - "@walletconnect/sign-client": "2.17.0", - "@walletconnect/types": "2.17.0", - "@walletconnect/universal-provider": "2.17.0", - "@walletconnect/utils": "2.17.0", - "events": "3.3.0" + "acorn": "^8.1.0", + "acorn-walk": "^8.0.2" } }, - "node_modules/@walletconnect/events": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@walletconnect/events/-/events-1.0.1.tgz", - "integrity": "sha512-NPTqaoi0oPBVNuLv7qPaJazmGHs5JGyO8eEAk5VGKmJzDR7AHzD4k6ilox5kxk1iwiOnFopBOOMLs86Oa76HpQ==", - "dependencies": { - "keyvaluestorage-interface": "^1.0.0", - "tslib": "1.14.1" + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "peerDependencies": { + "acorn": "^8" } }, - "node_modules/@walletconnect/events/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } }, - "node_modules/@walletconnect/heartbeat": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@walletconnect/heartbeat/-/heartbeat-1.2.2.tgz", - "integrity": "sha512-uASiRmC5MwhuRuf05vq4AT48Pq8RMi876zV8rr8cV969uTOzWdB/k+Lj5yI2PBtB1bGQisGen7MM1GcZlQTBXw==", + "node_modules/acorn-walk": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", + "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", "dependencies": { - "@walletconnect/events": "^1.0.1", - "@walletconnect/time": "^1.0.2", - "events": "^3.3.0" + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" } }, - "node_modules/@walletconnect/jsonrpc-http-connection": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-http-connection/-/jsonrpc-http-connection-1.0.8.tgz", - "integrity": "sha512-+B7cRuaxijLeFDJUq5hAzNyef3e3tBDIxyaCNmFtjwnod5AGis3RToNqzFU33vpVcxFhofkpE7Cx+5MYejbMGw==", - "dependencies": { - "@walletconnect/jsonrpc-utils": "^1.0.6", - "@walletconnect/safe-json": "^1.0.1", - "cross-fetch": "^3.1.4", - "events": "^3.3.0" + "node_modules/address": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", + "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", + "engines": { + "node": ">= 10.0.0" } }, - "node_modules/@walletconnect/jsonrpc-http-connection/node_modules/cross-fetch": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz", - "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==", - "dependencies": { - "node-fetch": "^2.6.12" + "node_modules/adm-zip": { + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.15.tgz", + "integrity": "sha512-jYPWSeOA8EFoZnucrKCNihqBjoEGQSU4HKgHYQgKNEQ0pQF9a/DYuo/+fAxY76k4qe75LUlLWpAM1QWcBMTOKw==", + "dev": true, + "engines": { + "node": ">=12.0" } }, - "node_modules/@walletconnect/jsonrpc-provider": { - "version": "1.0.14", - "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-provider/-/jsonrpc-provider-1.0.14.tgz", - "integrity": "sha512-rtsNY1XqHvWj0EtITNeuf8PHMvlCLiS3EjQL+WOkxEOA4KPxsohFnBDeyPYiNm4ZvkQdLnece36opYidmtbmow==", - "dependencies": { - "@walletconnect/jsonrpc-utils": "^1.0.8", - "@walletconnect/safe-json": "^1.0.2", - "events": "^3.3.0" + "node_modules/aes-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", + "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==", + "license": "MIT" + }, + "node_modules/agent-base": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", + "engines": { + "node": ">= 14" } }, - "node_modules/@walletconnect/jsonrpc-types": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-types/-/jsonrpc-types-1.0.4.tgz", - "integrity": "sha512-P6679fG/M+wuWg9TY8mh6xFSdYnFyFjwFelxyISxMDrlbXokorEVXYOxiqEbrU3x1BmBoCAJJ+vtEaEoMlpCBQ==", + "node_modules/agentkeepalive": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", + "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", + "license": "MIT", "dependencies": { - "events": "^3.3.0", - "keyvaluestorage-interface": "^1.0.0" + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" } }, - "node_modules/@walletconnect/jsonrpc-utils": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-utils/-/jsonrpc-utils-1.0.8.tgz", - "integrity": "sha512-vdeb03bD8VzJUL6ZtzRYsFMq1eZQcM3EAzT0a3st59dyLfJ0wq+tKMpmGH7HlB7waD858UWgfIcudbPFsbzVdw==", + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "dependencies": { - "@walletconnect/environment": "^1.0.1", - "@walletconnect/jsonrpc-types": "^1.0.3", - "tslib": "1.14.1" + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@walletconnect/jsonrpc-utils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/@walletconnect/jsonrpc-ws-connection": { - "version": "1.0.14", - "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-ws-connection/-/jsonrpc-ws-connection-1.0.14.tgz", - "integrity": "sha512-Jsl6fC55AYcbkNVkwNM6Jo+ufsuCQRqViOQ8ZBPH9pRREHH9welbBiszuTLqEJiQcO/6XfFDl6bzCJIkrEi8XA==", + "node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "dependencies": { - "@walletconnect/jsonrpc-utils": "^1.0.6", - "@walletconnect/safe-json": "^1.0.2", - "events": "^3.3.0", - "ws": "^7.5.1" + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@walletconnect/jsonrpc-ws-connection/node_modules/ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "engines": { - "node": ">=8.3.0" + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dependencies": { + "ajv": "^8.0.0" }, "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "ajv": "^8.0.0" }, "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { + "ajv": { "optional": true } } }, - "node_modules/@walletconnect/keyvaluestorage": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@walletconnect/keyvaluestorage/-/keyvaluestorage-1.1.1.tgz", - "integrity": "sha512-V7ZQq2+mSxAq7MrRqDxanTzu2RcElfK1PfNYiaVnJgJ7Q7G7hTVwF8voIBx92qsRyGHZihrwNPHuZd1aKkd0rA==", + "node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "dependencies": { - "@walletconnect/safe-json": "^1.0.1", - "idb-keyval": "^6.2.1", - "unstorage": "^1.9.0" + "fast-deep-equal": "^3.1.3" }, "peerDependencies": { - "@react-native-async-storage/async-storage": "1.x" - }, - "peerDependenciesMeta": { - "@react-native-async-storage/async-storage": { - "optional": true - } + "ajv": "^8.8.2" } }, - "node_modules/@walletconnect/logger": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@walletconnect/logger/-/logger-2.1.2.tgz", - "integrity": "sha512-aAb28I3S6pYXZHQm5ESB+V6rDqIYfsnHaQyzFbwUUBFY4H0OXx/YtTl8lvhUNhMMfb9UxbwEBS253TlXUYJWSw==", - "dependencies": { - "@walletconnect/safe-json": "^1.0.2", - "pino": "7.11.0" + "node_modules/algo-msgpack-with-bigint": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/algo-msgpack-with-bigint/-/algo-msgpack-with-bigint-2.1.1.tgz", + "integrity": "sha512-F1tGh056XczEaEAqu7s+hlZUDWwOBT70Eq0lfMpBP2YguSQVyxRbprLq5rELXKQOyOaixTWYhMeMQMzP0U5FoQ==", + "license": "ISC", + "engines": { + "node": ">= 10" } }, - "node_modules/@walletconnect/modal": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@walletconnect/modal/-/modal-2.7.0.tgz", - "integrity": "sha512-RQVt58oJ+rwqnPcIvRFeMGKuXb9qkgSmwz4noF8JZGUym3gUAzVs+uW2NQ1Owm9XOJAV+sANrtJ+VoVq1ftElw==", + "node_modules/algoliasearch": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.24.0.tgz", + "integrity": "sha512-bf0QV/9jVejssFBmz2HQLxUadxk574t4iwjCKp5E7NBzwKkrDEhKPISIIjAU/p6K5qDx3qoeh4+26zWN1jmw3g==", "dependencies": { - "@walletconnect/modal-core": "2.7.0", - "@walletconnect/modal-ui": "2.7.0" + "@algolia/cache-browser-local-storage": "4.24.0", + "@algolia/cache-common": "4.24.0", + "@algolia/cache-in-memory": "4.24.0", + "@algolia/client-account": "4.24.0", + "@algolia/client-analytics": "4.24.0", + "@algolia/client-common": "4.24.0", + "@algolia/client-personalization": "4.24.0", + "@algolia/client-search": "4.24.0", + "@algolia/logger-common": "4.24.0", + "@algolia/logger-console": "4.24.0", + "@algolia/recommend": "4.24.0", + "@algolia/requester-browser-xhr": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/requester-node-http": "4.24.0", + "@algolia/transporter": "4.24.0" } }, - "node_modules/@walletconnect/modal-core": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@walletconnect/modal-core/-/modal-core-2.7.0.tgz", - "integrity": "sha512-oyMIfdlNdpyKF2kTJowTixZSo0PGlCJRdssUN/EZdA6H6v03hZnf09JnwpljZNfir2M65Dvjm/15nGrDQnlxSA==", + "node_modules/algoliasearch-helper": { + "version": "3.22.3", + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.22.3.tgz", + "integrity": "sha512-2eoEz8mG4KHE+DzfrBTrCmDPxVXv7aZZWPojAJFtARpxxMO6lkos1dJ+XDCXdPvq7q3tpYWRi6xXmVQikejtpA==", "dependencies": { - "valtio": "1.11.2" + "@algolia/events": "^4.0.1" + }, + "peerDependencies": { + "algoliasearch": ">= 3.1 < 6" } }, - "node_modules/@walletconnect/modal-ui": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@walletconnect/modal-ui/-/modal-ui-2.7.0.tgz", - "integrity": "sha512-gERYvU7D7K1ANCN/8vUgsE0d2hnRemfAFZ2novm9aZBg7TEd/4EgB+AqbJ+1dc7GhOL6dazckVq78TgccHb7mQ==", + "node_modules/algosdk": { + "version": "1.23.1", + "resolved": "https://registry.npmjs.org/algosdk/-/algosdk-1.23.1.tgz", + "integrity": "sha512-7fKyTd2V6rsac3ADm6N5jJV80cCw+EIBzXVLzfPvKqranjOZtq7xIqwpEkZgBkZ/TJ5wxwTDJVPyswXChv+QPg==", + "license": "MIT", "dependencies": { - "@walletconnect/modal-core": "2.7.0", - "lit": "2.8.0", - "motion": "10.16.2", - "qrcode": "1.5.3" + "algo-msgpack-with-bigint": "^2.1.1", + "buffer": "^6.0.2", + "cross-fetch": "^3.1.5", + "hi-base32": "^0.5.1", + "js-sha256": "^0.9.0", + "js-sha3": "^0.8.0", + "js-sha512": "^0.8.0", + "json-bigint": "^1.0.0", + "tweetnacl": "^1.0.3", + "vlq": "^2.0.4" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@walletconnect/relay-api": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@walletconnect/relay-api/-/relay-api-1.0.11.tgz", - "integrity": "sha512-tLPErkze/HmC9aCmdZOhtVmYZq1wKfWTJtygQHoWtgg722Jd4homo54Cs4ak2RUFUZIGO2RsOpIcWipaua5D5Q==", + "node_modules/algosdk/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", "dependencies": { - "@walletconnect/jsonrpc-types": "^1.0.2" + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" } }, - "node_modules/@walletconnect/relay-auth": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@walletconnect/relay-auth/-/relay-auth-1.0.4.tgz", - "integrity": "sha512-kKJcS6+WxYq5kshpPaxGHdwf5y98ZwbfuS4EE/NkQzqrDFm5Cj+dP8LofzWvjrrLkZq7Afy7WrQMXdLy8Sx7HQ==", + "node_modules/algosdk/node_modules/cross-fetch": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", + "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", + "license": "MIT", "dependencies": { - "@stablelib/ed25519": "^1.0.2", - "@stablelib/random": "^1.0.1", - "@walletconnect/safe-json": "^1.0.1", - "@walletconnect/time": "^1.0.2", - "tslib": "1.14.1", - "uint8arrays": "^3.0.0" + "node-fetch": "^2.7.0" } }, - "node_modules/@walletconnect/relay-auth/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "node_modules/algosdk/node_modules/vlq": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-2.0.4.tgz", + "integrity": "sha512-aodjPa2wPQFkra1G8CzJBTHXhgk3EVSwxSWXNPr1fgdFLUb8kvLV1iEb6rFgasIsjP82HWI6dsb5Io26DDnasA==", + "license": "MIT" }, - "node_modules/@walletconnect/safe-json": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@walletconnect/safe-json/-/safe-json-1.0.2.tgz", - "integrity": "sha512-Ogb7I27kZ3LPC3ibn8ldyUr5544t3/STow9+lzz7Sfo808YD7SBWk7SAsdBFlYgP2zDRy2hS3sKRcuSRM0OTmA==", + "node_modules/anser": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/anser/-/anser-1.4.10.tgz", + "integrity": "sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==", + "license": "MIT", + "peer": true + }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", "dependencies": { - "tslib": "1.14.1" + "string-width": "^4.1.0" } }, - "node_modules/@walletconnect/safe-json/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "node_modules/ansi-align/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, - "node_modules/@walletconnect/sign-client": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/@walletconnect/sign-client/-/sign-client-2.17.0.tgz", - "integrity": "sha512-sErYwvSSHQolNXni47L3Bm10ptJc1s1YoJvJd34s5E9h9+d3rj7PrhbiW9X82deN+Dm5oA8X9tC4xty1yIBrVg==", - "dependencies": { - "@walletconnect/core": "2.17.0", - "@walletconnect/events": "1.0.1", - "@walletconnect/heartbeat": "1.2.2", - "@walletconnect/jsonrpc-utils": "1.0.8", - "@walletconnect/logger": "2.1.2", - "@walletconnect/time": "1.0.2", - "@walletconnect/types": "2.17.0", - "@walletconnect/utils": "2.17.0", - "events": "3.3.0" + "node_modules/ansi-align/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" } }, - "node_modules/@walletconnect/time": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@walletconnect/time/-/time-1.0.2.tgz", - "integrity": "sha512-uzdd9woDcJ1AaBZRhqy5rNC9laqWGErfc4dxA9a87mPdKOgWMD85mcFo9dIYIts/Jwocfwn07EC6EzclKubk/g==", + "node_modules/ansi-align/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dependencies": { - "tslib": "1.14.1" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@walletconnect/time/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "engines": { + "node": ">=6" + } }, - "node_modules/@walletconnect/types": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/@walletconnect/types/-/types-2.17.0.tgz", - "integrity": "sha512-i1pn9URpvt9bcjRDkabuAmpA9K7mzyKoLJlbsAujRVX7pfaG7wur7u9Jz0bk1HxvuABL5LHNncTnVKSXKQ5jZA==", + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "devOptional": true, "dependencies": { - "@walletconnect/events": "1.0.1", - "@walletconnect/heartbeat": "1.2.2", - "@walletconnect/jsonrpc-types": "1.0.4", - "@walletconnect/keyvaluestorage": "1.1.1", - "@walletconnect/logger": "2.1.2", - "events": "3.3.0" + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@walletconnect/universal-provider": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/@walletconnect/universal-provider/-/universal-provider-2.17.0.tgz", - "integrity": "sha512-d3V5Be7AqLrvzcdMZSBS8DmGDRdqnyLk1DWmRKAGgR6ieUWykhhUKlvfeoZtvJrIXrY7rUGYpH1X41UtFkW5Pw==", - "dependencies": { - "@walletconnect/jsonrpc-http-connection": "1.0.8", - "@walletconnect/jsonrpc-provider": "1.0.14", - "@walletconnect/jsonrpc-types": "1.0.4", - "@walletconnect/jsonrpc-utils": "1.0.8", - "@walletconnect/logger": "2.1.2", - "@walletconnect/sign-client": "2.17.0", - "@walletconnect/types": "2.17.0", - "@walletconnect/utils": "2.17.0", - "events": "3.3.0" + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "devOptional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@walletconnect/utils": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/@walletconnect/utils/-/utils-2.17.0.tgz", - "integrity": "sha512-1aeQvjwsXy4Yh9G6g2eGmXrEl+BzkNjHRdCrGdMYqFTFa8ROEJfTGsSH3pLsNDlOY94CoBUvJvM55q/PMoN/FQ==", - "dependencies": { - "@stablelib/chacha20poly1305": "1.0.1", - "@stablelib/hkdf": "1.0.1", - "@stablelib/random": "1.0.2", - "@stablelib/sha256": "1.0.1", - "@stablelib/x25519": "1.0.3", - "@walletconnect/relay-api": "1.0.11", - "@walletconnect/relay-auth": "1.0.4", - "@walletconnect/safe-json": "1.0.2", - "@walletconnect/time": "1.0.2", - "@walletconnect/types": "2.17.0", - "@walletconnect/window-getters": "1.0.1", - "@walletconnect/window-metadata": "1.0.1", - "detect-browser": "5.3.0", - "elliptic": "^6.5.7", - "query-string": "7.1.3", - "uint8arrays": "3.1.0" + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" } }, - "node_modules/@walletconnect/window-getters": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@walletconnect/window-getters/-/window-getters-1.0.1.tgz", - "integrity": "sha512-vHp+HqzGxORPAN8gY03qnbTMnhqIwjeRJNOMOAzePRg4xVEEE2WvYsI9G2NMjOknA8hnuYbU3/hwLcKbjhc8+Q==", - "dependencies": { - "tslib": "1.14.1" + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" } }, - "node_modules/@walletconnect/window-getters/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } }, - "node_modules/@walletconnect/window-metadata": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@walletconnect/window-metadata/-/window-metadata-1.0.1.tgz", - "integrity": "sha512-9koTqyGrM2cqFRW517BPY/iEtUDx2r1+Pwwu5m7sJ7ka79wi3EyqhqcICk/yDmv6jAS1rjKgTKXlEhanYjijcA==", + "node_modules/ansi-styles/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dependencies": { - "@walletconnect/window-getters": "^1.0.1", - "tslib": "1.14.1" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/@walletconnect/window-metadata/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "node_modules/ansi-styles/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "node_modules/@webassemblyjs/ast": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", - "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" + "node_modules/application-config-path": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/application-config-path/-/application-config-path-0.1.1.tgz", + "integrity": "sha512-zy9cHePtMP0YhwG+CfHm0bgwdnga2X3gZexpdCwEj//dpb+TKajtiC8REEUJUSq6Ab4f9cgNy2l8ObXzCXFkEw==", + "license": "MIT", + "optional": true, + "peer": true }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", - "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==" + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/aria-hidden": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.4.tgz", + "integrity": "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==", "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@xtuc/long": "4.2.2" + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" } }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", - "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", + "node_modules/aria-query": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.12.1" + "deep-equal": "^2.0.5" } }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", - "dependencies": { - "@xtuc/ieee754": "^1.2.0" + "node_modules/arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dependencies": { - "@xtuc/long": "4.2.2" + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", - "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-opt": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1", - "@webassemblyjs/wast-printer": "1.12.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", - "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "engines": { + "node": ">=8" } }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", - "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", - "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "node_modules/array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", - "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@xtuc/long": "4.2.2" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" - }, - "node_modules/@yarnpkg/lockfile": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", - "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", - "dev": true - }, - "node_modules/@yarnpkg/parsers": { - "version": "3.0.0-rc.46", - "resolved": "https://registry.npmjs.org/@yarnpkg/parsers/-/parsers-3.0.0-rc.46.tgz", - "integrity": "sha512-aiATs7pSutzda/rq8fnuPwTglyVwjM22bNnK2ZgjrpAjQHSSl3lztd2f9evst1W/qnC58DRz7T7QndUDumAR4Q==", + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", "dev": true, "dependencies": { - "js-yaml": "^3.10.0", - "tslib": "^2.4.0" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" }, "engines": { - "node": ">=14.15.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@yarnpkg/parsers/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/array.prototype.toreversed": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz", + "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==", "dev": true, "dependencies": { - "sprintf-js": "~1.0.2" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" } }, - "node_modules/@yarnpkg/parsers/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", "dev": true, "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">= 0.4" } }, - "node_modules/@yarnpkg/parsers/node_modules/sprintf-js": { + "node_modules/arraybuffer.prototype.slice": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "node_modules/@zkochan/js-yaml": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.7.tgz", - "integrity": "sha512-nrUSn7hzt7J6JWgWGz78ZYI8wj+gdIJdk0Ynjpp8l+trkn58Uqsf6RYrYkEK+3X18EX+TNdtJI0WxAtc+L84SQ==", - "dev": true, + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", "dependencies": { - "argparse": "^2.0.1" + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/abab": { + "node_modules/asap": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "deprecated": "Use your platform's native atob() and btoa() methods instead", - "dev": true + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" }, - "node_modules/abitype": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.4.tgz", - "integrity": "sha512-UivtYZOGJGE8rsrM/N5vdRkUpqEZVmuTumfTuolm7m/6O09wprd958rx8kUBwVAAAhQDveGAgD0GJdBuR8s6tw==", - "funding": { - "url": "https://github.com/sponsors/wevm" - }, - "peerDependencies": { - "typescript": ">=5.0.4", - "zod": "^3 >=3.22.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - }, - "zod": { - "optional": true - } - } + "node_modules/asmcrypto.js": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/asmcrypto.js/-/asmcrypto.js-0.22.0.tgz", + "integrity": "sha512-usgMoyXjMbx/ZPdzTSXExhMPur2FTdz/Vo5PVx2gIaBcdAAJNOFlsdgqveM8Cff7W0v+xrf9BwjOV26JSAF9qA==", + "license": "MIT" }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", "license": "MIT", - "peer": true, "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" + "safer-buffer": "~2.1.0" } }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "node_modules/asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" } }, - "node_modules/acorn": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", - "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", - "bin": { - "acorn": "bin/acorn" + "node_modules/asn1.js/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/asn1js": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.5.tgz", + "integrity": "sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==", + "license": "BSD-3-Clause", + "dependencies": { + "pvtsutils": "^1.3.2", + "pvutils": "^1.1.3", + "tslib": "^2.4.0" }, "engines": { - "node": ">=0.4.0" + "node": ">=12.0.0" } }, - "node_modules/acorn-globals": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", - "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", - "dev": true, + "node_modules/assert": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.0.0.tgz", + "integrity": "sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==", + "license": "MIT", "dependencies": { - "acorn": "^8.1.0", - "acorn-walk": "^8.0.2" - } - }, - "node_modules/acorn-import-attributes": { - "version": "1.9.5", - "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", - "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", - "peerDependencies": { - "acorn": "^8" + "es6-object-assign": "^1.1.0", + "is-nan": "^1.2.1", + "object-is": "^1.0.1", + "util": "^0.12.0" } }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "license": "MIT", + "engines": { + "node": ">=0.8" } }, - "node_modules/acorn-walk": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", - "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", + "node_modules/ast-types": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", + "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", + "license": "MIT", + "peer": true, "dependencies": { - "acorn": "^8.11.0" + "tslib": "^2.0.1" }, "engines": { - "node": ">=0.4.0" + "node": ">=4" } }, - "node_modules/address": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", - "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", - "engines": { - "node": ">= 10.0.0" + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true + }, + "node_modules/astring": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/astring/-/astring-1.8.6.tgz", + "integrity": "sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg==", + "bin": { + "astring": "bin/astring" } }, - "node_modules/adm-zip": { - "version": "0.5.15", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.15.tgz", - "integrity": "sha512-jYPWSeOA8EFoZnucrKCNihqBjoEGQSU4HKgHYQgKNEQ0pQF9a/DYuo/+fAxY76k4qe75LUlLWpAM1QWcBMTOKw==", - "dev": true, - "engines": { - "node": ">=12.0" + "node_modules/async": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" + }, + "node_modules/async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "license": "MIT" + }, + "node_modules/async-mutex": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.2.6.tgz", + "integrity": "sha512-Hs4R+4SPgamu6rSGW8C7cV9gaWUKEHykfzCCvIRuaVv636Ju10ZdeUbvb4TBEW0INuq2DHZqXbK4Nd3yG4RaRw==", + "dependencies": { + "tslib": "^2.0.0" } }, - "node_modules/agent-base": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", - "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", "engines": { - "node": ">= 14" + "node": ">= 4.0.0" } }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", "engines": { - "node": ">=8" + "node": ">=8.0.0" } }, - "node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "node_modules/autoprefixer": { + "version": "10.4.20", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", + "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "browserslist": "^4.23.3", + "caniuse-lite": "^1.0.30001646", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.1", + "postcss-value-parser": "^4.2.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dependencies": { - "ajv": "^8.0.0" + "possible-typed-array-names": "^1.0.0" }, - "peerDependencies": { - "ajv": "^8.0.0" + "engines": { + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "node_modules/avalanche": { + "version": "3.15.3", + "resolved": "https://registry.npmjs.org/avalanche/-/avalanche-3.15.3.tgz", + "integrity": "sha512-Oh63Q/Aj9MGI7vHODoSddpwa5JOgqFDX8ZhTMf2Ly8VFhJqgIa0JI9gynTsIHmxHCcdcDhtMh+7V+XJbX1ZbYw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "license": "BSD-3-Clause", "dependencies": { - "fast-deep-equal": "^3.1.3" + "assert": "2.0.0", + "axios": "0.27.2", + "bech32": "2.0.0", + "bip39": "3.0.4", + "bn.js": "5.2.1", + "buffer": "6.0.3", + "create-hash": "1.2.0", + "crypto-browserify": "3.12.0", + "elliptic": "6.5.4", + "ethers": "5.6.9", + "hdkey": "2.0.1", + "isomorphic-ws": "5.0.0", + "randombytes": "^2.1.0", + "store2": "2.13.2", + "stream-browserify": "3.0.0", + "ws": "8.8.0", + "xss": "1.0.13" }, - "peerDependencies": { - "ajv": "^8.8.2" + "engines": { + "node": ">=14.0.0" } }, - "node_modules/algoliasearch": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.24.0.tgz", - "integrity": "sha512-bf0QV/9jVejssFBmz2HQLxUadxk574t4iwjCKp5E7NBzwKkrDEhKPISIIjAU/p6K5qDx3qoeh4+26zWN1jmw3g==", + "node_modules/avalanche/node_modules/@ethersproject/abi": { + "version": "5.6.4", + "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.6.4.tgz", + "integrity": "sha512-TTeZUlCeIHG6527/2goZA6gW5F8Emoc7MrZDC7hhP84aRGvW3TEdTnZR08Ls88YXM1m2SuK42Osw/jSi3uO8gg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", "dependencies": { - "@algolia/cache-browser-local-storage": "4.24.0", - "@algolia/cache-common": "4.24.0", - "@algolia/cache-in-memory": "4.24.0", - "@algolia/client-account": "4.24.0", - "@algolia/client-analytics": "4.24.0", - "@algolia/client-common": "4.24.0", - "@algolia/client-personalization": "4.24.0", - "@algolia/client-search": "4.24.0", - "@algolia/logger-common": "4.24.0", - "@algolia/logger-console": "4.24.0", - "@algolia/recommend": "4.24.0", - "@algolia/requester-browser-xhr": "4.24.0", - "@algolia/requester-common": "4.24.0", - "@algolia/requester-node-http": "4.24.0", - "@algolia/transporter": "4.24.0" + "@ethersproject/address": "^5.6.1", + "@ethersproject/bignumber": "^5.6.2", + "@ethersproject/bytes": "^5.6.1", + "@ethersproject/constants": "^5.6.1", + "@ethersproject/hash": "^5.6.1", + "@ethersproject/keccak256": "^5.6.1", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/strings": "^5.6.1" } }, - "node_modules/algoliasearch-helper": { - "version": "3.22.3", - "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.22.3.tgz", - "integrity": "sha512-2eoEz8mG4KHE+DzfrBTrCmDPxVXv7aZZWPojAJFtARpxxMO6lkos1dJ+XDCXdPvq7q3tpYWRi6xXmVQikejtpA==", + "node_modules/avalanche/node_modules/@ethersproject/abstract-provider": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.6.1.tgz", + "integrity": "sha512-BxlIgogYJtp1FS8Muvj8YfdClk3unZH0vRMVX791Z9INBNT/kuACZ9GzaY1Y4yFq+YSy6/w4gzj3HCRKrK9hsQ==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", "dependencies": { - "@algolia/events": "^4.0.1" - }, - "peerDependencies": { - "algoliasearch": ">= 3.1 < 6" + "@ethersproject/bignumber": "^5.6.2", + "@ethersproject/bytes": "^5.6.1", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/networks": "^5.6.3", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/transactions": "^5.6.2", + "@ethersproject/web": "^5.6.1" } }, - "node_modules/anser": { - "version": "1.4.10", - "resolved": "https://registry.npmjs.org/anser/-/anser-1.4.10.tgz", - "integrity": "sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==", + "node_modules/avalanche/node_modules/@ethersproject/abstract-signer": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.6.2.tgz", + "integrity": "sha512-n1r6lttFBG0t2vNiI3HoWaS/KdOt8xyDjzlP2cuevlWLG6EX0OwcKLyG/Kp/cuwNxdy/ous+R/DEMdTUwWQIjQ==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], "license": "MIT", - "peer": true - }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", "dependencies": { - "string-width": "^4.1.0" - } - }, - "node_modules/ansi-align/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/ansi-align/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" + "@ethersproject/abstract-provider": "^5.6.1", + "@ethersproject/bignumber": "^5.6.2", + "@ethersproject/bytes": "^5.6.1", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0" } }, - "node_modules/ansi-align/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/avalanche/node_modules/@ethersproject/address": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.6.1.tgz", + "integrity": "sha512-uOgF0kS5MJv9ZvCz7x6T2EXJSzotiybApn4XlOgoTX0xdtyVIJ7pF+6cGPxiEq/dpBiTfMiw7Yc81JcwhSYA0Q==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true, - "engines": { - "node": ">=6" + "@ethersproject/bignumber": "^5.6.2", + "@ethersproject/bytes": "^5.6.1", + "@ethersproject/keccak256": "^5.6.1", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/rlp": "^5.6.1" } }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, + "node_modules/avalanche/node_modules/@ethersproject/base64": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.6.1.tgz", + "integrity": "sha512-qB76rjop6a0RIYYMiB4Eh/8n+Hxu2NIZm8S/Q7kNo5pmZfXhHGHmS4MinUainiBC54SCyRnwzL+KZjj8zbsSsw==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "@ethersproject/bytes": "^5.6.1" } }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node_modules/avalanche/node_modules/@ethersproject/basex": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.6.1.tgz", + "integrity": "sha512-a52MkVz4vuBXR06nvflPMotld1FJWSj2QT0985v7P/emPZO00PucFAkbcmq2vpVU7Ts7umKiSI6SppiLykVWsA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.6.1", + "@ethersproject/properties": "^5.6.0" } }, - "node_modules/ansi-html-community": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", - "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", - "engines": [ - "node >= 0.8.0" + "node_modules/avalanche/node_modules/@ethersproject/bignumber": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.6.2.tgz", + "integrity": "sha512-v7+EEUbhGqT3XJ9LMPsKvXYHFc8eHxTowFCG/HgJErmq4XHJ2WR7aeyICg3uTOAQ7Icn0GFHAohXEhxQHq4Ubw==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } ], - "bin": { - "ansi-html": "bin/ansi-html" + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.6.1", + "@ethersproject/logger": "^5.6.0", + "bn.js": "^5.2.1" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" + "node_modules/avalanche/node_modules/@ethersproject/bytes": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.6.1.tgz", + "integrity": "sha512-NwQt7cKn5+ZE4uDn+X5RAXLp46E1chXoaMmrxAyA0rblpxz8t58lVkrHXoRIn0lz1joQElQ8410GqhTqMOwc6g==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/logger": "^5.6.0" } }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/avalanche/node_modules/@ethersproject/constants": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.6.1.tgz", + "integrity": "sha512-QSq9WVnZbxXYFftrjSjZDUshp6/eKp6qrtdBtUCm0QxCV5z1fG/w3kdlcsjMCQuQHUnAclKoK7XpXMezhRDOLg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "@ethersproject/bignumber": "^5.6.2" } }, - "node_modules/ansi-styles/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/avalanche/node_modules/@ethersproject/contracts": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.6.2.tgz", + "integrity": "sha512-hguUA57BIKi6WY0kHvZp6PwPlWF87MCeB4B7Z7AbUpTxfFXFdn/3b0GmjZPagIHS+3yhcBJDnuEfU4Xz+Ks/8g==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "@ethersproject/abi": "^5.6.3", + "@ethersproject/abstract-provider": "^5.6.1", + "@ethersproject/abstract-signer": "^5.6.2", + "@ethersproject/address": "^5.6.1", + "@ethersproject/bignumber": "^5.6.2", + "@ethersproject/bytes": "^5.6.1", + "@ethersproject/constants": "^5.6.1", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/transactions": "^5.6.2" } }, - "node_modules/ansi-styles/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "dev": true - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "node_modules/avalanche/node_modules/@ethersproject/hash": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.6.1.tgz", + "integrity": "sha512-L1xAHurbaxG8VVul4ankNX5HgQ8PNCTrnVXEiFnE9xoRnaUcgfD12tZINtDinSllxPLCtGwguQxJ5E6keE84pA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" + "@ethersproject/abstract-signer": "^5.6.2", + "@ethersproject/address": "^5.6.1", + "@ethersproject/bignumber": "^5.6.2", + "@ethersproject/bytes": "^5.6.1", + "@ethersproject/keccak256": "^5.6.1", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/strings": "^5.6.1" } }, - "node_modules/append-field": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", - "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" - }, - "node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "node_modules/aria-hidden": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.4.tgz", - "integrity": "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==", + "node_modules/avalanche/node_modules/@ethersproject/hdnode": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.6.2.tgz", + "integrity": "sha512-tERxW8Ccf9CxW2db3WsN01Qao3wFeRsfYY9TCuhmG0xNpl2IO8wgXU3HtWIZ49gUWPggRy4Yg5axU0ACaEKf1Q==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", "dependencies": { - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=10" + "@ethersproject/abstract-signer": "^5.6.2", + "@ethersproject/basex": "^5.6.1", + "@ethersproject/bignumber": "^5.6.2", + "@ethersproject/bytes": "^5.6.1", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/pbkdf2": "^5.6.1", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/sha2": "^5.6.1", + "@ethersproject/signing-key": "^5.6.2", + "@ethersproject/strings": "^5.6.1", + "@ethersproject/transactions": "^5.6.2", + "@ethersproject/wordlists": "^5.6.1" + } + }, + "node_modules/avalanche/node_modules/@ethersproject/json-wallets": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.6.1.tgz", + "integrity": "sha512-KfyJ6Zwz3kGeX25nLihPwZYlDqamO6pfGKNnVMWWfEVVp42lTfCZVXXy5Ie8IZTN0HKwAngpIPi7gk4IJzgmqQ==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/abstract-signer": "^5.6.2", + "@ethersproject/address": "^5.6.1", + "@ethersproject/bytes": "^5.6.1", + "@ethersproject/hdnode": "^5.6.2", + "@ethersproject/keccak256": "^5.6.1", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/pbkdf2": "^5.6.1", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/random": "^5.6.1", + "@ethersproject/strings": "^5.6.1", + "@ethersproject/transactions": "^5.6.2", + "aes-js": "3.0.0", + "scrypt-js": "3.0.1" + } + }, + "node_modules/avalanche/node_modules/@ethersproject/keccak256": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.6.1.tgz", + "integrity": "sha512-bB7DQHCTRDooZZdL3lk9wpL0+XuG3XLGHLh3cePnybsO3V0rdCAOQGpn/0R3aODmnTOOkCATJiD2hnL+5bwthA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.6.1", + "js-sha3": "0.8.0" } }, - "node_modules/aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", - "dev": true, + "node_modules/avalanche/node_modules/@ethersproject/logger": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.6.0.tgz", + "integrity": "sha512-BiBWllUROH9w+P21RzoxJKzqoqpkyM1pRnEKG69bulE9TSQD8SAIvTQqIMZmmCO8pUNkgLP1wndX1gKghSpBmg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT" + }, + "node_modules/avalanche/node_modules/@ethersproject/networks": { + "version": "5.6.4", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.6.4.tgz", + "integrity": "sha512-KShHeHPahHI2UlWdtDMn2lJETcbtaJge4k7XSjDR9h79QTd6yQJmv6Cp2ZA4JdqWnhszAOLSuJEd9C0PRw7hSQ==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", "dependencies": { - "deep-equal": "^2.0.5" + "@ethersproject/logger": "^5.6.0" } }, - "node_modules/arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", - "engines": { - "node": ">=0.10.0" + "node_modules/avalanche/node_modules/@ethersproject/pbkdf2": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.6.1.tgz", + "integrity": "sha512-k4gRQ+D93zDRPNUfmduNKq065uadC2YjMP/CqwwX5qG6R05f47boq6pLZtV/RnC4NZAYOPH1Cyo54q0c9sshRQ==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.6.1", + "@ethersproject/sha2": "^5.6.1" } }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "node_modules/avalanche/node_modules/@ethersproject/properties": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.6.0.tgz", + "integrity": "sha512-szoOkHskajKePTJSZ46uHUWWkbv7TzP2ypdEK6jGMqJaEt2sb0jCgfBo0gH0m2HBpRixMuJ6TBRaQCF7a9DoCg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@ethersproject/logger": "^5.6.0" } }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" - }, - "node_modules/array-includes": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", - "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", - "dev": true, + "node_modules/avalanche/node_modules/@ethersproject/providers": { + "version": "5.6.8", + "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.6.8.tgz", + "integrity": "sha512-Wf+CseT/iOJjrGtAOf3ck9zS7AgPmr2fZ3N97r4+YXN3mBePTG2/bJ8DApl9mVwYL+RpYbNxMEkEp4mPGdwG/w==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "is-string": "^1.0.7" - }, + "@ethersproject/abstract-provider": "^5.6.1", + "@ethersproject/abstract-signer": "^5.6.2", + "@ethersproject/address": "^5.6.1", + "@ethersproject/base64": "^5.6.1", + "@ethersproject/basex": "^5.6.1", + "@ethersproject/bignumber": "^5.6.2", + "@ethersproject/bytes": "^5.6.1", + "@ethersproject/constants": "^5.6.1", + "@ethersproject/hash": "^5.6.1", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/networks": "^5.6.3", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/random": "^5.6.1", + "@ethersproject/rlp": "^5.6.1", + "@ethersproject/sha2": "^5.6.1", + "@ethersproject/strings": "^5.6.1", + "@ethersproject/transactions": "^5.6.2", + "@ethersproject/web": "^5.6.1", + "bech32": "1.1.4", + "ws": "7.4.6" + } + }, + "node_modules/avalanche/node_modules/@ethersproject/providers/node_modules/bech32": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", + "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", + "license": "MIT" + }, + "node_modules/avalanche/node_modules/@ethersproject/providers/node_modules/ws": { + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", + "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", + "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=8.3.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "engines": { - "node": ">=8" + "node_modules/avalanche/node_modules/@ethersproject/random": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.6.1.tgz", + "integrity": "sha512-/wtPNHwbmng+5yi3fkipA8YBT59DdkGRoC2vWk09Dci/q5DlgnMkhIycjHlavrvrjJBkFjO/ueLyT+aUDfc4lA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.6.1", + "@ethersproject/logger": "^5.6.0" } }, - "node_modules/array.prototype.findlast": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", - "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", - "dev": true, + "node_modules/avalanche/node_modules/@ethersproject/rlp": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.6.1.tgz", + "integrity": "sha512-uYjmcZx+DKlFUk7a5/W9aQVaoEC7+1MOBgNtvNg13+RnuUwT4F0zTovC0tmay5SmRslb29V1B7Y5KCri46WhuQ==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@ethersproject/bytes": "^5.6.1", + "@ethersproject/logger": "^5.6.0" } }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", - "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", - "dev": true, + "node_modules/avalanche/node_modules/@ethersproject/sha2": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.6.1.tgz", + "integrity": "sha512-5K2GyqcW7G4Yo3uenHegbXRPDgARpWUiXc6RiF7b6i/HXUoWlb7uCARh7BAHg7/qT/Q5ydofNwiZcim9qpjB6g==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@ethersproject/bytes": "^5.6.1", + "@ethersproject/logger": "^5.6.0", + "hash.js": "1.1.7" } }, - "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", - "dev": true, + "node_modules/avalanche/node_modules/@ethersproject/signing-key": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.6.2.tgz", + "integrity": "sha512-jVbu0RuP7EFpw82vHcL+GP35+KaNruVAZM90GxgQnGqB6crhBqW/ozBfFvdeImtmb4qPko0uxXjn8l9jpn0cwQ==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@ethersproject/bytes": "^5.6.1", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "bn.js": "^5.2.1", + "elliptic": "6.5.4", + "hash.js": "1.1.7" } }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", - "dev": true, + "node_modules/avalanche/node_modules/@ethersproject/solidity": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.6.1.tgz", + "integrity": "sha512-KWqVLkUUoLBfL1iwdzUVlkNqAUIFMpbbeH0rgCfKmJp0vFtY4AsaN91gHKo9ZZLkC4UOm3cI3BmMV4N53BOq4g==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@ethersproject/bignumber": "^5.6.2", + "@ethersproject/bytes": "^5.6.1", + "@ethersproject/keccak256": "^5.6.1", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/sha2": "^5.6.1", + "@ethersproject/strings": "^5.6.1" } }, - "node_modules/array.prototype.toreversed": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz", - "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==", - "dev": true, + "node_modules/avalanche/node_modules/@ethersproject/strings": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.6.1.tgz", + "integrity": "sha512-2X1Lgk6Jyfg26MUnsHiT456U9ijxKUybz8IM1Vih+NJxYtXhmvKBcHOmvGqpFSVJ0nQ4ZCoIViR8XlRw1v/+Cw==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "@ethersproject/bytes": "^5.6.1", + "@ethersproject/constants": "^5.6.1", + "@ethersproject/logger": "^5.6.0" } }, - "node_modules/array.prototype.tosorted": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", - "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", - "dev": true, + "node_modules/avalanche/node_modules/@ethersproject/transactions": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.6.2.tgz", + "integrity": "sha512-BuV63IRPHmJvthNkkt9G70Ullx6AcM+SDc+a8Aw/8Yew6YwT51TcBKEp1P4oOQ/bP25I18JJr7rcFRgFtU9B2Q==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.3", - "es-errors": "^1.3.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" + "@ethersproject/address": "^5.6.1", + "@ethersproject/bignumber": "^5.6.2", + "@ethersproject/bytes": "^5.6.1", + "@ethersproject/constants": "^5.6.1", + "@ethersproject/keccak256": "^5.6.1", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/rlp": "^5.6.1", + "@ethersproject/signing-key": "^5.6.2" } }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "node_modules/avalanche/node_modules/@ethersproject/units": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.6.1.tgz", + "integrity": "sha512-rEfSEvMQ7obcx3KWD5EWWx77gqv54K6BKiZzKxkQJqtpriVsICrktIQmKl8ReNToPeIYPnFHpXvKpi068YFZXw==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.2.1", - "get-intrinsic": "^1.2.3", - "is-array-buffer": "^3.0.4", - "is-shared-array-buffer": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@ethersproject/bignumber": "^5.6.2", + "@ethersproject/constants": "^5.6.1", + "@ethersproject/logger": "^5.6.0" } }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" - }, - "node_modules/asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "node_modules/avalanche/node_modules/@ethersproject/wallet": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.6.2.tgz", + "integrity": "sha512-lrgh0FDQPuOnHcF80Q3gHYsSUODp6aJLAdDmDV0xKCN/T7D99ta1jGVhulg3PY8wiXEngD0DfM0I2XKXlrqJfg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/abstract-provider": "^5.6.1", + "@ethersproject/abstract-signer": "^5.6.2", + "@ethersproject/address": "^5.6.1", + "@ethersproject/bignumber": "^5.6.2", + "@ethersproject/bytes": "^5.6.1", + "@ethersproject/hash": "^5.6.1", + "@ethersproject/hdnode": "^5.6.2", + "@ethersproject/json-wallets": "^5.6.1", + "@ethersproject/keccak256": "^5.6.1", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/random": "^5.6.1", + "@ethersproject/signing-key": "^5.6.2", + "@ethersproject/transactions": "^5.6.2", + "@ethersproject/wordlists": "^5.6.1" + } + }, + "node_modules/avalanche/node_modules/@ethersproject/web": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.6.1.tgz", + "integrity": "sha512-/vSyzaQlNXkO1WV+RneYKqCJwualcUdx/Z3gseVovZP0wIlOFcCE1hkRhKBH8ImKbGQbMl9EAAyJFrJu7V0aqA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", "dependencies": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" + "@ethersproject/base64": "^5.6.1", + "@ethersproject/bytes": "^5.6.1", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/strings": "^5.6.1" } }, - "node_modules/asn1.js/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "node_modules/ast-types": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", - "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", + "node_modules/avalanche/node_modules/@ethersproject/wordlists": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.6.1.tgz", + "integrity": "sha512-wiPRgBpNbNwCQFoCr8bcWO8o5I810cqO6mkdtKfLKFlLxeCWcnzDi4Alu8iyNzlhYuS9npCwivMbRWF19dyblw==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], "license": "MIT", - "peer": true, "dependencies": { - "tslib": "^2.0.1" - }, - "engines": { - "node": ">=4" + "@ethersproject/bytes": "^5.6.1", + "@ethersproject/hash": "^5.6.1", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/strings": "^5.6.1" } }, - "node_modules/ast-types-flow": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", - "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", - "dev": true + "node_modules/avalanche/node_modules/@types/node": { + "version": "11.11.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-11.11.6.tgz", + "integrity": "sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==", + "license": "MIT" }, - "node_modules/astring": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/astring/-/astring-1.8.6.tgz", - "integrity": "sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg==", - "bin": { - "astring": "bin/astring" + "node_modules/avalanche/node_modules/axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" } }, - "node_modules/async": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", - "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" + "node_modules/avalanche/node_modules/bip39": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.0.4.tgz", + "integrity": "sha512-YZKQlb752TrUWqHWj7XAwCSjYEgGAk+/Aas3V7NyjQeZYsztO8JnQUaCWhcnL4T+jL8nvB8typ2jRPzTlgugNw==", + "license": "ISC", + "dependencies": { + "@types/node": "11.11.6", + "create-hash": "^1.1.0", + "pbkdf2": "^3.0.9", + "randombytes": "^2.0.1" + } }, - "node_modules/async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "node_modules/avalanche/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "license": "MIT", - "peer": true - }, - "node_modules/async-mutex": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.2.6.tgz", - "integrity": "sha512-Hs4R+4SPgamu6rSGW8C7cV9gaWUKEHykfzCCvIRuaVv636Ju10ZdeUbvb4TBEW0INuq2DHZqXbK4Nd3yG4RaRw==", "dependencies": { - "tslib": "^2.0.0" + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" } }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "engines": { - "node": ">= 4.0.0" + "node_modules/avalanche/node_modules/elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" } }, - "node_modules/atomic-sleep": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", - "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", - "engines": { - "node": ">=8.0.0" - } + "node_modules/avalanche/node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "license": "MIT" }, - "node_modules/autoprefixer": { - "version": "10.4.20", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", - "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", + "node_modules/avalanche/node_modules/ethers": { + "version": "5.6.9", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.6.9.tgz", + "integrity": "sha512-lMGC2zv9HC5EC+8r429WaWu3uWJUCgUCt8xxKCFqkrFuBDZXDYIdzDUECxzjf2BMF8IVBByY1EBoGSL3RTm8RA==", "funding": [ { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" }, { - "type": "github", - "url": "https://github.com/sponsors/ai" + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "browserslist": "^4.23.3", - "caniuse-lite": "^1.0.30001646", - "fraction.js": "^4.3.7", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.1", - "postcss-value-parser": "^4.2.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, + "@ethersproject/abi": "5.6.4", + "@ethersproject/abstract-provider": "5.6.1", + "@ethersproject/abstract-signer": "5.6.2", + "@ethersproject/address": "5.6.1", + "@ethersproject/base64": "5.6.1", + "@ethersproject/basex": "5.6.1", + "@ethersproject/bignumber": "5.6.2", + "@ethersproject/bytes": "5.6.1", + "@ethersproject/constants": "5.6.1", + "@ethersproject/contracts": "5.6.2", + "@ethersproject/hash": "5.6.1", + "@ethersproject/hdnode": "5.6.2", + "@ethersproject/json-wallets": "5.6.1", + "@ethersproject/keccak256": "5.6.1", + "@ethersproject/logger": "5.6.0", + "@ethersproject/networks": "5.6.4", + "@ethersproject/pbkdf2": "5.6.1", + "@ethersproject/properties": "5.6.0", + "@ethersproject/providers": "5.6.8", + "@ethersproject/random": "5.6.1", + "@ethersproject/rlp": "5.6.1", + "@ethersproject/sha2": "5.6.1", + "@ethersproject/signing-key": "5.6.2", + "@ethersproject/solidity": "5.6.1", + "@ethersproject/strings": "5.6.1", + "@ethersproject/transactions": "5.6.2", + "@ethersproject/units": "5.6.1", + "@ethersproject/wallet": "5.6.2", + "@ethersproject/web": "5.6.1", + "@ethersproject/wordlists": "5.6.1" + } + }, + "node_modules/avalanche/node_modules/ws": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.8.0.tgz", + "integrity": "sha512-JDAgSYQ1ksuwqfChJusw1LSJ8BizJ2e/vVu5Lxjq3YvNJNlROv1ui4i+c/kUUrPheBvQl4c5UbERhTwKa6QBJQ==", + "license": "MIT", "engines": { - "node": "^10 || ^12 || >=14" + "node": ">=10.0.0" }, "peerDependencies": { - "postcss": "^8.1.0" + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "license": "Apache-2.0", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "*" } }, + "node_modules/aws4": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", + "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==", + "license": "MIT" + }, "node_modules/axe-core": { "version": "4.10.0", "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.0.tgz", @@ -22063,6 +33170,24 @@ "deep-equal": "^2.0.5" } }, + "node_modules/b64-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/b64-lite/-/b64-lite-1.4.0.tgz", + "integrity": "sha512-aHe97M7DXt+dkpa8fHlCcm1CnskAHrJqEfMI0KN7dwqlzml/aUe1AGt6lk51HzrSfVD67xOso84sOpr+0wIe2w==", + "license": "MIT", + "dependencies": { + "base-64": "^0.1.0" + } + }, + "node_modules/b64u-lite": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/b64u-lite/-/b64u-lite-1.1.0.tgz", + "integrity": "sha512-929qWGDVCRph7gQVTC6koHqQIpF4vtVaSbwLltFQo44B1bYUquALswZdBKFfrJCPEnsCOvWkJsPdQYZ/Ukhw8A==", + "license": "MIT", + "dependencies": { + "b64-lite": "^1.4.0" + } + }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -22202,6 +33327,23 @@ "node": ">= 6" } }, + "node_modules/babel-plugin-module-resolver": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-4.1.0.tgz", + "integrity": "sha512-MlX10UDheRr3lb3P0WcaIdtCSRlxdQsB1sBqL7W0raF070bGl1HQQq5K3T2vf2XAYie+ww+5AKC/WrkjRO2knA==", + "license": "MIT", + "peer": true, + "dependencies": { + "find-babel-config": "^1.2.0", + "glob": "^7.1.6", + "pkg-up": "^3.1.0", + "reselect": "^4.0.0", + "resolve": "^1.13.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, "node_modules/babel-plugin-polyfill-corejs2": { "version": "0.4.11", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", @@ -22238,6 +33380,13 @@ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, + "node_modules/babel-plugin-react-native-web": { + "version": "0.17.7", + "resolved": "https://registry.npmjs.org/babel-plugin-react-native-web/-/babel-plugin-react-native-web-0.17.7.tgz", + "integrity": "sha512-UBLfIsfU3vi//Ab4i0WSWAfm1whLTK9uJoH0RPZ6a67eS/h9JGYjKy7+1RpHxSBviHi9NIMiYfWseTLjyIsE1g==", + "license": "MIT", + "peer": true + }, "node_modules/babel-plugin-syntax-hermes-parser": { "version": "0.25.1", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.25.1.tgz", @@ -22289,6 +33438,21 @@ "@babel/core": "^7.0.0" } }, + "node_modules/babel-preset-expo": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/babel-preset-expo/-/babel-preset-expo-9.0.2.tgz", + "integrity": "sha512-NKVichCkbmb+ZIJ4hvuxzX3PnvHUKT42NxYIYTsKAfHPUKuaSAawtpsmMThph6pUc0GUYcLvCRql8ZX5A1zYNw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/plugin-proposal-decorators": "^7.12.9", + "@babel/plugin-transform-react-jsx": "^7.12.17", + "@babel/preset-env": "^7.12.9", + "babel-plugin-module-resolver": "^4.1.0", + "babel-plugin-react-native-web": "~0.17.1", + "metro-react-native-babel-preset": "~0.64.0" + } + }, "node_modules/babel-preset-jest": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", @@ -22318,6 +33482,29 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/base-64": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/base-64/-/base-64-0.1.0.tgz", + "integrity": "sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA==" + }, + "node_modules/base-x": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.10.tgz", + "integrity": "sha512-7d0s06rR9rYaIWHkpfLIFICM/tkSVdoPC9qYAQRpxn9DdKNWNsKC0uk++akckyLq16Tx2WIinnZ6WRriAt6njQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/base32.js": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/base32.js/-/base32.js-0.1.0.tgz", + "integrity": "sha512-n3TkB02ixgBOhTvANakDb4xaMXnYUVkNoRFJjQflcqMQhyEKxEHdj3E6N8t8sUQ0mjH/3/JxzlXuz3ul/J90pQ==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -22359,7 +33546,6 @@ "version": "5.0.5", "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==", - "dev": true, "engines": { "node": ">=10.0.0" } @@ -22369,6 +33555,60 @@ "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "license": "BSD-3-Clause", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/bcrypt-pbkdf/node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "license": "Unlicense" + }, + "node_modules/bech32": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz", + "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==", + "license": "MIT" + }, + "node_modules/bech32-buffer": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/bech32-buffer/-/bech32-buffer-0.2.1.tgz", + "integrity": "sha512-fCG1TyZuCN48Sdw97p/IR39fvqpFlWDVpG7qnuU1Uc3+Xtc/0uqAp8U7bMW/bGuVF5CcNVIXwxQsWwUr6un6FQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/better-opn": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/better-opn/-/better-opn-3.0.2.tgz", + "integrity": "sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "open": "^8.0.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/big-integer": { + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "license": "Unlicense", + "peer": true, + "engines": { + "node": ">=0.6" + } + }, "node_modules/big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", @@ -22377,6 +33617,45 @@ "node": "*" } }, + "node_modules/bigi": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/bigi/-/bigi-1.4.2.tgz", + "integrity": "sha512-ddkU+dFIuEIW8lE7ZwdIAf2UPoM90eaprg5m3YXAVVTmKlqV/9BX4A2M8BOK2yOq6/VgZFVhK6QAxJebhlbhzw==" + }, + "node_modules/bigint-buffer": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/bigint-buffer/-/bigint-buffer-1.1.5.tgz", + "integrity": "sha512-trfYco6AoZ+rKhKnxA0hgX0HAbVP/s808/EuDSe2JDzUnCp/xAsli35Orvk67UrTEcwuxZqYZDmfA2RXJgxVvA==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "bindings": "^1.3.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/bigint-crypto-utils": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/bigint-crypto-utils/-/bigint-crypto-utils-3.1.4.tgz", + "integrity": "sha512-niSkvARUEe8MiAiH+zKXPkgXzlvGDbOqXL3JDevWaA1TrPhUGSCgV+iedm8qMEBQwvSlMMn8GpSuoUjvsm2QfQ==", + "license": "MIT", + "dependencies": { + "bigint-mod-arith": "^3.1.0" + }, + "engines": { + "node": ">=10.4.0" + } + }, + "node_modules/bigint-mod-arith": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bigint-mod-arith/-/bigint-mod-arith-3.1.2.tgz", + "integrity": "sha512-nx8J8bBeiRR+NlsROFH9jHswW5HO8mgfOSqW0AmjicMMvaONDa8AO+5ViKDUUNytBPWiwfvZP4/Bj4Y3lUfvgQ==", + "license": "MIT", + "engines": { + "node": ">=10.4.0" + } + }, "node_modules/bignumber.js": { "version": "9.1.2", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", @@ -22400,11 +33679,375 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "optional": true, "dependencies": { "file-uri-to-path": "1.0.0" } }, + "node_modules/bip174": { + "name": "@bitgo-forks/bip174", + "version": "3.1.0-master.4", + "resolved": "https://registry.npmjs.org/@bitgo-forks/bip174/-/bip174-3.1.0-master.4.tgz", + "integrity": "sha512-WDRNzPSdJGDqQNqfN+L5KHNHFDmNOPYnUnT7NkEkfHWn5m1jSOfcf8Swaslt5P0xcSDiERdN2gZxFc6XtOqRYg==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/bip32": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bip32/-/bip32-3.1.0.tgz", + "integrity": "sha512-eoeajYEzJ4d6yyVtby8C+XkCeKItiC4Mx56a0M9VaqTMC73SWOm4xVZG7SaR8e/yp4eSyky2XcBpH3DApPdu7Q==", + "license": "MIT", + "dependencies": { + "bs58check": "^2.1.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "ripemd160": "^2.0.2", + "typeforce": "^1.11.5", + "wif": "^2.0.6" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/bip39": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.1.0.tgz", + "integrity": "sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A==", + "license": "ISC", + "dependencies": { + "@noble/hashes": "^1.2.0" + } + }, + "node_modules/bip66": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", + "integrity": "sha512-nemMHz95EmS38a26XbbdxIYj5csHd3RMP3H5bwQknX0WYHF01qhpufP42mLOwVICuH2JmhIhXiWs89MfUGL7Xw==", + "license": "MIT", + "optional": true, + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/bitcoin-ops": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/bitcoin-ops/-/bitcoin-ops-1.4.1.tgz", + "integrity": "sha512-pef6gxZFztEhaE9RY9HmWVmiIHqCb2OyS4HPKkpc6CIiiOa3Qmuoylxc5P2EkU3w+5eTSifI9SEZC88idAIGow==", + "license": "MIT" + }, + "node_modules/bitcoinjs-lib": { + "name": "@bitgo-forks/bitcoinjs-lib", + "version": "7.1.0-master.9", + "resolved": "https://registry.npmjs.org/@bitgo-forks/bitcoinjs-lib/-/bitcoinjs-lib-7.1.0-master.9.tgz", + "integrity": "sha512-iWDwsRZK30tW7jtBiOlOJhuJzZ2THIvdvREBHM2cHG669nGQxNPxpYXmk0Lgm5x4jG4GN1dM6dPR6Car6EtDsA==", + "license": "MIT", + "dependencies": { + "bech32": "^2.0.0", + "bip174": "npm:@bitgo-forks/bip174@3.1.0-master.4", + "bs58check": "^2.1.2", + "create-hash": "^1.1.0", + "fastpriorityqueue": "^0.7.1", + "json5": "^2.2.3", + "ripemd160": "^2.0.2", + "typeforce": "^1.11.3", + "varuint-bitcoin": "^1.1.2", + "wif": "^2.0.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/bitcoinjs-message": { + "name": "@bitgo-forks/bitcoinjs-message", + "version": "1.0.0-master.3", + "resolved": "https://registry.npmjs.org/@bitgo-forks/bitcoinjs-message/-/bitcoinjs-message-1.0.0-master.3.tgz", + "integrity": "sha512-mWMXFSb9pTcbxcvU4cQGkickuhPDnpadHs6eUK6F07pJZ42O4eA3j0anwfTsfpqs8UpSzM8UtrUEG4ao5+/yZg==", + "license": "MIT", + "dependencies": { + "bech32": "^1.1.3", + "bs58check": "^2.1.2", + "buffer-equals": "^1.0.3", + "create-hash": "^1.1.2", + "secp256k1": "5.0.1", + "varuint-bitcoin": "^1.0.1" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/bitcoinjs-message/node_modules/bech32": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", + "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", + "license": "MIT" + }, + "node_modules/bitgo": { + "version": "39.23.0", + "resolved": "https://registry.npmjs.org/bitgo/-/bitgo-39.23.0.tgz", + "integrity": "sha512-tXfizVeChDgGPK/DVvi3hqI1dSHa3V3mHJXJft6rfXiW8InY9IahiCw863R020kaVQlZMemmJom3rWgMuIFl2Q==", + "license": "Apache-2.0", + "dependencies": { + "@bitgo/abstract-lightning": "^1.2.38", + "@bitgo/abstract-utxo": "^9.12.0", + "@bitgo/account-lib": "^24.2.0", + "@bitgo/blockapis": "^1.10.9", + "@bitgo/sdk-api": "^1.58.2", + "@bitgo/sdk-coin-ada": "^4.6.0", + "@bitgo/sdk-coin-algo": "^2.1.58", + "@bitgo/sdk-coin-apt": "^1.4.1", + "@bitgo/sdk-coin-arbeth": "^21.0.52", + "@bitgo/sdk-coin-atom": "^13.1.16", + "@bitgo/sdk-coin-avaxc": "^5.2.10", + "@bitgo/sdk-coin-avaxp": "^5.0.59", + "@bitgo/sdk-coin-bch": "^2.1.10", + "@bitgo/sdk-coin-bcha": "^2.2.10", + "@bitgo/sdk-coin-bera": "^2.3.4", + "@bitgo/sdk-coin-bld": "^3.0.29", + "@bitgo/sdk-coin-bsc": "^22.2.13", + "@bitgo/sdk-coin-bsv": "^2.1.10", + "@bitgo/sdk-coin-btc": "^2.4.10", + "@bitgo/sdk-coin-btg": "^2.1.10", + "@bitgo/sdk-coin-celo": "^4.0.11", + "@bitgo/sdk-coin-coredao": "^1.2.12", + "@bitgo/sdk-coin-coreum": "^21.0.29", + "@bitgo/sdk-coin-cspr": "^2.0.60", + "@bitgo/sdk-coin-dash": "^2.1.10", + "@bitgo/sdk-coin-doge": "^2.1.10", + "@bitgo/sdk-coin-dot": "^4.1.38", + "@bitgo/sdk-coin-eos": "^2.1.53", + "@bitgo/sdk-coin-etc": "^2.2.27", + "@bitgo/sdk-coin-eth": "^24.2.49", + "@bitgo/sdk-coin-eth2": "^3.0.59", + "@bitgo/sdk-coin-ethlike": "^1.1.41", + "@bitgo/sdk-coin-ethw": "^20.0.60", + "@bitgo/sdk-coin-hash": "^3.0.29", + "@bitgo/sdk-coin-hbar": "^2.0.60", + "@bitgo/sdk-coin-icp": "^1.1.0", + "@bitgo/sdk-coin-injective": "^3.0.29", + "@bitgo/sdk-coin-islm": "^2.1.10", + "@bitgo/sdk-coin-lnbtc": "^1.1.38", + "@bitgo/sdk-coin-ltc": "^3.1.10", + "@bitgo/sdk-coin-near": "^2.0.60", + "@bitgo/sdk-coin-oas": "^1.1.13", + "@bitgo/sdk-coin-opeth": "^18.1.45", + "@bitgo/sdk-coin-osmo": "^3.0.29", + "@bitgo/sdk-coin-polygon": "^21.0.29", + "@bitgo/sdk-coin-rbtc": "^2.0.60", + "@bitgo/sdk-coin-rune": "^1.1.17", + "@bitgo/sdk-coin-sei": "^3.0.29", + "@bitgo/sdk-coin-sol": "^4.7.17", + "@bitgo/sdk-coin-stx": "^3.3.17", + "@bitgo/sdk-coin-sui": "^5.8.19", + "@bitgo/sdk-coin-tao": "^1.0.2", + "@bitgo/sdk-coin-tia": "^3.0.29", + "@bitgo/sdk-coin-ton": "^3.4.17", + "@bitgo/sdk-coin-trx": "^2.0.60", + "@bitgo/sdk-coin-xlm": "^3.2.34", + "@bitgo/sdk-coin-xrp": "^3.7.2", + "@bitgo/sdk-coin-xtz": "^2.1.58", + "@bitgo/sdk-coin-zec": "^2.1.10", + "@bitgo/sdk-coin-zeta": "^3.0.29", + "@bitgo/sdk-coin-zketh": "^2.0.52", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/sdk-lib-mpc": "^10.1.0", + "@bitgo/sjcl": "^1.0.1", + "@bitgo/statics": "^50.20.0", + "@bitgo/unspents": "^0.47.17", + "@bitgo/utxo-lib": "^11.2.1", + "@types/bluebird": "^3.5.25", + "@types/superagent": "^4.1.3", + "bignumber.js": "^9.1.1", + "bluebird": "^3.5.3", + "fs-extra": "^9.1.0", + "lodash": "^4.17.14", + "openpgp": "5.10.1", + "stellar-sdk": "^10.0.1", + "superagent": "^9.0.1" + }, + "engines": { + "node": ">=18 <21", + "npm": ">=3.10.10" + }, + "optionalDependencies": { + "@ethereumjs/common": "^2.6.5", + "@ethereumjs/tx": "^3.3.0", + "ethereumjs-abi": "^0.6.5", + "ethereumjs-util": "7.1.5" + } + }, + "node_modules/bitgo/node_modules/@bitgo/sdk-coin-sui": { + "version": "5.8.19", + "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-sui/-/sdk-coin-sui-5.8.19.tgz", + "integrity": "sha512-axpv9x6bOU63F97E3W5lJ97NaEjUxJhv5xVePnw1V4DWCvKGhTS/VxabflRiONY6F1ia8wgAYEGftgWkbXy2Pg==", + "license": "MIT", + "dependencies": { + "@bitgo/blake2b": "^3.2.4", + "@bitgo/sdk-core": "^28.20.0", + "@bitgo/sdk-lib-mpc": "^10.1.0", + "@bitgo/statics": "^50.20.0", + "@mysten/bcs": "^0.7.0", + "bignumber.js": "^9.0.0", + "bs58": "^4.0.1", + "lodash": "^4.17.21", + "superagent": "3.8.2", + "superstruct": "^1.0.3", + "tweetnacl": "^1.0.3" + }, + "engines": { + "node": ">=18 <21" + } + }, + "node_modules/bitgo/node_modules/@bitgo/sdk-coin-sui/node_modules/superagent": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.2.tgz", + "integrity": "sha512-gVH4QfYHcY3P0f/BZzavLreHW3T1v7hG9B+hpMQotGQqurOvhv87GcMCd6LWySmBuf+BDR44TQd0aISjVHLeNQ==", + "deprecated": "Please upgrade to v9.0.0+ as we have fixed a public vulnerability with formidable dependency. Note that v9.0.0+ requires Node.js v14.18.0+. See https://github.com/ladjs/superagent/pull/1800 for insight. This project is supported and maintained by the team at Forward Email @ https://forwardemail.net", + "license": "MIT", + "dependencies": { + "component-emitter": "^1.2.0", + "cookiejar": "^2.1.0", + "debug": "^3.1.0", + "extend": "^3.0.0", + "form-data": "^2.3.1", + "formidable": "^1.1.1", + "methods": "^1.1.1", + "mime": "^1.4.1", + "qs": "^6.5.1", + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/bitgo/node_modules/@ethereumjs/common": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", + "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", + "license": "MIT", + "optional": true, + "dependencies": { + "crc-32": "^1.2.0", + "ethereumjs-util": "^7.1.5" + } + }, + "node_modules/bitgo/node_modules/@ethereumjs/tx": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.5.2.tgz", + "integrity": "sha512-gQDNJWKrSDGu2w7w0PzVXVBNMzb7wwdDOmOqczmhNjqFxFuIbhVJDwiGEnxFNC2/b8ifcZzY7MLcluizohRzNw==", + "license": "MPL-2.0", + "optional": true, + "dependencies": { + "@ethereumjs/common": "^2.6.4", + "ethereumjs-util": "^7.1.5" + } + }, + "node_modules/bitgo/node_modules/@types/superagent": { + "version": "4.1.24", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.24.tgz", + "integrity": "sha512-mEafCgyKiMFin24SDzWN7yAADt4gt6YawFiNMp0QS5ZPboORfyxFt0s3VzJKhTaKg9py/4FUmrHLTNfJKt9Rbw==", + "license": "MIT", + "dependencies": { + "@types/cookiejar": "*", + "@types/node": "*" + } + }, + "node_modules/bitgo/node_modules/debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/bitgo/node_modules/form-data": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.2.tgz", + "integrity": "sha512-GgwY0PS7DbXqajuGf4OYlsrIu3zgxD6Vvql43IBhm6MahqA5SK/7mwhtNj2AdH2z35YR34ujJ7BN+3fFC3jP5Q==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/bitgo/node_modules/formidable": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", + "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==", + "deprecated": "Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau", + "license": "MIT", + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, + "node_modules/bitgo/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/bitgo/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/bitgo/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/bitgo/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/bitgo/node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/bitgo/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/bitgo/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -22416,6 +34059,25 @@ "readable-stream": "^3.4.0" } }, + "node_modules/blakejs": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", + "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==", + "license": "MIT" + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "license": "MIT" + }, + "node_modules/blueimp-md5": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.19.0.tgz", + "integrity": "sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==", + "license": "MIT", + "peer": true + }, "node_modules/bn.js": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", @@ -22457,6 +34119,121 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/bolt11": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/bolt11/-/bolt11-1.4.1.tgz", + "integrity": "sha512-jR0Y+MO+CK2at1Cg5mltLJ+6tdOwNKoTS/DJOBDdzVkQ+R9D6UgZMayTWOsuzY7OgV1gEqlyT5Tzk6t6r4XcNQ==", + "license": "MIT", + "dependencies": { + "@types/bn.js": "^4.11.3", + "bech32": "^1.1.2", + "bitcoinjs-lib": "^6.0.0", + "bn.js": "^4.11.8", + "create-hash": "^1.2.0", + "lodash": "^4.17.11", + "safe-buffer": "^5.1.1", + "secp256k1": "^4.0.2" + } + }, + "node_modules/bolt11/node_modules/@types/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/bolt11/node_modules/base-x": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.0.tgz", + "integrity": "sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw==", + "license": "MIT" + }, + "node_modules/bolt11/node_modules/bech32": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", + "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", + "license": "MIT" + }, + "node_modules/bolt11/node_modules/bip174": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bip174/-/bip174-2.1.1.tgz", + "integrity": "sha512-mdFV5+/v0XyNYXjBS6CQPLo9ekCx4gtKZFnJm5PMto7Fs9hTTDpkkzOB7/FtluRI6JbUUAu+snTYfJRgHLZbZQ==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/bolt11/node_modules/bitcoinjs-lib": { + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/bitcoinjs-lib/-/bitcoinjs-lib-6.1.7.tgz", + "integrity": "sha512-tlf/r2DGMbF7ky1MgUqXHzypYHakkEnm0SZP23CJKIqNY/5uNAnMbFhMJdhjrL/7anfb/U8+AlpdjPWjPnAalg==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "^1.2.0", + "bech32": "^2.0.0", + "bip174": "^2.1.1", + "bs58check": "^3.0.1", + "typeforce": "^1.11.3", + "varuint-bitcoin": "^1.1.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/bolt11/node_modules/bitcoinjs-lib/node_modules/bech32": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz", + "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==", + "license": "MIT" + }, + "node_modules/bolt11/node_modules/bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "license": "MIT" + }, + "node_modules/bolt11/node_modules/bs58": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-5.0.0.tgz", + "integrity": "sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==", + "license": "MIT", + "dependencies": { + "base-x": "^4.0.0" + } + }, + "node_modules/bolt11/node_modules/bs58check": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-3.0.1.tgz", + "integrity": "sha512-hjuuJvoWEybo7Hn/0xOrczQKKEKD63WguEjlhLExYs2wUBcebDC1jDNK17eEAD2lYfw82d5ASC1d7K3SWszjaQ==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "^1.2.0", + "bs58": "^5.0.0" + } + }, + "node_modules/bolt11/node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", + "license": "MIT" + }, + "node_modules/bolt11/node_modules/secp256k1": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.4.tgz", + "integrity": "sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "elliptic": "^6.5.7", + "node-addon-api": "^5.0.0", + "node-gyp-build": "^4.2.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/bonjour-service": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", @@ -22471,6 +34248,17 @@ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" }, + "node_modules/borsh": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/borsh/-/borsh-0.7.0.tgz", + "integrity": "sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA==", + "license": "Apache-2.0", + "dependencies": { + "bn.js": "^5.2.0", + "bs58": "^4.0.0", + "text-encoding-utf-8": "^1.0.2" + } + }, "node_modules/bowser": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", @@ -22508,6 +34296,29 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/bplist-creator": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.1.0.tgz", + "integrity": "sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg==", + "license": "MIT", + "peer": true, + "dependencies": { + "stream-buffers": "2.2.x" + } + }, + "node_modules/bplist-parser": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.1.tgz", + "integrity": "sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA==", + "license": "MIT", + "peer": true, + "dependencies": { + "big-integer": "1.6.x" + }, + "engines": { + "node": ">= 5.10.0" + } + }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -22532,6 +34343,133 @@ "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" }, + "node_modules/browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "license": "MIT", + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "license": "MIT", + "dependencies": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "node_modules/browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/browserify-rsa": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.1.tgz", + "integrity": "sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==", + "license": "MIT", + "dependencies": { + "bn.js": "^5.2.1", + "randombytes": "^2.1.0", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/browserify-sign": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.3.tgz", + "integrity": "sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw==", + "license": "ISC", + "dependencies": { + "bn.js": "^5.2.1", + "browserify-rsa": "^4.1.0", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.5", + "hash-base": "~3.0", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.7", + "readable-stream": "^2.3.8", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/browserify-sign/node_modules/hash-base": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.5.tgz", + "integrity": "sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/browserify-sign/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/browserify-sign/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/browserify-sign/node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/browserify-sign/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/browserify-sign/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, "node_modules/browserslist": { "version": "4.24.2", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", @@ -22575,6 +34513,26 @@ "node": ">= 6" } }, + "node_modules/bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "license": "MIT", + "dependencies": { + "base-x": "^3.0.2" + } + }, + "node_modules/bs58check": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", + "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", + "license": "MIT", + "dependencies": { + "bs58": "^4.0.0", + "create-hash": "^1.1.0", + "safe-buffer": "^5.1.2" + } + }, "node_modules/bser": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", @@ -22599,7 +34557,6 @@ "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, "funding": [ { "type": "github", @@ -22619,11 +34576,57 @@ "ieee754": "^1.1.13" } }, + "node_modules/buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "license": "MIT", + "peer": true, + "dependencies": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "node_modules/buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", + "license": "MIT", + "peer": true + }, + "node_modules/buffer-equals": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/buffer-equals/-/buffer-equals-1.0.4.tgz", + "integrity": "sha512-99MsCq0j5+RhubVEtKQgKaD6EM+UP3xJgIvQqwJ3SOLDUekzxMX1ylXBng+Wa2sh7mGT0W6RUly8ojjr1Tt6nA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==", + "license": "MIT", + "peer": true + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, + "node_modules/buffer-to-arraybuffer": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz", + "integrity": "sha512-3dthu5CYiVB1DEJp61FtApNnNndTckcqe4pFcLdvHtrpG+kcyekCJKg4MRiDcFW7A6AODnXB9U4dwQiCW5kzJQ==", + "license": "MIT" + }, + "node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", + "license": "MIT" + }, "node_modules/bufferutil": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.8.tgz", @@ -22636,6 +34639,14 @@ "node": ">=6.14.2" } }, + "node_modules/builtins": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", + "integrity": "sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==", + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/bull": { "version": "4.16.4", "resolved": "https://registry.npmjs.org/bull/-/bull-4.16.4.tgz", @@ -22698,6 +34709,27 @@ "node": ">=10.16.0" } }, + "node_modules/bytebuffer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/bytebuffer/-/bytebuffer-5.0.1.tgz", + "integrity": "sha512-IuzSdmADppkZ6DlpycMkm8l9zeEq16fWtLvunEwFiYciR/BHo4E8/xs5piFquG+Za8OWmMqHF8zuRviz2LHvRQ==", + "license": "Apache-2.0", + "dependencies": { + "long": "~3" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/bytebuffer/node_modules/long": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", + "integrity": "sha512-ZYvPPOMqUwPoDsbJaR10iQJYnMuZhRTvHYl62ErLIEX7RgFlziSBUUvrt3OVfc47QlHHpzPZYP17g3Fv7oeJkg==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.6" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -22706,6 +34738,149 @@ "node": ">= 0.8" } }, + "node_modules/c32check": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/c32check/-/c32check-1.1.3.tgz", + "integrity": "sha512-ADADE/PjAbJRlwpG3ShaOMbBUlJJZO7xaYSRD5Tub6PixQlgR4s36y9cvMf/YRGpkqX+QOxIdMw216iC320q9A==", + "license": "MIT", + "dependencies": { + "base-x": "^3.0.8", + "buffer": "^5.6.0", + "cross-sha256": "^1.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cacache": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cacache/node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "license": "ISC", + "optional": true, + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/cacache/node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cacache/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cacache/node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cacache/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "optional": true, + "peer": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cacache/node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cacache/node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "license": "ISC", + "optional": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, "node_modules/cache-content-type": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.1.tgz", @@ -22883,6 +35058,156 @@ } ] }, + "node_modules/capability": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/capability/-/capability-0.2.5.tgz", + "integrity": "sha512-rsJZYVCgXd08sPqwmaIqjAd5SUTfonV0z/gDJ8D6cN8wQphky1kkAYEqQ+hmDxTw7UihvBfjUVUSY+DBEe44jg==", + "license": "MIT" + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "license": "Apache-2.0" + }, + "node_modules/cashaddress": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/cashaddress/-/cashaddress-1.1.0.tgz", + "integrity": "sha512-cdqIjZodtErhoQOiojQ1SRqDKh6bOVkLYNJjMmFEUxGoErrO2am8txotXmEi8glvU/y9wzup+LsvEBl8AttUwA==", + "license": "MIT", + "dependencies": { + "bigi": "^1.4.2" + } + }, + "node_modules/casper-js-sdk": { + "version": "2.7.6", + "resolved": "https://registry.npmjs.org/casper-js-sdk/-/casper-js-sdk-2.7.6.tgz", + "integrity": "sha512-sFxcMcxnV+aq/d/BHyA7WfMuNUP9sKyZDKNbF/00TJR6Ii730Xl94HXO3y0YNgM8hOiRH5vqAcxtdxEuRuifmQ==", + "license": "Apache 2.0", + "dependencies": { + "@ethersproject/bignumber": "^5.0.8", + "@ethersproject/bytes": "^5.0.5", + "@ethersproject/constants": "^5.0.5", + "@open-rpc/client-js": "^1.6.2", + "@types/eccrypto": "^1.1.2", + "@types/ws": "^8.2.2", + "blakejs": "^1.1.0", + "eccrypto": "^1.1.6", + "eslint-plugin-prettier": "^3.4.0", + "ethereum-cryptography": "^0.1.3", + "glob": "^7.1.6", + "humanize-duration": "^3.24.0", + "key-encoder": "^2.0.3", + "reflect-metadata": "^0.1.13", + "ts-results": "^3.2.1", + "tweetnacl-ts": "^1.0.3", + "tweetnacl-util": "^0.15.0", + "typedjson": "^1.6.0-rc2", + "webpack": "^5.24.3" + } + }, + "node_modules/casper-js-sdk/node_modules/ethereum-cryptography": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", + "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "license": "MIT", + "dependencies": { + "@types/pbkdf2": "^3.0.0", + "@types/secp256k1": "^4.0.1", + "blakejs": "^1.1.0", + "browserify-aes": "^1.2.0", + "bs58check": "^2.1.2", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "hash.js": "^1.1.7", + "keccak": "^3.0.0", + "pbkdf2": "^3.0.17", + "randombytes": "^2.1.0", + "safe-buffer": "^5.1.2", + "scrypt-js": "^3.0.0", + "secp256k1": "^4.0.1", + "setimmediate": "^1.0.5" + } + }, + "node_modules/casper-js-sdk/node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", + "license": "MIT" + }, + "node_modules/casper-js-sdk/node_modules/secp256k1": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.4.tgz", + "integrity": "sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "elliptic": "^6.5.7", + "node-addon-api": "^5.0.0", + "node-gyp-build": "^4.2.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/catharsis": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", + "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", + "license": "MIT", + "dependencies": { + "lodash": "^4.17.15" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cbor-extract": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cbor-extract/-/cbor-extract-2.2.0.tgz", + "integrity": "sha512-Ig1zM66BjLfTXpNgKpvBePq271BPOvu8MR0Jl080yG7Jsl+wAZunfrwiwA+9ruzm/WEdIV5QF/bjDZTqyAIVHA==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "node-gyp-build-optional-packages": "5.1.1" + }, + "bin": { + "download-cbor-prebuilds": "bin/download-prebuilds.js" + }, + "optionalDependencies": { + "@cbor-extract/cbor-extract-darwin-arm64": "2.2.0", + "@cbor-extract/cbor-extract-darwin-x64": "2.2.0", + "@cbor-extract/cbor-extract-linux-arm": "2.2.0", + "@cbor-extract/cbor-extract-linux-arm64": "2.2.0", + "@cbor-extract/cbor-extract-linux-x64": "2.2.0", + "@cbor-extract/cbor-extract-win32-x64": "2.2.0" + } + }, + "node_modules/cbor-extract/node_modules/node-gyp-build-optional-packages": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.1.1.tgz", + "integrity": "sha512-+P72GAjVAbTxjjwUmwjVrqrdZROD4nf8KgpBoDxqXXTiYZZt/ud60dE5yvCSr9lRO8e8yv6kgJIC0K0PfZFVQw==", + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.1" + }, + "bin": { + "node-gyp-build-optional-packages": "bin.js", + "node-gyp-build-optional-packages-optional": "optional.js", + "node-gyp-build-optional-packages-test": "build-test.js" + } + }, + "node_modules/cbor-x": { + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/cbor-x/-/cbor-x-1.5.9.tgz", + "integrity": "sha512-OEI5rEu3MeR0WWNUXuIGkxmbXVhABP+VtgAXzm48c9ulkrsvxshjjk94XSOGphyAKeNGLPfAxxzEtgQ6rEVpYQ==", + "license": "MIT", + "optionalDependencies": { + "cbor-extract": "^2.2.0" + } + }, "node_modules/cbw-sdk": { "name": "@coinbase/wallet-sdk", "version": "3.9.3", @@ -23010,6 +35335,17 @@ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, + "node_modules/charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", + "license": "BSD-3-Clause", + "optional": true, + "peer": true, + "engines": { + "node": "*" + } + }, "node_modules/cheerio": { "version": "1.0.0-rc.12", "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", @@ -23080,6 +35416,12 @@ "fsevents": "~2.3.2" } }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "license": "ISC" + }, "node_modules/chrome-launcher": { "version": "0.15.2", "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.2.tgz", @@ -23149,6 +35491,48 @@ "node": ">=8" } }, + "node_modules/cids": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/cids/-/cids-0.7.5.tgz", + "integrity": "sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA==", + "deprecated": "This module has been superseded by the multiformats module", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "class-is": "^1.1.0", + "multibase": "~0.6.0", + "multicodec": "^1.0.0", + "multihashes": "~0.4.15" + }, + "engines": { + "node": ">=4.0.0", + "npm": ">=3.0.0" + } + }, + "node_modules/cids/node_modules/multicodec": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-1.0.4.tgz", + "integrity": "sha512-NDd7FeS3QamVtbgfvu5h7fd1IlbaC4EQ0/pgU4zqE2vdHCmBGsUa0TiM8/TdSeG6BMPC92OOCf8F1ocE/Wkrrg==", + "deprecated": "This module has been superseded by the multiformats module", + "license": "MIT", + "dependencies": { + "buffer": "^5.6.0", + "varint": "^5.0.0" + } + }, + "node_modules/cipher-base": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.6.tgz", + "integrity": "sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/citty": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", @@ -23170,6 +35554,12 @@ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==" }, + "node_modules/class-is": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/class-is/-/class-is-1.1.0.tgz", + "integrity": "sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw==", + "license": "MIT" + }, "node_modules/class-transformer": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", @@ -23239,7 +35629,7 @@ "version": "2.6.1", "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", - "dev": true, + "devOptional": true, "engines": { "node": ">=6" }, @@ -23580,7 +35970,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.8" } @@ -23611,6 +36001,27 @@ "node": ">=0.10.0" } }, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "license": "MIT", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/clone-response/node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/clsx": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", @@ -23743,6 +36154,14 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/command-exists": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", + "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/commander": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", @@ -23773,7 +36192,17 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", - "dev": true, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/component-type": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/component-type/-/component-type-1.2.2.tgz", + "integrity": "sha512-99VUHREHiN5cLeHm3YLq312p6v+HUEcwtLCAtelvUDI6+SH5g5Cr85oNR2S1o6ywzL0ykMbuwLzM2ANocjEOIA==", + "license": "MIT", + "optional": true, + "peer": true, "funding": { "url": "https://github.com/sponsors/sindresorhus" } @@ -24114,6 +36543,17 @@ "node": ">= 0.6" } }, + "node_modules/content-hash": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/content-hash/-/content-hash-2.5.2.tgz", + "integrity": "sha512-FvIQKy0S1JaWV10sMsA7TRx8bpU+pqPkhbsfvOJAdjRXvYxEckAwQWGwtRjiaJfh+E0DvcWUGqcdjwMGFjsSdw==", + "license": "ISC", + "dependencies": { + "cids": "^0.7.1", + "multicodec": "^0.5.5", + "multihashes": "^0.4.15" + } + }, "node_modules/content-type": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", @@ -24148,8 +36588,7 @@ "node_modules/cookiejar": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", - "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", - "dev": true + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==" }, "node_modules/cookies": { "version": "0.8.0", @@ -24359,6 +36798,57 @@ } } }, + "node_modules/cosmjs-types": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/cosmjs-types/-/cosmjs-types-0.6.1.tgz", + "integrity": "sha512-fRz6yzElHHBULDyLArF/G1UkkTWW4r3RondBUGnmSsZWYI5NpfDn32MVa5aRmpaaf4tJI2cbnXHs9fykwU7Ttg==", + "license": "Apache-2.0", + "dependencies": { + "long": "^4.0.0", + "protobufjs": "~6.11.2" + } + }, + "node_modules/cosmjs-types/node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", + "license": "Apache-2.0" + }, + "node_modules/cosmjs-types/node_modules/protobufjs": { + "version": "6.11.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.4.tgz", + "integrity": "sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "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/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + }, + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" + } + }, + "node_modules/crc": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "license": "MIT", + "dependencies": { + "buffer": "^5.1.0" + } + }, "node_modules/crc-32": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", @@ -24370,6 +36860,49 @@ "node": ">=0.8" } }, + "node_modules/create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + } + }, + "node_modules/create-ecdh/node_modules/bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "license": "MIT" + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, "node_modules/create-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", @@ -24416,6 +36949,15 @@ "node-fetch": "^2.6.12" } }, + "node_modules/cross-sha256": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/cross-sha256/-/cross-sha256-1.2.0.tgz", + "integrity": "sha512-KViLNMDZKV7jwFqjFx+rNhG26amnFYYQ0S+VaFlVvpk8tM+2XbFia/don/SjGHg9WQxnFVi6z64CGPuF3T+nNw==", + "license": "(MIT AND BSD-3-Clause)", + "dependencies": { + "buffer": "^5.6.0" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -24437,6 +36979,45 @@ "uncrypto": "^0.1.3" } }, + "node_modules/crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", + "license": "BSD-3-Clause", + "optional": true, + "peer": true, + "engines": { + "node": "*" + } + }, + "node_modules/crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "license": "MIT", + "dependencies": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + }, + "engines": { + "node": "*" + } + }, + "node_modules/crypto-js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==", + "license": "MIT" + }, "node_modules/crypto-random-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", @@ -24610,6 +37191,12 @@ "node": ">=4" } }, + "node_modules/cssfilter": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/cssfilter/-/cssfilter-0.0.10.tgz", + "integrity": "sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw==", + "license": "MIT" + }, "node_modules/cssnano": { "version": "6.1.2", "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-6.1.2.tgz", @@ -24762,17 +37349,49 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, + "node_modules/d": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", + "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", + "license": "ISC", + "dependencies": { + "es5-ext": "^0.10.64", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/dag-map": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/dag-map/-/dag-map-1.0.2.tgz", + "integrity": "sha512-+LSAiGFwQ9dRnRdOeaj7g47ZFJcOUPukAP8J3A3fuZ1g9Y44BG+P1sgApjLXTQPOzC4+7S9Wr8kXsfpINM4jpw==", + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", "dev": true }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/data-uri-to-buffer": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", - "dev": true, "engines": { "node": ">= 14" } @@ -24857,6 +37476,15 @@ "node": ">=4.0" } }, + "node_modules/dateformat": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", + "license": "MIT", + "engines": { + "node": "*" + } + }, "node_modules/debounce": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", @@ -24980,8 +37608,7 @@ "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "devOptional": true + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" }, "node_modules/deepmerge": { "version": "4.3.1", @@ -25034,7 +37661,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dev": true, + "devOptional": true, "dependencies": { "clone": "^1.0.2" }, @@ -25099,7 +37726,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", - "dev": true, "dependencies": { "ast-types": "^0.13.4", "escodegen": "^2.1.0", @@ -25113,7 +37739,6 @@ "version": "0.13.4", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", - "dev": true, "dependencies": { "tslib": "^2.0.1" }, @@ -25142,6 +37767,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/delay": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz", + "integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -25180,6 +37817,16 @@ "node": ">=6" } }, + "node_modules/des.js": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz", + "integrity": "sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, "node_modules/destr": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.3.tgz", @@ -25288,7 +37935,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", - "dev": true, "dependencies": { "asap": "^2.0.0", "wrappy": "1" @@ -25318,6 +37964,23 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "node_modules/diffie-hellman/node_modules/bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "license": "MIT" + }, "node_modules/dijkstrajs": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", @@ -25355,7 +38018,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "devOptional": true, "dependencies": { "esutils": "^2.0.2" }, @@ -25390,6 +38052,11 @@ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, + "node_modules/dom-walk": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", + "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" + }, "node_modules/domelementtype": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", @@ -25516,11 +38183,32 @@ "node": ">=4" } }, + "node_modules/drbg.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/drbg.js/-/drbg.js-1.0.1.tgz", + "integrity": "sha512-F4wZ06PvqxYLFEZKkFxTDcns9oFNk34hvmJSEwdzsxVQ8YI5YaxtACgQatkYgv2VI2CFkUd2Y+xosPQnHv809g==", + "license": "MIT", + "optional": true, + "dependencies": { + "browserify-aes": "^1.0.6", + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/duplexer": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" }, + "node_modules/duplexer3": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz", + "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==", + "license": "BSD-3-Clause" + }, "node_modules/duplexify": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.3.tgz", @@ -25546,6 +38234,92 @@ "wcwidth": ">=1.0.1" } }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "license": "MIT", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/ecc-jsbn/node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "license": "MIT" + }, + "node_modules/eccrypto": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/eccrypto/-/eccrypto-1.1.6.tgz", + "integrity": "sha512-d78ivVEzu7Tn0ZphUUaL43+jVPKTMPFGtmgtz1D0LrFn7cY3K8CdrvibuLz2AAkHBLKZtR8DMbB2ukRYFk987A==", + "hasInstallScript": true, + "license": "CC0-1.0", + "dependencies": { + "acorn": "7.1.1", + "elliptic": "6.5.4", + "es6-promise": "4.2.8", + "nan": "2.14.0" + }, + "optionalDependencies": { + "secp256k1": "3.7.1" + } + }, + "node_modules/eccrypto/node_modules/acorn": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz", + "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/eccrypto/node_modules/bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "license": "MIT" + }, + "node_modules/eccrypto/node_modules/elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/eccrypto/node_modules/secp256k1": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.7.1.tgz", + "integrity": "sha512-1cf8sbnRreXrQFdH6qsg2H71Xw91fCCS9Yp021GnUNJzWJS/py96fS4lHbnTnouLp08Xj6jBoBB6V78Tdbdu5g==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "bindings": "^1.5.0", + "bip66": "^1.1.5", + "bn.js": "^4.11.8", + "create-hash": "^1.2.0", + "drbg.js": "^1.0.1", + "elliptic": "^6.4.1", + "nan": "^2.14.0", + "safe-buffer": "^5.1.2" + }, + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/eciesjs": { "version": "0.3.21", "resolved": "https://registry.npmjs.org/eciesjs/-/eciesjs-0.3.21.tgz", @@ -25557,6 +38331,30 @@ "secp256k1": "^5.0.1" } }, + "node_modules/ecpair": { + "name": "@bitgo/ecpair", + "version": "2.1.0-rc.0", + "resolved": "https://registry.npmjs.org/@bitgo/ecpair/-/ecpair-2.1.0-rc.0.tgz", + "integrity": "sha512-qPZetcEA1Lzzm9NsqsGF9NGorAGaXrv20eZjopLUjsdwftWcsYTE7lwzE/Xjdf4fcq6G4+vjrCudWAMGNfJqOQ==", + "license": "MIT", + "dependencies": { + "randombytes": "^2.1.0", + "typeforce": "^1.18.0", + "wif": "^2.0.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ecurve": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/ecurve/-/ecurve-1.0.5.tgz", + "integrity": "sha512-1Z3Zu5Nh5LSVGnwEnie1LDoHZByZxG2tk3wftkqeVHrfujmR8O+dOh96HVPxRPh4BjRWX0Z9mpwCYv/O/njgDw==", + "license": "MIT", + "dependencies": { + "bigi": "^1.1.0" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -25657,6 +38455,29 @@ "node": ">= 0.8" } }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "license": "MIT", + "peer": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "peer": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -25740,6 +38561,142 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/env-editor": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/env-editor/-/env-editor-0.4.2.tgz", + "integrity": "sha512-ObFo8v4rQJAE59M69QzwloxPZtd33TpYEIjtKD1rrFDcM1Gd7IkDxEBU+HriziN6HSHQnBJi8Dmy+JWkav5HKA==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eol": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/eol/-/eol-0.5.1.tgz", + "integrity": "sha512-mlG6+lv5G7pXnSK/k7jh7B++h3nIxoNdevctYQWfd14UUvowwseRWpYdqXdYeumDwPAp69DorsnK/eWK9lm4AA==", + "license": "MIT" + }, + "node_modules/eosjs": { + "version": "21.0.4", + "resolved": "https://registry.npmjs.org/eosjs/-/eosjs-21.0.4.tgz", + "integrity": "sha512-XbuIoidplA1hHIejy7VQ+hmBfC6T28kYFaQMsn6G1DMTg1CFwUzxwzUvZg/dGNPuf7hgPxOpaQvAUsdidTgGhQ==", + "license": "MIT", + "dependencies": { + "bn.js": "5.2.0", + "elliptic": "6.5.4", + "hash.js": "1.1.7", + "pako": "2.0.3" + } + }, + "node_modules/eosjs-ecc": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eosjs-ecc/-/eosjs-ecc-4.0.7.tgz", + "integrity": "sha512-uuqhqnrDy9XTpKfkhiZqRDUTCCI9oWBalVK5IosL7kpYwA9I3lm68INYFLyWsHpF2xwHqPql8MrMYJ3zfOn5Qg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "7.6.0", + "bigi": "1.4.2", + "browserify-aes": "1.0.6", + "bs58": "4.0.1", + "bytebuffer": "5.0.1", + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "ecurve": "1.0.5", + "randombytes": "2.0.5" + } + }, + "node_modules/eosjs-ecc/node_modules/@babel/runtime": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.0.tgz", + "integrity": "sha512-89eSBLJsxNxOERC0Op4vd+0Bqm6wRMqMbFtV3i0/fbaWw/mJ8Q3eBvgX0G4SyrOOLCtbu98HspF8o09MRT+KzQ==", + "license": "MIT", + "dependencies": { + "regenerator-runtime": "^0.13.2" + } + }, + "node_modules/eosjs-ecc/node_modules/browserify-aes": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.0.6.tgz", + "integrity": "sha512-MMvWM6jpfsiuzY2Y+pRJvHRac3x3rHWQisWoz1dJaF9qDFsD8HdVxB7MyZKeLKeEt0fEjrXXZ0mxgTHSoJusug==", + "license": "MIT", + "dependencies": { + "buffer-xor": "^1.0.2", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/eosjs-ecc/node_modules/create-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", + "integrity": "sha512-snRpch/kwQhcdlnZKYanNF1m0RDlrCdSKQaH87w1FCFPVPNCQ/Il9QJKAX2jVBZddRdaHBMC+zXa9Gw9tmkNUA==", + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "sha.js": "^2.4.0" + } + }, + "node_modules/eosjs-ecc/node_modules/create-hmac": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", + "integrity": "sha512-23osI7H2SH6Zm4g7A7BTM9+3XicGZkemw00eEhrFViR3EdGru+azj2fMKf9J2zWMGO7AfPgYRdIRL96kkdy8QA==", + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/eosjs-ecc/node_modules/randombytes": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz", + "integrity": "sha512-8T7Zn1AhMsQ/HI1SjcCfT/t4ii3eAqco3yOcSzS4mozsOz69lHLsoMXmF9nZgnFanYscnSlUSgs8uZyKzpE6kg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/eosjs-ecc/node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "license": "MIT" + }, + "node_modules/eosjs/node_modules/bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", + "license": "MIT" + }, + "node_modules/eosjs/node_modules/elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/eosjs/node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "license": "MIT" + }, "node_modules/errno": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", @@ -25767,6 +38724,17 @@ "integrity": "sha512-JM8N6PytDbmIYm1IhPWlo8vr3NtfjhDY/1MhD/a5b/aad/USE8a0+NsqE9d5n+GVGmuNkPQWm4bFQWv18d8tMg==", "dev": true }, + "node_modules/error-polyfill": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/error-polyfill/-/error-polyfill-0.1.3.tgz", + "integrity": "sha512-XHJk60ufE+TG/ydwp4lilOog549iiQF2OAPhkk9DdiYWMrltz5yhDz/xnKuenNwP7gy3dsibssO5QpVhkrSzzg==", + "license": "MIT", + "dependencies": { + "capability": "^0.2.5", + "o3": "^1.0.3", + "u3": "^0.1.1" + } + }, "node_modules/error-stack-parser": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", @@ -25954,6 +38922,79 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es5-ext": { + "version": "0.10.64", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", + "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", + "hasInstallScript": true, + "license": "ISC", + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "esniff": "^2.0.1", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "license": "MIT", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-object-assign": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", + "integrity": "sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw==", + "license": "MIT" + }, + "node_modules/es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", + "license": "MIT" + }, + "node_modules/es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==", + "license": "MIT", + "dependencies": { + "es6-promise": "^4.0.3" + } + }, + "node_modules/es6-symbol": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz", + "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==", + "license": "ISC", + "dependencies": { + "d": "^1.0.2", + "ext": "^1.7.0" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "license": "ISC", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -25993,7 +39034,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", - "dev": true, "dependencies": { "esprima": "^4.0.1", "estraverse": "^5.2.0", @@ -26014,7 +39054,6 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, "optional": true, "engines": { "node": ">=0.10.0" @@ -26024,7 +39063,6 @@ "version": "8.57.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", - "devOptional": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -26604,6 +39642,27 @@ "node": "*" } }, + "node_modules/eslint-plugin-prettier": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz", + "integrity": "sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==", + "license": "MIT", + "dependencies": { + "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "peerDependencies": { + "eslint": ">=5.0.0", + "prettier": ">=1.13.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } + } + }, "node_modules/eslint-plugin-react": { "version": "7.34.3", "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.3.tgz", @@ -26703,7 +39762,6 @@ "version": "7.2.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "devOptional": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -26719,7 +39777,6 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "devOptional": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -26731,7 +39788,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "devOptional": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -26747,7 +39803,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "devOptional": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -26757,7 +39812,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "devOptional": true, "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -26773,7 +39827,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "devOptional": true, "dependencies": { "is-glob": "^4.0.3" }, @@ -26785,7 +39838,6 @@ "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "devOptional": true, "dependencies": { "type-fest": "^0.20.2" }, @@ -26799,14 +39851,12 @@ "node_modules/eslint/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "devOptional": true + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "node_modules/eslint/node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "devOptional": true, "dependencies": { "p-locate": "^5.0.0" }, @@ -26821,7 +39871,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "devOptional": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -26833,7 +39882,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "devOptional": true, "dependencies": { "p-limit": "^3.0.2" }, @@ -26848,7 +39896,6 @@ "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "devOptional": true, "engines": { "node": ">=10" }, @@ -26856,11 +39903,25 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/esniff": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", + "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", + "license": "ISC", + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "event-emitter": "^0.3.5", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/espree": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "devOptional": true, "dependencies": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", @@ -26889,7 +39950,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", - "devOptional": true, "dependencies": { "estraverse": "^5.1.0" }, @@ -27074,6 +40134,22 @@ "node": ">=10" } }, + "node_modules/eth-ens-namehash": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz", + "integrity": "sha512-VWEI1+KJfz4Km//dadyvBBoBeSQ0MHTXPvr8UIXiLW6IanxvAV+DmlZAijZwAyggqGUfwQBeHf7tc9wzc1piSw==", + "license": "ISC", + "dependencies": { + "idna-uts46-hx": "^2.3.1", + "js-sha3": "^0.5.7" + } + }, + "node_modules/eth-ens-namehash/node_modules/js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha512-GII20kjaPX0zJ8wzkTbNDYMY7msuZcTWk8S5UOh6806Jq/wz1J8/bnr8uGU0DAUmYDjj2Mr4X1cW8v/GLYnR+g==", + "license": "MIT" + }, "node_modules/eth-json-rpc-filters": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/eth-json-rpc-filters/-/eth-json-rpc-filters-6.0.1.tgz", @@ -27100,6 +40176,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/eth-lib": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", + "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/eth-lib/node_modules/bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "license": "MIT" + }, "node_modules/eth-query": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/eth-query/-/eth-query-2.1.2.tgz", @@ -27117,6 +40210,15 @@ "fast-safe-stringify": "^2.0.6" } }, + "node_modules/ethereum-bloom-filters": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.2.0.tgz", + "integrity": "sha512-28hyiE7HVsWubqhpVLVmZXFd4ITeHi+BUu05o9isf0GUpMtzBUi+8/gFrGaGYzvGAJQmJ3JKj77Mk9G98T84rA==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "^1.4.0" + } + }, "node_modules/ethereum-cryptography": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", @@ -27152,6 +40254,325 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/ethereumjs-abi": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz", + "integrity": "sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==", + "deprecated": "This library has been deprecated and usage is discouraged.", + "license": "MIT", + "dependencies": { + "bn.js": "^4.11.8", + "ethereumjs-util": "^6.0.0" + } + }, + "node_modules/ethereumjs-abi/node_modules/@types/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/ethereumjs-abi/node_modules/bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "license": "MIT" + }, + "node_modules/ethereumjs-abi/node_modules/ethereum-cryptography": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", + "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "license": "MIT", + "dependencies": { + "@types/pbkdf2": "^3.0.0", + "@types/secp256k1": "^4.0.1", + "blakejs": "^1.1.0", + "browserify-aes": "^1.2.0", + "bs58check": "^2.1.2", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "hash.js": "^1.1.7", + "keccak": "^3.0.0", + "pbkdf2": "^3.0.17", + "randombytes": "^2.1.0", + "safe-buffer": "^5.1.2", + "scrypt-js": "^3.0.0", + "secp256k1": "^4.0.1", + "setimmediate": "^1.0.5" + } + }, + "node_modules/ethereumjs-abi/node_modules/ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "license": "MPL-2.0", + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, + "node_modules/ethereumjs-abi/node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", + "license": "MIT" + }, + "node_modules/ethereumjs-abi/node_modules/secp256k1": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.4.tgz", + "integrity": "sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "elliptic": "^6.5.7", + "node-addon-api": "^5.0.0", + "node-gyp-build": "^4.2.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/ethereumjs-common": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/ethereumjs-common/-/ethereumjs-common-1.5.2.tgz", + "integrity": "sha512-hTfZjwGX52GS2jcVO6E2sx4YuFnf0Fhp5ylo4pEPhEffNln7vS59Hr5sLnp3/QCazFLluuBZ+FZ6J5HTp0EqCA==", + "deprecated": "New package name format for new versions: @ethereumjs/common. Please update.", + "license": "MIT" + }, + "node_modules/ethereumjs-tx": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz", + "integrity": "sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw==", + "deprecated": "New package name format for new versions: @ethereumjs/tx. Please update.", + "license": "MPL-2.0", + "dependencies": { + "ethereumjs-common": "^1.5.0", + "ethereumjs-util": "^6.0.0" + } + }, + "node_modules/ethereumjs-tx/node_modules/@types/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/ethereumjs-tx/node_modules/bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "license": "MIT" + }, + "node_modules/ethereumjs-tx/node_modules/ethereum-cryptography": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", + "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "license": "MIT", + "dependencies": { + "@types/pbkdf2": "^3.0.0", + "@types/secp256k1": "^4.0.1", + "blakejs": "^1.1.0", + "browserify-aes": "^1.2.0", + "bs58check": "^2.1.2", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "hash.js": "^1.1.7", + "keccak": "^3.0.0", + "pbkdf2": "^3.0.17", + "randombytes": "^2.1.0", + "safe-buffer": "^5.1.2", + "scrypt-js": "^3.0.0", + "secp256k1": "^4.0.1", + "setimmediate": "^1.0.5" + } + }, + "node_modules/ethereumjs-tx/node_modules/ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "license": "MPL-2.0", + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, + "node_modules/ethereumjs-tx/node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", + "license": "MIT" + }, + "node_modules/ethereumjs-tx/node_modules/secp256k1": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.4.tgz", + "integrity": "sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "elliptic": "^6.5.7", + "node-addon-api": "^5.0.0", + "node-gyp-build": "^4.2.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/ethereumjs-util": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz", + "integrity": "sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==", + "license": "MPL-2.0", + "dependencies": { + "@types/bn.js": "^5.1.0", + "bn.js": "^5.1.2", + "create-hash": "^1.1.2", + "ethereum-cryptography": "^0.1.3", + "rlp": "^2.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/ethereumjs-util/node_modules/ethereum-cryptography": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", + "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "license": "MIT", + "dependencies": { + "@types/pbkdf2": "^3.0.0", + "@types/secp256k1": "^4.0.1", + "blakejs": "^1.1.0", + "browserify-aes": "^1.2.0", + "bs58check": "^2.1.2", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "hash.js": "^1.1.7", + "keccak": "^3.0.0", + "pbkdf2": "^3.0.17", + "randombytes": "^2.1.0", + "safe-buffer": "^5.1.2", + "scrypt-js": "^3.0.0", + "secp256k1": "^4.0.1", + "setimmediate": "^1.0.5" + } + }, + "node_modules/ethereumjs-util/node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", + "license": "MIT" + }, + "node_modules/ethereumjs-util/node_modules/secp256k1": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.4.tgz", + "integrity": "sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "elliptic": "^6.5.7", + "node-addon-api": "^5.0.0", + "node-gyp-build": "^4.2.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/ethers": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", + "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/abi": "5.7.0", + "@ethersproject/abstract-provider": "5.7.0", + "@ethersproject/abstract-signer": "5.7.0", + "@ethersproject/address": "5.7.0", + "@ethersproject/base64": "5.7.0", + "@ethersproject/basex": "5.7.0", + "@ethersproject/bignumber": "5.7.0", + "@ethersproject/bytes": "5.7.0", + "@ethersproject/constants": "5.7.0", + "@ethersproject/contracts": "5.7.0", + "@ethersproject/hash": "5.7.0", + "@ethersproject/hdnode": "5.7.0", + "@ethersproject/json-wallets": "5.7.0", + "@ethersproject/keccak256": "5.7.0", + "@ethersproject/logger": "5.7.0", + "@ethersproject/networks": "5.7.1", + "@ethersproject/pbkdf2": "5.7.0", + "@ethersproject/properties": "5.7.0", + "@ethersproject/providers": "5.7.2", + "@ethersproject/random": "5.7.0", + "@ethersproject/rlp": "5.7.0", + "@ethersproject/sha2": "5.7.0", + "@ethersproject/signing-key": "5.7.0", + "@ethersproject/solidity": "5.7.0", + "@ethersproject/strings": "5.7.0", + "@ethersproject/transactions": "5.7.0", + "@ethersproject/units": "5.7.0", + "@ethersproject/wallet": "5.7.0", + "@ethersproject/web": "5.7.1", + "@ethersproject/wordlists": "5.7.0" + } + }, + "node_modules/ethjs-unit": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", + "integrity": "sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw==", + "license": "MIT", + "dependencies": { + "bn.js": "4.11.6", + "number-to-bn": "1.7.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/ethjs-unit/node_modules/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==", + "license": "MIT" + }, + "node_modules/ethjs-util": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", + "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", + "license": "MIT", + "dependencies": { + "is-hex-prefixed": "1.0.0", + "strip-hex-prefix": "1.0.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, "node_modules/eval": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/eval/-/eval-0.1.8.tgz", @@ -27164,12 +40585,21 @@ "node": ">= 0.8" } }, + "node_modules/event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", + "license": "MIT", + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, "node_modules/event-target-shim": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=6" } @@ -27192,6 +40622,33 @@ "node": ">=0.8.x" } }, + "node_modules/eventsource": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.1.2.tgz", + "integrity": "sha512-xAH3zWhgO2/3KIniEKYPr8plNSzlGINOUqYj0m0u7AB81iRw8b/3E73W6AuU+6klLbaSFmZnaETQ2lXPfAydrA==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "license": "MIT", + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/exec-async": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/exec-async/-/exec-async-2.2.0.tgz", + "integrity": "sha512-87OpwcEiMia/DeiKFzaQNBNFeN3XkkpYIh9FyOqq5mS2oKv3CBE67PXoEKcr6nodWdXNogTiQ0jE2NGuoffXPw==", + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -27251,6 +40708,406 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/expo": { + "version": "44.0.6", + "resolved": "https://registry.npmjs.org/expo/-/expo-44.0.6.tgz", + "integrity": "sha512-iHnra6uD5kXZgdSUrvxZ3sLjg1FtgtA4p4uaSKVQ39IaMHJBngo8RKqFUJ+BF2kPDpBLJ251eLlhgYUlnAyuag==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.14.0", + "@expo/metro-config": "~0.2.6", + "@expo/vector-icons": "^12.0.4", + "babel-preset-expo": "~9.0.2", + "cross-spawn": "^6.0.5", + "expo-application": "~4.0.2", + "expo-asset": "~8.4.6", + "expo-constants": "~13.0.2", + "expo-file-system": "~13.1.3", + "expo-font": "~10.0.5", + "expo-keep-awake": "~10.0.2", + "expo-modules-autolinking": "0.5.5", + "expo-modules-core": "0.6.5", + "fbemitter": "^2.1.1", + "invariant": "^2.2.4", + "md5-file": "^3.2.3", + "pretty-format": "^26.5.2", + "uuid": "^3.4.0" + }, + "bin": { + "expo": "bin/cli.js" + }, + "optionalDependencies": { + "expo-error-recovery": "~3.0.5" + } + }, + "node_modules/expo-application": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/expo-application/-/expo-application-4.0.2.tgz", + "integrity": "sha512-ngTaFplTkWn0X45gMC+VNXGyJfGxX4wOwKmtr17rNMVWOQUhhLlyMkTj9bAamzsuwZh35l3S/eD/N1aMWWUwMw==", + "license": "MIT", + "peer": true, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-asset": { + "version": "8.4.6", + "resolved": "https://registry.npmjs.org/expo-asset/-/expo-asset-8.4.6.tgz", + "integrity": "sha512-Kpzcmmf1lceHnZkAdJOvq7l7SU/hCL59vAj2xUZS66U6lFkUf7LNEA/NzILA56loCd4cka5ShYlWs+BMchyFDQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "blueimp-md5": "^2.10.0", + "invariant": "^2.2.4", + "md5-file": "^3.2.3", + "path-browserify": "^1.0.0", + "url-parse": "^1.4.4" + } + }, + "node_modules/expo-constants": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-13.0.2.tgz", + "integrity": "sha512-vGs/kI65vplPFvG8z4W1ariGEtVHHp9Avl28G0zJprt2v/q1E/BnXjwvFSBPc1GB+Zb/7crWSHWRwjaFULBjsg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@expo/config": "^6.0.6", + "uuid": "^3.3.2" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-constants/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "license": "MIT", + "peer": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/expo-crypto": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/expo-crypto/-/expo-crypto-10.2.0.tgz", + "integrity": "sha512-YVFp+DJXBtt4t6oZXepnzb+xwpKzFbXn3B9Oma1Tfh6J0rIlm/I20UW/5apdvEdbj44fxJ5DsiZeyADI3bcZkQ==", + "license": "MIT", + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-error-recovery": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/expo-error-recovery/-/expo-error-recovery-3.0.5.tgz", + "integrity": "sha512-VM6OOecjt0aPu5/eCdGGJfNjvAZIemaQym0JF/+SA5IlLiPpEfbVCDTO/5yiS8Zb5fKpeABx+GCRmtfnFqvRRw==", + "license": "MIT", + "optional": true, + "peer": true, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-file-system": { + "version": "13.1.4", + "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-13.1.4.tgz", + "integrity": "sha512-/C2FKCzrdWuEt4m8Pzl9J4MhKgfU0denVLbqoKjidv8DnsLQrscFNlLhXuiooqWwsxB2OWAtGEVnPGJBWVuNEQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@expo/config-plugins": "^4.0.2", + "uuid": "^3.4.0" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-file-system/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "license": "MIT", + "peer": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/expo-font": { + "version": "10.0.5", + "resolved": "https://registry.npmjs.org/expo-font/-/expo-font-10.0.5.tgz", + "integrity": "sha512-x9YwM0xLkDdSvFjeNbyuh33Q1Hk3uc2jbMuuAN5W2ZVcUZqG0M8GCX/KV/D/7rYqdXKbliQA5r44MyDwZe/XRw==", + "license": "MIT", + "peer": true, + "dependencies": { + "fontfaceobserver": "^2.1.0" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-keep-awake": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-10.0.2.tgz", + "integrity": "sha512-Ro1lgyKldbFs4mxhWM+goX9sg0S2SRR8FiJJeOvaRzf8xNhrZfWA00Zpr+/3ocCoWQ3eEL+X9UF4PXXHf0KoOg==", + "license": "MIT", + "peer": true, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-modules-autolinking": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-0.5.5.tgz", + "integrity": "sha512-bILEG0Fg+ZhIhdEaShHzsEN1WC0hUmXJ5Kcd4cd+8rVk1Ead9vRZxA/yLx1cNBDCOwMe0GAMrhF7TKT+A1P+YA==", + "license": "MIT", + "peer": true, + "dependencies": { + "chalk": "^4.1.0", + "commander": "^7.2.0", + "fast-glob": "^3.2.5", + "find-up": "^5.0.0", + "fs-extra": "^9.1.0" + }, + "bin": { + "expo-modules-autolinking": "bin/expo-modules-autolinking.js" + } + }, + "node_modules/expo-modules-autolinking/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/expo-modules-autolinking/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "license": "MIT", + "peer": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/expo-modules-autolinking/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/expo-modules-autolinking/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "license": "MIT", + "peer": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/expo-modules-autolinking/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "license": "MIT", + "peer": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/expo-modules-core": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-0.6.5.tgz", + "integrity": "sha512-h/9+SJ3m8XkDUV1QrPO8WeXaeRYWLBJrOqhokDyhgWUYSqe6JOuRx1ZkoGq/GmTiwjouRDbXPsXUBiU9HWLYyA==", + "license": "MIT", + "peer": true, + "dependencies": { + "compare-versions": "^3.4.0", + "invariant": "^2.2.4" + } + }, + "node_modules/expo-modules-core/node_modules/compare-versions": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", + "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", + "license": "MIT", + "peer": true + }, + "node_modules/expo-random": { + "version": "12.3.0", + "resolved": "https://registry.npmjs.org/expo-random/-/expo-random-12.3.0.tgz", + "integrity": "sha512-q+AsTfGNT+Q+fb2sRrYtRkI3g5tV4H0kuYXM186aueILGO/vLn/YYFa7xFZj1IZ8LJZg2h96JDPDpsqHfRG2mQ==", + "deprecated": "This package is now deprecated in favor of expo-crypto, which provides the same functionality. To migrate, replace all imports from expo-random with imports from expo-crypto.", + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.0" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo/node_modules/@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/expo/node_modules/@types/yargs": { + "version": "15.0.19", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.19.tgz", + "integrity": "sha512-2XUaGVmyQjgyAZldf0D0c14vvo/yv0MhQBSTJcejMMaitsn3nxCB6TmH4G0ZQf+uxROOa9mpanoSm8h6SG/1ZA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/expo/node_modules/cross-spawn": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", + "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", + "license": "MIT", + "peer": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/expo/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/expo/node_modules/pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/expo/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/expo/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "license": "MIT", + "peer": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expo/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expo/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "license": "MIT", + "peer": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/expo/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "license": "ISC", + "peer": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, "node_modules/exponential-backoff": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", @@ -27317,6 +41174,15 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, + "node_modules/ext": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", + "license": "ISC", + "dependencies": { + "type": "^2.7.2" + } + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -27371,16 +41237,44 @@ "node": ">=0.6.0" } }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "engines": [ + "node >=0.6.0" + ], + "license": "MIT" + }, + "node_modules/eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==", + "engines": { + "node": "> 0.1.90" + } + }, + "node_modules/fast-copy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.2.tgz", + "integrity": "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==", + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "license": "Apache-2.0" + }, "node_modules/fast-glob": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", - "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -27400,8 +41294,7 @@ "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "devOptional": true + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" }, "node_modules/fast-redact": { "version": "3.5.0", @@ -27416,6 +41309,12 @@ "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" }, + "node_modules/fast-stable-stringify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-stable-stringify/-/fast-stable-stringify-1.0.0.tgz", + "integrity": "sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag==", + "license": "MIT" + }, "node_modules/fast-url-parser": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", @@ -27445,6 +41344,12 @@ "fxparser": "src/cli/cli.js" } }, + "node_modules/fastpriorityqueue": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/fastpriorityqueue/-/fastpriorityqueue-0.7.5.tgz", + "integrity": "sha512-3Pa0n9gwy8yIbEsT3m2j/E9DXgWvvjfiZjjqcJ+AdNKTAlVMIuFYrYG5Y3RHEM8O6cwv9hOpOWY/NaMfywoQVA==", + "license": "Apache-2.0" + }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", @@ -27484,6 +41389,90 @@ "bser": "2.1.1" } }, + "node_modules/fbemitter": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fbemitter/-/fbemitter-2.1.1.tgz", + "integrity": "sha512-hd8PgD+Q6RQtlcGrkM9oY3MFIjq6CA6wurCK1TKn2eaA76Ww4VAOihmq98NyjRhjJi/axgznZnh9lF8+TcTsNQ==", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "fbjs": "^0.8.4" + } + }, + "node_modules/fbjs": { + "version": "0.8.18", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.18.tgz", + "integrity": "sha512-EQaWFK+fEPSoibjNy8IxUtaFOMXcWsY0JaVrQoZR9zC8N2Ygf9iDITPWjUTVIax95b6I742JFLqASHfsag/vKA==", + "license": "MIT", + "peer": true, + "dependencies": { + "core-js": "^1.0.0", + "isomorphic-fetch": "^2.1.1", + "loose-envify": "^1.0.0", + "object-assign": "^4.1.0", + "promise": "^7.1.1", + "setimmediate": "^1.0.5", + "ua-parser-js": "^0.7.30" + } + }, + "node_modules/fbjs-css-vars": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz", + "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==", + "license": "MIT", + "optional": true, + "peer": true + }, + "node_modules/fbjs/node_modules/core-js": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "integrity": "sha512-ZiPp9pZlgxpWRu0M+YWbm6+aQ84XEfH1JRXvfOc/fILWI0VKhLC2LX13X1NYq4fULzLMq7Hfh43CSo2/aIaUPA==", + "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", + "license": "MIT", + "peer": true + }, + "node_modules/fbjs/node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fbjs/node_modules/isomorphic-fetch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", + "integrity": "sha512-9c4TNAKYXM5PRyVcwUZrF3W09nQ+sO7+jydgs4ZGW9dhsLG2VOlISJABombdQqQRXCwuYG3sYV/puGf5rp0qmA==", + "license": "MIT", + "peer": true, + "dependencies": { + "node-fetch": "^1.0.1", + "whatwg-fetch": ">=0.10.0" + } + }, + "node_modules/fbjs/node_modules/node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "encoding": "^0.1.11", + "is-stream": "^1.0.1" + } + }, + "node_modules/fbjs/node_modules/promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "license": "MIT", + "peer": true, + "dependencies": { + "asap": "~2.0.3" + } + }, "node_modules/fecha": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", @@ -27500,6 +41489,37 @@ "node": ">=0.4.0" } }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/fetch-retry": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/fetch-retry/-/fetch-retry-4.1.1.tgz", + "integrity": "sha512-e6eB7zN6UBSwGVwrbWVH+gdLnkW9WwHhmq2YDK1Sh30pzx1onRVGBvogTlUeWxwTa+L86NYdo4hFkh7O8ZjSnA==", + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -27528,7 +41548,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "devOptional": true, "dependencies": { "flat-cache": "^3.0.4" }, @@ -27603,8 +41622,7 @@ "node_modules/file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "optional": true + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" }, "node_modules/filelist": { "version": "1.0.4", @@ -27682,6 +41700,43 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/find-babel-config": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-1.2.2.tgz", + "integrity": "sha512-oK59njMyw2y3yxto1BCfVK7MQp/OYf4FleHu0RgosH3riFJ1aOuo/7naLDLAObfrgn3ueFhw5sAT/cp0QuJI3Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "json5": "^1.0.2", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/find-babel-config/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "license": "MIT", + "peer": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/find-babel-config/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, "node_modules/find-cache-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-4.0.0.tgz", @@ -27733,6 +41788,17 @@ "node": ">=8" } }, + "node_modules/find-yarn-workspace-root": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", + "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "dependencies": { + "micromatch": "^4.0.2" + } + }, "node_modules/flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", @@ -27745,7 +41811,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "devOptional": true, "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.3", @@ -27758,8 +41823,7 @@ "node_modules/flatted": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "devOptional": true + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==" }, "node_modules/flow-enums-runtime": { "version": "0.0.6", @@ -27802,6 +41866,13 @@ } } }, + "node_modules/fontfaceobserver": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/fontfaceobserver/-/fontfaceobserver-2.3.0.tgz", + "integrity": "sha512-6FPvD/IVyT4ZlNe7Wcn5Fb/4ChigpucKYSvD6a+0iMoLn2inpo711eyIcKjmDtE5XNcgAkSH9uN/nfAeZzHEfg==", + "license": "BSD-2-Clause", + "peer": true + }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -27833,7 +41904,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", - "dev": true, "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" @@ -27849,7 +41919,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, "engines": { "node": ">=14" }, @@ -27857,6 +41926,15 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, "node_modules/fork-ts-checker-webpack-plugin": { "version": "7.2.13", "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-7.2.13.tgz", @@ -28043,11 +42121,22 @@ "node": ">=0.4.x" } }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "license": "MIT", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/formidable": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.1.tgz", "integrity": "sha512-WJWKelbRHN41m5dumb0/k8TeAx7Id/y3a+Z7QfhxP/htI9Js5zYaEDtG8uMgG0vM0lOlqnmjE99/kfpOYi/0Og==", - "dev": true, "dependencies": { "dezalgo": "^1.0.4", "hexoid": "^1.0.0", @@ -28065,6 +42154,12 @@ "node": ">= 0.6" } }, + "node_modules/fp-ts": { + "version": "2.16.9", + "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-2.16.9.tgz", + "integrity": "sha512-+I2+FnVB+tVaxcYyQkHUq7ZdKScaBlX53A41mxQtpIccsfyv8PzdzP7fzp2AY832T4aoK6UZ5WRX/ebGd8uZuQ==", + "license": "MIT" + }, "node_modules/fraction.js": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", @@ -28077,6 +42172,17 @@ "url": "https://github.com/sponsors/rawify" } }, + "node_modules/freeport-async": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/freeport-async/-/freeport-async-2.0.0.tgz", + "integrity": "sha512-K7od3Uw45AJg00XUmy15+Hae2hOcgKcmN3/EF6Y7i01O0gaqiRx8sUSpsb9+BRNL8RPBrhzPsVfy8q9ADlJuWQ==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -28141,6 +42247,31 @@ "node": ">=14.14" } }, + "node_modules/fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "license": "ISC", + "dependencies": { + "minipass": "^2.6.0" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "license": "ISC", + "dependencies": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "node_modules/fs-minipass/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "license": "ISC" + }, "node_modules/fs-monkey": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", @@ -28360,7 +42491,6 @@ "version": "6.0.4", "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.4.tgz", "integrity": "sha512-E1b1lFFLvLgak2whF2xDBcOy6NLVGZBqqjJjsIhvopKfWWEi64pLVTWWehV8KlLerZkfNTA95sTe2OdJKm1OzQ==", - "dev": true, "dependencies": { "basic-ftp": "^5.0.2", "data-uri-to-buffer": "^6.0.2", @@ -28370,6 +42500,25 @@ "node": ">= 14" } }, + "node_modules/getenv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/getenv/-/getenv-1.0.0.tgz", + "integrity": "sha512-7yetJWqbS9sbn0vIfliPsFgoXMKn/YMF+Wuiog97x+urnSRRRZ7xB+uVkwGKzRgq9CDFfMQnE9ruL5DHv9c6Xg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, "node_modules/github-slugger": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.5.0.tgz", @@ -28431,6 +42580,16 @@ "node": "*" } }, + "node_modules/global": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", + "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", + "license": "MIT", + "dependencies": { + "min-document": "^2.19.0", + "process": "^0.11.10" + } + }, "node_modules/global-dirs": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", @@ -28599,19 +42758,35 @@ "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "devOptional": true + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" }, "node_modules/graphql": { "version": "16.9.0", "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.9.0.tgz", "integrity": "sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" } }, + "node_modules/graphql-tag": { + "version": "2.12.6", + "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz", + "integrity": "sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, "node_modules/gray-matter": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", @@ -28715,6 +42890,51 @@ "node": ">=0.10.0" } }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", + "license": "ISC", + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", + "license": "MIT", + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/har-validator/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/har-validator/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" + }, "node_modules/harmony-reflect": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/harmony-reflect/-/harmony-reflect-1.6.2.tgz", @@ -28804,6 +43024,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/hash.js": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", @@ -29002,6 +43236,38 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hdkey": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hdkey/-/hdkey-2.0.1.tgz", + "integrity": "sha512-c+tl9PHG9/XkGgG0tD7CJpRVaE0jfZizDNmnErUAKQ4EjQSOcOUcV3EN9ZEZS8pZ4usaeiiK0H7stzuzna8feA==", + "license": "MIT", + "dependencies": { + "bs58check": "^2.1.2", + "safe-buffer": "^5.1.1", + "secp256k1": "^4.0.0" + } + }, + "node_modules/hdkey/node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", + "license": "MIT" + }, + "node_modules/hdkey/node_modules/secp256k1": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.4.tgz", + "integrity": "sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "elliptic": "^6.5.7", + "node-addon-api": "^5.0.0", + "node-gyp-build": "^4.2.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -29017,6 +43283,12 @@ "dev": true, "license": "MIT" }, + "node_modules/help-me": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==", + "license": "MIT" + }, "node_modules/hermes-estree": { "version": "0.25.1", "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", @@ -29038,7 +43310,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", - "dev": true, "engines": { "node": ">=8" } @@ -29048,6 +43319,12 @@ "resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz", "integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==" }, + "node_modules/hi-base32": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/hi-base32/-/hi-base32-0.5.1.tgz", + "integrity": "sha512-EmBBpvdYh/4XxsnUybsPag6VikPYnN30td+vQk+GI3qpahVEG9+gTkG0aXVxTjBqQ5T6ijbWIu77O+C5WFWsnA==", + "license": "MIT" + }, "node_modules/history": { "version": "4.10.1", "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", @@ -29392,6 +43669,12 @@ "node": ">= 0.8" } }, + "node_modules/http-https": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/http-https/-/http-https-1.0.0.tgz", + "integrity": "sha512-o0PWwVCSp3O0wS6FvNr6xfBCHgt0m1tvPLFOCc2iFDKTRAXhB7m8klDf7ErowFH8POa6dVdGatKU5I1YYwzUyg==", + "license": "ISC" + }, "node_modules/http-parser-js": { "version": "0.5.8", "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", @@ -29506,6 +43789,21 @@ "node": ">= 0.12.0" } }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, "node_modules/http2-wrapper": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", @@ -29538,6 +43836,21 @@ "node": ">=10.17.0" } }, + "node_modules/humanize-duration": { + "version": "3.32.1", + "resolved": "https://registry.npmjs.org/humanize-duration/-/humanize-duration-3.32.1.tgz", + "integrity": "sha512-inh5wue5XdfObhu/IGEMiA1nUXigSGcaKNemcbLRKa7jXYGDZXr3LoT9pTIzq2hPEbld7w/qv9h+ikWGz8fL1g==", + "license": "Unlicense" + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.0.0" + } + }, "node_modules/hyperdyperid": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz", @@ -29616,6 +43929,27 @@ "node": ">=4" } }, + "node_modules/idna-uts46-hx": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz", + "integrity": "sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA==", + "license": "MIT", + "dependencies": { + "punycode": "2.1.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/idna-uts46-hx/node_modules/punycode": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz", + "integrity": "sha512-Yxz2kRwT90aPiWEMHVYnEf4+rhwF1tBmmZ4KepCP+Wkium9JxtWnUm1nqGwpiAHr/tnTSeHqr3wb++jgSkXjhA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -29761,6 +44095,14 @@ "node": ">=8" } }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "license": "ISC", + "optional": true, + "peer": true + }, "node_modules/infima": { "version": "0.2.0-alpha.43", "resolved": "https://registry.npmjs.org/infima/-/infima-0.2.0-alpha.43.tgz", @@ -29789,6 +44131,12 @@ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, + "node_modules/injectpromise": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/injectpromise/-/injectpromise-1.0.0.tgz", + "integrity": "sha512-qNq5wy4qX4uWHcVFOEU+RqZkoVG65FhvGkyDWbuBxILMjK6A1LFf5A1mgXZkD4nRx5FCorD81X/XvPKp/zVfPA==", + "license": "MIT" + }, "node_modules/inline-style-parser": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", @@ -29886,6 +44234,174 @@ "node": ">=8" } }, + "node_modules/internal-ip": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", + "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "default-gateway": "^4.2.0", + "ipaddr.js": "^1.9.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/internal-ip/node_modules/cross-spawn": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", + "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/internal-ip/node_modules/default-gateway": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", + "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==", + "license": "BSD-2-Clause", + "optional": true, + "peer": true, + "dependencies": { + "execa": "^1.0.0", + "ip-regex": "^2.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/internal-ip/node_modules/execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/internal-ip/node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/internal-ip/node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/internal-ip/node_modules/npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/internal-ip/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/internal-ip/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", + "optional": true, + "peer": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/internal-ip/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/internal-ip/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/internal-ip/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, "node_modules/internal-slot": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", @@ -29915,6 +44431,28 @@ "loose-envify": "^1.0.0" } }, + "node_modules/io-ts": { + "name": "@bitgo-forks/io-ts", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@bitgo-forks/io-ts/-/io-ts-2.1.4.tgz", + "integrity": "sha512-jCt3WPfDM+wM0SJMGJkY0TS6JmaQ78ATAYtsppJYJfts8geOS/N/UftwAROXwv6azKAMz8uo163t6dWWwfsYug==", + "license": "MIT", + "peerDependencies": { + "fp-ts": "^2.0.0" + } + }, + "node_modules/io-ts-types": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/io-ts-types/-/io-ts-types-0.5.19.tgz", + "integrity": "sha512-kQOYYDZG5vKre+INIDZbLeDJe+oM+4zLpUkjXyTMyUfoCpjJNyi29ZLkuEAwcPufaYo3yu/BsemZtbdD+NtRfQ==", + "license": "MIT", + "peerDependencies": { + "fp-ts": "^2.0.0", + "io-ts": "^2.0.0", + "monocle-ts": "^2.0.0", + "newtype-ts": "^0.3.2" + } + }, "node_modules/ioredis": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.4.1.tgz", @@ -29942,7 +44480,6 @@ "version": "9.0.5", "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", - "dev": true, "dependencies": { "jsbn": "1.1.0", "sprintf-js": "^1.1.3" @@ -29951,6 +44488,17 @@ "node": ">= 12" } }, + "node_modules/ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha512-58yWmlHpp7VYfcdTwMTvwMmqx/Elfxjd9RXTDyMsbL7lLWmhMylLEqiYVLKuLzOZqVgiWXD9MfR62Vv89VRxkw==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -30218,6 +44766,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", + "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==", + "license": "MIT" + }, "node_modules/is-generator-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", @@ -30252,6 +44806,16 @@ "node": ">=0.10.0" } }, + "node_modules/is-hex-prefixed": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", + "integrity": "sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA==", + "license": "MIT", + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, "node_modules/is-hexadecimal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", @@ -30316,6 +44880,45 @@ "node": ">=8" } }, + "node_modules/is-invalid-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-invalid-path/-/is-invalid-path-0.1.0.tgz", + "integrity": "sha512-aZMG0T3F34mTg4eTdszcGXx54oiZ4NtHSft3hWNJMGJXUUqdIj3cOZuHcU0nCWWcY3jd7yRe/3AEm3vSNTpBGQ==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "is-glob": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-invalid-path/node_modules/is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-invalid-path/node_modules/is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "is-extglob": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-map": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", @@ -30328,6 +44931,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-negative-zero": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", @@ -30443,6 +45062,12 @@ "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", "dev": true }, + "node_modules/is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "license": "MIT" + }, "node_modules/is-reference": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.2.tgz", @@ -30589,6 +45214,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-valid-path": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-valid-path/-/is-valid-path-0.1.1.tgz", + "integrity": "sha512-+kwPrVDu9Ms03L90Qaml+79+6DZHqHyRoANI6IsZJ/g8frhnfchDOBCa0RbQ6/kdHt5CS5OeIEyrYznNuVN+8A==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "is-invalid-path": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-weakmap": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", @@ -30694,11 +45333,41 @@ "node": ">=0.10.0" } }, + "node_modules/isomorphic-fetch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz", + "integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==", + "license": "MIT", + "dependencies": { + "node-fetch": "^2.6.1", + "whatwg-fetch": "^3.4.1" + } + }, + "node_modules/isomorphic-webcrypto": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/isomorphic-webcrypto/-/isomorphic-webcrypto-2.3.8.tgz", + "integrity": "sha512-XddQSI0WYlSCjxtm1AI8kWQOulf7hAN3k3DclF1sxDJZqOe0pcsOt675zvWW91cZH9hYs3nlA3Ev8QK5i80SxQ==", + "license": "MIT", + "dependencies": { + "@peculiar/webcrypto": "^1.0.22", + "asmcrypto.js": "^0.22.0", + "b64-lite": "^1.3.1", + "b64u-lite": "^1.0.1", + "msrcrypto": "^1.5.6", + "str2buf": "^1.3.0", + "webcrypto-shim": "^0.1.4" + }, + "optionalDependencies": { + "@unimodules/core": "*", + "@unimodules/react-native-adapter": "*", + "expo-random": "*", + "react-native-securerandom": "^0.1.1" + } + }, "node_modules/isomorphic-ws": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", - "dev": true, "peerDependencies": { "ws": "*" } @@ -30717,6 +45386,12 @@ "ws": "*" } }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "license": "MIT" + }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", @@ -30879,6 +45554,92 @@ "node": "*" } }, + "node_modules/jayson": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/jayson/-/jayson-4.1.3.tgz", + "integrity": "sha512-LtXh5aYZodBZ9Fc3j6f2w+MTNcnxteMOrb+QgIouguGOulWi0lieEkOUg+HkjjFs0DGoWDds6bi4E9hpNFLulQ==", + "license": "MIT", + "dependencies": { + "@types/connect": "^3.4.33", + "@types/node": "^12.12.54", + "@types/ws": "^7.4.4", + "commander": "^2.20.3", + "delay": "^5.0.0", + "es6-promisify": "^5.0.0", + "eyes": "^0.1.8", + "isomorphic-ws": "^4.0.1", + "json-stringify-safe": "^5.0.1", + "JSONStream": "^1.3.5", + "uuid": "^8.3.2", + "ws": "^7.5.10" + }, + "bin": { + "jayson": "bin/jayson.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jayson/node_modules/@types/node": { + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", + "license": "MIT" + }, + "node_modules/jayson/node_modules/@types/ws": { + "version": "7.4.7", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", + "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/jayson/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" + }, + "node_modules/jayson/node_modules/isomorphic-ws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", + "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", + "license": "MIT", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/jayson/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/jayson/node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", @@ -31884,6 +46645,14 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/jimp-compact": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/jimp-compact/-/jimp-compact-0.16.1.tgz", + "integrity": "sha512-dZ6Ra7u1G8c4Letq/B5EzAxj4tLFHL+cGtdpR+PVm4yzPDj+lCk+AbivWt1eOM+ikzkowtyV7qSqX6qr3t71Ww==", + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/jiti": { "version": "1.21.6", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", @@ -31904,6 +46673,14 @@ "@sideway/pinpoint": "^2.0.0" } }, + "node_modules/join-component": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/join-component/-/join-component-1.1.0.tgz", + "integrity": "sha512-bF7vcQxbODoGK1imE2P9GS9aw4zD0Sd+Hni68IMZLj7zRnquH7dXUmMw9hDI5S/Jzt7q+IyTXN0rSg2GI0IKhQ==", + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/jose": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/jose/-/jose-5.5.0.tgz", @@ -31912,11 +46689,64 @@ "url": "https://github.com/sponsors/panva" } }, + "node_modules/joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/js-base64": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.7.tgz", + "integrity": "sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==", + "license": "BSD-3-Clause" + }, + "node_modules/js-sha256": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.9.0.tgz", + "integrity": "sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA==", + "license": "MIT" + }, + "node_modules/js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", + "license": "MIT" + }, + "node_modules/js-sha512": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha512/-/js-sha512-0.8.0.tgz", + "integrity": "sha512-PWsmefG6Jkodqt+ePTvBZCSMFgN7Clckjd0O7su3I0+BW2QWUTJNzjktHsztGLhncP2h8mcF9V9Y2Ha59pAViQ==", + "license": "MIT" + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, + "node_modules/js-xdr": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/js-xdr/-/js-xdr-1.3.0.tgz", + "integrity": "sha512-fjLTm2uBtFvWsE3l2J14VjTuuB8vJfeTtYuNS7LiLHDWIX2kt0l1pqq9334F8kODUkKPMuULjEcbGbkFFwhx5g==", + "deprecated": "⚠️ This package has moved to @stellar/js-xdr! 🚚", + "license": "Apache-2.0", + "dependencies": { + "lodash": "^4.17.5", + "long": "^2.2.3" + } + }, + "node_modules/js-xdr/node_modules/long": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/long/-/long-2.4.0.tgz", + "integrity": "sha512-ijUtjmO/n2A5PaosNG9ZGDsQ3vxJg7ZW8vsY8Kp0f2yIZWhSJvjmegV7t+9RPQKxKrvj8yKGehhS+po14hPLGQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.6" + } + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -31928,11 +46758,19 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/js2xmlparser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", + "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", + "license": "Apache-2.0", + "dependencies": { + "xmlcreate": "^2.0.4" + } + }, "node_modules/jsbn": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", - "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", - "dev": true + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" }, "node_modules/jsc-android": { "version": "250231.0.0", @@ -32016,6 +46854,56 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/jsdoc": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.4.tgz", + "integrity": "sha512-zeFezwyXeG4syyYHbvh1A967IAqq/67yXtXvuL5wnqCkFZe8I0vKfm+EO+YEvLguo6w9CDUbrAXVtJSHh2E8rw==", + "license": "Apache-2.0", + "dependencies": { + "@babel/parser": "^7.20.15", + "@jsdoc/salty": "^0.2.1", + "@types/markdown-it": "^14.1.1", + "bluebird": "^3.7.2", + "catharsis": "^0.9.0", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.2", + "klaw": "^3.0.0", + "markdown-it": "^14.1.0", + "markdown-it-anchor": "^8.6.7", + "marked": "^4.0.10", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "underscore": "~1.13.2" + }, + "bin": { + "jsdoc": "jsdoc.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/jsdoc/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jsdoc/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/jsdom": { "version": "20.0.3", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz", @@ -32156,6 +47044,57 @@ "resolved": "https://registry.npmjs.org/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz", "integrity": "sha512-RJ9YYNCkhVDBuP4zN5BBtYAzEl03yq/jIIsyif0JY9qyJuQQZNeDK7anAPKKlyEtLSj2s8h6hNh2F8zO5q7ScA==" }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "license": "(AFL-2.1 OR BSD-3-Clause)" + }, + "node_modules/json-schema-deref-sync": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/json-schema-deref-sync/-/json-schema-deref-sync-0.13.0.tgz", + "integrity": "sha512-YBOEogm5w9Op337yb6pAT6ZXDqlxAsQCanM3grid8lMWNxRJO/zWEJi3ZzqDL8boWfwhTFym5EFrNgWwpqcBRg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "clone": "^2.1.2", + "dag-map": "~1.0.0", + "is-valid-path": "^0.1.1", + "lodash": "^4.17.13", + "md5": "~2.2.0", + "memory-cache": "~0.2.0", + "traverse": "~0.6.6", + "valid-url": "~1.0.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/json-schema-deref-sync/node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/json-schema-deref-sync/node_modules/md5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", + "integrity": "sha512-PlGG4z5mBANDGCKsYQe0CaUYHdZYZt8ZPZLmEt+Urf0W4GlpTX4HescwHU+dc9+Z/G/vZKYZYFrwgm9VxK6QOQ==", + "license": "BSD-3-Clause", + "optional": true, + "peer": true, + "dependencies": { + "charenc": "~0.0.1", + "crypt": "~0.0.1", + "is-buffer": "~1.1.1" + } + }, "node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", @@ -32164,14 +47103,12 @@ "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "devOptional": true + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" }, "node_modules/json5": { "version": "2.2.3", @@ -32231,6 +47168,46 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "engines": [ + "node >= 0.2.0" + ], + "license": "MIT" + }, + "node_modules/JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "license": "(MIT OR Apache-2.0)", + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "license": "MIT", + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -32246,6 +47223,15 @@ "node": ">=4.0" } }, + "node_modules/jwt-decode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", + "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/keccak": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.4.tgz", @@ -32260,6 +47246,24 @@ "node": ">=10.0.0" } }, + "node_modules/key-encoder": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/key-encoder/-/key-encoder-2.0.3.tgz", + "integrity": "sha512-fgBtpAGIr/Fy5/+ZLQZIPPhsZEcbSlYu/Wu96tNDFNSjSACw5lEIOFeaVdQ/iwrb8oxjlWi6wmWdH76hV6GZjg==", + "license": "MIT", + "dependencies": { + "@types/elliptic": "^6.4.9", + "asn1.js": "^5.0.1", + "bn.js": "^4.11.8", + "elliptic": "^6.4.1" + } + }, + "node_modules/key-encoder/node_modules/bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "license": "MIT" + }, "node_modules/keygrip": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz", @@ -32293,6 +47297,15 @@ "node": ">=0.10.0" } }, + "node_modules/klaw": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.9" + } + }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -32591,7 +47604,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "devOptional": true, "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -32605,6 +47617,36 @@ "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.11.4.tgz", "integrity": "sha512-F/R50HQuWWYcmU/esP5jrH5LiWYaN7DpN0a/99U8+mnGGtnx8kmRE+649dQh3v+CowXXZc8vpkf5AmYkO0AQ7Q==" }, + "node_modules/libsodium": { + "version": "0.7.15", + "resolved": "https://registry.npmjs.org/libsodium/-/libsodium-0.7.15.tgz", + "integrity": "sha512-sZwRknt/tUpE2AwzHq3jEyUU5uvIZHtSssktXq7owd++3CSgn8RGrv6UZJJBpP7+iBghBqe7Z06/2M31rI2NKw==", + "license": "ISC" + }, + "node_modules/libsodium-sumo": { + "version": "0.7.15", + "resolved": "https://registry.npmjs.org/libsodium-sumo/-/libsodium-sumo-0.7.15.tgz", + "integrity": "sha512-5tPmqPmq8T8Nikpm1Nqj0hBHvsLFCXvdhBFV7SGOitQPZAA6jso8XoL0r4L7vmfKXr486fiQInvErHtEvizFMw==", + "license": "ISC" + }, + "node_modules/libsodium-wrappers": { + "version": "0.7.15", + "resolved": "https://registry.npmjs.org/libsodium-wrappers/-/libsodium-wrappers-0.7.15.tgz", + "integrity": "sha512-E4anqJQwcfiC6+Yrl01C1m8p99wEhLmJSs0VQqST66SbQXXBoaJY0pF4BNjRYa/sOQAxx6lXAaAFIlx+15tXJQ==", + "license": "ISC", + "dependencies": { + "libsodium": "^0.7.15" + } + }, + "node_modules/libsodium-wrappers-sumo": { + "version": "0.7.15", + "resolved": "https://registry.npmjs.org/libsodium-wrappers-sumo/-/libsodium-wrappers-sumo-0.7.15.tgz", + "integrity": "sha512-aSWY8wKDZh5TC7rMvEdTHoyppVq/1dTSAeAR7H6pzd6QRT3vQWcT5pGwCotLcpPEOLXX6VvqihSPkpEhYAjANA==", + "license": "ISC", + "dependencies": { + "libsodium-sumo": "^0.7.15" + } + }, "node_modules/license-webpack-plugin": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-4.0.2.tgz", @@ -32670,6 +47712,15 @@ "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, "node_modules/lint-staged": { "version": "15.2.0", "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.0.tgz", @@ -33112,6 +48163,13 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==", + "license": "MIT", + "peer": true + }, "node_modules/lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", @@ -33133,6 +48191,13 @@ "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==" }, + "node_modules/lodash.frompairs": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.frompairs/-/lodash.frompairs-4.0.1.tgz", + "integrity": "sha512-dvqe2I+cO5MzXCMhUnfYFa9MD+/760yx2aTAN1lqEcEkf896TxgrX373igVdqSJj6tQd0jnSLE1UMuKufqqxFw==", + "license": "MIT", + "peer": true + }, "node_modules/lodash.isarguments": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", @@ -33143,6 +48208,13 @@ "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "license": "MIT", + "peer": true + }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -33151,8 +48223,42 @@ "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "devOptional": true + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + }, + "node_modules/lodash.omit": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", + "integrity": "sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg==", + "license": "MIT", + "peer": true + }, + "node_modules/lodash.pick": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", + "integrity": "sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q==", + "license": "MIT", + "peer": true + }, + "node_modules/lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "license": "MIT", + "peer": true, + "dependencies": { + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "node_modules/lodash.templatesettings": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "lodash._reinterpolate": "^3.0.0" + } }, "node_modules/lodash.throttle": { "version": "4.1.1", @@ -33469,6 +48575,15 @@ "node": ">=10" } }, + "node_modules/lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", + "license": "MIT", + "dependencies": { + "es5-ext": "~0.10.2" + } + }, "node_modules/luxon": { "version": "3.4.4", "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.4.tgz", @@ -33486,6 +48601,17 @@ "lz-string": "bin/bin.js" } }, + "node_modules/macaroon": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/macaroon/-/macaroon-3.0.4.tgz", + "integrity": "sha512-Tja2jvupseKxltPZbu5RPSz2Pgh6peYA3O46YCTcYL8PI1VqtGwDqRhGfP8pows26xx9wTiygk+en62Bq+Y8JA==", + "license": "BSD-3-Clause", + "dependencies": { + "sjcl": "^1.0.6", + "tweetnacl": "^1.0.0", + "tweetnacl-util": "^0.15.0" + } + }, "node_modules/magic-string": { "version": "0.30.0", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.0.tgz", @@ -33550,6 +48676,33 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/markdown-it-anchor": { + "version": "8.6.7", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz", + "integrity": "sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==", + "license": "Unlicense", + "peerDependencies": { + "@types/markdown-it": "*", + "markdown-it": "*" + } + }, "node_modules/markdown-table": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz", @@ -33559,6 +48712,18 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, "node_modules/marky": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.5.tgz", @@ -33566,6 +48731,54 @@ "license": "Apache-2.0", "peer": true }, + "node_modules/md5": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", + "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", + "license": "BSD-3-Clause", + "optional": true, + "peer": true, + "dependencies": { + "charenc": "0.0.2", + "crypt": "0.0.2", + "is-buffer": "~1.1.6" + } + }, + "node_modules/md5-file": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/md5-file/-/md5-file-3.2.3.tgz", + "integrity": "sha512-3Tkp1piAHaworfcCgH0jKbTvj1jWWFgbvh2cXaNCgHwyTCBxxvD1Y04rmfpvdPm1P4oXMOpm6+2H7sr7v9v8Fw==", + "license": "MIT", + "peer": true, + "dependencies": { + "buffer-alloc": "^1.1.0" + }, + "bin": { + "md5-file": "cli.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "license": "MIT", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/md5hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/md5hex/-/md5hex-1.0.0.tgz", + "integrity": "sha512-c2YOUbp33+6thdCUi34xIyOU/a7bvGKj/3DB1iaPMTuPHf/Q2d5s4sn1FaCOO43XkXggnb08y5W2PU8UNYNLKQ==", + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/mdast-util-directive": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/mdast-util-directive/-/mdast-util-directive-3.0.0.tgz", @@ -33949,6 +49162,12 @@ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "license": "MIT" + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -33975,6 +49194,30 @@ "license": "MIT", "peer": true }, + "node_modules/memoizee": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", + "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", + "license": "ISC", + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.53", + "es6-weak-map": "^2.0.3", + "event-emitter": "^0.3.5", + "is-promise": "^2.2.2", + "lru-queue": "^0.1.0", + "next-tick": "^1.1.0", + "timers-ext": "^0.1.7" + } + }, + "node_modules/memory-cache": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/memory-cache/-/memory-cache-0.2.0.tgz", + "integrity": "sha512-OcjA+jzjOYzKmKS6IQVALHLVz+rNTMPoJvCztFaZxwG14wtAW7VRZjwTQu06vKCYOxh4jVnik7ya0SXTB0W+xA==", + "license": "BSD-2-Clause", + "optional": true, + "peer": true + }, "node_modules/merge-deep": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/merge-deep/-/merge-deep-3.0.3.tgz", @@ -34296,6 +49539,67 @@ "node": ">=18.18" } }, + "node_modules/metro-react-native-babel-preset": { + "version": "0.64.0", + "resolved": "https://registry.npmjs.org/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.64.0.tgz", + "integrity": "sha512-HcZ0RWQRuJfpPiaHyFQJzcym+/dDIVUPwUAXWoub/C4GkGu+mPjp8vqK6g0FxokCnnI2TK0gZTza2IDfiNNscQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/core": "^7.0.0", + "@babel/plugin-proposal-class-properties": "^7.0.0", + "@babel/plugin-proposal-export-default-from": "^7.0.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0", + "@babel/plugin-proposal-object-rest-spread": "^7.0.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.0.0", + "@babel/plugin-proposal-optional-chaining": "^7.0.0", + "@babel/plugin-syntax-dynamic-import": "^7.0.0", + "@babel/plugin-syntax-export-default-from": "^7.0.0", + "@babel/plugin-syntax-flow": "^7.2.0", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.0.0", + "@babel/plugin-syntax-optional-chaining": "^7.0.0", + "@babel/plugin-transform-arrow-functions": "^7.0.0", + "@babel/plugin-transform-block-scoping": "^7.0.0", + "@babel/plugin-transform-classes": "^7.0.0", + "@babel/plugin-transform-computed-properties": "^7.0.0", + "@babel/plugin-transform-destructuring": "^7.0.0", + "@babel/plugin-transform-exponentiation-operator": "^7.0.0", + "@babel/plugin-transform-flow-strip-types": "^7.0.0", + "@babel/plugin-transform-for-of": "^7.0.0", + "@babel/plugin-transform-function-name": "^7.0.0", + "@babel/plugin-transform-literals": "^7.0.0", + "@babel/plugin-transform-modules-commonjs": "^7.0.0", + "@babel/plugin-transform-object-assign": "^7.0.0", + "@babel/plugin-transform-parameters": "^7.0.0", + "@babel/plugin-transform-react-display-name": "^7.0.0", + "@babel/plugin-transform-react-jsx": "^7.0.0", + "@babel/plugin-transform-react-jsx-self": "^7.0.0", + "@babel/plugin-transform-react-jsx-source": "^7.0.0", + "@babel/plugin-transform-regenerator": "^7.0.0", + "@babel/plugin-transform-runtime": "^7.0.0", + "@babel/plugin-transform-shorthand-properties": "^7.0.0", + "@babel/plugin-transform-spread": "^7.0.0", + "@babel/plugin-transform-sticky-regex": "^7.0.0", + "@babel/plugin-transform-template-literals": "^7.0.0", + "@babel/plugin-transform-typescript": "^7.5.0", + "@babel/plugin-transform-unicode-regex": "^7.0.0", + "@babel/template": "^7.0.0", + "react-refresh": "^0.4.0" + }, + "peerDependencies": { + "@babel/core": "*" + } + }, + "node_modules/metro-react-native-babel-preset/node_modules/react-refresh": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.4.3.tgz", + "integrity": "sha512-Hwln1VNuGl/6bVwnd0Xdn1e84gT/8T9aYNL+HAKDArLCS7LWjwr7StE30IEYbIkx0Vi3vs+coQxe+SQDbGbbpA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/metro-resolver": { "version": "0.81.1", "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.81.1.tgz", @@ -34536,11 +49840,72 @@ "node": ">=12" } }, + "node_modules/micro-eth-signer": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/micro-eth-signer/-/micro-eth-signer-0.7.2.tgz", + "integrity": "sha512-uFH23nqPNdg2KZ9ZdvLG4GO3bTAOWRhwGTsecY4Et2IdQOJ26x6inu8lJ9oyslnYL/0o1vnETCGhMimMvO0SqQ==", + "license": "MIT", + "dependencies": { + "@ethereumjs/rlp": "5.0.0", + "@noble/curves": "~1.3.0", + "@noble/hashes": "~1.3.3", + "@scure/base": "~1.1.5", + "micro-packed": "~0.5.1" + } + }, + "node_modules/micro-eth-signer/node_modules/@ethereumjs/rlp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-5.0.0.tgz", + "integrity": "sha512-WuS1l7GJmB0n0HsXLozCoEFc9IwYgf3l0gCkKVYgR67puVF1O4OpEaN0hWmm1c+iHUHFCKt1hJrvy5toLg+6ag==", + "license": "MPL-2.0", + "bin": { + "rlp": "bin/rlp" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/micro-eth-signer/node_modules/@noble/curves": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz", + "integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.3.3" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/micro-eth-signer/node_modules/@noble/hashes": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", + "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/micro-ftch": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/micro-ftch/-/micro-ftch-0.3.1.tgz", "integrity": "sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg==" }, + "node_modules/micro-packed": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/micro-packed/-/micro-packed-0.5.3.tgz", + "integrity": "sha512-zWRoH+qUb/ZMp9gVZhexvRGCENDM5HEQF4sflqpdilUHWK2/zKR7/MT8GBctnTwbhNJwy1iuk5q6+TYP7/twYA==", + "license": "MIT", + "dependencies": { + "@scure/base": "~1.1.5" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/micromark": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.0.tgz", @@ -36224,6 +51589,25 @@ "node": ">=8.6" } }, + "node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, + "node_modules/miller-rabin/node_modules/bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "license": "MIT" + }, "node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -36273,6 +51657,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==", + "dependencies": { + "dom-walk": "^0.1.0" + } + }, "node_modules/mini-css-extract-plugin": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.0.tgz", @@ -36329,11 +51721,119 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, "engines": { "node": ">=16 || 14 >=14.17" } }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-collect/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "license": "MIT", + "dependencies": { + "minipass": "^2.9.0" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "license": "ISC", + "dependencies": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "license": "ISC" + }, "node_modules/mipd": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/mipd/-/mipd-0.0.7.tgz", @@ -36384,6 +51884,19 @@ "mkdirp": "bin/cmd.js" } }, + "node_modules/mkdirp-promise": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz", + "integrity": "sha512-Hepn5kb1lJPtVW84RFT40YG1OddBNTOVUZR2bzQUHc+Z03en8/3uX0+060JDhcEzyO08HmipsN9DcnFMxhIL9w==", + "deprecated": "This package is broken and no longer maintained. 'mkdirp' itself supports promises now, please switch to that.", + "license": "ISC", + "dependencies": { + "mkdirp": "*" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/mlly": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.3.tgz", @@ -36395,6 +51908,21 @@ "ufo": "^1.5.4" } }, + "node_modules/mock-fs": { + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-4.14.0.tgz", + "integrity": "sha512-qYvlv/exQ4+svI3UOvPUpLDF0OMX5euvUH0Ny4N5QyRyhNdgAgUrVH3iUINSzEPLvx0kbo/Bp28GJKIqvE7URw==", + "license": "MIT" + }, + "node_modules/mock-socket": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/mock-socket/-/mock-socket-9.3.1.tgz", + "integrity": "sha512-qxBgB7Qa2sEQgHFjj0dSigq7fX4k6Saisd5Nelwp2q8mlbAFh5dHV9JTTlF8viYJLSSWgMCZFUom8PJcMNBoJw==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, "node_modules/module-details-from-path": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.3.tgz", @@ -36407,6 +51935,15 @@ "license": "MIT", "peer": true }, + "node_modules/monocle-ts": { + "version": "2.3.13", + "resolved": "https://registry.npmjs.org/monocle-ts/-/monocle-ts-2.3.13.tgz", + "integrity": "sha512-D5Ygd3oulEoAm3KuGO0eeJIrhFf1jlQIoEVV2DYsZUMz42j4tGxgct97Aq68+F8w4w4geEnwFa8HayTS/7lpKQ==", + "license": "MIT", + "peerDependencies": { + "fp-ts": "^2.5.0" + } + }, "node_modules/motion": { "version": "10.16.2", "resolved": "https://registry.npmjs.org/motion/-/motion-10.16.2.tgz", @@ -36462,6 +51999,12 @@ "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" } }, + "node_modules/msrcrypto": { + "version": "1.5.8", + "resolved": "https://registry.npmjs.org/msrcrypto/-/msrcrypto-1.5.8.tgz", + "integrity": "sha512-ujZ0TRuozHKKm6eGbKHfXef7f+esIhEckmThVnz7RNyiOJd7a6MXj2JGBoL9cnPDW+JMG16MoTUh5X+XXjI66Q==", + "license": "Apache-2.0" + }, "node_modules/msw": { "version": "2.6.8", "resolved": "https://registry.npmjs.org/msw/-/msw-2.6.8.tgz", @@ -36595,6 +52138,17 @@ "node": ">= 6.0.0" } }, + "node_modules/multibase": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/multibase/-/multibase-0.6.1.tgz", + "integrity": "sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw==", + "deprecated": "This module has been superseded by the multiformats module", + "license": "MIT", + "dependencies": { + "base-x": "^3.0.8", + "buffer": "^5.5.0" + } + }, "node_modules/multicast-dns": { "version": "7.2.5", "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", @@ -36607,17 +52161,134 @@ "multicast-dns": "cli.js" } }, + "node_modules/multicodec": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-0.5.7.tgz", + "integrity": "sha512-PscoRxm3f+88fAtELwUnZxGDkduE2HD9Q6GHUOywQLjOGT/HAdhjLDYNZ1e7VR0s0TP0EwZ16LNUTFpoBGivOA==", + "deprecated": "This module has been superseded by the multiformats module", + "license": "MIT", + "dependencies": { + "varint": "^5.0.0" + } + }, "node_modules/multiformats": { "version": "9.9.0", "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.9.0.tgz", "integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==" }, + "node_modules/multihashes": { + "version": "0.4.21", + "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-0.4.21.tgz", + "integrity": "sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw==", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "multibase": "^0.7.0", + "varint": "^5.0.0" + } + }, + "node_modules/multihashes/node_modules/multibase": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/multibase/-/multibase-0.7.0.tgz", + "integrity": "sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg==", + "deprecated": "This module has been superseded by the multiformats module", + "license": "MIT", + "dependencies": { + "base-x": "^3.0.8", + "buffer": "^5.5.0" + } + }, + "node_modules/mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "license": "MIT", + "bin": { + "mustache": "bin/mustache" + } + }, "node_modules/mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, + "node_modules/mv": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz", + "integrity": "sha512-at/ZndSy3xEGJ8i0ygALh8ru9qy7gWW1cmkaqBN29JmMlIvM//MEO9y1sk/avxuwnPcfhkejkLsuPxH81BrkSg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "mkdirp": "~0.5.1", + "ncp": "~2.0.0", + "rimraf": "~2.4.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/mv/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/mv/node_modules/glob": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "integrity": "sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mv/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mv/node_modules/rimraf": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", + "integrity": "sha512-J5xnxTyqaiw06JjMftq7L9ouA448dw/E7dKghkP9WpKNuwmARNNg+Gk8/u5ryb9N/Yo2+z3MCwuqFK/+qPOPfQ==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "glob": "^6.0.1" + }, + "bin": { + "rimraf": "bin.js" + } + }, "node_modules/mylas": { "version": "2.1.13", "resolved": "https://registry.npmjs.org/mylas/-/mylas-2.1.13.tgz", @@ -36635,13 +52306,30 @@ "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, + "node_modules/nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", + "license": "MIT" + }, + "node_modules/nano-json-stream-parser": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz", + "integrity": "sha512-9MqxMH/BSJC7dnLsEMPyfN5Dvoo49IsPFYMcHw3Bcfc2kN0lpHRBSzlMSVx4HGyJ7s9B31CyBTVehWJoQ8Ctew==", + "license": "MIT" + }, + "node_modules/nanoassert": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/nanoassert/-/nanoassert-2.0.0.tgz", + "integrity": "sha512-7vO7n28+aYO4J+8w96AzhmU8G+Y/xpPDJz/se19ICsqj/momRbb9mh9ZUtkoJ5X3nTnPdhEJyc0qnM6yAsHBaA==", + "license": "ISC" + }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -36662,8 +52350,88 @@ "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "devOptional": true + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + }, + "node_modules/ncp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", + "integrity": "sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA==", + "license": "MIT", + "optional": true, + "peer": true, + "bin": { + "ncp": "bin/ncp" + } + }, + "node_modules/near-api-js": { + "version": "0.44.2", + "resolved": "https://registry.npmjs.org/near-api-js/-/near-api-js-0.44.2.tgz", + "integrity": "sha512-eMnc4V+geggapEUa3nU2p8HSHn/njtloI4P2mceHQWO8vDE1NGpnAw8FuTBrLmXSgIv9m6oocgFc9t3VNf5zwg==", + "license": "(MIT AND Apache-2.0)", + "dependencies": { + "bn.js": "5.2.0", + "borsh": "^0.6.0", + "bs58": "^4.0.0", + "depd": "^2.0.0", + "error-polyfill": "^0.1.3", + "http-errors": "^1.7.2", + "js-sha256": "^0.9.0", + "mustache": "^4.0.0", + "node-fetch": "^2.6.1", + "text-encoding-utf-8": "^1.0.2", + "tweetnacl": "^1.0.1" + } + }, + "node_modules/near-api-js/node_modules/bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", + "license": "MIT" + }, + "node_modules/near-api-js/node_modules/borsh": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/borsh/-/borsh-0.6.0.tgz", + "integrity": "sha512-sl5k89ViqsThXQpYa9XDtz1sBl3l1lI313cFUY1HKr+wvMILnb+58xpkqTNrYbelh99dY7K8usxoCusQmqix9Q==", + "license": "Apache-2.0", + "dependencies": { + "bn.js": "^5.2.0", + "bs58": "^4.0.0", + "text-encoding-utf-8": "^1.0.2" + } + }, + "node_modules/near-api-js/node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "license": "MIT", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/near-api-js/node_modules/http-errors/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/near-api-js/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } }, "node_modules/needle": { "version": "3.3.1", @@ -36708,6 +52476,14 @@ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, + "node_modules/nested-error-stacks": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.0.1.tgz", + "integrity": "sha512-SrQrok4CATudVzBS7coSz26QRSmlK9TzzoFbeKfcPBUFPjcQM9Rqvr/DlJkOrwI/0KcgvMub1n1g5Jt9EgRn4A==", + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/nestjs-zod": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/nestjs-zod/-/nestjs-zod-3.0.0.tgz", @@ -36741,11 +52517,20 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", - "dev": true, "engines": { "node": ">= 0.4.0" } }, + "node_modules/newtype-ts": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/newtype-ts/-/newtype-ts-0.3.5.tgz", + "integrity": "sha512-v83UEQMlVR75yf1OUdoSFssjitxzjZlqBAjiGQ4WJaML8Jdc68LJ+BaSAXUmKY4bNzp7hygkKLYTsDi14PxI2g==", + "license": "MIT", + "peerDependencies": { + "fp-ts": "^2.0.0", + "monocle-ts": "^2.0.0" + } + }, "node_modules/next": { "version": "14.2.4", "resolved": "https://registry.npmjs.org/next/-/next-14.2.4.tgz", @@ -36795,6 +52580,12 @@ } } }, + "node_modules/next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", + "license": "ISC" + }, "node_modules/next/node_modules/@swc/helpers": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", @@ -36831,6 +52622,13 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "license": "MIT", + "peer": true + }, "node_modules/no-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", @@ -36840,6 +52638,13 @@ "tslib": "^2.0.3" } }, + "node_modules/noble-bls12-381": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/noble-bls12-381/-/noble-bls12-381-0.7.2.tgz", + "integrity": "sha512-Z5isbU6opuWPL3dxsGqO5BdOE8WP1XUM7HFIn/xeE5pATTnml/PEIy4MFQQrktHiitkuJdsCDtzEOnS9eIpC3Q==", + "deprecated": "Switch to @noble/curves for security updates", + "license": "MIT" + }, "node_modules/nock": { "version": "13.5.4", "resolved": "https://registry.npmjs.org/nock/-/nock-13.5.4.tgz", @@ -36865,6 +52670,25 @@ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, "node_modules/node-emoji": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.1.3.tgz", @@ -37073,6 +52897,26 @@ "license": "MIT", "peer": true }, + "node_modules/number-to-bn": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", + "integrity": "sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig==", + "license": "MIT", + "dependencies": { + "bn.js": "4.11.6", + "strip-hex-prefix": "1.0.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/number-to-bn/node_modules/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==", + "license": "MIT" + }, "node_modules/nwsapi": { "version": "2.2.12", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.12.tgz", @@ -37224,6 +53068,24 @@ "node": ">=12" } }, + "node_modules/o3": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/o3/-/o3-1.0.3.tgz", + "integrity": "sha512-f+4n+vC6s4ysy7YO7O2gslWZBUu8Qj2i2OUJOvjRxQva7jVjYjB29jrr9NCjmxZQR0gzrOcv1RnqoYOeMs5VRQ==", + "license": "MIT", + "dependencies": { + "capability": "^0.2.5" + } + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, "node_modules/ob1": { "version": "0.81.1", "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.81.1.tgz", @@ -37311,7 +53173,6 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", - "dev": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1" @@ -37428,6 +53289,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/oboe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/oboe/-/oboe-2.1.5.tgz", + "integrity": "sha512-zRFWiF+FoicxEs3jNI/WYUrVEgA7DeET/InK0XQuudGHRg8iIob3cNPrJTKaz4004uaA9Pbe+Dwa8iluhjLZWA==", + "license": "BSD", + "dependencies": { + "http-https": "^1.0.0" + } + }, "node_modules/obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", @@ -37532,11 +53402,22 @@ "opener": "bin/opener-bin.js" } }, + "node_modules/openpgp": { + "version": "5.10.1", + "resolved": "https://registry.npmjs.org/openpgp/-/openpgp-5.10.1.tgz", + "integrity": "sha512-SR5Ft+ej51d0+p53ld5Ney0Yiz0y8Mh1YYLJrvpRMbTaNhvS1QcDX0Oq1rW9sjBnQXtgrpWw2Zve3rm7K5C/pw==", + "license": "LGPL-3.0+", + "dependencies": { + "asn1.js": "^5.0.0" + }, + "engines": { + "node": ">= 8.0.0" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "devOptional": true, "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", @@ -37571,15 +53452,39 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.10.0" } }, + "node_modules/osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, "node_modules/outvariant": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz", @@ -37617,6 +53522,17 @@ "node": ">=12.20" } }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -37694,7 +53610,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.1.0.tgz", "integrity": "sha512-Z5FnLVVZSnX7WjBg0mhDtydeRZ1xMcATZThjySQUHqr+0ksP8kqaw23fNKkaaN/Z8gwLUs/W7xdl0I75eP2Xyw==", - "dev": true, "dependencies": { "@tootallnate/quickjs-emscripten": "^0.23.0", "agent-base": "^7.1.2", @@ -37713,7 +53628,6 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" @@ -37726,7 +53640,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", - "dev": true, "dependencies": { "degenerator": "^5.0.0", "netmask": "^2.0.2" @@ -37755,8 +53668,7 @@ "node_modules/package-json-from-dist": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", - "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", - "dev": true + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==" }, "node_modules/package-json/node_modules/semver": { "version": "7.6.2", @@ -37769,6 +53681,24 @@ "node": ">=10" } }, + "node_modules/paillier-bigint": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/paillier-bigint/-/paillier-bigint-3.3.0.tgz", + "integrity": "sha512-Aa8a75dODYOGxLYQhi1Y0Xsi0Vbl+5gzPvaVfxuCA/zT8CK/keXv5CA2Ddn5AV9VxmTkpIEdYs40hv1rkFcODg==", + "license": "MIT", + "dependencies": { + "bigint-crypto-utils": "^3.0.17" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/pako": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.0.3.tgz", + "integrity": "sha512-WjR1hOeg+kki3ZIOjaf4b5WVcay1jaliKSYiEaB1XzwhMQZJxRdQRv0V31EKBYlxb4T7SK3hjfc/jxyU64BoSw==", + "license": "(MIT AND Zlib)" + }, "node_modules/param-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", @@ -37789,6 +53719,53 @@ "node": ">=6" } }, + "node_modules/parse-asn1": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.7.tgz", + "integrity": "sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg==", + "license": "ISC", + "dependencies": { + "asn1.js": "^4.10.1", + "browserify-aes": "^1.2.0", + "evp_bytestokey": "^1.0.3", + "hash-base": "~3.0", + "pbkdf2": "^3.1.2", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/parse-asn1/node_modules/asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/parse-asn1/node_modules/bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "license": "MIT" + }, + "node_modules/parse-asn1/node_modules/hash-base": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.5.tgz", + "integrity": "sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/parse-entities": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.1.tgz", @@ -37813,6 +53790,12 @@ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" }, + "node_modules/parse-headers": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.5.tgz", + "integrity": "sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA==", + "license": "MIT" + }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -37858,6 +53841,37 @@ "node": ">=0.10.0" } }, + "node_modules/parse-png": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/parse-png/-/parse-png-2.1.0.tgz", + "integrity": "sha512-Nt/a5SfCLiTnQAjx3fHlqp8hRgTL3z7kTQZzvIMS9uCAepnCyjpdEc6M/sz69WqMBdaDBw9sF1F1UaHROYzGkQ==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "pngjs": "^3.3.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/parse-png/node_modules/pngjs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", + "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/parse-srcset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", + "integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==", + "license": "MIT" + }, "node_modules/parse5": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", @@ -37904,6 +53918,25 @@ "tslib": "^2.0.3" } }, + "node_modules/password-prompt": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/password-prompt/-/password-prompt-1.1.3.tgz", + "integrity": "sha512-HkrjG2aJlvF0t2BMH0e2LB/EHf3Lcq3fNMzy4GYHcQblAvOl+QQji1Lx7WRBMqpVK8p+KR7bCg7oqAMXtdgqyw==", + "license": "0BSD", + "optional": true, + "peer": true, + "dependencies": { + "ansi-escapes": "^4.3.2", + "cross-spawn": "^7.0.3" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "license": "MIT", + "peer": true + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -37942,7 +53975,6 @@ "version": "1.11.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" @@ -37957,8 +53989,7 @@ "node_modules/path-scurry/node_modules/lru-cache": { "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" }, "node_modules/path-to-regexp": { "version": "3.2.0", @@ -37978,6 +54009,28 @@ "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==" }, + "node_modules/pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "license": "MIT", + "dependencies": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "license": "MIT" + }, "node_modules/periscopic": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz", @@ -38091,6 +54144,99 @@ "split2": "^4.0.0" } }, + "node_modules/pino-pretty": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-10.3.1.tgz", + "integrity": "sha512-az8JbIYeN/1iLj2t0jR9DV48/LQ3RC6hZPpapKPkb84Q+yTidMCpgWxIT3N0flnBDilyBQ1luWNpOeJptjdp/g==", + "license": "MIT", + "dependencies": { + "colorette": "^2.0.7", + "dateformat": "^4.6.3", + "fast-copy": "^3.0.0", + "fast-safe-stringify": "^2.1.1", + "help-me": "^5.0.0", + "joycon": "^3.1.1", + "minimist": "^1.2.6", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^1.0.0", + "pump": "^3.0.0", + "readable-stream": "^4.0.0", + "secure-json-parse": "^2.4.0", + "sonic-boom": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "bin": { + "pino-pretty": "bin.js" + } + }, + "node_modules/pino-pretty/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/pino-pretty/node_modules/on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/pino-pretty/node_modules/pino-abstract-transport": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz", + "integrity": "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==", + "license": "MIT", + "dependencies": { + "readable-stream": "^4.0.0", + "split2": "^4.0.0" + } + }, + "node_modules/pino-pretty/node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/pino-pretty/node_modules/sonic-boom": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.1.tgz", + "integrity": "sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg==", + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, "node_modules/pino-std-serializers": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-4.0.0.tgz", @@ -38283,6 +54429,41 @@ "node": ">=12" } }, + "node_modules/plist": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", + "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@xmldom/xmldom": "^0.8.8", + "base64-js": "^1.5.1", + "xmlbuilder": "^15.1.1" + }, + "engines": { + "node": ">=10.4.0" + } + }, + "node_modules/plist/node_modules/@xmldom/xmldom": { + "version": "0.8.10", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", + "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/plist/node_modules/xmlbuilder": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8.0" + } + }, "node_modules/pluralize": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", @@ -38340,6 +54521,12 @@ "ms": "^2.1.1" } }, + "node_modules/poseidon-lite": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/poseidon-lite/-/poseidon-lite-0.2.1.tgz", + "integrity": "sha512-xIr+G6HeYfOhCuswdqcFpSX47SPhm0EpisWJ6h7fHlWwaVIvH3dLnejpatrtw6Xc6HaLrpq05y7VRfvDmDGIog==", + "license": "MIT" + }, "node_modules/possible-typed-array-names": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", @@ -39065,16 +55252,23 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "devOptional": true, "engines": { "node": ">= 0.8.0" } }, + "node_modules/prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/prettier": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", - "dev": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -39085,6 +55279,18 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "license": "MIT", + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/prettier-plugin-organize-imports": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-3.2.4.tgz", @@ -39105,6 +55311,20 @@ } } }, + "node_modules/pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/pretty-error": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", @@ -39193,6 +55413,15 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -39203,6 +55432,17 @@ "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-1.0.0.tgz", "integrity": "sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==" }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/promise": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", @@ -39213,6 +55453,14 @@ "asap": "~2.0.6" } }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "license": "ISC", + "optional": true, + "peer": true + }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -39244,7 +55492,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", - "dev": true, "engines": { "node": ">= 8" } @@ -39286,6 +55533,169 @@ "node": ">=12.0.0" } }, + "node_modules/protobufjs-cli": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/protobufjs-cli/-/protobufjs-cli-1.1.3.tgz", + "integrity": "sha512-MqD10lqF+FMsOayFiNOdOGNlXc4iKDCf0ZQPkPR+gizYh9gqUeGTWulABUCdI+N67w5RfJ6xhgX4J8pa8qmMXQ==", + "license": "BSD-3-Clause", + "dependencies": { + "chalk": "^4.0.0", + "escodegen": "^1.13.0", + "espree": "^9.0.0", + "estraverse": "^5.1.0", + "glob": "^8.0.0", + "jsdoc": "^4.0.0", + "minimist": "^1.2.0", + "semver": "^7.1.2", + "tmp": "^0.2.1", + "uglify-js": "^3.7.7" + }, + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "protobufjs": "^7.0.0" + } + }, + "node_modules/protobufjs-cli/node_modules/escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=4.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/protobufjs-cli/node_modules/escodegen/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/protobufjs-cli/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/protobufjs-cli/node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "license": "MIT", + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/protobufjs-cli/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/protobufjs-cli/node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "license": "MIT", + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/protobufjs-cli/node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/protobufjs-cli/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/protobufjs-cli/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/protobufjs-cli/node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "license": "MIT", + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -39302,7 +55712,6 @@ "version": "6.4.0", "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz", "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==", - "dev": true, "dependencies": { "agent-base": "^7.0.2", "debug": "^4.3.4", @@ -39321,7 +55730,6 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" @@ -39334,7 +55742,6 @@ "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, "engines": { "node": ">=12" } @@ -39359,8 +55766,27 @@ "node_modules/psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" + }, + "node_modules/public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/public-encrypt/node_modules/bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "license": "MIT" }, "node_modules/pump": { "version": "3.0.2", @@ -39376,6 +55802,15 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/pupa": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/pupa/-/pupa-3.1.0.tgz", @@ -39406,6 +55841,30 @@ } ] }, + "node_modules/pvtsutils": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.6.tgz", + "integrity": "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.8.1" + } + }, + "node_modules/pvtsutils/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/pvutils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", + "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/qr-code-styling": { "version": "1.8.4", "resolved": "https://registry.npmjs.org/qr-code-styling/-/qr-code-styling-1.8.4.tgz", @@ -39439,6 +55898,16 @@ "resolved": "https://registry.npmjs.org/qrcode-generator/-/qrcode-generator-1.4.4.tgz", "integrity": "sha512-HM7yY8O2ilqhmULxGMpcHSF1EhJJ9yBj8gvDEuZ6M+KGJ0YY2hKpnXvRD+hZPLrDVck3ExIGhmPtSdcjC+guuw==" }, + "node_modules/qrcode-terminal": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/qrcode-terminal/-/qrcode-terminal-0.11.0.tgz", + "integrity": "sha512-Uu7ii+FQy4Qf82G4xu7ShHhjhGahEpCWc3x8UavY3CTcWV+ufmmCtwkr7ZKsX42jdL0kr1B5FKUeqJvAn51jzQ==", + "optional": true, + "peer": true, + "bin": { + "qrcode-terminal": "bin/qrcode-terminal.js" + } + }, "node_modules/qrcode-terminal-nooctal": { "version": "0.12.1", "resolved": "https://registry.npmjs.org/qrcode-terminal-nooctal/-/qrcode-terminal-nooctal-0.12.1.tgz", @@ -39576,8 +56045,7 @@ "node_modules/querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" }, "node_modules/queue": { "version": "6.0.2", @@ -39663,6 +56131,16 @@ "safe-buffer": "^5.1.0" } }, + "node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "license": "MIT", + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -40037,8 +56515,7 @@ "node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, "node_modules/react-json-view-lite": { "version": "1.4.0", @@ -40139,6 +56616,19 @@ } } }, + "node_modules/react-native-securerandom": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/react-native-securerandom/-/react-native-securerandom-0.1.1.tgz", + "integrity": "sha512-CozcCx0lpBLevxiXEb86kwLRalBCHNjiGPlw3P7Fi27U6ZLdfjOCNRHD1LtBKcvPvI3TvkBXB3GOtLvqaYJLGw==", + "license": "MIT", + "optional": true, + "dependencies": { + "base64-js": "*" + }, + "peerDependencies": { + "react-native": "*" + } + }, "node_modules/react-native-webview": { "version": "11.26.1", "resolved": "https://registry.npmjs.org/react-native-webview/-/react-native-webview-11.26.1.tgz", @@ -40484,6 +56974,12 @@ "license": "BSD", "peer": true }, + "node_modules/readonly-date": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/readonly-date/-/readonly-date-1.0.0.tgz", + "integrity": "sha512-tMKIV7hlk0h4mO3JTmmVuIlJVXjKk3Sep9Bf5OH0O+758ruuVkUy2J9SttDLm91IEX/WHlXPSpxMGjPj4beMIQ==", + "license": "Apache-2.0" + }, "node_modules/real-require": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.1.0.tgz", @@ -40862,6 +57358,14 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/remove-trailing-slash": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/remove-trailing-slash/-/remove-trailing-slash-0.1.1.tgz", + "integrity": "sha512-o4S4Qh6L2jpnCy83ysZDau+VORNvnFw07CKSAymkd6ICNVEPisMyzlc00KlvvicsxKck94SEwhDnMNdICzO+tA==", + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/renderkid": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", @@ -40955,6 +57459,93 @@ "entities": "^2.0.0" } }, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "license": "Apache-2.0", + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/request/node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/request/node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/request/node_modules/qs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/request/node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "license": "BSD-3-Clause", + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/request/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "license": "MIT", + "bin": { + "uuid": "bin/uuid" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -40997,11 +57588,53 @@ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, + "node_modules/requireg": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/requireg/-/requireg-0.2.2.tgz", + "integrity": "sha512-nYzyjnFcPNGR3lx9lwPPPnuQxv6JWEZd2Ci0u9opN7N5zUEPIhY/GbL3vMGOr2UXwEg9WwSyV9X9Y/kLFgPsOg==", + "optional": true, + "peer": true, + "dependencies": { + "nested-error-stacks": "~2.0.1", + "rc": "~1.2.7", + "resolve": "~1.7.1" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/requireg/node_modules/resolve": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", + "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "path-parse": "^1.0.5" + } + }, "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" }, + "node_modules/requizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz", + "integrity": "sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw==", + "license": "MIT", + "dependencies": { + "lodash": "^4.17.21" + } + }, + "node_modules/reselect": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", + "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==", + "license": "MIT", + "peer": true + }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -41195,6 +57828,105 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "license": "MIT", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/ripemd160-min": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/ripemd160-min/-/ripemd160-min-0.0.6.tgz", + "integrity": "sha512-+GcJgQivhs6S9qvLogusiTcS9kQUfgR75whKuy5jIhuiOfQuJ8fjqxV6EGD5duH1Y/FawFUMtMhyeq3Fbnib8A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ripple-address-codec": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ripple-address-codec/-/ripple-address-codec-5.0.0.tgz", + "integrity": "sha512-de7osLRH/pt5HX2xw2TRJtbdLLWHu0RXirpQaEeCnWKY5DYHykh3ETSkofvm0aX0LJiV7kwkegJxQkmbO94gWw==", + "license": "ISC", + "dependencies": { + "@scure/base": "^1.1.3", + "@xrplf/isomorphic": "^1.0.0" + }, + "engines": { + "node": ">= 16" + } + }, + "node_modules/ripple-binary-codec": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ripple-binary-codec/-/ripple-binary-codec-2.1.0.tgz", + "integrity": "sha512-q0GAx+hj3UVcDbhXVjk7qeNfgUMehlElYJwiCuIBwqs/51GVTOwLr39Ht3eNsX5ow2xPRaC5mqHwcFDvLRm6cA==", + "license": "ISC", + "dependencies": { + "@xrplf/isomorphic": "^1.0.1", + "bignumber.js": "^9.0.0", + "ripple-address-codec": "^5.0.0" + }, + "engines": { + "node": ">= 16" + } + }, + "node_modules/ripple-keypairs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ripple-keypairs/-/ripple-keypairs-2.0.0.tgz", + "integrity": "sha512-b5rfL2EZiffmklqZk1W+dvSy97v3V/C7936WxCCgDynaGPp7GE6R2XO7EU9O2LlM/z95rj870IylYnOQs+1Rag==", + "license": "ISC", + "dependencies": { + "@noble/curves": "^1.0.0", + "@xrplf/isomorphic": "^1.0.0", + "ripple-address-codec": "^5.0.0" + }, + "engines": { + "node": ">= 16" + } + }, + "node_modules/rlp": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.7.tgz", + "integrity": "sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==", + "license": "MPL-2.0", + "dependencies": { + "bn.js": "^5.2.0" + }, + "bin": { + "rlp": "bin/rlp" + } + }, + "node_modules/rpc-websockets": { + "version": "7.11.2", + "resolved": "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-7.11.2.tgz", + "integrity": "sha512-pL9r5N6AVHlMN/vT98+fcO+5+/UcPLf/4tq+WUaid/PPUGS/ttJ3y8e9IqmaWKtShNAysMSjkczuEA49NuV7UQ==", + "license": "LGPL-3.0-only", + "dependencies": { + "eventemitter3": "^4.0.7", + "uuid": "^8.3.2", + "ws": "^8.5.0" + }, + "funding": { + "type": "paypal", + "url": "https://paypal.me/kozjak" + }, + "optionalDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + } + }, + "node_modules/rpc-websockets/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/rtl-detect": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/rtl-detect/-/rtl-detect-1.1.2.tgz", @@ -41304,6 +58036,14 @@ } ] }, + "node_modules/safe-json-stringify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz", + "integrity": "sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg==", + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/safe-regex-test": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", @@ -41333,6 +58073,29 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "node_modules/sanitize-html": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.14.0.tgz", + "integrity": "sha512-CafX+IUPxZshXqqRaG9ZClSlfPVjSxI0td7n07hk8QO2oO+9JDnlcL8iM8TWeOXOIBFgIOx6zioTzM53AOMn3g==", + "license": "MIT", + "dependencies": { + "deepmerge": "^4.2.2", + "escape-string-regexp": "^4.0.0", + "htmlparser2": "^8.0.0", + "is-plain-object": "^5.0.0", + "parse-srcset": "^1.0.2", + "postcss": "^8.3.11" + } + }, + "node_modules/sanitize-html/node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/sass": { "version": "1.77.8", "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.8.tgz", @@ -41405,6 +58168,13 @@ "node": ">=v12.22.7" } }, + "node_modules/scale-ts": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/scale-ts/-/scale-ts-1.6.1.tgz", + "integrity": "sha512-PBMc2AWc6wSEqJYBDPcyCLUj9/tMKnLX70jLOSndMtcUoLQucP/DM0vnQo1wJAYjTrQiq8iG9rD0q6wFzgjH7g==", + "license": "MIT", + "optional": true + }, "node_modules/scheduler": { "version": "0.23.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", @@ -41431,6 +58201,12 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/scrypt-js": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", + "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==", + "license": "MIT" + }, "node_modules/search-insights": { "version": "2.17.3", "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.17.3.tgz", @@ -41444,7 +58220,6 @@ "integrity": "sha512-lDFs9AAIaWP9UCdtWrotXWWF9t8PWgQDcxqgAnpM9rMqxb3Oaq2J0thzPVSxBwdJgyQtkU/sYtFtbM1RSt/iYA==", "hasInstallScript": true, "license": "MIT", - "peer": true, "dependencies": { "elliptic": "^6.5.7", "node-addon-api": "^5.0.0", @@ -41458,8 +58233,13 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", - "license": "MIT", - "peer": true + "license": "MIT" + }, + "node_modules/secrets.js-grempe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/secrets.js-grempe/-/secrets.js-grempe-1.1.0.tgz", + "integrity": "sha512-OsbpZUFTjvQPKHpseAbFPY82U3mVNP4G3WSbJiDtMLjzwsV52MTdc6rTwIooIkg3klf5eCrg62ZuGIz5GaW02A==", + "license": "MIT" }, "node_modules/section-matter": { "version": "1.0.0", @@ -41479,6 +58259,12 @@ "integrity": "sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==", "dev": true }, + "node_modules/secure-json-parse": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", + "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==", + "license": "BSD-3-Clause" + }, "node_modules/select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", @@ -41755,6 +58541,22 @@ "node": ">= 0.8.0" } }, + "node_modules/servify": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/servify/-/servify-0.1.12.tgz", + "integrity": "sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw==", + "license": "MIT", + "dependencies": { + "body-parser": "^1.16.0", + "cors": "^2.8.1", + "express": "^4.14.0", + "request": "^2.79.0", + "xhr": "^2.3.3" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -41790,6 +58592,12 @@ "node": ">= 0.4" } }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "license": "MIT" + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -41915,6 +58723,70 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/simple-get": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.2.tgz", + "integrity": "sha512-Ijd/rV5o+mSBBs4F/x9oDPtTx9Zb6X9brmnXvMW4J7IR15ngi9q5xxqWBKU744jTZiaXtxaPL7uHG6vtN8kUkw==", + "license": "MIT", + "dependencies": { + "decompress-response": "^3.3.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/simple-get/node_modules/decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", + "license": "MIT", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/simple-get/node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/simple-plist": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/simple-plist/-/simple-plist-1.3.1.tgz", + "integrity": "sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw==", + "license": "MIT", + "peer": true, + "dependencies": { + "bplist-creator": "0.1.0", + "bplist-parser": "0.3.1", + "plist": "^3.0.5" + } + }, "node_modules/simple-swizzle": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", @@ -41969,6 +58841,15 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==" }, + "node_modules/sjcl": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/sjcl/-/sjcl-1.0.8.tgz", + "integrity": "sha512-LzIjEQ0S0DpIgnxMEayM1rq9aGwGRG4OnZhCdjx7glTaJtf4zRfpg87ImfjSJjoW9vKpagd82McDOwbRT5kQKQ==", + "license": "(BSD-2-Clause OR GPL-2.0-only)", + "engines": { + "node": "*" + } + }, "node_modules/skin-tone": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/skin-tone/-/skin-tone-2.0.0.tgz", @@ -42016,16 +58897,35 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/slugify": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.6.tgz", + "integrity": "sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/smart-buffer": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true, "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" } }, + "node_modules/smoldot": { + "version": "2.0.26", + "resolved": "https://registry.npmjs.org/smoldot/-/smoldot-2.0.26.tgz", + "integrity": "sha512-F+qYmH4z2s2FK+CxGj8moYcd1ekSIKH8ywkdqlOz88Dat35iB1DIYL11aILN46YSGMzQW/lbJNS307zBSDN5Ig==", + "license": "GPL-3.0-or-later WITH Classpath-exception-2.0", + "optional": true, + "dependencies": { + "ws": "^8.8.1" + } + }, "node_modules/snake-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", @@ -42083,7 +58983,6 @@ "version": "2.8.3", "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", - "dev": true, "dependencies": { "ip-address": "^9.0.5", "smart-buffer": "^4.2.0" @@ -42097,7 +58996,6 @@ "version": "8.0.5", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", - "dev": true, "dependencies": { "agent-base": "^7.1.2", "debug": "^4.3.4", @@ -42107,6 +59005,17 @@ "node": ">= 14" } }, + "node_modules/sodium-native": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-3.4.1.tgz", + "integrity": "sha512-PaNN/roiFWzVVTL6OqjzYct38NSXewdl2wz8SRB51Br/MLIJPrbM3XexhVWkq7D3UWMysfrhKVf1v1phZq6MeQ==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + } + }, "node_modules/sonic-boom": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-2.8.0.tgz", @@ -42237,6 +59146,20 @@ "wbuf": "^1.7.3" } }, + "node_modules/split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "through": "2" + }, + "engines": { + "node": "*" + } + }, "node_modules/split-on-first": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", @@ -42269,6 +59192,71 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/sshpk": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", + "license": "MIT", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sshpk/node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "license": "MIT" + }, + "node_modules/sshpk/node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "license": "Unlicense" + }, + "node_modules/ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/ssri/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", @@ -42349,6 +59337,83 @@ "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==" }, + "node_modules/stellar-base": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/stellar-base/-/stellar-base-8.2.2.tgz", + "integrity": "sha512-YVCIuJXU1bPn+vU0ded+g0D99DcpYXH9CEXfpYEDc4Gf04h65YjOVhGojQBm1hqVHq3rKT7m1tgfNACkU84FTA==", + "deprecated": "⚠️ This package has moved to @stellar/stellar-base! 🚚", + "license": "Apache-2.0", + "dependencies": { + "base32.js": "^0.1.0", + "bignumber.js": "^4.0.0", + "crc": "^3.5.0", + "js-xdr": "^1.1.3", + "lodash": "^4.17.21", + "sha.js": "^2.3.6", + "tweetnacl": "^1.0.3" + }, + "optionalDependencies": { + "sodium-native": "^3.3.0" + } + }, + "node_modules/stellar-base/node_modules/bignumber.js": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-4.1.0.tgz", + "integrity": "sha512-eJzYkFYy9L4JzXsbymsFn3p54D+llV27oTQ+ziJG7WFRheJcNZilgVXMG0LoZtlQSKBsJdWtLFqOD0u+U0jZKA==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/stellar-sdk": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/stellar-sdk/-/stellar-sdk-10.4.1.tgz", + "integrity": "sha512-Wdm2UoLuN9SNrSEHO0R/I+iZuRwUkfny1xg4akhGCpO8LQZw8QzuMTJvbEoMT3sHT4/eWYiteVLp7ND21xZf5A==", + "deprecated": "⚠️ This package has moved to @stellar/stellar-sdk! 🚚", + "license": "Apache-2.0", + "dependencies": { + "@types/eventsource": "^1.1.2", + "@types/node": ">= 8", + "@types/randombytes": "^2.0.0", + "@types/urijs": "^1.19.6", + "axios": "0.25.0", + "bignumber.js": "^4.0.0", + "detect-node": "^2.0.4", + "es6-promise": "^4.2.4", + "eventsource": "^1.1.1", + "lodash": "^4.17.21", + "randombytes": "^2.1.0", + "stellar-base": "^8.2.2", + "toml": "^2.3.0", + "tslib": "^1.10.0", + "urijs": "^1.19.1", + "utility-types": "^3.7.0" + } + }, + "node_modules/stellar-sdk/node_modules/axios": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz", + "integrity": "sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.14.7" + } + }, + "node_modules/stellar-sdk/node_modules/bignumber.js": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-4.1.0.tgz", + "integrity": "sha512-eJzYkFYy9L4JzXsbymsFn3p54D+llV27oTQ+ziJG7WFRheJcNZilgVXMG0LoZtlQSKBsJdWtLFqOD0u+U0jZKA==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/stellar-sdk/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, "node_modules/steno": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/steno/-/steno-4.0.2.tgz", @@ -42372,6 +59437,38 @@ "node": ">= 0.4" } }, + "node_modules/store2": { + "version": "2.13.2", + "resolved": "https://registry.npmjs.org/store2/-/store2-2.13.2.tgz", + "integrity": "sha512-CMtO2Uneg3SAz/d6fZ/6qbqqQHi2ynq6/KzMD/26gTkiEShCcpqFfTHgOxsE0egAq6SX3FmN4CeSqn8BzXQkJg==", + "license": "(MIT OR GPL-3.0)" + }, + "node_modules/str2buf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/str2buf/-/str2buf-1.3.0.tgz", + "integrity": "sha512-xIBmHIUHYZDP4HyoXGHYNVmxlXLXDrtFHYT0eV6IOdEj3VO9ccaF1Ejl9Oq8iFjITllpT8FhaXb4KsNmw+3EuA==", + "license": "MIT" + }, + "node_modules/stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "license": "MIT", + "dependencies": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + } + }, + "node_modules/stream-buffers": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz", + "integrity": "sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==", + "license": "Unlicense", + "peer": true, + "engines": { + "node": ">= 0.10.0" + } + }, "node_modules/stream-shift": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", @@ -42438,6 +59535,12 @@ "dev": true, "license": "MIT" }, + "node_modules/strict-event-emitter-types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-event-emitter-types/-/strict-event-emitter-types-2.0.0.tgz", + "integrity": "sha512-Nk/brWYpD85WlOgzw5h173aci0Teyv8YdIAEtV+N88nDB0dLlazZyJMIsN6eo1/AR61l+p6CJTG1JIyFaoNEEA==", + "license": "ISC" + }, "node_modules/strict-uri-encode": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", @@ -42497,7 +59600,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -42510,14 +59612,12 @@ "node_modules/string-width-cjs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -42671,7 +59771,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -42696,6 +59795,17 @@ "node": ">=0.10.0" } }, + "node_modules/strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", @@ -42704,6 +59814,19 @@ "node": ">=6" } }, + "node_modules/strip-hex-prefix": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", + "integrity": "sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==", + "license": "MIT", + "dependencies": { + "is-hex-prefixed": "1.0.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -42737,6 +59860,14 @@ "node": ">=4" } }, + "node_modules/structured-headers": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/structured-headers/-/structured-headers-0.4.1.tgz", + "integrity": "sha512-0MP/Cxx5SzeeZ10p/bZI0S6MpgD+yxAhi1BOQ34jgnMXsCq3j1t6tQnZu+KdlL7dvJTLT3g9xN8tl10TqgFMcg==", + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/style-loader": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz", @@ -42867,7 +59998,6 @@ "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", - "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", @@ -42889,7 +60019,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true, "engines": { "node": ">= 6" } @@ -42898,7 +60027,6 @@ "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", @@ -42918,7 +60046,6 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, "dependencies": { "@isaacs/cliui": "^8.0.2" }, @@ -42932,14 +60059,12 @@ "node_modules/sucrase/node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, "node_modules/sucrase/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -42950,11 +60075,19 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/sudo-prompt": { + "version": "8.2.5", + "resolved": "https://registry.npmjs.org/sudo-prompt/-/sudo-prompt-8.2.5.tgz", + "integrity": "sha512-rlBo3HU/1zAJUrkY6jNxDOC9eVYliG6nS4JA8u8KAshITd07tafMc/Br7xQwCSseXwJ2iCcHCE8SNWX3q8Z+kw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/superagent": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/superagent/-/superagent-9.0.2.tgz", "integrity": "sha512-xuW7dzkUpcJq7QnhOsnNUgtYp3xRwpt2F7abdRYIpCsAt0hhUqia0EdxyXZQQpNmGtsCzYHryaKSV3q3GJnq7w==", - "dev": true, "dependencies": { "component-emitter": "^1.3.0", "cookiejar": "^2.1.4", @@ -42974,7 +60107,6 @@ "version": "2.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", - "dev": true, "bin": { "mime": "cli.js" }, @@ -43014,6 +60146,21 @@ "node": ">=8" } }, + "node_modules/supports-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -43067,6 +60214,225 @@ "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.17.14.tgz", "integrity": "sha512-CVbSfaLpstV65OnSjbXfVd6Sta3q3F7Cj/yYuvHMp1P90LztOLs6PfUnKEVAeiIVQt9u2SaPwv0LiH/OyMjHRw==" }, + "node_modules/swarm-js": { + "version": "0.1.42", + "resolved": "https://registry.npmjs.org/swarm-js/-/swarm-js-0.1.42.tgz", + "integrity": "sha512-BV7c/dVlA3R6ya1lMlSSNPLYrntt0LUq4YMgy3iwpCIc6rZnS5W2wUoctarZ5pXlpKtxDDf9hNziEkcfrxdhqQ==", + "license": "MIT", + "dependencies": { + "bluebird": "^3.5.0", + "buffer": "^5.0.5", + "eth-lib": "^0.1.26", + "fs-extra": "^4.0.2", + "got": "^11.8.5", + "mime-types": "^2.1.16", + "mkdirp-promise": "^5.0.1", + "mock-fs": "^4.1.0", + "setimmediate": "^1.0.5", + "tar": "^4.0.2", + "xhr-request": "^1.0.1" + } + }, + "node_modules/swarm-js/node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "license": "MIT", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/swarm-js/node_modules/bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "license": "MIT" + }, + "node_modules/swarm-js/node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "license": "MIT", + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/swarm-js/node_modules/cacheable-request": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", + "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "license": "MIT", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/swarm-js/node_modules/eth-lib": { + "version": "0.1.29", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.29.tgz", + "integrity": "sha512-bfttrr3/7gG4E02HoWTDUcDDslN003OlOoBxk9virpAZQ1ja/jDgwkWB8QfJF7ojuEowrqy+lzp9VcJG7/k5bQ==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "nano-json-stream-parser": "^0.1.2", + "servify": "^0.1.12", + "ws": "^3.0.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/swarm-js/node_modules/fs-extra": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", + "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "node_modules/swarm-js/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/swarm-js/node_modules/got": { + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/swarm-js/node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "license": "MIT", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/swarm-js/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/swarm-js/node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/swarm-js/node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/swarm-js/node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/swarm-js/node_modules/responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "license": "MIT", + "dependencies": { + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/swarm-js/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/swarm-js/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/swarm-js/node_modules/ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "license": "MIT", + "dependencies": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } + }, "node_modules/swr": { "version": "2.2.5", "resolved": "https://registry.npmjs.org/swr/-/swr-2.2.5.tgz", @@ -43079,6 +60445,15 @@ "react": "^16.11.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/symbol-observable": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-2.0.3.tgz", + "integrity": "sha512-sQV7phh2WCYAn81oAkakC5qjq2Ml0g8ozqz03wOGnx9dDlG1de6yrF+0RAzSJD8fPUow3PTSMf2SAbOGxb93BA==", + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", @@ -43216,6 +60591,24 @@ "node": ">=6" } }, + "node_modules/tar": { + "version": "4.4.19", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", + "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", + "license": "ISC", + "dependencies": { + "chownr": "^1.1.4", + "fs-minipass": "^1.2.7", + "minipass": "^2.9.0", + "minizlib": "^1.3.3", + "mkdirp": "^0.5.5", + "safe-buffer": "^5.2.1", + "yallist": "^3.1.1" + }, + "engines": { + "node": ">=4.5" + } + }, "node_modules/tar-stream": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", @@ -43232,6 +60625,117 @@ "node": ">=6" } }, + "node_modules/tar/node_modules/minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "license": "ISC", + "dependencies": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "license": "ISC" + }, + "node_modules/tcomb": { + "version": "3.2.29", + "resolved": "https://registry.npmjs.org/tcomb/-/tcomb-3.2.29.tgz", + "integrity": "sha512-di2Hd1DB2Zfw6StGv861JoAF5h/uQVu/QJp2g8KVbtfKnoHdBQl5M32YWq6mnSYBQ1vFFrns5B1haWJL7rKaOQ==", + "license": "MIT" + }, + "node_modules/temp-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/tempy": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.7.1.tgz", + "integrity": "sha512-vXPxwOyaNVi9nyczO16mxmHGpl6ASC5/TVhRRHpqeYHvKQm58EaWNvZXxAhR0lYYnBOQFjXjhzeLsaXdjxLjRg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "del": "^6.0.0", + "is-stream": "^2.0.0", + "temp-dir": "^2.0.0", + "type-fest": "^0.16.0", + "unique-string": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tempy/node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/tempy/node_modules/type-fest": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", + "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", + "license": "(MIT OR CC0-1.0)", + "optional": true, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tempy/node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/terminal-link": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", + "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "supports-hyperlinks": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/terser": { "version": "5.31.2", "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.2.tgz", @@ -43409,6 +60913,11 @@ "node": "*" } }, + "node_modules/text-encoding-utf-8": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz", + "integrity": "sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==" + }, "node_modules/text-hex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", @@ -43423,7 +60932,6 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dev": true, "dependencies": { "any-promise": "^1.0.0" } @@ -43432,7 +60940,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "dev": true, "dependencies": { "thenify": ">= 3.1.0 < 4" }, @@ -43470,14 +60977,35 @@ "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" }, "node_modules/thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" }, + "node_modules/timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha512-G7r3AhovYtr5YKOWQkta8RKAPb+J9IsO4uVmzjl8AZwfhs8UcUwTiD6gcJYSgOtzyjvQKrKYn41syHbUWMkafA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/timers-ext": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.8.tgz", + "integrity": "sha512-wFH7+SEAcKfJpfLPkrgMPvvwnEtj8W4IurvEyrKsDleXnKLCDw71w8jltvfLa8Rm4qQxxT4jmDBYbJG/z7qoww==", + "license": "ISC", + "dependencies": { + "es5-ext": "^0.10.64", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.12" + } + }, "node_modules/tiny-invariant": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", @@ -43501,6 +61029,15 @@ "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==" }, + "node_modules/to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -43520,6 +61057,76 @@ "node": ">=0.6" } }, + "node_modules/toml": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/toml/-/toml-2.3.6.tgz", + "integrity": "sha512-gVweAectJU3ebq//Ferr2JUY4WKSDe5N+z0FvjDncLGyHmIDoxgY/2Ie4qfEIDm4IS7OA6Rmdm7pdEEdMcV/xQ==", + "license": "MIT" + }, + "node_modules/tonweb": { + "version": "0.0.62", + "resolved": "https://registry.npmjs.org/tonweb/-/tonweb-0.0.62.tgz", + "integrity": "sha512-Uwu2DQwmVkI85WVLzqIqUvqNk++N97e2EH3hKb+Tvq3fA6pcEP7AugcNr1xU33GmajtLT9vquMo7/kNcnS1Fuw==", + "license": "MIT", + "dependencies": { + "@ledgerhq/hw-transport-web-ble": "5.48.0", + "@ledgerhq/hw-transport-webhid": "5.48.0", + "@ledgerhq/hw-transport-webusb": "5.48.0", + "bn.js": "5.1.1", + "ethjs-unit": "0.1.6", + "isomorphic-webcrypto": "2.3.8", + "node-fetch": "2.6.7", + "tweetnacl": "1.0.3" + } + }, + "node_modules/tonweb/node_modules/bn.js": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.1.tgz", + "integrity": "sha512-IUTD/REb78Z2eodka1QZyyEk66pciRcP6Sroka0aI3tG/iwIdYLrBD62RsubR7vqdt3WyX8p4jxeatzmRSphtA==", + "license": "MIT" + }, + "node_modules/tonweb/node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/tonweb/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/tonweb/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/tonweb/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/totalist": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", @@ -43640,6 +61247,49 @@ "node": ">= 14.0.0" } }, + "node_modules/tronweb": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/tronweb/-/tronweb-5.1.0.tgz", + "integrity": "sha512-8a+mYKVUzsUWjeTHSAKcxAp82FseFTLlNLoLQ0KIL1rIt6Dy5whcyJwYatxUktbaztl55lnImHbupkKqMdIj1w==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.0.0", + "@tronweb3/google-protobuf": "^3.21.2", + "axios": "^0.26.1", + "bignumber.js": "^9.0.1", + "elliptic": "^6.5.4", + "ethers": "^5.4.4", + "eventemitter3": "^3.1.0", + "injectpromise": "^1.0.0", + "lodash": "^4.17.21", + "semver": "^5.6.0", + "validator": "^13.7.0" + } + }, + "node_modules/tronweb/node_modules/axios": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.14.8" + } + }, + "node_modules/tronweb/node_modules/eventemitter3": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", + "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==", + "license": "MIT" + }, + "node_modules/tronweb/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, "node_modules/trough": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", @@ -43673,8 +61323,7 @@ "node_modules/ts-interface-checker": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", - "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", - "dev": true + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" }, "node_modules/ts-jest": { "version": "29.2.3", @@ -43817,6 +61466,12 @@ "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true }, + "node_modules/ts-results": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ts-results/-/ts-results-3.3.0.tgz", + "integrity": "sha512-FWqxGX2NHp5oCyaMd96o2y2uMQmSu8Dey6kvyuFdRJ2AzfmWo3kWa4UsPlCGlfQ/qu03m09ZZtppMoY8EMHuiA==", + "license": "MIT" + }, "node_modules/tsc-alias": { "version": "1.8.8", "resolved": "https://registry.npmjs.org/tsc-alias/-/tsc-alias-1.8.8.tgz", @@ -43894,11 +61549,55 @@ "node": ">=0.6.x" } }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", + "license": "Unlicense" + }, + "node_modules/tweetnacl-ts": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl-ts/-/tweetnacl-ts-1.0.3.tgz", + "integrity": "sha512-C5I/dWf6xjAXaCDlf84T4HvozU/8ycAlq5WRllF1hAeeq5390tfXD+bNas5bhEV0HMSOx8bsQYpLjPl8wfnEeQ==", + "license": "UNLICENSED", + "dependencies": { + "tslib": "^1" + } + }, + "node_modules/tweetnacl-ts/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, + "node_modules/tweetnacl-util": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz", + "integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==", + "license": "Unlicense" + }, + "node_modules/type": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz", + "integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==", + "license": "ISC" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "devOptional": true, "dependencies": { "prelude-ls": "^1.2.1" }, @@ -44044,6 +61743,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/typedjson": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/typedjson/-/typedjson-1.8.0.tgz", + "integrity": "sha512-taVJVGebQDagEmVc3Cu6vVVLkWLnxqPcTrkVgbpAsI02ZDDrnHy5zvt1JVqXv4/yztBgZAX1oR07+bkiusGJLQ==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.1" + } + }, + "node_modules/typeforce": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz", + "integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==", + "license": "MIT" + }, "node_modules/typescript": { "version": "5.4.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", @@ -44056,6 +61770,45 @@ "node": ">=14.17" } }, + "node_modules/u3": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/u3/-/u3-0.1.1.tgz", + "integrity": "sha512-+J5D5ir763y+Am/QY6hXNRlwljIeRMZMGs0cT6qqZVVzzT3X3nFPXVyPOFRMOR4kupB0T8JnCdpWdp6Q/iXn3w==", + "license": "MIT" + }, + "node_modules/ua-parser-js": { + "version": "0.7.40", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.40.tgz", + "integrity": "sha512-us1E3K+3jJppDBa3Tl0L3MOJiGhe1C6P0+nIvQAFYbxlMAx0h81eOwLmU57xgqToduDDPx3y5QsdjPfDu+FgOQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + }, + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + } + ], + "license": "MIT", + "peer": true, + "bin": { + "ua-parser-js": "script/cli.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "license": "MIT" + }, "node_modules/ufo": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz", @@ -44065,7 +61818,6 @@ "version": "3.18.0", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.18.0.tgz", "integrity": "sha512-SyVVbcNBCk0dzr9XL/R/ySrmYf0s372K6/hFklzgcp2lBFyXtw4I7BOdDjlLhE1aVqaI/SHWXWmYdlZxuyF38A==", - "optional": true, "bin": { "uglifyjs": "bin/uglifyjs" }, @@ -44092,6 +61844,12 @@ "multiformats": "^9.4.2" } }, + "node_modules/ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", + "license": "MIT" + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -44111,6 +61869,12 @@ "resolved": "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz", "integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==" }, + "node_modules/underscore": { + "version": "1.13.7", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz", + "integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==", + "license": "MIT" + }, "node_modules/unenv": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/unenv/-/unenv-1.10.0.tgz", @@ -44216,6 +61980,28 @@ "node": ">= 0.8.0" } }, + "node_modules/unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "imurmurhash": "^0.1.4" + } + }, "node_modules/unique-string": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", @@ -44585,6 +62371,12 @@ "node": ">=6" } }, + "node_modules/urijs": { + "version": "1.19.11", + "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.11.tgz", + "integrity": "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==", + "license": "MIT" + }, "node_modules/url-join": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", @@ -44666,12 +62458,29 @@ "version": "1.5.10", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" } }, + "node_modules/url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==", + "license": "MIT", + "dependencies": { + "prepend-http": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/url-set-query": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-set-query/-/url-set-query-1.0.0.tgz", + "integrity": "sha512-3AChu4NiXquPfeckE5R5cGdiHCMWJx1dwCWOmWIL4KHAziJNOFIYJlpGFeKDvwLPHovZRCxK3cYlwzqI9Vp+Gg==", + "license": "MIT" + }, "node_modules/use-callback-ref": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.2.tgz", @@ -44747,6 +62556,12 @@ "node": ">=6.14.2" } }, + "node_modules/utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", + "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==", + "license": "MIT" + }, "node_modules/util": { "version": "0.12.5", "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", @@ -44817,6 +62632,13 @@ "node": ">=10.12.0" } }, + "node_modules/valid-url": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz", + "integrity": "sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA==", + "optional": true, + "peer": true + }, "node_modules/validate-npm-package-name": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", @@ -44871,6 +62693,21 @@ "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" }, + "node_modules/varint": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz", + "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==", + "license": "MIT" + }, + "node_modules/varuint-bitcoin": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/varuint-bitcoin/-/varuint-bitcoin-1.1.2.tgz", + "integrity": "sha512-4EVb+w4rx+YfVM32HQX42AbbT7/1f5zwAYhIujKXKk8NQK+JfRVl3pqT3hjNn/L+RstigmGGKVwHA/P0wgITZw==", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.1" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -44879,6 +62716,26 @@ "node": ">= 0.8" } }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "engines": [ + "node >=0.6.0" + ], + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/verror/node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "license": "MIT" + }, "node_modules/vfile": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", @@ -45098,7 +62955,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dev": true, + "devOptional": true, "dependencies": { "defaults": "^1.0.3" } @@ -45112,6 +62969,734 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/web3": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/web3/-/web3-1.3.6.tgz", + "integrity": "sha512-jEpPhnL6GDteifdVh7ulzlPrtVQeA30V9vnki9liYlUvLV82ZM7BNOQJiuzlDePuE+jZETZSP/0G/JlUVt6pOA==", + "hasInstallScript": true, + "license": "LGPL-3.0", + "dependencies": { + "web3-bzz": "1.3.6", + "web3-core": "1.3.6", + "web3-eth": "1.3.6", + "web3-eth-personal": "1.3.6", + "web3-net": "1.3.6", + "web3-shh": "1.3.6", + "web3-utils": "1.3.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-bzz": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.3.6.tgz", + "integrity": "sha512-ibHdx1wkseujFejrtY7ZyC0QxQ4ATXjzcNUpaLrvM6AEae8prUiyT/OloG9FWDgFD2CPLwzKwfSQezYQlANNlw==", + "hasInstallScript": true, + "license": "LGPL-3.0", + "dependencies": { + "@types/node": "^12.12.6", + "got": "9.6.0", + "swarm-js": "^0.1.40", + "underscore": "1.12.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-bzz/node_modules/@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/web3-bzz/node_modules/@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "license": "MIT", + "dependencies": { + "defer-to-connect": "^1.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/web3-bzz/node_modules/@types/node": { + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", + "license": "MIT" + }, + "node_modules/web3-bzz/node_modules/cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "license": "MIT", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/web3-bzz/node_modules/cacheable-request/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/web3-bzz/node_modules/cacheable-request/node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/web3-bzz/node_modules/decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", + "license": "MIT", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/web3-bzz/node_modules/defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "license": "MIT" + }, + "node_modules/web3-bzz/node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/web3-bzz/node_modules/got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/web3-bzz/node_modules/json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==", + "license": "MIT" + }, + "node_modules/web3-bzz/node_modules/keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.0" + } + }, + "node_modules/web3-bzz/node_modules/lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/web3-bzz/node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/web3-bzz/node_modules/normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/web3-bzz/node_modules/p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/web3-bzz/node_modules/responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", + "license": "MIT", + "dependencies": { + "lowercase-keys": "^1.0.0" + } + }, + "node_modules/web3-bzz/node_modules/underscore": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", + "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", + "license": "MIT" + }, + "node_modules/web3-core": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.3.6.tgz", + "integrity": "sha512-gkLDM4T1Sc0T+HZIwxrNrwPg0IfWI0oABSglP2X5ZbBAYVUeEATA0o92LWV8BeF+okvKXLK1Fek/p6axwM/h3Q==", + "license": "LGPL-3.0", + "dependencies": { + "@types/bn.js": "^4.11.5", + "@types/node": "^12.12.6", + "bignumber.js": "^9.0.0", + "web3-core-helpers": "1.3.6", + "web3-core-method": "1.3.6", + "web3-core-requestmanager": "1.3.6", + "web3-utils": "1.3.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-core-helpers": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.3.6.tgz", + "integrity": "sha512-nhtjA2ZbkppjlxTSwG0Ttu6FcPkVu1rCN5IFAOVpF/L0SEt+jy+O5l90+cjDq0jAYvlBwUwnbh2mR9hwDEJCNA==", + "license": "LGPL-3.0", + "dependencies": { + "underscore": "1.12.1", + "web3-eth-iban": "1.3.6", + "web3-utils": "1.3.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-core-helpers/node_modules/underscore": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", + "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", + "license": "MIT" + }, + "node_modules/web3-core-method": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.3.6.tgz", + "integrity": "sha512-RyegqVGxn0cyYW5yzAwkPlsSEynkdPiegd7RxgB4ak1eKk2Cv1q2x4C7D2sZjeeCEF+q6fOkVmo2OZNqS2iQxg==", + "license": "LGPL-3.0", + "dependencies": { + "@ethersproject/transactions": "^5.0.0-beta.135", + "underscore": "1.12.1", + "web3-core-helpers": "1.3.6", + "web3-core-promievent": "1.3.6", + "web3-core-subscriptions": "1.3.6", + "web3-utils": "1.3.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-core-method/node_modules/underscore": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", + "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", + "license": "MIT" + }, + "node_modules/web3-core-promievent": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.3.6.tgz", + "integrity": "sha512-Z+QzfyYDTXD5wJmZO5wwnRO8bAAHEItT1XNSPVb4J1CToV/I/SbF7CuF8Uzh2jns0Cm1109o666H7StFFvzVKw==", + "license": "LGPL-3.0", + "dependencies": { + "eventemitter3": "4.0.4" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-core-promievent/node_modules/eventemitter3": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz", + "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==", + "license": "MIT" + }, + "node_modules/web3-core-requestmanager": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.3.6.tgz", + "integrity": "sha512-2rIaeuqeo7QN1Eex7aXP0ZqeteJEPWXYFS/M3r3LXMiV8R4STQBKE+//dnHJXoo2ctzEB5cgd+7NaJM8S3gPyA==", + "license": "LGPL-3.0", + "dependencies": { + "underscore": "1.12.1", + "util": "^0.12.0", + "web3-core-helpers": "1.3.6", + "web3-providers-http": "1.3.6", + "web3-providers-ipc": "1.3.6", + "web3-providers-ws": "1.3.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-core-requestmanager/node_modules/underscore": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", + "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", + "license": "MIT" + }, + "node_modules/web3-core-subscriptions": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.3.6.tgz", + "integrity": "sha512-wi9Z9X5X75OKvxAg42GGIf81ttbNR2TxzkAsp1g+nnp5K8mBwgZvXrIsDuj7Z7gx72Y45mWJADCWjk/2vqNu8g==", + "license": "LGPL-3.0", + "dependencies": { + "eventemitter3": "4.0.4", + "underscore": "1.12.1", + "web3-core-helpers": "1.3.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-core-subscriptions/node_modules/eventemitter3": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz", + "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==", + "license": "MIT" + }, + "node_modules/web3-core-subscriptions/node_modules/underscore": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", + "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", + "license": "MIT" + }, + "node_modules/web3-core/node_modules/@types/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/web3-core/node_modules/@types/node": { + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", + "license": "MIT" + }, + "node_modules/web3-eth": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.3.6.tgz", + "integrity": "sha512-9+rnywRRpyX3C4hfsAQXPQh6vHh9XzQkgLxo3gyeXfbhbShUoq2gFVuy42vsRs//6JlsKdyZS7Z3hHPHz2wreA==", + "license": "LGPL-3.0", + "dependencies": { + "underscore": "1.12.1", + "web3-core": "1.3.6", + "web3-core-helpers": "1.3.6", + "web3-core-method": "1.3.6", + "web3-core-subscriptions": "1.3.6", + "web3-eth-abi": "1.3.6", + "web3-eth-accounts": "1.3.6", + "web3-eth-contract": "1.3.6", + "web3-eth-ens": "1.3.6", + "web3-eth-iban": "1.3.6", + "web3-eth-personal": "1.3.6", + "web3-net": "1.3.6", + "web3-utils": "1.3.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-abi": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.3.6.tgz", + "integrity": "sha512-Or5cRnZu6WzgScpmbkvC6bfNxR26hqiKK4i8sMPFeTUABQcb/FU3pBj7huBLYbp9dH+P5W79D2MqwbWwjj9DoQ==", + "license": "LGPL-3.0", + "dependencies": { + "@ethersproject/abi": "5.0.7", + "underscore": "1.12.1", + "web3-utils": "1.3.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-abi/node_modules/@ethersproject/abi": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.0.7.tgz", + "integrity": "sha512-Cqktk+hSIckwP/W8O47Eef60VwmoSC/L3lY0+dIBhQPCNn9E4V7rwmm2aFrNRRDJfFlGuZ1khkQUOc3oBX+niw==", + "license": "MIT", + "dependencies": { + "@ethersproject/address": "^5.0.4", + "@ethersproject/bignumber": "^5.0.7", + "@ethersproject/bytes": "^5.0.4", + "@ethersproject/constants": "^5.0.4", + "@ethersproject/hash": "^5.0.4", + "@ethersproject/keccak256": "^5.0.3", + "@ethersproject/logger": "^5.0.5", + "@ethersproject/properties": "^5.0.3", + "@ethersproject/strings": "^5.0.4" + } + }, + "node_modules/web3-eth-abi/node_modules/underscore": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", + "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", + "license": "MIT" + }, + "node_modules/web3-eth-accounts": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.3.6.tgz", + "integrity": "sha512-Ilr0hG6ONbCdSlVKffasCmNwftD5HsNpwyQASevocIQwHdTlvlwO0tb3oGYuajbKOaDzNTwXfz25bttAEoFCGA==", + "license": "LGPL-3.0", + "dependencies": { + "crypto-browserify": "3.12.0", + "eth-lib": "0.2.8", + "ethereumjs-common": "^1.3.2", + "ethereumjs-tx": "^2.1.1", + "scrypt-js": "^3.0.1", + "underscore": "1.12.1", + "uuid": "3.3.2", + "web3-core": "1.3.6", + "web3-core-helpers": "1.3.6", + "web3-core-method": "1.3.6", + "web3-utils": "1.3.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-accounts/node_modules/underscore": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", + "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", + "license": "MIT" + }, + "node_modules/web3-eth-accounts/node_modules/uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "license": "MIT", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/web3-eth-contract": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.3.6.tgz", + "integrity": "sha512-8gDaRrLF2HCg+YEZN1ov0zN35vmtPnGf3h1DxmJQK5Wm2lRMLomz9rsWsuvig3UJMHqZAQKD7tOl3ocJocQsmA==", + "license": "LGPL-3.0", + "dependencies": { + "@types/bn.js": "^4.11.5", + "underscore": "1.12.1", + "web3-core": "1.3.6", + "web3-core-helpers": "1.3.6", + "web3-core-method": "1.3.6", + "web3-core-promievent": "1.3.6", + "web3-core-subscriptions": "1.3.6", + "web3-eth-abi": "1.3.6", + "web3-utils": "1.3.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-contract/node_modules/@types/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/web3-eth-contract/node_modules/underscore": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", + "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", + "license": "MIT" + }, + "node_modules/web3-eth-ens": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.3.6.tgz", + "integrity": "sha512-n27HNj7lpSkRxTgSx+Zo7cmKAgyg2ElFilaFlUu/X2CNH23lXfcPm2bWssivH9z0ndhg0OyR4AYFZqPaqDHkJA==", + "license": "LGPL-3.0", + "dependencies": { + "content-hash": "^2.5.2", + "eth-ens-namehash": "2.0.8", + "underscore": "1.12.1", + "web3-core": "1.3.6", + "web3-core-helpers": "1.3.6", + "web3-core-promievent": "1.3.6", + "web3-eth-abi": "1.3.6", + "web3-eth-contract": "1.3.6", + "web3-utils": "1.3.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-ens/node_modules/underscore": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", + "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", + "license": "MIT" + }, + "node_modules/web3-eth-iban": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.3.6.tgz", + "integrity": "sha512-nfMQaaLA/zsg5W4Oy/EJQbs8rSs1vBAX6b/35xzjYoutXlpHMQadujDx2RerTKhSHqFXSJeQAfE+2f6mdhYkRQ==", + "license": "LGPL-3.0", + "dependencies": { + "bn.js": "^4.11.9", + "web3-utils": "1.3.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-iban/node_modules/bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "license": "MIT" + }, + "node_modules/web3-eth-personal": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.3.6.tgz", + "integrity": "sha512-pOHU0+/h1RFRYoh1ehYBehRbcKWP4OSzd4F7mDljhHngv6W8ewMHrAN8O1ol9uysN2MuCdRE19qkRg5eNgvzFQ==", + "license": "LGPL-3.0", + "dependencies": { + "@types/node": "^12.12.6", + "web3-core": "1.3.6", + "web3-core-helpers": "1.3.6", + "web3-core-method": "1.3.6", + "web3-net": "1.3.6", + "web3-utils": "1.3.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-personal/node_modules/@types/node": { + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", + "license": "MIT" + }, + "node_modules/web3-eth/node_modules/underscore": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", + "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", + "license": "MIT" + }, + "node_modules/web3-net": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.3.6.tgz", + "integrity": "sha512-KhzU3wMQY/YYjyMiQzbaLPt2kut88Ncx2iqjy3nw28vRux3gVX0WOCk9EL/KVJBiAA/fK7VklTXvgy9dZnnipw==", + "license": "LGPL-3.0", + "dependencies": { + "web3-core": "1.3.6", + "web3-core-method": "1.3.6", + "web3-utils": "1.3.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-providers-http": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.3.6.tgz", + "integrity": "sha512-OQkT32O1A06dISIdazpGLveZcOXhEo5cEX6QyiSQkiPk/cjzDrXMw4SKZOGQbbS1+0Vjizm1Hrp7O8Vp2D1M5Q==", + "license": "LGPL-3.0", + "dependencies": { + "web3-core-helpers": "1.3.6", + "xhr2-cookies": "1.1.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-providers-ipc": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.3.6.tgz", + "integrity": "sha512-+TVsSd2sSVvVgHG4s6FXwwYPPT91boKKcRuEFXqEfAbUC5t52XOgmyc2LNiD9LzPhed65FbV4LqICpeYGUvSwA==", + "license": "LGPL-3.0", + "dependencies": { + "oboe": "2.1.5", + "underscore": "1.12.1", + "web3-core-helpers": "1.3.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-providers-ipc/node_modules/underscore": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", + "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", + "license": "MIT" + }, + "node_modules/web3-providers-ws": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.3.6.tgz", + "integrity": "sha512-bk7MnJf5or0Re2zKyhR3L3CjGululLCHXx4vlbc/drnaTARUVvi559OI5uLytc/1k5HKUUyENAxLvetz2G1dnQ==", + "license": "LGPL-3.0", + "dependencies": { + "eventemitter3": "4.0.4", + "underscore": "1.12.1", + "web3-core-helpers": "1.3.6", + "websocket": "^1.0.32" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-providers-ws/node_modules/eventemitter3": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz", + "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==", + "license": "MIT" + }, + "node_modules/web3-providers-ws/node_modules/underscore": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", + "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", + "license": "MIT" + }, + "node_modules/web3-shh": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.3.6.tgz", + "integrity": "sha512-9zRo415O0iBslxBnmu9OzYjNErzLnzOsy+IOvSpIreLYbbAw0XkDWxv3SfcpKnTIWIACBR4AYMIxmmyi5iB3jw==", + "hasInstallScript": true, + "license": "LGPL-3.0", + "dependencies": { + "web3-core": "1.3.6", + "web3-core-method": "1.3.6", + "web3-core-subscriptions": "1.3.6", + "web3-net": "1.3.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-utils": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.6.tgz", + "integrity": "sha512-hHatFaQpkQgjGVER17gNx8u1qMyaXFZtM0y0XLGH1bzsjMPlkMPLRcYOrZ00rOPfTEuYFOdrpGOqZXVmGrMZRg==", + "license": "LGPL-3.0", + "dependencies": { + "bn.js": "^4.11.9", + "eth-lib": "0.2.8", + "ethereum-bloom-filters": "^1.0.6", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "underscore": "1.12.1", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-utils/node_modules/bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "license": "MIT" + }, + "node_modules/web3-utils/node_modules/underscore": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", + "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", + "license": "MIT" + }, + "node_modules/webcrypto-core": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.8.1.tgz", + "integrity": "sha512-P+x1MvlNCXlKbLSOY4cYrdreqPG5hbzkmawbcXLKN/mf6DZW0SdNNkZ+sjwsqVkI4A4Ko2sPZmkZtCKY58w83A==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.13", + "@peculiar/json-schema": "^1.1.12", + "asn1js": "^3.0.5", + "pvtsutils": "^1.3.5", + "tslib": "^2.7.0" + } + }, + "node_modules/webcrypto-core/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/webcrypto-shim": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/webcrypto-shim/-/webcrypto-shim-0.1.7.tgz", + "integrity": "sha512-JAvAQR5mRNRxZW2jKigWMjCMkjSdmP5cColRP1U/pTg69VgHXEi1orv5vVpJ55Zc5MIaPc1aaurzd9pjv2bveg==", + "license": "MIT" + }, "node_modules/webextension-polyfill": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/webextension-polyfill/-/webextension-polyfill-0.10.0.tgz", @@ -45470,6 +64055,23 @@ "webpack": "3 || 4 || 5" } }, + "node_modules/websocket": { + "version": "1.0.35", + "resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.35.tgz", + "integrity": "sha512-/REy6amwPZl44DDzvRCkaI1q1bIiQB0mEFQLUrhz3z2EK91cp3n72rAjUlrTP0zV22HJIUOVHQGPxhFRjxjt+Q==", + "license": "Apache-2.0", + "dependencies": { + "bufferutil": "^4.0.1", + "debug": "^2.2.0", + "es5-ext": "^0.10.63", + "typedarray-to-buffer": "^3.1.5", + "utf-8-validate": "^5.0.2", + "yaeti": "^0.0.6" + }, + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/websocket-driver": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", @@ -45491,6 +64093,21 @@ "node": ">=0.8.0" } }, + "node_modules/websocket/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/websocket/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, "node_modules/whatwg-encoding": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", @@ -45519,8 +64136,7 @@ "version": "3.6.20", "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/whatwg-mimetype": { "version": "3.0.0", @@ -45654,6 +64270,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/wif": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/wif/-/wif-2.0.6.tgz", + "integrity": "sha512-HIanZn1zmduSF+BQhkE+YXIbEiH0xPr1012QbFEGB0xsKqJii0/SqJjyn8dFv6y36kOznMgMB+LGcbZTJ1xACQ==", + "license": "MIT", + "dependencies": { + "bs58check": "<3.0.0" + } + }, "node_modules/wildcard": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", @@ -45701,11 +64326,18 @@ "node": ">=0.1.90" } }, + "node_modules/wonka": { + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/wonka/-/wonka-4.0.15.tgz", + "integrity": "sha512-U0IUQHKXXn6PFo9nqsHphVCE5m3IntqZNB9Jjn7EB1lrR7YTDY3YWgFvEvwniTzXSvOH/XMzAZaIfJF/LvHYXg==", + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -45736,7 +64368,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -45752,14 +64383,12 @@ "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -45768,7 +64397,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -45851,6 +64479,30 @@ } } }, + "node_modules/xcode": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/xcode/-/xcode-3.0.1.tgz", + "integrity": "sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "simple-plist": "^1.1.0", + "uuid": "^7.0.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/xcode/node_modules/uuid": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", + "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", + "license": "MIT", + "peer": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/xdg-basedir": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz", @@ -45862,6 +64514,74 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/xhr": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.6.0.tgz", + "integrity": "sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA==", + "license": "MIT", + "dependencies": { + "global": "~4.4.0", + "is-function": "^1.0.1", + "parse-headers": "^2.0.0", + "xtend": "^4.0.0" + } + }, + "node_modules/xhr-request": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xhr-request/-/xhr-request-1.1.0.tgz", + "integrity": "sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA==", + "license": "MIT", + "dependencies": { + "buffer-to-arraybuffer": "^0.0.5", + "object-assign": "^4.1.1", + "query-string": "^5.0.1", + "simple-get": "^2.7.0", + "timed-out": "^4.0.1", + "url-set-query": "^1.0.0", + "xhr": "^2.0.4" + } + }, + "node_modules/xhr-request-promise": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/xhr-request-promise/-/xhr-request-promise-0.1.3.tgz", + "integrity": "sha512-YUBytBsuwgitWtdRzXDDkWAXzhdGB8bYm0sSzMPZT7Z2MBjMSTHFsyCT1yCRATY+XC69DUrQraRAEgcoCRaIPg==", + "license": "MIT", + "dependencies": { + "xhr-request": "^1.1.0" + } + }, + "node_modules/xhr-request/node_modules/query-string": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", + "license": "MIT", + "dependencies": { + "decode-uri-component": "^0.2.0", + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/xhr-request/node_modules/strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/xhr2-cookies": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz", + "integrity": "sha512-hjXUA6q+jl/bd8ADHcVfFsSPIf+tyLIjuO9TwJC9WI6JP2zKcS7C+p56I9kCLLsaCiNT035iYvEUUzdEFj/8+g==", + "license": "MIT", + "dependencies": { + "cookiejar": "^2.1.1" + } + }, "node_modules/xml-js": { "version": "1.6.11", "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz", @@ -45882,12 +64602,52 @@ "node": ">=12" } }, + "node_modules/xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "license": "MIT", + "peer": true, + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xml2js/node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xmlbuilder": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-14.0.0.tgz", + "integrity": "sha512-ts+B2rSe4fIckR6iquDjsKbQFK2NlUk6iG5nf14mDEyldgoc2nEKZ3jZWMPTxGQwVgToSjt6VGIho1H8/fNFTg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8.0" + } + }, "node_modules/xmlchars": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", "dev": true }, + "node_modules/xmlcreate": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", + "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", + "license": "Apache-2.0" + }, "node_modules/xmlhttprequest-ssl": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz", @@ -45896,6 +64656,64 @@ "node": ">=0.4.0" } }, + "node_modules/xrpl": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xrpl/-/xrpl-4.0.0.tgz", + "integrity": "sha512-VZm1lQWHQ6PheAAFGdH+ISXKvqB2hZDQ0w4ZcdAEtmqZQXtSIVQHOKPz95rEgGANbos7+XClxJ73++joPhA8Cw==", + "license": "ISC", + "dependencies": { + "@scure/bip32": "^1.3.1", + "@scure/bip39": "^1.2.1", + "@xrplf/isomorphic": "^1.0.1", + "@xrplf/secret-numbers": "^1.0.0", + "bignumber.js": "^9.0.0", + "eventemitter3": "^5.0.1", + "ripple-address-codec": "^5.0.0", + "ripple-binary-codec": "^2.1.0", + "ripple-keypairs": "^2.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/xrpl/node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" + }, + "node_modules/xss": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/xss/-/xss-1.0.13.tgz", + "integrity": "sha512-clu7dxTm1e8Mo5fz3n/oW3UCXBfV89xZ72jM8yzo1vR/pIS0w3sgB3XV2H8Vm6zfGnHL0FzvLJPJEBhd86/z4Q==", + "license": "MIT", + "dependencies": { + "commander": "^2.20.3", + "cssfilter": "0.0.10" + }, + "bin": { + "xss": "bin/xss" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/xss/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" + }, + "node_modules/xstream": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/xstream/-/xstream-11.14.0.tgz", + "integrity": "sha512-1bLb+kKKtKPbgTK6i/BaoAn03g47PpFstlbe1BA+y3pNS/LfvcaghS5BFf9+EE1J+KwSQsEpfJvFN5GqFtiNmw==", + "license": "MIT", + "dependencies": { + "globalthis": "^1.0.1", + "symbol-observable": "^2.0.3" + } + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -45912,6 +64730,15 @@ "node": ">=10" } }, + "node_modules/yaeti": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", + "integrity": "sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug==", + "license": "MIT", + "engines": { + "node": ">=0.10.32" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", diff --git a/package.json b/package.json index 7bba43f77..72a96e9e5 100644 --- a/package.json +++ b/package.json @@ -73,6 +73,9 @@ }, "dependencies": { "@aws-crypto/client-node": "4.0.1", + "@bitgo/public-types": "4.11.2", + "@bitgo/sdk-api": "1.58.2", + "@bitgo/sdk-core": "28.20.0", "@bull-board/api": "5.20.1", "@bull-board/express": "5.20.1", "@bull-board/nestjs": "5.20.1", @@ -117,6 +120,7 @@ "@tanstack/react-query": "5.51.11", "axios": "1.7.7", "axios-retry": "4.5.0", + "bitgo": "39.23.0", "bull": "4.16.4", "cache-manager": "6.3.2", "class-transformer": "0.5.1", From 4874ea8040fa864ef718f23203a887025ba83a05 Mon Sep 17 00:00:00 2001 From: Matt Schoch Date: Mon, 3 Feb 2025 17:10:28 +0100 Subject: [PATCH 113/120] Revert "BitGo Integration" This reverts commit 37cc70faa53b35e99256fa728a1de0b1c34de5df. --- .github/workflows/vault.yml | 7 +- Makefile | 4 +- apps/vault/src/broker/broker.module.ts | 6 - .../bitgo/bitgo-scoped-sync.service.ts | 194 - .../provider/bitgo/bitgo-transfer.service.ts | 331 - .../broker/core/provider/bitgo/bitgo.util.ts | 110 - .../fireblocks/fireblocks-transfer.service.ts | 6 +- .../src/broker/core/service/asset.service.ts | 8 - .../core/service/raw-account.service.ts | 72 +- .../core/service/scoped-sync.service.ts | 4 - .../broker/core/service/transfer.service.ts | 4 - .../core/type/indexed-resources.type.ts | 2 +- .../src/broker/http/client/bitgo.client.ts | 300 - .../src/broker/shared/__test__/mock-server.ts | 3 +- .../migration.sql | 8 - examples/unified-api/.gitignore | 1 + examples/unified-api/7-bitgo-stake.ts | 62 - examples/unified-api/8-bitgo-transfer.ts | 48 - examples/unified-api/9-bitgo-connect.ts | 31 - package-lock.json | 47627 +++++----------- package.json | 4 - 21 files changed, 14411 insertions(+), 34421 deletions(-) delete mode 100644 apps/vault/src/broker/core/provider/bitgo/bitgo-scoped-sync.service.ts delete mode 100644 apps/vault/src/broker/core/provider/bitgo/bitgo-transfer.service.ts delete mode 100644 apps/vault/src/broker/core/provider/bitgo/bitgo.util.ts delete mode 100644 apps/vault/src/broker/http/client/bitgo.client.ts delete mode 100644 apps/vault/src/shared/module/persistence/schema/migrations/20250123154218_account_wallet_id_nullable/migration.sql delete mode 100644 examples/unified-api/7-bitgo-stake.ts delete mode 100644 examples/unified-api/8-bitgo-transfer.ts delete mode 100644 examples/unified-api/9-bitgo-connect.ts diff --git a/.github/workflows/vault.yml b/.github/workflows/vault.yml index 78d61bd51..05493b8ab 100644 --- a/.github/workflows/vault.yml +++ b/.github/workflows/vault.yml @@ -23,8 +23,7 @@ on: jobs: test: name: Test - runs-on: - labels: default-larger + runs-on: ubuntu-latest services: postgres: @@ -106,9 +105,7 @@ jobs: release: name: Release - runs-on: - labels: default-larger - + runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' # Only run if the Test job succeeds diff --git a/Makefile b/Makefile index 2e51c46e9..c62ba0193 100644 --- a/Makefile +++ b/Makefile @@ -19,10 +19,10 @@ TERM_GREEN := \033[0;32m # === Install === install: - npm install + npm install --engine-strict install/ci: - npm ci + npm ci --engine-strict # === Setup === diff --git a/apps/vault/src/broker/broker.module.ts b/apps/vault/src/broker/broker.module.ts index fddf2be63..80629a778 100644 --- a/apps/vault/src/broker/broker.module.ts +++ b/apps/vault/src/broker/broker.module.ts @@ -16,8 +16,6 @@ import { AnchorageProxyService } from './core/provider/anchorage/anchorage-proxy import { AnchorageScopedSyncService } from './core/provider/anchorage/anchorage-scoped-sync.service' import { AnchorageTransferService } from './core/provider/anchorage/anchorage-transfer.service' import { BitgoCredentialService } from './core/provider/bitgo/bitgo-credential.service' -import { BitgoScopedSyncService } from './core/provider/bitgo/bitgo-scoped-sync.service' -import { BitgoTransferService } from './core/provider/bitgo/bitgo-transfer.service' import { FireblocksCredentialService } from './core/provider/fireblocks/fireblocks-credential.service' import { FireblocksKnownDestinationService } from './core/provider/fireblocks/fireblocks-known-destination.service' import { FireblocksProxyService } from './core/provider/fireblocks/fireblocks-proxy.service' @@ -38,7 +36,6 @@ import { TransferService } from './core/service/transfer.service' import { WalletService } from './core/service/wallet.service' import { ConnectionScopedSyncEventHandler } from './event/handler/connection-scoped-sync.event-handler' import { AnchorageClient } from './http/client/anchorage.client' -import { BitgoClient } from './http/client/bitgo.client' import { FireblocksClient } from './http/client/fireblocks.client' import { ProviderAccountController } from './http/rest/controller/account.controller' import { ProviderAddressController } from './http/rest/controller/address.controller' @@ -105,13 +102,10 @@ import { NetworkSeed } from './persistence/seed/network.seed' AnchorageKnownDestinationService, AnchorageProxyService, AnchorageScopedSyncService, - BitgoScopedSyncService, AnchorageTransferService, AssetRepository, AssetService, BitgoCredentialService, - BitgoClient, - BitgoTransferService, ConnectionRepository, ConnectionService, ConnectionScopedSyncEventHandler, diff --git a/apps/vault/src/broker/core/provider/bitgo/bitgo-scoped-sync.service.ts b/apps/vault/src/broker/core/provider/bitgo/bitgo-scoped-sync.service.ts deleted file mode 100644 index 8e0c8fa8e..000000000 --- a/apps/vault/src/broker/core/provider/bitgo/bitgo-scoped-sync.service.ts +++ /dev/null @@ -1,194 +0,0 @@ -import { LoggerService } from '@narval/nestjs-shared' -import { Injectable } from '@nestjs/common' -import { randomUUID } from 'crypto' -import { chunk, uniqBy } from 'lodash/fp' -import { BitGoWallet, BitgoClient } from '../../../http/client/bitgo.client' -import { ConnectionWithCredentials } from '../../type/connection.type' -import { Account, Address } from '../../type/indexed-resources.type' -import { NetworkMap } from '../../type/network.type' -import { Provider, ProviderScopedSyncService } from '../../type/provider.type' -import { - RawAccount, - RawAccountError, - RawAccountSyncFailure, - ScopedSyncContext, - ScopedSyncResult -} from '../../type/scoped-sync.type' -import { CONCURRENT_BITGO_REQUEST, validateConnection } from './bitgo.util' - -type RawAccountSyncSuccess = { - success: true - account: Account - address: Address -} - -type RawAccountSyncFailed = { - success: false - failure: RawAccountSyncFailure -} - -type RawAccountSyncResult = RawAccountSyncSuccess | RawAccountSyncFailed - -@Injectable() -export class BitgoScopedSyncService implements ProviderScopedSyncService { - constructor( - private readonly bitgoClient: BitgoClient, - private readonly logger: LoggerService - ) {} - - private resolveFailure(failure: RawAccountSyncFailure): RawAccountSyncFailed { - this.logger.log('Failed to sync Raw Account', failure) - return { success: false, failure } - } - - private resolveSuccess({ - rawAccount, - account, - address - }: { - address: Address - rawAccount: RawAccount - account: Account - }): RawAccountSyncSuccess { - this.logger.log('Successfully fetched and map Raw Account', { - rawAccount, - account - }) - return { - success: true, - account, - address - } - } - - syncRawAccount({ - rawAccount, - networks, - bitgoWallet, - connection, - now, - existingAccounts - }: { - rawAccount: RawAccount - networks: NetworkMap - bitgoWallet: BitGoWallet - connection: ConnectionWithCredentials - now: Date - existingAccounts: Account[] - }): RawAccountSyncResult { - const network = networks.get(bitgoWallet.coin.toUpperCase()) - - if (!network) { - return this.resolveFailure({ - rawAccount, - message: 'Network not found', - code: RawAccountError.UNLISTED_NETWORK, - networkId: bitgoWallet.coin - }) - } - - const addressObj = bitgoWallet.receiveAddress - const existingAcc = existingAccounts.find((a) => a.externalId === bitgoWallet.id) - const accountId = existingAcc?.accountId || randomUUID() - - const account: Account = { - externalId: bitgoWallet.id, - accountId, - addresses: [], - clientId: connection.clientId, - connectionId: connection.connectionId, - createdAt: now, - label: bitgoWallet.label, - networkId: network.networkId, - provider: Provider.BITGO, - updatedAt: now, - walletId: null // BitGo doesn't have a concept that maps to our "wallet" - } - - const address: Address = { - accountId, - address: addressObj.address, - addressId: randomUUID(), - clientId: connection.clientId, - connectionId: connection.connectionId, - createdAt: now, - externalId: addressObj.id, - provider: Provider.BITGO, - updatedAt: now - } - - return this.resolveSuccess({ - rawAccount, - account, - address - }) - } - - async scopeSync({ - connection, - rawAccounts, - networks, - existingAccounts - }: ScopedSyncContext): Promise { - const now = new Date() - - this.logger.log('Sync BitGo accounts', { - connectionId: connection.connectionId, - clientId: connection.clientId, - url: connection.url - }) - - validateConnection(connection) - - const bitgoWallets = await this.bitgoClient.getWallets({ - url: connection.url, - apiKey: connection.credentials.apiKey, - options: { - walletIds: rawAccounts.map((account) => account.externalId) - } - }) - - const accounts: Account[] = [] - const addresses: Address[] = [] - const failures: RawAccountSyncFailure[] = [] - - const chunkedRawAccounts = chunk(CONCURRENT_BITGO_REQUEST, rawAccounts) - const results = [] - - for (const chunk of chunkedRawAccounts) { - const chunkResults = await Promise.all( - chunk.map((rawAccount) => { - const bitgoWallet = bitgoWallets.find((b) => b.id === rawAccount.externalId) - - if (!bitgoWallet) { - return this.resolveFailure({ - rawAccount, - message: 'BitGo wallet not found', - code: RawAccountError.EXTERNAL_RESOURCE_NOT_FOUND, - externalResourceId: rawAccount.externalId, - externalResourceType: 'wallet' - }) - } - return this.syncRawAccount({ connection, rawAccount, networks, bitgoWallet, now, existingAccounts }) - }) - ) - results.push(...chunkResults) - } - - for (const result of results) { - if (result.success) { - accounts.push(result.account) - addresses.push(result.address) - } else { - failures.push(result.failure) - } - } - - return { - wallets: [], - accounts: uniqBy('externalId', accounts), - addresses: uniqBy('externalId', addresses), - failures - } - } -} diff --git a/apps/vault/src/broker/core/provider/bitgo/bitgo-transfer.service.ts b/apps/vault/src/broker/core/provider/bitgo/bitgo-transfer.service.ts deleted file mode 100644 index 4abdfa6ab..000000000 --- a/apps/vault/src/broker/core/provider/bitgo/bitgo-transfer.service.ts +++ /dev/null @@ -1,331 +0,0 @@ -import { LoggerService } from '@narval/nestjs-shared' -import { HttpStatus, Injectable } from '@nestjs/common' -import { randomUUID } from 'crypto' -import { BitGoTransferType, BitgoClient } from '../../../http/client/bitgo.client' -import { TransferRepository } from '../../../persistence/repository/transfer.repository' -import { BrokerException } from '../../exception/broker.exception' -import { AccountService } from '../../service/account.service' -import { AddressService } from '../../service/address.service' -import { AssetService } from '../../service/asset.service' -import { NetworkService } from '../../service/network.service' -import { ResolvedTransferAsset } from '../../service/transfer-asset.service' -import { ConnectionWithCredentials } from '../../type/connection.type' -import { ExternalNetwork } from '../../type/network.type' -import { Provider, ProviderTransferService } from '../../type/provider.type' -import { ConnectionScope } from '../../type/scope.type' -import { - Destination, - InternalTransfer, - NetworkFeeAttribution, - SendTransfer, - Source, - Transfer, - TransferAsset, - TransferPartyType, - isAddressDestination -} from '../../type/transfer.type' -import { ValidConnection, decideState, mapBitgoStateToInternalStatus, validateConnection } from './bitgo.util' - -type BitGoResolvedTransferAsset = Omit & { - assetId: string - decimals: number - contractAddress?: string -} - -@Injectable() -export class BitgoTransferService implements ProviderTransferService { - constructor( - private readonly bitgoClient: BitgoClient, - private readonly accountService: AccountService, - private readonly addressService: AddressService, - private readonly networkService: NetworkService, - private readonly transferRepository: TransferRepository, - private readonly assetService: AssetService, - private readonly logger: LoggerService - ) {} - - async findById(connection: ConnectionWithCredentials, id: string): Promise { - validateConnection(connection) - const transfer = await this.transferRepository.findById(connection.clientId, id) - - if (!transfer) { - throw new BrokerException({ - message: 'Transfer not found', - suggestedHttpStatusCode: HttpStatus.NOT_FOUND, - context: { connectionId: connection.connectionId, id } - }) - } - - const { source } = transfer - - let account - if (source.type === TransferPartyType.ACCOUNT) { - account = await this.accountService.findById(connection, source.id) - } else if (source.type === TransferPartyType.WALLET) { - throw new BrokerException({ - message: 'Wallet does not exist in Bitgo. This is an invalid state', - suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, - context: { connectionId: connection.connectionId, source } - }) - } else if (source.type === TransferPartyType.ADDRESS) { - const address = await this.addressService.findById(connection, source.id) - account = await this.accountService.findById(connection, address.accountId) - } - - if (!account) { - throw new BrokerException({ - message: 'Account not found', - suggestedHttpStatusCode: HttpStatus.NOT_FOUND, - context: { connectionId: connection.connectionId, source } - }) - } - - if (!transfer.assetExternalId) { - throw new BrokerException({ - message: 'Asset not found', - suggestedHttpStatusCode: HttpStatus.NOT_FOUND, - context: { connectionId: connection.connectionId, transfer } - }) - } - - transfer.externalId - - const events = await this.bitgoClient.getTransaction({ - url: connection.url, - apiKey: connection.credentials.apiKey, - data: { - txRequestIds: [transfer.externalId], - walletId: account.externalId - } - }) - - this.logger.error('Fees are not supported for Bitgo transfers', { transfer }) - - const states = events.map((ext) => mapBitgoStateToInternalStatus(ext.state)) - - return { - ...transfer, - status: decideState(states), - fees: [] - } - } - - private async getSource(scope: ConnectionScope, source: Source) { - if (source.type === TransferPartyType.ACCOUNT) { - const account = await this.accountService.findById(scope, source.id) - return account.externalId - } - - throw new BrokerException({ - message: 'Cannot resolve Bitgo transfer source', - suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, - context: { scope, source } - }) - } - - private async getDestination(connection: ValidConnection, destination: Destination) { - if (isAddressDestination(destination)) { - return destination.address - } - - if (destination.type === TransferPartyType.ACCOUNT) { - const account = await this.accountService.findById(connection, destination.id) - - if (!account) { - throw new BrokerException({ - message: 'Account not found', - suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, - context: { scope: connection, destination } - }) - } - - const { addresses } = account - - if (!addresses || !addresses.length) { - throw new BrokerException({ - message: 'Account does not have any addresses', - suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, - context: { scope: connection, destination } - }) - } - - if (addresses.length !== 1) { - const bitgoWallet = await this.bitgoClient.getWallets({ - url: connection.url, - apiKey: connection.credentials.apiKey, - options: { - walletIds: [account.externalId] - } - }) - - if (!bitgoWallet || bitgoWallet.length !== 1) { - throw new BrokerException({ - message: 'Could not resolve an address for this account', - suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, - context: { account } - }) - } - - return bitgoWallet[0].receiveAddress.address - } - - return addresses[0].address - } - - throw new BrokerException({ - message: 'Cannot resolve Bitgo transfer destination', - suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, - context: { scope: connection, destination } - }) - } - - private async findAsset(transferAsset: TransferAsset): Promise { - if (transferAsset.assetId) { - const asset = await this.assetService.findById(transferAsset.assetId) - if (asset?.decimals) { - const network = await this.networkService.findById(asset.networkId) - const bitGoAssetId = asset.externalAssets.find( - (externalAsset) => externalAsset.provider === Provider.BITGO - )?.externalId - if (bitGoAssetId && network) { - return { - assetExternalId: bitGoAssetId, - decimals: asset.decimals, - network, - assetId: asset.assetId, - contractAddress: asset.onchainId || undefined - } - } - } - } - - if (transferAsset.address && transferAsset.networkId) { - const asset = await this.assetService.findByOnchainId(transferAsset.networkId, transferAsset.address) - if (asset?.decimals) { - const network = await this.networkService.findById(asset.networkId) - const bitGoAssetId = asset.externalAssets.find( - (externalAsset) => externalAsset.provider === Provider.BITGO - )?.externalId - if (bitGoAssetId && network) { - return { - assetExternalId: bitGoAssetId, - decimals: asset.decimals, - network, - assetId: asset.assetId, - contractAddress: asset.onchainId || undefined - } - } - } - } - - if (transferAsset.externalAssetId) { - const asset = await this.assetService.findByExternalId(Provider.BITGO, transferAsset.externalAssetId) - if (asset?.decimals) { - const network = await this.networkService.findById(asset.networkId) - - if (network) { - return { - assetExternalId: transferAsset.externalAssetId, - decimals: asset.decimals, - network, - assetId: asset.assetId, - contractAddress: asset.onchainId || undefined - } - } - } - } - - throw new BrokerException({ - message: 'Cannot find transfer asset', - suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, - context: { transferAsset } - }) - } - - private async findTransferNetwork(transferAsset: TransferAsset): Promise { - const { network } = await this.findAsset(transferAsset) - - const bitgoNetwork = network.externalNetworks.find((externalNetwork) => externalNetwork.provider === Provider.BITGO) - if (!bitgoNetwork) { - throw new BrokerException({ - message: 'Cannot find Bitgo network', - suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, - context: { transferAsset } - }) - } - - return bitgoNetwork - } - - async send(connection: ConnectionWithCredentials, sendTransfer: SendTransfer): Promise { - validateConnection(connection) - const now = new Date() - const { - amount, - source, - destination, - asset: transferAsset, - memo, - transferId, - idempotenceId, - customerRefId - } = sendTransfer - - const walletId = await this.getSource(connection, source) - const address = await this.getDestination(connection, destination) - - const asset = await this.findAsset(transferAsset) - - const native = await this.assetService.findNative(asset.network.networkId) - - const { externalId: coin } = await this.findTransferNetwork(transferAsset) - - const networkFeeAttribution = sendTransfer.networkFeeAttribution || NetworkFeeAttribution.ON_TOP - - const transferType = asset.assetId === native?.assetId ? BitGoTransferType.NATIVE : BitGoTransferType.TOKEN - - const amountInBaseUnits = this.assetService.toBaseUnit(amount, +asset.decimals) - - const res = await this.bitgoClient.createTransfer({ - url: connection.url, - apiKey: connection.credentials.apiKey, - walletPassphrase: connection.credentials.walletPassphrase, - data: { - walletId, - coin, - amount: amountInBaseUnits, - address, - asset: asset.assetExternalId, - tokenContractAddress: asset.contractAddress || undefined, - type: transferType, - networkFeeAttribution, - idempotenceId, - decimals: asset.decimals - } - }) - - const internalTransfer: InternalTransfer = { - clientId: connection.clientId, - connectionId: connection.connectionId, - provider: Provider.BITGO, - createdAt: now, - assetExternalId: asset.assetExternalId, - assetId: asset.assetId, - customerRefId: customerRefId || null, - destination, - source, - status: mapBitgoStateToInternalStatus(res.state), - grossAmount: amount, - idempotenceId, - memo: memo || null, - transferId: transferId || randomUUID(), - externalId: res.txRequestId, - externalStatus: res.state, - networkFeeAttribution - } - - await this.transferRepository.bulkCreate([internalTransfer]) - - return internalTransfer - } -} diff --git a/apps/vault/src/broker/core/provider/bitgo/bitgo.util.ts b/apps/vault/src/broker/core/provider/bitgo/bitgo.util.ts deleted file mode 100644 index 0c650eff0..000000000 --- a/apps/vault/src/broker/core/provider/bitgo/bitgo.util.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { HttpStatus } from '@nestjs/common' -import { BrokerException } from '../../exception/broker.exception' -import { ConnectionInvalidException } from '../../exception/connection-invalid.exception' -import { ConnectionWithCredentials } from '../../type/connection.type' -import { Provider } from '../../type/provider.type' -import { TransferStatus } from '../../type/transfer.type' -import { BitgoInputCredentials } from './bitgo.type' - -export const CONCURRENT_BITGO_REQUEST = 5 - -export type ValidConnection = { - url: string - credentials: { - apiKey: string - walletPassphrase?: string - } - clientId: string - connectionId: string -} - -export function validateConnection( - connection: ConnectionWithCredentials -): asserts connection is ConnectionWithCredentials & ValidConnection { - const context = { - clientId: connection.clientId, - connectionId: connection.connectionId, - provider: connection.provider, - status: connection.status, - url: connection.url - } - - if (connection.provider !== Provider.BITGO) { - throw new ConnectionInvalidException({ - message: 'Invalid connection provider for BitGo', - context - }) - } - - if (!connection.url) { - throw new ConnectionInvalidException({ - message: 'BitGo connection missing URL', - context - }) - } - - if (!connection.credentials) { - throw new ConnectionInvalidException({ - message: 'BitGo connection missing credentials', - context - }) - } - - const credentials = BitgoInputCredentials.parse(connection.credentials) - - if (!credentials.apiKey) { - throw new ConnectionInvalidException({ - message: 'BitGo connection missing API key', - context - }) - } -} - -export function mapBitgoStateToInternalStatus(state: string): TransferStatus { - switch (state) { - case 'pendingCommitment': - return TransferStatus.PROCESSING - case 'signed': - return TransferStatus.PROCESSING - case 'pendingApproval': - return TransferStatus.PROCESSING - case 'initialized': - return TransferStatus.PROCESSING - case 'pendingDelivery': - return TransferStatus.PROCESSING - case 'pendingUserSignature': - return TransferStatus.PROCESSING - case 'canceled': - return TransferStatus.FAILED - case 'rejected': - return TransferStatus.FAILED - case 'delivered': - return TransferStatus.SUCCESS - default: - throw new BrokerException({ - message: `Unknown BitGo state: ${state}`, - context: { state }, - suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY - }) - } -} - -export function decideState(states: TransferStatus[]): TransferStatus { - if (states.includes(TransferStatus.FAILED)) { - return TransferStatus.FAILED - } - - if (states.some((state) => state === TransferStatus.SUCCESS)) { - return TransferStatus.SUCCESS - } - - if (states.includes(TransferStatus.PROCESSING)) { - return TransferStatus.PROCESSING - } - - throw new BrokerException({ - message: 'Unknown or empty state list', - context: { states }, - suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY - }) -} diff --git a/apps/vault/src/broker/core/provider/fireblocks/fireblocks-transfer.service.ts b/apps/vault/src/broker/core/provider/fireblocks/fireblocks-transfer.service.ts index 737a4de2d..ae141445b 100644 --- a/apps/vault/src/broker/core/provider/fireblocks/fireblocks-transfer.service.ts +++ b/apps/vault/src/broker/core/provider/fireblocks/fireblocks-transfer.service.ts @@ -244,7 +244,7 @@ export class FireblocksTransferService implements ProviderTransferService { if (sendTransfer.source.type === TransferPartyType.ACCOUNT) { const account = await this.accountService.findById(scope, sendTransfer.source.id) - if (account && account.walletId) { + if (account) { const wallet = await this.walletService.findById(scope, account.walletId) if (wallet) { @@ -280,7 +280,7 @@ export class FireblocksTransferService implements ProviderTransferService { if (address) { const account = await this.accountService.findById(scope, address.accountId) - if (account && account.walletId) { + if (account) { const wallet = await this.walletService.findById(scope, account.walletId) if (wallet) { @@ -303,7 +303,7 @@ export class FireblocksTransferService implements ProviderTransferService { if (destination.type === TransferPartyType.ACCOUNT) { const account = await this.accountService.findById(scope, destination.id) - if (account && account.walletId) { + if (account) { const wallet = await this.walletService.findById(scope, account.walletId) if (wallet) { diff --git a/apps/vault/src/broker/core/service/asset.service.ts b/apps/vault/src/broker/core/service/asset.service.ts index 53d4b492b..8ce9ecf49 100644 --- a/apps/vault/src/broker/core/service/asset.service.ts +++ b/apps/vault/src/broker/core/service/asset.service.ts @@ -22,14 +22,6 @@ export class AssetService { @Inject(CACHE_MANAGER) private cacheManager: Cache ) {} - toBaseUnit(amount: string, decimals: number): string { - const amountStr = amount.toString() - const [integerPart, decimalPart = ''] = amountStr.split('.') - const paddedDecimal = decimalPart.padEnd(decimals, '0').slice(0, decimals) - const cleanInteger = integerPart.replace(/^0+/, '') || '0' - return cleanInteger + paddedDecimal - } - async bulkCreate(assets: Asset[]): Promise { const createdAssets: Asset[] = [] diff --git a/apps/vault/src/broker/core/service/raw-account.service.ts b/apps/vault/src/broker/core/service/raw-account.service.ts index 818e34cf2..9bdec023c 100644 --- a/apps/vault/src/broker/core/service/raw-account.service.ts +++ b/apps/vault/src/broker/core/service/raw-account.service.ts @@ -1,15 +1,12 @@ import { LoggerService, PaginatedResult, PaginationOptions } from '@narval/nestjs-shared' import { HttpStatus, Injectable } from '@nestjs/common' -import { formatUnits } from 'viem' import { z } from 'zod' import { AnchorageClient } from '../../http/client/anchorage.client' -import { BitgoClient } from '../../http/client/bitgo.client' import { FireblocksClient } from '../../http/client/fireblocks.client' import { AccountRepository } from '../../persistence/repository/account.repository' import { AssetRepository } from '../../persistence/repository/asset.repository' import { BrokerException } from '../exception/broker.exception' import { validateConnection as validateAnchorageConnection } from '../provider/anchorage/anchorage.util' -import { validateConnection as validateBitgoConnection } from '../provider/bitgo/bitgo.util' import { buildFireblocksAssetWalletExternalId, validateConnection as validateFireblocksConnection @@ -59,7 +56,6 @@ export class RawAccountService { private readonly assetRepository: AssetRepository, private readonly anchorageClient: AnchorageClient, private readonly fireblocksClient: FireblocksClient, - private readonly bitgoClient: BitgoClient, private readonly loggerService: LoggerService ) {} @@ -264,74 +260,8 @@ export class RawAccountService { return { data: rawAccountsWithAddresses.map((account) => RawAccount.parse(account)) // TODO: don't re-do the parse. It's an asset typedef because the .filter isn't inferred that it's no longer nullable. } - } else if (connection.provider === Provider.BITGO) { - validateBitgoConnection(connection) - - let bitgoNetworkFilter: string | undefined - if (networkFilter) { - const baseAsset = await this.assetRepository.findNative(networkFilter.networkId) - bitgoNetworkFilter = baseAsset?.externalAssets.find((a) => a.provider === Provider.BITGO)?.externalId - if (!bitgoNetworkFilter) { - throw new BrokerException({ - message: 'BitGo does not support this network', - suggestedHttpStatusCode: HttpStatus.BAD_REQUEST, - context: { - networkId: networkFilter.networkId - } - }) - } - } - // BitGo "coin" filter can be a network or asset - const bitgoCoinFilter = - assetFilter?.externalAssets.find((a) => a.provider === Provider.BITGO)?.externalId || bitgoNetworkFilter - - const wallets = await this.bitgoClient.getWallets({ - url: connection.url, - apiKey: connection.credentials.apiKey, - walletPassphrase: connection.credentials.walletPassphrase, - options: { - labelContains: options?.filters?.namePrefix || options?.filters?.nameSuffix, - limit: options?.pagination?.take, - after: options?.pagination?.cursor?.id, // TODO: Our cursor has too strict of typing, it can't pass-through - coin: bitgoCoinFilter - } - }) - - const accounts = await Promise.all( - wallets.map(async (w) => ({ - provider: Provider.BITGO, - externalId: w.id, - label: w.label, - subLabel: w.coin, - defaultAddress: w.receiveAddress?.address, - network: await this.networkService.findByExternalId(Provider.BITGO, w.coin), - assets: await Promise.all( - Object.entries({ - [w.coin]: { - balanceString: w.balanceString || '0', - confirmedBalanceString: w.confirmedBalanceString || '0', - spendableBalanceString: w.spendableBalanceString || '0', - transferCount: 0 // unknown - }, - ...(w.tokens || {}) - }).map(async ([coin, balance]) => { - if (balance.balanceString === '0' && balance.transferCount === 0) return undefined // bitgo returns some other "tokens" that are defaults, so filter them out - const asset = await this.assetRepository.findByExternalId(Provider.BITGO, coin) - - if (!asset) return undefined - return { - asset, - balance: asset?.decimals ? formatUnits(BigInt(balance.balanceString), asset.decimals) : undefined - } - }) - ).then((a) => [...a.filter((a) => !!a)]) - })) - ) - - return { - data: accounts.map((a) => RawAccount.parse(a)) - } } + throw new BrokerException({ message: 'Unsupported provider', suggestedHttpStatusCode: HttpStatus.NOT_IMPLEMENTED, diff --git a/apps/vault/src/broker/core/service/scoped-sync.service.ts b/apps/vault/src/broker/core/service/scoped-sync.service.ts index 026895274..6969b2ca8 100644 --- a/apps/vault/src/broker/core/service/scoped-sync.service.ts +++ b/apps/vault/src/broker/core/service/scoped-sync.service.ts @@ -10,7 +10,6 @@ import { OTEL_ATTR_CONNECTION_ID, OTEL_ATTR_CONNECTION_PROVIDER, OTEL_ATTR_SYNC_ import { ScopedSyncStartedEvent } from '../../shared/event/scoped-sync-started.event' import { ScopedSyncException } from '../exception/scoped-sync.exception' import { AnchorageScopedSyncService } from '../provider/anchorage/anchorage-scoped-sync.service' -import { BitgoScopedSyncService } from '../provider/bitgo/bitgo-scoped-sync.service' import { FireblocksScopedSyncService } from '../provider/fireblocks/fireblocks-scoped-sync.service' import { ConnectionWithCredentials } from '../type/connection.type' import { Provider, ProviderScopedSyncService } from '../type/provider.type' @@ -35,7 +34,6 @@ export class ScopedSyncService { private readonly scopedSyncRepository: ScopedSyncRepository, private readonly anchorageScopedSyncService: AnchorageScopedSyncService, private readonly fireblocksScopedSyncService: FireblocksScopedSyncService, - private readonly bitgoScopedSyncService: BitgoScopedSyncService, private readonly walletService: WalletService, private readonly accountService: AccountService, private readonly addressService: AddressService, @@ -320,8 +318,6 @@ export class ScopedSyncService { return this.anchorageScopedSyncService case Provider.FIREBLOCKS: return this.fireblocksScopedSyncService - case Provider.BITGO: - return this.bitgoScopedSyncService default: throw new NotImplementedException(`Unsupported Scoped Sync for provider ${provider}`) } diff --git a/apps/vault/src/broker/core/service/transfer.service.ts b/apps/vault/src/broker/core/service/transfer.service.ts index 0dac1c98a..180b23c67 100644 --- a/apps/vault/src/broker/core/service/transfer.service.ts +++ b/apps/vault/src/broker/core/service/transfer.service.ts @@ -5,7 +5,6 @@ import { TransferRepository } from '../../persistence/repository/transfer.reposi import { OTEL_ATTR_CONNECTION_PROVIDER } from '../../shared/constant' import { BrokerException } from '../exception/broker.exception' import { AnchorageTransferService } from '../provider/anchorage/anchorage-transfer.service' -import { BitgoTransferService } from '../provider/bitgo/bitgo-transfer.service' import { FireblocksTransferService } from '../provider/fireblocks/fireblocks-transfer.service' import { isActiveConnection } from '../type/connection.type' import { Provider, ProviderTransferService } from '../type/provider.type' @@ -20,7 +19,6 @@ export class TransferService { private readonly connectionService: ConnectionService, private readonly anchorageTransferService: AnchorageTransferService, private readonly fireblocksTransferService: FireblocksTransferService, - private readonly bitgoTransferService: BitgoTransferService, private readonly logger: LoggerService, @Inject(TraceService) private readonly traceService: TraceService ) {} @@ -84,8 +82,6 @@ export class TransferService { return this.anchorageTransferService case Provider.FIREBLOCKS: return this.fireblocksTransferService - case Provider.BITGO: - return this.bitgoTransferService default: throw new NotImplementedException(`Unsupported transfer for provider ${provider}`) } diff --git a/apps/vault/src/broker/core/type/indexed-resources.type.ts b/apps/vault/src/broker/core/type/indexed-resources.type.ts index 0ed378b03..48632292c 100644 --- a/apps/vault/src/broker/core/type/indexed-resources.type.ts +++ b/apps/vault/src/broker/core/type/indexed-resources.type.ts @@ -25,7 +25,7 @@ export const Account = z.object({ networkId: z.string(), provider: z.nativeEnum(Provider), updatedAt: z.date(), - walletId: z.string().nullable() + walletId: z.string() }) export type Account = z.infer diff --git a/apps/vault/src/broker/http/client/bitgo.client.ts b/apps/vault/src/broker/http/client/bitgo.client.ts deleted file mode 100644 index 7c6396f1f..000000000 --- a/apps/vault/src/broker/http/client/bitgo.client.ts +++ /dev/null @@ -1,300 +0,0 @@ -import { LoggerService } from '@narval/nestjs-shared' -import { HttpStatus, Injectable } from '@nestjs/common' -import { AxiosError } from 'axios' -import { BitGo, TokenType, TxRequest } from 'bitgo' -import { randomUUID } from 'crypto' -import { Observable, OperatorFunction, catchError, from, lastValueFrom, map, switchMap, tap } from 'rxjs' -import { z } from 'zod' -import { ProviderHttpException } from '../../core/exception/provider-http.exception' -import { Provider } from '../../core/type/provider.type' -import { NetworkFeeAttribution } from '../../core/type/transfer.type' - -// -// Response Schema -// - -const BitGoCoinSpecific = z.object({ - deployedInBlock: z.boolean(), - lastChainIndex: z.unknown(), - baseAddress: z.string(), - feeAddress: z.string(), - pendingChainInitialization: z.boolean(), - pendingEcdsaTssInitialization: z.boolean(), - creationFailure: z.array(z.unknown()), - gasPriceTier: z.string(), - tokenFlushThresholds: z.record(z.unknown()), - lowPriorityFeeAddress: z.string(), - salt: z.string(), - walletVersion: z.number(), - pendingDeployment: z.boolean(), - deployForwardersManually: z.boolean(), - flushForwardersManually: z.boolean(), - enableMMI: z.boolean(), - enableNFT: z.boolean() -}) - -const BitGoReceiveAddress = z.object({ - id: z.string(), - address: z.string(), - chain: z.number(), - index: z.number(), - coin: z.string(), - lastNonce: z.number().optional(), - wallet: z.string(), - lastConsolidatedTime: z.string().optional(), - needsConsolidation: z.boolean().optional(), - coinSpecific: z.unknown() -}) - -export const BitGoWallet = z.object({ - id: z.string(), - coin: z.string(), - label: z.string(), - enterprise: z.string(), - organization: z.string(), - bitgoOrg: z.string(), - freeze: z.record(z.unknown()), - deleted: z.boolean(), - approvalsRequired: z.number(), - isCold: z.boolean(), - coinSpecific: BitGoCoinSpecific, - startDate: z.string(), - type: z.string(), - hasLargeNumberOfAddresses: z.boolean(), - receiveAddress: BitGoReceiveAddress, - balanceString: z.string().optional(), - confirmedBalanceString: z.string().optional(), - spendableBalanceString: z.string().optional(), - tokens: z - .record( - z.object({ - balanceString: z.string(), - confirmedBalanceString: z.string(), - spendableBalanceString: z.string(), - lockedBalanceString: z.string(), - transferCount: z.number() - }) - ) - .optional() -}) -export type BitGoWallet = z.infer - -const GetWalletsResponse = z.object({ - wallets: z.array(BitGoWallet) -}) -type GetWalletsResponse = z.infer - -export const MinimalTransactionObject = z.object({ - state: z.string(), - txRequestId: z.string() -}) -export type MinimalTransactionObject = z.infer - -export const GetTransactions = z.object({ - txRequests: z.array(MinimalTransactionObject) -}) -export type GetTransactions = z.infer - -// -// Request Options Types -// -interface RequestOptions { - url: string - apiKey: string - walletPassphrase?: string -} - -interface GetWalletsOptions extends RequestOptions { - options: { - labelContains?: string - limit?: number - after?: string - coin?: string - walletIds?: string[] - } -} - -interface CreateTransferOptions extends RequestOptions { - data: { - walletId: string - coin: string - amount: string - address: string - asset?: string - tokenContractAddress?: string - type: BitGoTransferType - networkFeeAttribution: NetworkFeeAttribution - idempotenceId: string - decimals: number - } -} - -interface GetTransactionOptions extends RequestOptions { - data: { - txRequestIds: string[] - walletId: string - } -} - -export const BitGoTransferType = { - NATIVE: 'transfer', - TOKEN: 'transfertoken' -} as const -export type BitGoTransferType = (typeof BitGoTransferType)[keyof typeof BitGoTransferType] - -@Injectable() -export class BitgoClient { - constructor(private readonly logger: LoggerService) {} - - private getBitGoInstance(url: string, apiKey: string): BitGo { - return new BitGo({ - env: url.includes('test') ? 'test' : 'prod', - accessToken: apiKey - }) - } - - private handleError(logMessage: string): OperatorFunction { - return catchError((error: unknown): Observable => { - this.logger.error(logMessage, { error }) - - if (error instanceof AxiosError) { - throw new ProviderHttpException({ - provider: Provider.BITGO, - origin: error, - response: { - status: HttpStatus.INTERNAL_SERVER_ERROR, - body: error.message - } - }) - } - - throw error - }) - } - async createTransfer(opts: CreateTransferOptions): Promise { - const bitgo = this.getBitGoInstance(opts.url, opts.apiKey) - - this.logger.log('Creating BitGo transfer', { - walletId: opts.data.walletId, - coin: opts.data.coin, - type: opts.data.type, - asset: opts.data.asset - }) - - const txRequestId = randomUUID() - return lastValueFrom( - from(bitgo.coin(opts.data.coin.toLowerCase()).wallets().get({ id: opts.data.walletId })).pipe( - switchMap((wallet) => { - const txData = - opts.data.type === BitGoTransferType.NATIVE - ? { - txRequestId, - recipients: [ - { - amount: opts.data.amount, - address: opts.data.address - } - ], - walletPassphrase: opts.walletPassphrase, - type: opts.data.type - } - : { - txRequestId, - recipients: [ - { - tokenData: { - tokenType: TokenType.ERC20, - tokenQuantity: opts.data.amount, - tokenContractAddress: opts.data.tokenContractAddress, - tokenName: opts.data.asset?.toLowerCase(), - decimalPlaces: opts.data.decimals - }, - amount: '0', - address: opts.data.address - } - ], - walletPassphrase: opts.walletPassphrase, - type: opts.data.type - } - - return from(wallet.prebuildAndSignTransaction(txData) as Promise) - }), - tap((tx: TxRequest) => { - this.logger.log('Successfully created BitGo transfer', { - walletId: opts.data.walletId, - txRequestId: tx.txRequestId - }) - }), - this.handleError('Failed to create BitGo transfer') - ) - ) - } - - async getWallets(opts: GetWalletsOptions): Promise { - const bitgo = this.getBitGoInstance(opts.url, opts.apiKey) - - this.logger.log('Requesting BitGo wallets', { - url: opts.url, - options: opts.options - }) - - const queryParams = new URLSearchParams() - if (opts.options.walletIds) { - opts.options.walletIds.forEach((id) => { - queryParams.append('id[]', id) - }) - } - if (opts.options.labelContains) queryParams.append('labelContains', opts.options.labelContains) - if (opts.options.limit) queryParams.append('limit', opts.options.limit.toString()) - if (opts.options.after) queryParams.append('prevId', opts.options.after) - if (opts.options.coin) queryParams.append('coin', opts.options.coin.toLowerCase()) - queryParams.append('expandBalance', 'true') - - const url = `${opts.url.replace(/\/+$/, '')}/api/v2/wallets${queryParams.toString() ? '?' + queryParams.toString() : ''}` - - return lastValueFrom( - from(bitgo.get(url)).pipe( - map((response) => GetWalletsResponse.parse(response.body)), - map((response) => response.wallets), - tap((wallets) => { - this.logger.log('Successfully fetched BitGo wallets', { - url, - walletsCount: wallets.length - }) - }), - this.handleError('Failed to get BitGo wallets') - ) - ) - } - - async getTransaction(opts: GetTransactionOptions): Promise { - const bitgo = this.getBitGoInstance(opts.url, opts.apiKey) - - this.logger.log('Requesting BitGo transaction', { - txRequestIds: opts.data.txRequestIds, - walletId: opts.data.walletId - }) - - const queryParams = new URLSearchParams() - - if (opts.data.txRequestIds) { - opts.data.txRequestIds.forEach((id) => { - queryParams.append('txRequestIds[]', id) - }) - } - - const url = `${opts.url.replace(/\/+$/, '')}/api/v2/wallet/${opts.data.walletId}/txrequests${queryParams.toString() ? '?' + queryParams.toString() : ''}` - return lastValueFrom( - from(bitgo.get(url)).pipe( - map((response) => GetTransactions.parse(response.body).txRequests), - tap((tx) => { - this.logger.log('Successfully fetched BitGo transaction', { - url, - txCount: tx.length - }) - }), - this.handleError('Failed to get BitGo transaction') - ) - ) - } -} diff --git a/apps/vault/src/broker/shared/__test__/mock-server.ts b/apps/vault/src/broker/shared/__test__/mock-server.ts index e2b0c61f1..82f1b1a80 100644 --- a/apps/vault/src/broker/shared/__test__/mock-server.ts +++ b/apps/vault/src/broker/shared/__test__/mock-server.ts @@ -16,8 +16,7 @@ export const useRequestSpy = (server: SetupServerApi): [jest.Mock, SetupServerAp spy({ method: clone.method, url: clone.url, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - headers: Object.fromEntries(request.headers as any), // For some reason, adding the BitGo SDK causes this to break typedefs.. + headers: Object.fromEntries(request.headers), body }) }) diff --git a/apps/vault/src/shared/module/persistence/schema/migrations/20250123154218_account_wallet_id_nullable/migration.sql b/apps/vault/src/shared/module/persistence/schema/migrations/20250123154218_account_wallet_id_nullable/migration.sql deleted file mode 100644 index 6513132d6..000000000 --- a/apps/vault/src/shared/module/persistence/schema/migrations/20250123154218_account_wallet_id_nullable/migration.sql +++ /dev/null @@ -1,8 +0,0 @@ --- DropForeignKey -ALTER TABLE "provider_account" DROP CONSTRAINT "provider_account_wallet_id_fkey"; - --- AlterTable -ALTER TABLE "provider_account" ALTER COLUMN "wallet_id" DROP NOT NULL; - --- AddForeignKey -ALTER TABLE "provider_account" ADD CONSTRAINT "provider_account_wallet_id_fkey" FOREIGN KEY ("wallet_id") REFERENCES "provider_wallet"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/examples/unified-api/.gitignore b/examples/unified-api/.gitignore index a8bfb1fed..49ba8cf09 100644 --- a/examples/unified-api/.gitignore +++ b/examples/unified-api/.gitignore @@ -1,3 +1,4 @@ .env node_modules config.yaml +config.*.yaml diff --git a/examples/unified-api/7-bitgo-stake.ts b/examples/unified-api/7-bitgo-stake.ts deleted file mode 100644 index c555b62e3..000000000 --- a/examples/unified-api/7-bitgo-stake.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { BitGo } from 'bitgo' -import dotenv from 'dotenv' - -dotenv.config() - -const main = async () => { - const WALLET_ID = '6784d7a77e4213f088e81b36ed7dd699' - const bitgo = new BitGo({ - env: 'prod', - accessToken: process.env.BITGO_ACCESS_TOKEN - }) - - const sui = await bitgo.coin('sui') - // const wallets = await (await sui.wallets().list()).wallets - const wallet = await sui.wallets().get({ id: WALLET_ID }) - console.log(wallet._wallet) - const stakingWallet = await wallet.toStakingWallet() - // const stakeRes = await stakingWallet.stake({ - // amount: '1000000000', // 1 SUI = 10^9 MIST, similar to 1 ETH = 10^18 WEI - // validator: '0x92c7bf9914897e8878e559c19a6cffd22e6a569a6dd4d26f8e82e0f2ad1873d6' // Kiln validator, from BitGo UI - // }) - // console.log('StakingRequest - Response', stakeRes) - let transactions - do { - // transactions = await stakingWallet.getStakingRequest(stakeRes.id) - transactions = await stakingWallet.getStakingRequest('9fd7864f-738d-40a4-a584-49f6ad4d327c') - if (!transactions.transactions.some((tx) => tx.txRequestId)) { - console.log('Waiting for transactions to be ready to sign; txRequestId not found', transactions) - await new Promise((resolve) => setTimeout(resolve, 1000)) // Wait 1 second before polling again - } - } while (!transactions.transactions.some((tx) => tx.txRequestId)) - - console.log('Transactions Ready to Sign', transactions) - // if (!transactions.allSigningComplete && transactions.transactions.length > 0) { - // for (const transaction of transactions.transactions) { - // console.log('Signing and Sending Transaction', transaction) - // // const res = await stakingWallet.buildSignAndSend( - // // { walletPassphrase: process.env.BITGO_WALLET_PASSPHRASE || '' }, - // // transaction - // // ) - // // console.log('Build and Send Response', res) - // } - // } -} - -main() - .then(() => console.log('done')) - .catch(console.error) - -const x = { - intent: { - intentType: 'payment', - recipients: [ - { - address: { address: '0x14e7e397d684856f28ad09d04cc550eab2b16e23' }, - amount: { value: '10000000000000000', symbol: 'hteth' } - } - ] - }, - apiVersion: 'full', - preview: false -} diff --git a/examples/unified-api/8-bitgo-transfer.ts b/examples/unified-api/8-bitgo-transfer.ts deleted file mode 100644 index 47d18f42c..000000000 --- a/examples/unified-api/8-bitgo-transfer.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { BitGo } from 'bitgo' -import dotenv from 'dotenv' - -dotenv.config() - -const stakingWalletId = '678a30728bda4b5d7a23a1896e031cda' -const stakingWalletAddress = '0xa9d15711933cfcd8332131eeed76ec9054e40518' -const defaultWalletId = '678a2a006bb272c9d62870f1994291ab' -const defaultWalletAddress = '0xdee7439a1f337d645df0b6804aaabc6ea4a17972' - -const main = async () => { - const bitgo = new BitGo({ - env: (process.env.BITGO_ENV as any) || 'test', - accessToken: process.env.BITGO_ACCESS_TOKEN - }) - const coin = 'hteth' - - const myCoin = await bitgo.coin(coin) - - // const wallets = await (await sui.wallets().list()).wallets - const wallet = await myCoin.wallets().get({ id: stakingWalletId }) - console.log(wallet._wallet) - - const transfer = await wallet.prebuildAndSignTransaction({ - recipients: [ - { - tokenData: { - tokenType: 'ERC20' as any, - tokenQuantity: '4100000000000000', - tokenContractAddress: '0x94373a4919b3240d86ea41593d5eba789fef3848', - tokenName: 'tweth', // This is the TokenId from https://developers.bitgo.com/coins/test-ethereum-terc20-tokens - decimalPlaces: undefined - }, - - amount: '0', // 0.0141 ETH in wei (1 ETH = 10^18 wei) - address: defaultWalletAddress - } - ], - walletPassphrase: process.env.BITGO_WALLET_PASSPHRASE, - type: 'transfertoken' - }) - console.log('transfer', transfer) - // console.log('txRequestId to Poll', transfer?.txRequest?.txRequestId) -} - -main() - .then(() => console.log('done')) - .catch(console.error) diff --git a/examples/unified-api/9-bitgo-connect.ts b/examples/unified-api/9-bitgo-connect.ts deleted file mode 100644 index f3c897a7c..000000000 --- a/examples/unified-api/9-bitgo-connect.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { rsaPublicKeySchema } from '@narval-xyz/armory-sdk' -import { rsaEncrypt } from '@narval-xyz/armory-sdk/signature' -import dotenv from 'dotenv' -import { setConfig, vaultClient } from './vault.client' -dotenv.config() - -const main = async () => { - const url = 'https://app.bitgo-test.com' - const credentials = { - apiKey: process.env.BITGO_ACCESS_TOKEN, - walletPassphrase: process.env.BITGO_WALLET_PASSPHRASE - } - - const jwk = await vaultClient.generateEncryptionKey() - const encryptionKey = rsaPublicKeySchema.parse(jwk) - - const encryptedCredentials = await rsaEncrypt(JSON.stringify(credentials), encryptionKey) - - const connection = await vaultClient.createConnection({ - data: { url, encryptedCredentials, provider: 'bitgo' as any } - }) - - // Save the connectionId to the config file - setConfig('connectionId', connection.data.connectionId) - - console.dir(connection.data) -} - -main() - .then(() => console.log('done')) - .catch(console.error) diff --git a/package-lock.json b/package-lock.json index a48b3a755..da253687a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,9 +13,6 @@ ], "dependencies": { "@aws-crypto/client-node": "4.0.1", - "@bitgo/public-types": "4.11.2", - "@bitgo/sdk-api": "1.58.2", - "@bitgo/sdk-core": "28.20.0", "@bull-board/api": "5.20.1", "@bull-board/express": "5.20.1", "@bull-board/nestjs": "5.20.1", @@ -60,7 +57,6 @@ "@tanstack/react-query": "5.51.11", "axios": "1.7.7", "axios-retry": "4.5.0", - "bitgo": "39.23.0", "bull": "4.16.4", "cache-manager": "6.3.2", "class-transformer": "0.5.1", @@ -447,213 +443,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@aptos-labs/aptos-cli": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@aptos-labs/aptos-cli/-/aptos-cli-1.0.2.tgz", - "integrity": "sha512-PYPsd0Kk3ynkxNfe3S4fanI3DiUICCoh4ibQderbvjPFL5A0oK6F4lPEO2t0MDsQySTk2t4vh99Xjy6Bd9y+aQ==", - "license": "Apache-2.0", - "dependencies": { - "commander": "^12.1.0" - }, - "bin": { - "aptos": "dist/aptos.js" - } - }, - "node_modules/@aptos-labs/aptos-cli/node_modules/commander": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", - "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@aptos-labs/aptos-client": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@aptos-labs/aptos-client/-/aptos-client-0.1.1.tgz", - "integrity": "sha512-kJsoy4fAPTOhzVr7Vwq8s/AUg6BQiJDa7WOqRzev4zsuIS3+JCuIZ6vUd7UBsjnxtmguJJulMRs9qWCzVBt2XA==", - "license": "Apache-2.0", - "dependencies": { - "axios": "1.7.4", - "got": "^11.8.6" - }, - "engines": { - "node": ">=15.10.0" - } - }, - "node_modules/@aptos-labs/aptos-client/node_modules/@szmarczak/http-timer": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", - "license": "MIT", - "dependencies": { - "defer-to-connect": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@aptos-labs/aptos-client/node_modules/axios": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", - "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/@aptos-labs/aptos-client/node_modules/cacheable-lookup": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", - "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", - "license": "MIT", - "engines": { - "node": ">=10.6.0" - } - }, - "node_modules/@aptos-labs/aptos-client/node_modules/cacheable-request": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", - "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", - "license": "MIT", - "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^4.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^6.0.1", - "responselike": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@aptos-labs/aptos-client/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "license": "MIT", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@aptos-labs/aptos-client/node_modules/got": { - "version": "11.8.6", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", - "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", - "license": "MIT", - "dependencies": { - "@sindresorhus/is": "^4.0.0", - "@szmarczak/http-timer": "^4.0.5", - "@types/cacheable-request": "^6.0.1", - "@types/responselike": "^1.0.0", - "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.2", - "decompress-response": "^6.0.0", - "http2-wrapper": "^1.0.0-beta.5.2", - "lowercase-keys": "^2.0.0", - "p-cancelable": "^2.0.0", - "responselike": "^2.0.0" - }, - "engines": { - "node": ">=10.19.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" - } - }, - "node_modules/@aptos-labs/aptos-client/node_modules/http2-wrapper": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", - "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", - "license": "MIT", - "dependencies": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.0.0" - }, - "engines": { - "node": ">=10.19.0" - } - }, - "node_modules/@aptos-labs/aptos-client/node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@aptos-labs/aptos-client/node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@aptos-labs/aptos-client/node_modules/p-cancelable": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@aptos-labs/aptos-client/node_modules/responselike": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", - "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", - "license": "MIT", - "dependencies": { - "lowercase-keys": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@aptos-labs/ts-sdk": { - "version": "1.33.1", - "resolved": "https://registry.npmjs.org/@aptos-labs/ts-sdk/-/ts-sdk-1.33.1.tgz", - "integrity": "sha512-d6nWtUI//fyEN8DeLjm3+ro87Ad6+IKwR9pCqfrs/Azahso1xR1Llxd/O6fj/m1DDsuDj/HAsCsy5TC/aKD6Eg==", - "license": "Apache-2.0", - "dependencies": { - "@aptos-labs/aptos-cli": "^1.0.2", - "@aptos-labs/aptos-client": "^0.1.1", - "@noble/curves": "^1.4.0", - "@noble/hashes": "^1.4.0", - "@scure/bip32": "^1.4.0", - "@scure/bip39": "^1.3.0", - "eventemitter3": "^5.0.1", - "form-data": "^4.0.0", - "js-base64": "^3.7.7", - "jwt-decode": "^4.0.0", - "poseidon-lite": "^0.2.0" - }, - "engines": { - "node": ">=11.0.0" - } - }, - "node_modules/@aptos-labs/ts-sdk/node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "license": "MIT" - }, "node_modules/@automock/adapters.nestjs": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@automock/adapters.nestjs/-/adapters.nestjs-2.1.0.tgz", @@ -1850,83 +1639,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/highlight": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.9.tgz", - "integrity": "sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "license": "MIT", - "peer": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/parser": { "version": "7.26.7", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.7.tgz", @@ -2002,28 +1714,11 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-proposal-class-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", - "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-proposal-decorators": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.24.7.tgz", "integrity": "sha512-RL9GR0pUG5Kc8BUWLNDm2T5OpYwSX15r98I0IkgmRQTXuELq/OynH8xtMTMvTJFjXbMWFVTKtYkTaYQsuAwQlQ==", + "dev": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7", @@ -2052,82 +1747,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", - "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead.", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-object-rest-spread": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz", - "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-object-rest-spread instead.", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.20.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-optional-catch-binding": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", - "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-catch-binding instead.", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-optional-chaining": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", - "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead.", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-proposal-private-property-in-object": { "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", @@ -2190,6 +1809,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.24.7.tgz", "integrity": "sha512-Ui4uLJJrRV1lb38zg1yYTmRKmiZLiftDEvZN2iq3kd9kUFU+PttmzTbAFC2ucRk/XJmtek6G23gPsuZbhrT8fQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -2896,22 +2516,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-object-assign": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.25.9.tgz", - "integrity": "sha512-I/Vl1aQnPsrrn837oLbo+VQtkNcjuuiATqwmuweg4fTauwHHQoxyjmjjOVKyO8OaTxgqYTKW3LuQsykXjDf5Ag==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-transform-object-rest-spread": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", @@ -3773,3305 +3377,2445 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, - "node_modules/@bitgo-forks/avalanchejs": { - "version": "4.1.0-alpha.1", - "resolved": "https://registry.npmjs.org/@bitgo-forks/avalanchejs/-/avalanchejs-4.1.0-alpha.1.tgz", - "integrity": "sha512-iVyxSLaNEBL1GNNYOAnvvNCuYOTz07b/8Y20WLWVtGSTjeZS/MSfoo31uUlDYTQX01CsI16WvbFDyRBKlKh1Jg==", - "dependencies": { - "@noble/curves": "1.3.0", - "@noble/hashes": "1.3.3", - "@noble/secp256k1": "2.0.0", - "@scure/base": "1.1.5", - "micro-eth-signer": "0.7.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@bitgo-forks/avalanchejs/node_modules/@noble/curves": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz", - "integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==", - "license": "MIT", + "node_modules/@bull-board/api": { + "version": "5.20.1", + "resolved": "https://registry.npmjs.org/@bull-board/api/-/api-5.20.1.tgz", + "integrity": "sha512-45aDhnOzWRrtUUAKHxdClSnLIus5f8BK3ATzb2IwI/BRgOi1lWTe1YG266hVqDdWXsUDxKzf75DAANKfAoEsRA==", "dependencies": { - "@noble/hashes": "1.3.3" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@bitgo-forks/avalanchejs/node_modules/@noble/hashes": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", - "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", - "license": "MIT", - "engines": { - "node": ">= 16" + "redis-info": "^3.0.8" }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@bitgo-forks/avalanchejs/node_modules/@noble/secp256k1": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-2.0.0.tgz", - "integrity": "sha512-rUGBd95e2a45rlmFTqQJYEFA4/gdIARFfuTuTqLglz0PZ6AKyzyXsEZZq7UZn8hZsvaBgpCzKKBJizT2cJERXw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "license": "MIT" - }, - "node_modules/@bitgo-forks/avalanchejs/node_modules/@scure/base": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.5.tgz", - "integrity": "sha512-Brj9FiG2W1MRQSTB212YVPRrcbjkv48FoZi/u4l/zds/ieRrqsh7aUf6CLwkAq61oKXr/ZlTzlY66gLIj3TFTQ==", - "license": "MIT", - "funding": { - "url": "https://paulmillr.com/funding/" + "peerDependencies": { + "@bull-board/ui": "5.20.1" } }, - "node_modules/@bitgo/abstract-cosmos": { - "version": "11.2.16", - "resolved": "https://registry.npmjs.org/@bitgo/abstract-cosmos/-/abstract-cosmos-11.2.16.tgz", - "integrity": "sha512-G5Gnh46U3bHP3zcMe9NUNvQ5ggiIebrbvoJ+XEgMSglWz1F8XX4pKvfaFIoH8iR014EOAuivfdLKUY+pZFn4LA==", - "license": "MIT", + "node_modules/@bull-board/express": { + "version": "5.20.1", + "resolved": "https://registry.npmjs.org/@bull-board/express/-/express-5.20.1.tgz", + "integrity": "sha512-980wGA8kjMyw7MrYNN25l7lJNlLz22ln3jW/H3ef98BXhTeBnPR16XhXu1Z6471X5Aor9WXZ6FRQ5pJhP4iXuA==", "dependencies": { - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/statics": "^50.20.0", - "@bitgo/utxo-lib": "^11.2.1", - "@cosmjs/amino": "^0.29.5", - "@cosmjs/crypto": "^0.30.1", - "@cosmjs/encoding": "^0.29.5", - "@cosmjs/proto-signing": "^0.29.5", - "@cosmjs/stargate": "^0.29.5", - "bignumber.js": "^9.1.1", - "cosmjs-types": "^0.6.1", - "lodash": "^4.17.21", - "protobufjs": "^7.4.0", - "superagent": "^9.0.1" - }, - "engines": { - "node": ">=18 <21" + "@bull-board/api": "5.20.1", + "@bull-board/ui": "5.20.1", + "ejs": "^3.1.10", + "express": "^4.19.2" } }, - "node_modules/@bitgo/abstract-eth": { - "version": "22.4.10", - "resolved": "https://registry.npmjs.org/@bitgo/abstract-eth/-/abstract-eth-22.4.10.tgz", - "integrity": "sha512-phcnbNIqrPbFm9/dThkXrNczTqZ/BaUsstMS9w6mJX96lidpi9wYn0tGB21rZhNXnieqUIMaRF7Ifo5sYhHPdg==", - "license": "MIT", + "node_modules/@bull-board/nestjs": { + "version": "5.20.1", + "resolved": "https://registry.npmjs.org/@bull-board/nestjs/-/nestjs-5.20.1.tgz", + "integrity": "sha512-6WREzrJdrAuJ3LcZVETzfEpQxUSF2xxC7plPiSj11jyO30i/moKkc7gUVuP2h6YgQnhhH3ppFxECVduXWRBDLQ==", "dependencies": { - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/statics": "^50.20.0", - "@bitgo/utxo-lib": "^11.2.1", - "@ethereumjs/common": "^2.6.5", - "@ethereumjs/tx": "^3.3.0", - "@metamask/eth-sig-util": "^5.0.2", - "bignumber.js": "^9.1.1", - "bn.js": "^5.2.1", - "debug": "^3.1.0", - "ethereumjs-abi": "^0.6.5", - "ethereumjs-util": "7.1.5", - "ethers": "^5.1.3", - "keccak": "^3.0.3", - "lodash": "4.17.21", - "secp256k1": "5.0.1", - "superagent": "^9.0.1" + "@nestjs/bull-shared": "^10.0.0" }, - "engines": { - "node": ">=18 <21" - } - }, - "node_modules/@bitgo/abstract-eth/node_modules/@ethereumjs/common": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", - "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", - "license": "MIT", - "dependencies": { - "crc-32": "^1.2.0", - "ethereumjs-util": "^7.1.5" - } - }, - "node_modules/@bitgo/abstract-eth/node_modules/@ethereumjs/tx": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.5.2.tgz", - "integrity": "sha512-gQDNJWKrSDGu2w7w0PzVXVBNMzb7wwdDOmOqczmhNjqFxFuIbhVJDwiGEnxFNC2/b8ifcZzY7MLcluizohRzNw==", - "license": "MPL-2.0", - "dependencies": { - "@ethereumjs/common": "^2.6.4", - "ethereumjs-util": "^7.1.5" - } - }, - "node_modules/@bitgo/abstract-eth/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" + "peerDependencies": { + "@bull-board/api": "^5.20.1", + "@bull-board/express": "^5.20.1", + "@nestjs/common": "^9.0.0 || ^10.0.0", + "@nestjs/core": "^9.0.0 || ^10.0.0", + "reflect-metadata": "^0.1.13 || ^0.2.0", + "rxjs": "^7.8.1" } }, - "node_modules/@bitgo/abstract-lightning": { - "version": "1.2.38", - "resolved": "https://registry.npmjs.org/@bitgo/abstract-lightning/-/abstract-lightning-1.2.38.tgz", - "integrity": "sha512-pW0LNvAHOZaeV/JtZ9aCevkwLFg6HTo7eU4LKpo4MRDcsjkJ4/7xX0cIuJK1y3G1HuequQGmimDagIwA59vW0g==", - "license": "MIT", + "node_modules/@bull-board/ui": { + "version": "5.20.1", + "resolved": "https://registry.npmjs.org/@bull-board/ui/-/ui-5.20.1.tgz", + "integrity": "sha512-RzNinC4FKHNuxzkIRsCL+n9iO5RxmF5YM7byCuuv1/UeFjtCtsLHFi6TI9ZgJsXETA2Uxq9Mg7ppncojUjrINw==", "dependencies": { - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/utxo-lib": "^11.2.1" - }, - "engines": { - "node": ">=18 <21" + "@bull-board/api": "5.20.1" } }, - "node_modules/@bitgo/abstract-substrate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@bitgo/abstract-substrate/-/abstract-substrate-1.0.2.tgz", - "integrity": "sha512-lHlITYQQelNNI5qfc1PO/nVLNKGEnw4oHlofEoDK7k0KTyIjLteAmpWseQHEuJLe5+xliQ7H1QODZDZorRvIJg==", - "license": "MIT", + "node_modules/@bundled-es-modules/cookie": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/cookie/-/cookie-2.0.1.tgz", + "integrity": "sha512-8o+5fRPLNbjbdGRRmJj3h6Hh1AQJf2dk3qQ/5ZFb+PXkRNiSoMGGUKlsgLfrxneb72axVJyIYji64E2+nNfYyw==", + "dev": true, + "license": "ISC", "dependencies": { - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/statics": "^50.20.0" - }, - "engines": { - "node": ">=18 <21" + "cookie": "^0.7.2" } }, - "node_modules/@bitgo/abstract-utxo": { - "version": "9.12.0", - "resolved": "https://registry.npmjs.org/@bitgo/abstract-utxo/-/abstract-utxo-9.12.0.tgz", - "integrity": "sha512-iB8FVbsv/7NNYizZQTZ3Wt+IFBWE82Ei9qhJy5kS2ujT1hffKSCNuVBquqXRsh2yqmz3KTygkxmY+ZNLph1/+Q==", + "node_modules/@bundled-es-modules/cookie/node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "dev": true, "license": "MIT", - "dependencies": { - "@bitgo/blockapis": "^1.10.9", - "@bitgo/sdk-api": "^1.58.2", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/unspents": "^0.47.17", - "@bitgo/utxo-lib": "^11.2.1", - "@bitgo/wasm-miniscript": "^2.0.0-beta.2", - "@types/bluebird": "^3.5.25", - "@types/lodash": "^4.14.121", - "@types/superagent": "4.1.15", - "bignumber.js": "^9.0.2", - "bip174": "npm:@bitgo-forks/bip174@3.1.0-master.4", - "bitcoinjs-message": "npm:@bitgo-forks/bitcoinjs-message@1.0.0-master.3", - "bluebird": "^3.5.3", - "debug": "^3.1.0", - "io-ts": "npm:@bitgo-forks/io-ts@2.1.4", - "lodash": "^4.17.14", - "superagent": "^9.0.1" - }, "engines": { - "node": ">=18 <21" - } - }, - "node_modules/@bitgo/abstract-utxo/node_modules/@types/superagent": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.15.tgz", - "integrity": "sha512-mu/N4uvfDN2zVQQ5AYJI/g4qxn2bHB6521t1UuH09ShNWjebTqN0ZFuYK9uYjcgmI0dTQEs+Owi1EO6U0OkOZQ==", - "license": "MIT", - "dependencies": { - "@types/cookiejar": "*", - "@types/node": "*" + "node": ">= 0.6" } }, - "node_modules/@bitgo/abstract-utxo/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "license": "MIT", + "node_modules/@bundled-es-modules/statuses": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/statuses/-/statuses-1.0.1.tgz", + "integrity": "sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==", + "dev": true, + "license": "ISC", "dependencies": { - "ms": "^2.1.1" + "statuses": "^2.0.1" } }, - "node_modules/@bitgo/account-lib": { - "version": "24.2.0", - "resolved": "https://registry.npmjs.org/@bitgo/account-lib/-/account-lib-24.2.0.tgz", - "integrity": "sha512-t0GzSCmRdQC/qt6xYV05OL5Q3qp6eZR166yvUHiko3GIiv2JVesl+DD4Yf56RbC1wBiD7TmDH8qiOw2vzyI1vg==", + "node_modules/@bundled-es-modules/tough-cookie": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/tough-cookie/-/tough-cookie-0.1.6.tgz", + "integrity": "sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw==", + "dev": true, "license": "ISC", "dependencies": { - "@bitgo/sdk-coin-algo": "^2.1.58", - "@bitgo/sdk-coin-apt": "^1.4.1", - "@bitgo/sdk-coin-arbeth": "^21.0.52", - "@bitgo/sdk-coin-atom": "^13.1.16", - "@bitgo/sdk-coin-avaxc": "^5.2.10", - "@bitgo/sdk-coin-avaxp": "^5.0.59", - "@bitgo/sdk-coin-bera": "^2.3.4", - "@bitgo/sdk-coin-bld": "^3.0.29", - "@bitgo/sdk-coin-bsc": "^22.2.13", - "@bitgo/sdk-coin-celo": "^4.0.11", - "@bitgo/sdk-coin-coredao": "^1.2.12", - "@bitgo/sdk-coin-coreum": "^21.0.29", - "@bitgo/sdk-coin-cspr": "^2.0.60", - "@bitgo/sdk-coin-dot": "^4.1.38", - "@bitgo/sdk-coin-etc": "^2.2.27", - "@bitgo/sdk-coin-eth": "^24.2.49", - "@bitgo/sdk-coin-eth2": "^3.0.59", - "@bitgo/sdk-coin-hash": "^3.0.29", - "@bitgo/sdk-coin-hbar": "^2.0.60", - "@bitgo/sdk-coin-icp": "^1.1.0", - "@bitgo/sdk-coin-injective": "^3.0.29", - "@bitgo/sdk-coin-islm": "^2.1.10", - "@bitgo/sdk-coin-near": "^2.0.60", - "@bitgo/sdk-coin-oas": "^1.1.13", - "@bitgo/sdk-coin-opeth": "^18.1.45", - "@bitgo/sdk-coin-osmo": "^3.0.29", - "@bitgo/sdk-coin-polygon": "^21.0.29", - "@bitgo/sdk-coin-rbtc": "^2.0.60", - "@bitgo/sdk-coin-rune": "^1.1.17", - "@bitgo/sdk-coin-sei": "^3.0.29", - "@bitgo/sdk-coin-sol": "^4.7.17", - "@bitgo/sdk-coin-stx": "^3.3.17", - "@bitgo/sdk-coin-sui": "^5.8.19", - "@bitgo/sdk-coin-tia": "^3.0.29", - "@bitgo/sdk-coin-ton": "^3.4.17", - "@bitgo/sdk-coin-trx": "^2.0.60", - "@bitgo/sdk-coin-xrp": "^3.7.2", - "@bitgo/sdk-coin-xtz": "^2.1.58", - "@bitgo/sdk-coin-zeta": "^3.0.29", - "@bitgo/sdk-coin-zketh": "^2.0.52", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/sdk-lib-mpc": "^10.1.0", - "@bitgo/statics": "^50.20.0", - "bignumber.js": "^9.1.1", - "bs58": "^4.0.1" - }, - "engines": { - "node": ">=18 <21" - } - }, - "node_modules/@bitgo/account-lib/node_modules/@bitgo/sdk-coin-sui": { - "version": "5.8.19", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-sui/-/sdk-coin-sui-5.8.19.tgz", - "integrity": "sha512-axpv9x6bOU63F97E3W5lJ97NaEjUxJhv5xVePnw1V4DWCvKGhTS/VxabflRiONY6F1ia8wgAYEGftgWkbXy2Pg==", - "license": "MIT", - "dependencies": { - "@bitgo/blake2b": "^3.2.4", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/sdk-lib-mpc": "^10.1.0", - "@bitgo/statics": "^50.20.0", - "@mysten/bcs": "^0.7.0", - "bignumber.js": "^9.0.0", - "bs58": "^4.0.1", - "lodash": "^4.17.21", - "superagent": "3.8.2", - "superstruct": "^1.0.3", - "tweetnacl": "^1.0.3" - }, - "engines": { - "node": ">=18 <21" + "@types/tough-cookie": "^4.0.5", + "tough-cookie": "^4.1.4" } }, - "node_modules/@bitgo/account-lib/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "license": "MIT", + "node_modules/@coinbase/wallet-sdk": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@coinbase/wallet-sdk/-/wallet-sdk-4.2.3.tgz", + "integrity": "sha512-BcyHZ/Ec84z0emORzqdXDv4P0oV+tV3a0OirfA8Ko1JGBIAVvB+hzLvZzCDvnuZx7MTK+Dd8Y9Tjlo446BpCIg==", "dependencies": { - "ms": "^2.1.1" + "@noble/hashes": "^1.4.0", + "clsx": "^1.2.1", + "eventemitter3": "^5.0.1", + "preact": "^10.24.2" } }, - "node_modules/@bitgo/account-lib/node_modules/form-data": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.2.tgz", - "integrity": "sha512-GgwY0PS7DbXqajuGf4OYlsrIu3zgxD6Vvql43IBhm6MahqA5SK/7mwhtNj2AdH2z35YR34ujJ7BN+3fFC3jP5Q==", - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12", - "safe-buffer": "^5.2.1" - }, + "node_modules/@coinbase/wallet-sdk/node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", "engines": { - "node": ">= 0.12" - } - }, - "node_modules/@bitgo/account-lib/node_modules/formidable": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", - "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==", - "deprecated": "Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau", - "license": "MIT", - "funding": { - "url": "https://ko-fi.com/tunnckoCore/commissions" - } - }, - "node_modules/@bitgo/account-lib/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "license": "MIT" - }, - "node_modules/@bitgo/account-lib/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "node": ">=6" } }, - "node_modules/@bitgo/account-lib/node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "license": "MIT" + "node_modules/@coinbase/wallet-sdk/node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" }, - "node_modules/@bitgo/account-lib/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "optional": true, + "engines": { + "node": ">=0.1.90" } }, - "node_modules/@bitgo/account-lib/node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "license": "MIT" - }, - "node_modules/@bitgo/account-lib/node_modules/superagent": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.2.tgz", - "integrity": "sha512-gVH4QfYHcY3P0f/BZzavLreHW3T1v7hG9B+hpMQotGQqurOvhv87GcMCd6LWySmBuf+BDR44TQd0aISjVHLeNQ==", - "deprecated": "Please upgrade to v9.0.0+ as we have fixed a public vulnerability with formidable dependency. Note that v9.0.0+ requires Node.js v14.18.0+. See https://github.com/ladjs/superagent/pull/1800 for insight. This project is supported and maintained by the team at Forward Email @ https://forwardemail.net", - "license": "MIT", + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, "dependencies": { - "component-emitter": "^1.2.0", - "cookiejar": "^2.1.0", - "debug": "^3.1.0", - "extend": "^3.0.0", - "form-data": "^2.3.1", - "formidable": "^1.1.1", - "methods": "^1.1.1", - "mime": "^1.4.1", - "qs": "^6.5.1", - "readable-stream": "^2.0.5" + "@jridgewell/trace-mapping": "0.3.9" }, "engines": { - "node": ">= 4.0" - } - }, - "node_modules/@bitgo/blake2b": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@bitgo/blake2b/-/blake2b-3.2.4.tgz", - "integrity": "sha512-46PEgEVPxecNJ/xczggIllSxIkFIvvbVM0OfIDdNJ5qpFHUeBCkNIiGdzC3fYZlsv7bVTdUZOj79GcFBLMYBqA==", - "license": "ISC", - "dependencies": { - "@bitgo/blake2b-wasm": "^3.2.3", - "nanoassert": "^2.0.0" - } - }, - "node_modules/@bitgo/blake2b-wasm": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@bitgo/blake2b-wasm/-/blake2b-wasm-3.2.3.tgz", - "integrity": "sha512-NaurBrMaEpjfg7EdUJgW/c6byt27O6q1ZaxB5Ita10MjjYjUu0SyYF4q7JPNxpHF/lMxb0YZakOxigbDBu9Jjw==", - "license": "MIT", - "dependencies": { - "nanoassert": "^1.0.0" - } - }, - "node_modules/@bitgo/blake2b-wasm/node_modules/nanoassert": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/nanoassert/-/nanoassert-1.1.0.tgz", - "integrity": "sha512-C40jQ3NzfkP53NsO8kEOFd79p4b9kDXQMwgiY1z8ZwrDZgUyom0AHwGegF4Dm99L+YoYhuaB0ceerUcXmqr1rQ==", - "license": "ISC" - }, - "node_modules/@bitgo/blockapis": { - "version": "1.10.9", - "resolved": "https://registry.npmjs.org/@bitgo/blockapis/-/blockapis-1.10.9.tgz", - "integrity": "sha512-8GWR1oruh9WrfxWq9RCKDvMrB3WXcCJ7Gb3uyk5OXt0/bMdpa0QCrLv4e1dG/QeBipCBnLiOkb6NSzS4cbocFA==", - "license": "MIT", - "dependencies": { - "@bitgo/utxo-lib": "^11.2.1", - "@types/superagent": "4.1.16", - "bluebird": "^3.7.2", - "superagent": "^9.0.1" - } - }, - "node_modules/@bitgo/blockapis/node_modules/@types/superagent": { - "version": "4.1.16", - "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.16.tgz", - "integrity": "sha512-tLfnlJf6A5mB6ddqF159GqcDizfzbMUB1/DeT59/wBNqzRTNNKsaw79A/1TZ84X+f/EwWH8FeuSkjlCLyqS/zQ==", - "license": "MIT", - "dependencies": { - "@types/cookiejar": "*", - "@types/node": "*" + "node": ">=12" } }, - "node_modules/@bitgo/bls-dkg": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@bitgo/bls-dkg/-/bls-dkg-1.3.1.tgz", - "integrity": "sha512-pD5f3LQVoCUOczQxGJcEAq3DfchVbdojJ5azikJE64WjV/zR5HkPQDgYcznbM+ou2xX3sbweN893brtYTCNtRw==", - "license": "ISC", + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, "dependencies": { - "noble-bls12-381": "^0.7.2" + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "node_modules/@bitgo/public-types": { - "version": "4.11.2", - "resolved": "https://registry.npmjs.org/@bitgo/public-types/-/public-types-4.11.2.tgz", - "integrity": "sha512-McGUcJrvDMHMcCrdnLdgv++k+NasMZliFQARGV2i4czGjSVwK/DHzyNLAiFy0keNoT66nIZ3bV0CTc1uMjlH4g==", - "license": "UNLICENSED", + "node_modules/@dabh/diagnostics": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", + "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", "dependencies": { - "fp-ts": "^2.0.0", - "io-ts": "npm:@bitgo-forks/io-ts@2.1.4", - "io-ts-types": "^0.5.16", - "monocle-ts": "^2.3.13", - "newtype-ts": "^0.3.5" + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" } }, - "node_modules/@bitgo/sdk-api": { - "version": "1.58.2", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-api/-/sdk-api-1.58.2.tgz", - "integrity": "sha512-egMomQ6n0u4x8y1J1oHsHjEcGX3CbXt+1I6SoXQwSaSWChWY6pN1i2npUJTmuDUCYH9wqazW0yTIhMCUPdQb7A==", - "license": "MIT", - "dependencies": { - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/sdk-hmac": "^1.1.0", - "@bitgo/sjcl": "^1.0.1", - "@bitgo/unspents": "^0.47.17", - "@bitgo/utxo-lib": "^11.2.1", - "@types/superagent": "4.1.15", - "bitcoinjs-message": "npm:@bitgo-forks/bitcoinjs-message@1.0.0-master.3", - "bluebird": "^3.5.3", - "debug": "3.1.0", - "eol": "^0.5.0", - "lodash": "^4.17.15", - "proxy-agent": "6.4.0", - "sanitize-html": "^2.11", - "secp256k1": "5.0.1", - "secrets.js-grempe": "^1.1.0", - "superagent": "^9.0.1" + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "engines": { + "node": ">=10.0.0" } }, - "node_modules/@bitgo/sdk-api/node_modules/@types/superagent": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.15.tgz", - "integrity": "sha512-mu/N4uvfDN2zVQQ5AYJI/g4qxn2bHB6521t1UuH09ShNWjebTqN0ZFuYK9uYjcgmI0dTQEs+Owi1EO6U0OkOZQ==", - "license": "MIT", - "dependencies": { - "@types/cookiejar": "*", - "@types/node": "*" - } + "node_modules/@docsearch/css": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.6.1.tgz", + "integrity": "sha512-VtVb5DS+0hRIprU2CO6ZQjK2Zg4QU5HrDM1+ix6rT0umsYvFvatMAnf97NHZlVWDaaLlx7GRfR/7FikANiM2Fg==" }, - "node_modules/@bitgo/sdk-api/node_modules/debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "license": "MIT", + "node_modules/@docsearch/react": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.6.1.tgz", + "integrity": "sha512-qXZkEPvybVhSXj0K7U3bXc233tk5e8PfhoZ6MhPOiik/qUQxYC+Dn9DnoS7CxHQQhHfCvTiN0eY9M12oRghEXw==", "dependencies": { - "ms": "2.0.0" + "@algolia/autocomplete-core": "1.9.3", + "@algolia/autocomplete-preset-algolia": "1.9.3", + "@docsearch/css": "3.6.1", + "algoliasearch": "^4.19.1" + }, + "peerDependencies": { + "@types/react": ">= 16.8.0 < 19.0.0", + "react": ">= 16.8.0 < 19.0.0", + "react-dom": ">= 16.8.0 < 19.0.0", + "search-insights": ">= 1 < 3" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "search-insights": { + "optional": true + } } }, - "node_modules/@bitgo/sdk-api/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/@bitgo/sdk-coin-ada": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-ada/-/sdk-coin-ada-4.6.0.tgz", - "integrity": "sha512-VJEvh0ahtgmfQa1oYplzJU7evnLHSNTQY1rASwE4eqbD+Iwr6tIefBC2c0eNdaaMib5LMrqZ//dobEwh5XRn1g==", - "license": "MIT", + "node_modules/@docusaurus/core": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.4.0.tgz", + "integrity": "sha512-g+0wwmN2UJsBqy2fQRQ6fhXruoEa62JDeEa5d8IdTJlMoaDaEDfHh7WjwGRn4opuTQWpjAwP/fbcgyHKlE+64w==", "dependencies": { - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/sdk-lib-mpc": "^10.1.0", - "@bitgo/statics": "^50.20.0", - "@emurgo/cardano-serialization-lib-browser": "^12.0.1", - "@emurgo/cardano-serialization-lib-nodejs": "^12.0.1", - "bech32": "^2.0.0", - "bignumber.js": "^9.0.2", + "@babel/core": "^7.23.3", + "@babel/generator": "^7.23.3", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-runtime": "^7.22.9", + "@babel/preset-env": "^7.22.9", + "@babel/preset-react": "^7.22.5", + "@babel/preset-typescript": "^7.22.5", + "@babel/runtime": "^7.22.6", + "@babel/runtime-corejs3": "^7.22.6", + "@babel/traverse": "^7.22.8", + "@docusaurus/cssnano-preset": "3.4.0", + "@docusaurus/logger": "3.4.0", + "@docusaurus/mdx-loader": "3.4.0", + "@docusaurus/utils": "3.4.0", + "@docusaurus/utils-common": "3.4.0", + "@docusaurus/utils-validation": "3.4.0", + "autoprefixer": "^10.4.14", + "babel-loader": "^9.1.3", + "babel-plugin-dynamic-import-node": "^2.3.3", + "boxen": "^6.2.1", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "clean-css": "^5.3.2", + "cli-table3": "^0.6.3", + "combine-promises": "^1.1.0", + "commander": "^5.1.0", + "copy-webpack-plugin": "^11.0.0", + "core-js": "^3.31.1", + "css-loader": "^6.8.1", + "css-minimizer-webpack-plugin": "^5.0.1", + "cssnano": "^6.1.2", + "del": "^6.1.1", + "detect-port": "^1.5.1", + "escape-html": "^1.0.3", + "eta": "^2.2.0", + "eval": "^0.1.8", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "html-minifier-terser": "^7.2.0", + "html-tags": "^3.3.1", + "html-webpack-plugin": "^5.5.3", + "leven": "^3.1.0", "lodash": "^4.17.21", - "superagent": "^9.0.1", - "tweetnacl": "^1.0.3" + "mini-css-extract-plugin": "^2.7.6", + "p-map": "^4.0.0", + "postcss": "^8.4.26", + "postcss-loader": "^7.3.3", + "prompts": "^2.4.2", + "react-dev-utils": "^12.0.1", + "react-helmet-async": "^1.3.0", + "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", + "react-loadable-ssr-addon-v5-slorber": "^1.0.1", + "react-router": "^5.3.4", + "react-router-config": "^5.1.1", + "react-router-dom": "^5.3.4", + "rtl-detect": "^1.0.4", + "semver": "^7.5.4", + "serve-handler": "^6.1.5", + "shelljs": "^0.8.5", + "terser-webpack-plugin": "^5.3.9", + "tslib": "^2.6.0", + "update-notifier": "^6.0.2", + "url-loader": "^4.1.1", + "webpack": "^5.88.1", + "webpack-bundle-analyzer": "^4.9.0", + "webpack-dev-server": "^4.15.1", + "webpack-merge": "^5.9.0", + "webpackbar": "^5.0.2" }, - "engines": { - "node": ">=18 <21" - } - }, - "node_modules/@bitgo/sdk-coin-algo": { - "version": "2.1.58", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-algo/-/sdk-coin-algo-2.1.58.tgz", - "integrity": "sha512-AxdCaZ7cJ+Gj9Es+6CRxiLTSTFfDHhtr4WP6gliCNT+fRPnaSC5iGrMjJEp2HFd2NnTxv7DnvesjzOEAmqQ4sg==", - "license": "MIT", - "dependencies": { - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/statics": "^50.20.0", - "@hashgraph/cryptography": "1.1.2", - "@stablelib/hex": "^1.0.0", - "algosdk": "1.23.1", - "bignumber.js": "^9.0.0", - "hi-base32": "^0.5.1", - "joi": "^17.4.0", - "js-sha512": "0.8.0", - "lodash": "^4.17.14", - "stellar-sdk": "^10.0.1", - "tweetnacl": "^1.0.3" + "bin": { + "docusaurus": "bin/docusaurus.mjs" }, "engines": { - "node": ">=18 <21" - } - }, - "node_modules/@bitgo/sdk-coin-apt": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-apt/-/sdk-coin-apt-1.4.1.tgz", - "integrity": "sha512-doM4SeOHwEV3XgoDZcG2Hud0hgy+xjLmGpEfVgtL/Z2iWNhC9oHMaVJCxyba/w/eArMcZIkdxXTttsULqrsT6A==", - "license": "MIT", - "dependencies": { - "@aptos-labs/ts-sdk": "^1.32.0", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/statics": "^50.20.0", - "bignumber.js": "^9.1.2", - "lodash": "^4.17.21" + "node": ">=18.0" }, - "engines": { - "node": ">=16 <21" + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "node_modules/@bitgo/sdk-coin-arbeth": { - "version": "21.0.52", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-arbeth/-/sdk-coin-arbeth-21.0.52.tgz", - "integrity": "sha512-2zz0jw30uh9TwwmIZQ+EufYKdsgHlMgNzofq7fsl2e9V8rR/8DJxw75I1iPFHJN3AQ7hdFYzs+/avpCJmtItfQ==", - "license": "MIT", - "dependencies": { - "@bitgo/abstract-eth": "^22.4.10", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/statics": "^50.20.0", - "@bitgo/utxo-lib": "^11.2.1", - "@ethereumjs/common": "^2.6.5", - "ethereumjs-abi": "^0.6.5", - "ethereumjs-util": "7.1.5" + "node_modules/@docusaurus/core/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=18 <21" - } - }, - "node_modules/@bitgo/sdk-coin-arbeth/node_modules/@ethereumjs/common": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", - "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", - "license": "MIT", - "dependencies": { - "crc-32": "^1.2.0", - "ethereumjs-util": "^7.1.5" + "node": ">=10" } }, - "node_modules/@bitgo/sdk-coin-atom": { - "version": "13.1.16", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-atom/-/sdk-coin-atom-13.1.16.tgz", - "integrity": "sha512-TbJ9QEkavJKhIeBs3hg2HBIESgSJcvDleDuUnipDGKFI33O5f/WgKVozVUyjE+5/kIZTzLS9rHxkTgbhEWmDug==", - "license": "MIT", + "node_modules/@docusaurus/cssnano-preset": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.4.0.tgz", + "integrity": "sha512-qwLFSz6v/pZHy/UP32IrprmH5ORce86BGtN0eBtG75PpzQJAzp9gefspox+s8IEOr0oZKuQ/nhzZ3xwyc3jYJQ==", "dependencies": { - "@bitgo/abstract-cosmos": "^11.2.16", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/sdk-lib-mpc": "^10.1.0", - "@bitgo/statics": "^50.20.0", - "@cosmjs/amino": "^0.29.5", - "@cosmjs/encoding": "^0.29.5", - "@cosmjs/stargate": "^0.29.5", - "bignumber.js": "^9.1.1" + "cssnano-preset-advanced": "^6.1.2", + "postcss": "^8.4.38", + "postcss-sort-media-queries": "^5.2.0", + "tslib": "^2.6.0" }, "engines": { - "node": ">=18 <21" + "node": ">=18.0" } }, - "node_modules/@bitgo/sdk-coin-avaxc": { - "version": "5.2.10", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-avaxc/-/sdk-coin-avaxc-5.2.10.tgz", - "integrity": "sha512-FymTUNo0Isb0uzLrxBLqscf4bu9FUsvbMHXfGd/1RbIjKH/BR6sZPYhJo+ESxYhbrNcEhjDjdg21EuFHYXw2ZA==", - "license": "MIT", + "node_modules/@docusaurus/logger": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.4.0.tgz", + "integrity": "sha512-bZwkX+9SJ8lB9kVRkXw+xvHYSMGG4bpYHKGXeXFvyVc79NMeeBSGgzd4TQLHH+DYeOJoCdl8flrFJVxlZ0wo/Q==", "dependencies": { - "@bitgo/abstract-eth": "^22.4.10", - "@bitgo/sdk-coin-avaxp": "^5.0.59", - "@bitgo/sdk-coin-eth": "^24.2.49", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/statics": "^50.20.0", - "@bitgo/utxo-lib": "^11.2.1", - "@ethereumjs/common": "^2.6.5", - "bignumber.js": "^9.1.1", - "ethereumjs-abi": "^0.6.5", - "ethereumjs-util": "7.1.5", - "keccak": "^3.0.3", - "lodash": "^4.17.14", - "secp256k1": "5.0.1", - "superagent": "^9.0.1" + "chalk": "^4.1.2", + "tslib": "^2.6.0" }, "engines": { - "node": ">=18 <21" - } - }, - "node_modules/@bitgo/sdk-coin-avaxc/node_modules/@ethereumjs/common": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", - "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", - "license": "MIT", - "dependencies": { - "crc-32": "^1.2.0", - "ethereumjs-util": "^7.1.5" + "node": ">=18.0" } }, - "node_modules/@bitgo/sdk-coin-avaxp": { - "version": "5.0.59", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-avaxp/-/sdk-coin-avaxp-5.0.59.tgz", - "integrity": "sha512-m7NJhRKJ2YHJuK5OLNw6mmZxkW8yR25jw+XJ7mCNarJDcIa8ocDsWwt3NkZ7GMmdo9Hz9kgSmVm9Ob8yDQY9fQ==", - "license": "MIT", + "node_modules/@docusaurus/mdx-loader": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.4.0.tgz", + "integrity": "sha512-kSSbrrk4nTjf4d+wtBA9H+FGauf2gCax89kV8SUSJu3qaTdSIKdWERlngsiHaCFgZ7laTJ8a67UFf+xlFPtuTw==", "dependencies": { - "@bitgo-forks/avalanchejs": "4.1.0-alpha.1", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/statics": "^50.20.0", - "@bitgo/utxo-lib": "^11.2.1", - "avalanche": "3.15.3", - "bignumber.js": "^9.0.0", - "create-hash": "^1.2.0", - "elliptic": "^6.5.2", - "ethereumjs-util": "7.1.5", - "lodash": "^4.17.14", - "safe-buffer": "^5.2.1" + "@docusaurus/logger": "3.4.0", + "@docusaurus/utils": "3.4.0", + "@docusaurus/utils-validation": "3.4.0", + "@mdx-js/mdx": "^3.0.0", + "@slorber/remark-comment": "^1.0.0", + "escape-html": "^1.0.3", + "estree-util-value-to-estree": "^3.0.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "image-size": "^1.0.2", + "mdast-util-mdx": "^3.0.0", + "mdast-util-to-string": "^4.0.0", + "rehype-raw": "^7.0.0", + "remark-directive": "^3.0.0", + "remark-emoji": "^4.0.0", + "remark-frontmatter": "^5.0.0", + "remark-gfm": "^4.0.0", + "stringify-object": "^3.3.0", + "tslib": "^2.6.0", + "unified": "^11.0.3", + "unist-util-visit": "^5.0.0", + "url-loader": "^4.1.1", + "vfile": "^6.0.1", + "webpack": "^5.88.1" }, "engines": { - "node": ">=18 <21" - } - }, - "node_modules/@bitgo/sdk-coin-bch": { - "version": "2.1.10", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-bch/-/sdk-coin-bch-2.1.10.tgz", - "integrity": "sha512-rJncGy0cLxCbiYDQFyOuy/H04nZDOBufwwPYLRKzTL1YJtdzYlEqEJKKFdSKZ9+1PCQk7ihVFho3QXX8Br3iPg==", - "license": "MIT", - "dependencies": { - "@bitgo/abstract-utxo": "^9.12.0", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/utxo-lib": "^11.2.1" + "node": ">=18.0" }, - "engines": { - "node": ">=18 <21" + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "node_modules/@bitgo/sdk-coin-bcha": { - "version": "2.2.10", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-bcha/-/sdk-coin-bcha-2.2.10.tgz", - "integrity": "sha512-UZnSrnLgahWIUI5jTI0Fwm9u5Fr8l1DZdMOJhje/E7ysx/5dAhXMoKyvW9K9McbWHwqX7AO87PFzzCwYcuW+gQ==", - "license": "MIT", + "node_modules/@docusaurus/module-type-aliases": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.4.0.tgz", + "integrity": "sha512-A1AyS8WF5Bkjnb8s+guTDuYmUiwJzNrtchebBHpc0gz0PyHJNMaybUlSrmJjHVcGrya0LKI4YcR3lBDQfXRYLw==", "dependencies": { - "@bitgo/abstract-utxo": "^9.12.0", - "@bitgo/sdk-coin-bch": "^2.1.10", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/utxo-lib": "^11.2.1" + "@docusaurus/types": "3.4.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router-config": "*", + "@types/react-router-dom": "*", + "react-helmet-async": "*", + "react-loadable": "npm:@docusaurus/react-loadable@6.0.0" }, - "engines": { - "node": ">=18 <21" + "peerDependencies": { + "react": "*", + "react-dom": "*" } }, - "node_modules/@bitgo/sdk-coin-bera": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-bera/-/sdk-coin-bera-2.3.4.tgz", - "integrity": "sha512-mBsyYT1YAWhyD2zYAF/Ta+xgmecanx6GLx/OT14W4V0uZOmtxQMtc4kh3qFi7ZpxMu+A7zsBJe7V/rnI0OWgEw==", - "license": "MIT", + "node_modules/@docusaurus/module-type-aliases/node_modules/@docusaurus/types": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", + "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", "dependencies": { - "@bitgo/abstract-eth": "^22.4.10", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/statics": "^50.20.0", - "@bitgo/utxo-lib": "^11.2.1", - "@ethereumjs/common": "^2.6.5" - }, - "engines": { - "node": ">=18 <21" - } - }, - "node_modules/@bitgo/sdk-coin-bera/node_modules/@ethereumjs/common": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", - "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", - "license": "MIT", - "dependencies": { - "crc-32": "^1.2.0", - "ethereumjs-util": "^7.1.5" - } - }, - "node_modules/@bitgo/sdk-coin-bld": { - "version": "3.0.29", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-bld/-/sdk-coin-bld-3.0.29.tgz", - "integrity": "sha512-ZJsw2beH5FWc8XuCFM818R7AnnctJlyCTE/6GUIavL4TR0o4uDTguPCfiRz5cF2RCxtW7zE0EJoOjPPlCloI+Q==", - "license": "MIT", - "dependencies": { - "@bitgo/abstract-cosmos": "^11.2.16", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/sdk-lib-mpc": "^10.1.0", - "@bitgo/statics": "^50.20.0", - "@cosmjs/amino": "^0.29.5", - "@cosmjs/encoding": "^0.29.5", - "@cosmjs/stargate": "^0.29.5", - "bignumber.js": "^9.1.1" + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "^1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1", + "webpack-merge": "^5.9.0" }, - "engines": { - "node": ">=18 <21" + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "node_modules/@bitgo/sdk-coin-bsc": { - "version": "22.2.13", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-bsc/-/sdk-coin-bsc-22.2.13.tgz", - "integrity": "sha512-+w/AnrROqBXR4ip9xsPLttAkYxcuA2cHb4dVBo/WOSumA/FkizhCzPn3EZ3ryNZU5PEfz0xJ6HnoECz5QocMyQ==", - "license": "MIT", + "node_modules/@docusaurus/plugin-content-blog": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.4.0.tgz", + "integrity": "sha512-vv6ZAj78ibR5Jh7XBUT4ndIjmlAxkijM3Sx5MAAzC1gyv0vupDQNhzuFg1USQmQVj3P5I6bquk12etPV3LJ+Xw==", "dependencies": { - "@bitgo/abstract-eth": "^22.4.10", - "@bitgo/sdk-coin-eth": "^24.2.49", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/statics": "^50.20.0", - "@ethereumjs/common": "^2.6.5" + "@docusaurus/core": "3.4.0", + "@docusaurus/logger": "3.4.0", + "@docusaurus/mdx-loader": "3.4.0", + "@docusaurus/types": "3.4.0", + "@docusaurus/utils": "3.4.0", + "@docusaurus/utils-common": "3.4.0", + "@docusaurus/utils-validation": "3.4.0", + "cheerio": "^1.0.0-rc.12", + "feed": "^4.2.2", + "fs-extra": "^11.1.1", + "lodash": "^4.17.21", + "reading-time": "^1.5.0", + "srcset": "^4.0.0", + "tslib": "^2.6.0", + "unist-util-visit": "^5.0.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" }, "engines": { - "node": ">=18 <21" - } - }, - "node_modules/@bitgo/sdk-coin-bsc/node_modules/@ethereumjs/common": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", - "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", - "license": "MIT", - "dependencies": { - "crc-32": "^1.2.0", - "ethereumjs-util": "^7.1.5" - } - }, - "node_modules/@bitgo/sdk-coin-bsv": { - "version": "2.1.10", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-bsv/-/sdk-coin-bsv-2.1.10.tgz", - "integrity": "sha512-Jo4II1N7IJsn2RnA6QE1lPLyVDIu7M/ev+0Tge4VAFoOOJGnz0VRomP06Bjn82WW6oaGridFAy+/7oJQNfSw2A==", - "license": "MIT", - "dependencies": { - "@bitgo/abstract-utxo": "^9.12.0", - "@bitgo/sdk-coin-bch": "^2.1.10", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/utxo-lib": "^11.2.1" + "node": ">=18.0" }, - "engines": { - "node": ">=18 <21" + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "node_modules/@bitgo/sdk-coin-btc": { - "version": "2.4.10", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-btc/-/sdk-coin-btc-2.4.10.tgz", - "integrity": "sha512-trO8txafVN2CUXrMP9qHjAgX5BDxcJXTDg4gknyD8mucK9y2Bbqd7hTZZEEATTl9jdwFTNKNQZ1k7QQhxmSpFQ==", - "license": "MIT", + "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/types": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", + "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", "dependencies": { - "@bitgo/abstract-utxo": "^9.12.0", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/utxo-lib": "^11.2.1", - "@bitgo/utxo-ord": "^1.20.65" + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "^1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1", + "webpack-merge": "^5.9.0" }, - "engines": { - "node": ">=18 <21" + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "node_modules/@bitgo/sdk-coin-btg": { - "version": "2.1.10", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-btg/-/sdk-coin-btg-2.1.10.tgz", - "integrity": "sha512-TWDberjOACQCopSGklaIuqfBGaznOl13ZQgCvMtPdb2zXvLSplrPBrJDjjqneVPSfvbH81dNqIcV3fM7ExBMEQ==", - "license": "MIT", + "node_modules/@docusaurus/plugin-content-docs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.4.0.tgz", + "integrity": "sha512-HkUCZffhBo7ocYheD9oZvMcDloRnGhBMOZRyVcAQRFmZPmNqSyISlXA1tQCIxW+r478fty97XXAGjNYzBjpCsg==", "dependencies": { - "@bitgo/abstract-utxo": "^9.12.0", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/utxo-lib": "^11.2.1" + "@docusaurus/core": "3.4.0", + "@docusaurus/logger": "3.4.0", + "@docusaurus/mdx-loader": "3.4.0", + "@docusaurus/module-type-aliases": "3.4.0", + "@docusaurus/types": "3.4.0", + "@docusaurus/utils": "3.4.0", + "@docusaurus/utils-common": "3.4.0", + "@docusaurus/utils-validation": "3.4.0", + "@types/react-router-config": "^5.0.7", + "combine-promises": "^1.1.0", + "fs-extra": "^11.1.1", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "tslib": "^2.6.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" }, "engines": { - "node": ">=18 <21" - } - }, - "node_modules/@bitgo/sdk-coin-celo": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-celo/-/sdk-coin-celo-4.0.11.tgz", - "integrity": "sha512-nh3TfQpM1kCcm7RF24+kXjCzSOKSZrqpazeybrwjQCG3Mnuc8wypx0MXpVibqkWf6B30qJxsMya7IIsI+f1t2g==", - "license": "MIT", - "dependencies": { - "@bitgo/abstract-eth": "^22.4.10", - "@bitgo/sdk-coin-eth": "^24.2.49", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/statics": "^50.20.0", - "@celo/connect": "^2.0.0", - "@celo/contractkit": "^2.0.0", - "@celo/wallet-base": "^2.0.0", - "@celo/wallet-local": "^2.0.0", - "@ethereumjs/common": "^2.6.5", - "bignumber.js": "^9.0.0", - "ethereumjs-abi": "^0.6.5", - "ethereumjs-util": "7.1.5", - "ethers": "^5.1.3" + "node": ">=18.0" }, - "engines": { - "node": ">=18 <21" + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "node_modules/@bitgo/sdk-coin-celo/node_modules/@ethereumjs/common": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", - "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", - "license": "MIT", + "node_modules/@docusaurus/plugin-content-docs/node_modules/@docusaurus/types": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", + "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", "dependencies": { - "crc-32": "^1.2.0", - "ethereumjs-util": "^7.1.5" + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "^1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "node_modules/@bitgo/sdk-coin-coredao": { - "version": "1.2.12", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-coredao/-/sdk-coin-coredao-1.2.12.tgz", - "integrity": "sha512-hGON3B/2Xkadq8DpOgMXUbPGe2yslWeAxX3ZtyKpSHa/zHywL11vgA5bblq2AFBYeaGoP9woJvdlrSoyRGypHQ==", - "license": "MIT", + "node_modules/@docusaurus/plugin-content-pages": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.4.0.tgz", + "integrity": "sha512-h2+VN/0JjpR8fIkDEAoadNjfR3oLzB+v1qSXbIAKjQ46JAHx3X22n9nqS+BWSQnTnp1AjkjSvZyJMekmcwxzxg==", "dependencies": { - "@bitgo/abstract-eth": "^22.4.10", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/statics": "^50.20.0", - "@ethereumjs/common": "^2.6.5" + "@docusaurus/core": "3.4.0", + "@docusaurus/mdx-loader": "3.4.0", + "@docusaurus/types": "3.4.0", + "@docusaurus/utils": "3.4.0", + "@docusaurus/utils-validation": "3.4.0", + "fs-extra": "^11.1.1", + "tslib": "^2.6.0", + "webpack": "^5.88.1" }, "engines": { - "node": ">=18 <21" - } - }, - "node_modules/@bitgo/sdk-coin-coredao/node_modules/@ethereumjs/common": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", - "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", - "license": "MIT", - "dependencies": { - "crc-32": "^1.2.0", - "ethereumjs-util": "^7.1.5" + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "node_modules/@bitgo/sdk-coin-coreum": { - "version": "21.0.29", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-coreum/-/sdk-coin-coreum-21.0.29.tgz", - "integrity": "sha512-8l4peds9CcFzuhD5WjKxIU/0niFLPTQUq5G2izRRLZuCD1Kh1TlJslROp1GnfzR+U3EgSdr5JIpKmO8WIuDrQw==", - "license": "MIT", + "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/types": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", + "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", "dependencies": { - "@bitgo/abstract-cosmos": "^11.2.16", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/sdk-lib-mpc": "^10.1.0", - "@bitgo/statics": "^50.20.0", - "@cosmjs/amino": "^0.29.5", - "@cosmjs/encoding": "^0.29.5", - "@cosmjs/stargate": "^0.29.5", - "bignumber.js": "^9.1.1" + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "^1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1", + "webpack-merge": "^5.9.0" }, - "engines": { - "node": ">=18 <21" + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "node_modules/@bitgo/sdk-coin-cspr": { - "version": "2.0.60", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-cspr/-/sdk-coin-cspr-2.0.60.tgz", - "integrity": "sha512-v9xWUgdWGdlEIcLwCjWy3ovKWYHnmgpSyebeaeAsUYjomWSoYM97r2DSByZt37fUs1WUnnmFNeffZNF+/H6olA==", - "license": "MIT", + "node_modules/@docusaurus/plugin-debug": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.4.0.tgz", + "integrity": "sha512-uV7FDUNXGyDSD3PwUaf5YijX91T5/H9SX4ErEcshzwgzWwBtK37nUWPU3ZLJfeTavX3fycTOqk9TglpOLaWkCg==", "dependencies": { - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/statics": "^50.20.0", - "@bitgo/utxo-lib": "^11.2.1", - "@ethersproject/bignumber": "^5.6.0", - "@stablelib/hex": "^1.0.0", - "bignumber.js": "^9.0.0", - "casper-js-sdk": "2.7.6", - "lodash": "^4.17.15", - "secp256k1": "5.0.1" + "@docusaurus/core": "3.4.0", + "@docusaurus/types": "3.4.0", + "@docusaurus/utils": "3.4.0", + "fs-extra": "^11.1.1", + "react-json-view-lite": "^1.2.0", + "tslib": "^2.6.0" }, "engines": { - "node": ">=18 <21" + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "node_modules/@bitgo/sdk-coin-dash": { - "version": "2.1.10", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-dash/-/sdk-coin-dash-2.1.10.tgz", - "integrity": "sha512-Tnub50BNpLU1dja3iYr8YEYx5bRKHjRykiumoRTI2vXsk39kXJFWJhBbUeMuViCwlt+b7jDgT9uzaQu4ihrVOQ==", - "license": "MIT", + "node_modules/@docusaurus/plugin-debug/node_modules/@docusaurus/types": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", + "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", "dependencies": { - "@bitgo/abstract-utxo": "^9.12.0", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/utxo-lib": "^11.2.1" + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "^1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1", + "webpack-merge": "^5.9.0" }, - "engines": { - "node": ">=18 <21" + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "node_modules/@bitgo/sdk-coin-doge": { - "version": "2.1.10", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-doge/-/sdk-coin-doge-2.1.10.tgz", - "integrity": "sha512-xwizHhFd9hPu2BiOTHj8n9pvmaUMgE8moIxV61BGjXvQrNni0ALfxefp+Iikmw1wjfzLnEfpgyjOOnCMqYVfYA==", - "license": "MIT", + "node_modules/@docusaurus/plugin-google-analytics": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.4.0.tgz", + "integrity": "sha512-mCArluxEGi3cmYHqsgpGGt3IyLCrFBxPsxNZ56Mpur0xSlInnIHoeLDH7FvVVcPJRPSQ9/MfRqLsainRw+BojA==", "dependencies": { - "@bitgo/abstract-utxo": "^9.12.0", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/utxo-lib": "^11.2.1" + "@docusaurus/core": "3.4.0", + "@docusaurus/types": "3.4.0", + "@docusaurus/utils-validation": "3.4.0", + "tslib": "^2.6.0" }, "engines": { - "node": ">=18 <21" + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "node_modules/@bitgo/sdk-coin-dot": { - "version": "4.1.38", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-dot/-/sdk-coin-dot-4.1.38.tgz", - "integrity": "sha512-2/HY3dMDrCffLpFRmEdItY3/a9uPNXA/MghpGr25Lzkk2ooQVAP3yLAiTJM9Kj7JnxukY62FFFDiYAKZ72IVhg==", - "license": "MIT", - "dependencies": { - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/sdk-lib-mpc": "^10.1.0", - "@bitgo/statics": "^50.20.0", - "@polkadot/api": "14.1.1", - "@polkadot/api-augment": "14.1.1", - "@polkadot/keyring": "13.2.3", - "@polkadot/types": "14.1.1", - "@polkadot/util": "13.2.3", - "@polkadot/util-crypto": "13.2.3", - "@substrate/txwrapper-core": "7.5.2", - "@substrate/txwrapper-polkadot": "7.5.2", - "bignumber.js": "^9.0.0", - "bs58": "^4.0.1", - "hi-base32": "^0.5.1", - "joi": "^17.4.0", - "lodash": "^4.17.15", - "tweetnacl": "^1.0.3" - }, - "engines": { - "node": ">=18 <21" - } - }, - "node_modules/@bitgo/sdk-coin-eos": { - "version": "2.1.53", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-eos/-/sdk-coin-eos-2.1.53.tgz", - "integrity": "sha512-8ePzNgvE3rwNnJ/E5boXC9FwNTfkb2gJrdgCpPMas3DVqX51FwGfBS5izadAiZuG0KUSBDXDuoPjzUWCVoCHJw==", - "license": "MIT", + "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/types": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", + "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", "dependencies": { - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/statics": "^50.20.0", - "@bitgo/utxo-lib": "^11.2.1", - "bignumber.js": "^9.0.2", - "eosjs": "^21.0.2", - "eosjs-ecc": "^4.0.4", - "lodash": "^4.17.14", - "superagent": "^9.0.1" + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "^1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1", + "webpack-merge": "^5.9.0" }, - "engines": { - "node": ">=18 <21" + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "node_modules/@bitgo/sdk-coin-etc": { - "version": "2.2.27", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-etc/-/sdk-coin-etc-2.2.27.tgz", - "integrity": "sha512-ZyHbxRQk/yHRj/s4uVsVqCImAY+AyB/t9MFZcj4gzPx4fsKlqGWZVWHbGkh3j1umD6v+AbXaOBctJTAuQWs7Jw==", - "license": "MIT", + "node_modules/@docusaurus/plugin-google-gtag": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.4.0.tgz", + "integrity": "sha512-Dsgg6PLAqzZw5wZ4QjUYc8Z2KqJqXxHxq3vIoyoBWiLEEfigIs7wHR+oiWUQy3Zk9MIk6JTYj7tMoQU0Jm3nqA==", "dependencies": { - "@bitgo/abstract-eth": "^22.4.10", - "@bitgo/sdk-coin-eth": "^24.2.49", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/statics": "^50.20.0", - "@bitgo/utxo-lib": "^11.2.1", - "@ethereumjs/common": "^2.6.5", - "bignumber.js": "^9.1.1", - "ethereumjs-abi": "^0.6.5", - "ethereumjs-util": "7.1.5", - "lodash": "^4.17.14", - "superagent": "^9.0.1" + "@docusaurus/core": "3.4.0", + "@docusaurus/types": "3.4.0", + "@docusaurus/utils-validation": "3.4.0", + "@types/gtag.js": "^0.0.12", + "tslib": "^2.6.0" }, "engines": { - "node": ">=18 <21" + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "node_modules/@bitgo/sdk-coin-etc/node_modules/@ethereumjs/common": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", - "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", - "license": "MIT", + "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/types": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", + "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", "dependencies": { - "crc-32": "^1.2.0", - "ethereumjs-util": "^7.1.5" + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "^1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "node_modules/@bitgo/sdk-coin-eth": { - "version": "24.2.49", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-eth/-/sdk-coin-eth-24.2.49.tgz", - "integrity": "sha512-NYKm57BZy+Y4rGh2lsrZy0373rpGYV8Sh1jVkeq4Xj9vh/hdWqmekFjoTNcY0uST/DdLD982sOtZm4u2CVlTlg==", - "license": "MIT", + "node_modules/@docusaurus/plugin-google-tag-manager": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.4.0.tgz", + "integrity": "sha512-O9tX1BTwxIhgXpOLpFDueYA9DWk69WCbDRrjYoMQtFHSkTyE7RhNgyjSPREUWJb9i+YUg3OrsvrBYRl64FCPCQ==", "dependencies": { - "@bitgo/abstract-eth": "^22.4.10", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/statics": "^50.20.0", - "@bitgo/utxo-lib": "^11.2.1", - "@ethereumjs/tx": "^3.3.0", - "@ethereumjs/util": "8.0.3", - "bignumber.js": "^9.1.1", - "ethereumjs-abi": "^0.6.5", - "ethereumjs-util": "7.1.5", - "ethers": "^5.1.3", - "lodash": "^4.17.14", - "secp256k1": "5.0.1", - "superagent": "^9.0.1" + "@docusaurus/core": "3.4.0", + "@docusaurus/types": "3.4.0", + "@docusaurus/utils-validation": "3.4.0", + "tslib": "^2.6.0" }, "engines": { - "node": ">=18 <21" - } - }, - "node_modules/@bitgo/sdk-coin-eth/node_modules/@ethereumjs/common": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", - "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", - "license": "MIT", - "dependencies": { - "crc-32": "^1.2.0", - "ethereumjs-util": "^7.1.5" + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "node_modules/@bitgo/sdk-coin-eth/node_modules/@ethereumjs/tx": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.5.2.tgz", - "integrity": "sha512-gQDNJWKrSDGu2w7w0PzVXVBNMzb7wwdDOmOqczmhNjqFxFuIbhVJDwiGEnxFNC2/b8ifcZzY7MLcluizohRzNw==", - "license": "MPL-2.0", + "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/types": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", + "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", "dependencies": { - "@ethereumjs/common": "^2.6.4", - "ethereumjs-util": "^7.1.5" + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "^1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "node_modules/@bitgo/sdk-coin-eth/node_modules/@ethereumjs/util": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/@ethereumjs/util/-/util-8.0.3.tgz", - "integrity": "sha512-0apCbwc8xAaie6W7q6QyogfyRS2BMU816a8KwpnpRw9Qrc6Bws+l7J3LfCLMt2iL6Wi8CYb0B29AeIr2N4vHnw==", - "license": "MPL-2.0", + "node_modules/@docusaurus/plugin-sitemap": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.4.0.tgz", + "integrity": "sha512-+0VDvx9SmNrFNgwPoeoCha+tRoAjopwT0+pYO1xAbyLcewXSemq+eLxEa46Q1/aoOaJQ0qqHELuQM7iS2gp33Q==", "dependencies": { - "@ethereumjs/rlp": "^4.0.0-beta.2", - "async": "^3.2.4", - "ethereum-cryptography": "^1.1.2" + "@docusaurus/core": "3.4.0", + "@docusaurus/logger": "3.4.0", + "@docusaurus/types": "3.4.0", + "@docusaurus/utils": "3.4.0", + "@docusaurus/utils-common": "3.4.0", + "@docusaurus/utils-validation": "3.4.0", + "fs-extra": "^11.1.1", + "sitemap": "^7.1.1", + "tslib": "^2.6.0" }, "engines": { - "node": ">=14" - } - }, - "node_modules/@bitgo/sdk-coin-eth/node_modules/@noble/hashes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz", - "integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "license": "MIT" - }, - "node_modules/@bitgo/sdk-coin-eth/node_modules/@noble/secp256k1": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz", - "integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "license": "MIT" - }, - "node_modules/@bitgo/sdk-coin-eth/node_modules/@scure/bip32": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.1.5.tgz", - "integrity": "sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "license": "MIT", - "dependencies": { - "@noble/hashes": "~1.2.0", - "@noble/secp256k1": "~1.7.0", - "@scure/base": "~1.1.0" - } - }, - "node_modules/@bitgo/sdk-coin-eth/node_modules/@scure/bip39": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.1.tgz", - "integrity": "sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "license": "MIT", - "dependencies": { - "@noble/hashes": "~1.2.0", - "@scure/base": "~1.1.0" - } - }, - "node_modules/@bitgo/sdk-coin-eth/node_modules/ethereum-cryptography": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz", - "integrity": "sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "1.2.0", - "@noble/secp256k1": "1.7.1", - "@scure/bip32": "1.1.5", - "@scure/bip39": "1.1.1" + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "node_modules/@bitgo/sdk-coin-eth2": { - "version": "3.0.59", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-eth2/-/sdk-coin-eth2-3.0.59.tgz", - "integrity": "sha512-5JtW6sjb10iOE8T5JERFDOv6WH5vRgfjW126bmI8bUowPrddqPRwMco4Pcu71+3/Z6lcHPLzIy3hvTaOC7mFrg==", - "license": "MIT", + "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/types": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", + "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", "dependencies": { - "@bitgo/sdk-core": "^28.20.0", - "bignumber.js": "^9.1.1", - "ethereumjs-util": "7.1.5", - "lodash": "^4.17.14", - "superagent": "^9.0.1" + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "^1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1", + "webpack-merge": "^5.9.0" }, - "engines": { - "node": ">=18 <21" + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "node_modules/@bitgo/sdk-coin-ethlike": { - "version": "1.1.41", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-ethlike/-/sdk-coin-ethlike-1.1.41.tgz", - "integrity": "sha512-vEorAiVpmwi6QThcmhkoFs4dJkg81cyQUm45AP1yLT8RZ7x9ZSPVoJJUbA6lKjCo3GVyhtt7h5M6UVJ/ekahdg==", - "license": "MIT", + "node_modules/@docusaurus/preset-classic": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.4.0.tgz", + "integrity": "sha512-Ohj6KB7siKqZaQhNJVMBBUzT3Nnp6eTKqO+FXO3qu/n1hJl3YLwVKTWBg28LF7MWrKu46UuYavwMRxud0VyqHg==", "dependencies": { - "@bitgo/abstract-eth": "^22.4.10", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/statics": "^50.20.0", - "@ethereumjs/common": "2.6.5", - "ethereumjs-util": "7.1.5" + "@docusaurus/core": "3.4.0", + "@docusaurus/plugin-content-blog": "3.4.0", + "@docusaurus/plugin-content-docs": "3.4.0", + "@docusaurus/plugin-content-pages": "3.4.0", + "@docusaurus/plugin-debug": "3.4.0", + "@docusaurus/plugin-google-analytics": "3.4.0", + "@docusaurus/plugin-google-gtag": "3.4.0", + "@docusaurus/plugin-google-tag-manager": "3.4.0", + "@docusaurus/plugin-sitemap": "3.4.0", + "@docusaurus/theme-classic": "3.4.0", + "@docusaurus/theme-common": "3.4.0", + "@docusaurus/theme-search-algolia": "3.4.0", + "@docusaurus/types": "3.4.0" }, "engines": { - "node": ">=18 <21" + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "node_modules/@bitgo/sdk-coin-ethlike/node_modules/@ethereumjs/common": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", - "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", - "license": "MIT", + "node_modules/@docusaurus/preset-classic/node_modules/@docusaurus/types": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", + "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", "dependencies": { - "crc-32": "^1.2.0", - "ethereumjs-util": "^7.1.5" + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "^1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "node_modules/@bitgo/sdk-coin-ethw": { - "version": "20.0.60", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-ethw/-/sdk-coin-ethw-20.0.60.tgz", - "integrity": "sha512-RT/5rKahckwhKGsLbDXOqtQkEx/ax+lxFl5hjgN6ymqim72z+l3xFdMdndPby9CJT3byaavnuKKH9i+v5A7vKw==", - "license": "MIT", + "node_modules/@docusaurus/theme-classic": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.4.0.tgz", + "integrity": "sha512-0IPtmxsBYv2adr1GnZRdMkEQt1YW6tpzrUPj02YxNpvJ5+ju4E13J5tB4nfdaen/tfR1hmpSPlTFPvTf4kwy8Q==", "dependencies": { - "@bitgo/sdk-coin-eth": "^24.2.49", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/statics": "^50.20.0", - "ethereumjs-util": "7.1.5", - "superagent": "^9.0.1" + "@docusaurus/core": "3.4.0", + "@docusaurus/mdx-loader": "3.4.0", + "@docusaurus/module-type-aliases": "3.4.0", + "@docusaurus/plugin-content-blog": "3.4.0", + "@docusaurus/plugin-content-docs": "3.4.0", + "@docusaurus/plugin-content-pages": "3.4.0", + "@docusaurus/theme-common": "3.4.0", + "@docusaurus/theme-translations": "3.4.0", + "@docusaurus/types": "3.4.0", + "@docusaurus/utils": "3.4.0", + "@docusaurus/utils-common": "3.4.0", + "@docusaurus/utils-validation": "3.4.0", + "@mdx-js/react": "^3.0.0", + "clsx": "^2.0.0", + "copy-text-to-clipboard": "^3.2.0", + "infima": "0.2.0-alpha.43", + "lodash": "^4.17.21", + "nprogress": "^0.2.0", + "postcss": "^8.4.26", + "prism-react-renderer": "^2.3.0", + "prismjs": "^1.29.0", + "react-router-dom": "^5.3.4", + "rtlcss": "^4.1.0", + "tslib": "^2.6.0", + "utility-types": "^3.10.0" }, "engines": { - "node": ">=18 <21" + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "node_modules/@bitgo/sdk-coin-hash": { - "version": "3.0.29", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-hash/-/sdk-coin-hash-3.0.29.tgz", - "integrity": "sha512-mQ6H4BS86A834RjzQ0lP7xJ84SbRstbOky7K0t9Y/KpUyJn3BPzvgryti57knhCyd0sdiJ0pI9X4osjqncMIvQ==", - "license": "MIT", + "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/types": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", + "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", "dependencies": { - "@bitgo/abstract-cosmos": "^11.2.16", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/sdk-lib-mpc": "^10.1.0", - "@bitgo/statics": "^50.20.0", - "@cosmjs/amino": "^0.29.5", - "@cosmjs/encoding": "^0.29.5", - "@cosmjs/stargate": "^0.29.5", - "bignumber.js": "^9.1.1" + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "^1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1", + "webpack-merge": "^5.9.0" }, - "engines": { - "node": ">=18 <21" + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "node_modules/@bitgo/sdk-coin-hbar": { - "version": "2.0.60", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-hbar/-/sdk-coin-hbar-2.0.60.tgz", - "integrity": "sha512-EpI4pEhzuFJIwTJaqSVa+WCK7Wmk9zPWw5OM0mAXW+txO8vEOS4l9ZRgkUPMemtHAphzJAi0P/5PG1t0QxeVsQ==", - "license": "MIT", + "node_modules/@docusaurus/theme-common": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.4.0.tgz", + "integrity": "sha512-0A27alXuv7ZdCg28oPE8nH/Iz73/IUejVaCazqu9elS4ypjiLhK3KfzdSQBnL/g7YfHSlymZKdiOHEo8fJ0qMA==", "dependencies": { - "@bitgo/sdk-coin-algo": "^2.1.58", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/statics": "^50.20.0", - "@hashgraph/proto": "2.12.0", - "@hashgraph/sdk": "2.29.0", - "@stablelib/sha384": "^1.0.0", - "bignumber.js": "^9.0.0", - "lodash": "^4.17.15", - "long": "^4.0.0", - "protobufjs": "7.2.5", - "stellar-sdk": "^10.0.1", - "tweetnacl": "^1.0.3" + "@docusaurus/mdx-loader": "3.4.0", + "@docusaurus/module-type-aliases": "3.4.0", + "@docusaurus/plugin-content-blog": "3.4.0", + "@docusaurus/plugin-content-docs": "3.4.0", + "@docusaurus/plugin-content-pages": "3.4.0", + "@docusaurus/utils": "3.4.0", + "@docusaurus/utils-common": "3.4.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router-config": "*", + "clsx": "^2.0.0", + "parse-numeric-range": "^1.3.0", + "prism-react-renderer": "^2.3.0", + "tslib": "^2.6.0", + "utility-types": "^3.10.0" }, "engines": { - "node": ">=18 <21" + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/@expo/config": { - "version": "6.0.26", - "resolved": "https://registry.npmjs.org/@expo/config/-/config-6.0.26.tgz", - "integrity": "sha512-nMQaZl69r6CMJFhCj0xcGJN9bIi4Uws0k9K6q6rGFPFNarS0z0aexeyNLv93/J+hsTJVn0GEYtGz5Y/R8boXxw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@babel/code-frame": "~7.10.4", - "@expo/config-plugins": "4.1.5", - "@expo/config-types": "^45.0.0", - "@expo/json-file": "8.2.36", - "getenv": "^1.0.0", - "glob": "7.1.6", - "require-from-string": "^2.0.2", - "resolve-from": "^5.0.0", - "semver": "7.3.2", - "slugify": "^1.3.4", - "sucrase": "^3.20.0" - } - }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/@expo/config-plugins": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-4.1.5.tgz", - "integrity": "sha512-RVvU40RtZt12HavuDAe+LDIq9lHj7sheOfMEHdmpJ/uTA8pgvkbc56XF6JHQD+yRr6+uhhb+JnAasGq49dsQbw==", - "license": "MIT", - "optional": true, - "peer": true, + "node_modules/@docusaurus/theme-search-algolia": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.4.0.tgz", + "integrity": "sha512-aiHFx7OCw4Wck1z6IoShVdUWIjntC8FHCw9c5dR8r3q4Ynh+zkS8y2eFFunN/DL6RXPzpnvKCg3vhLQYJDmT9Q==", "dependencies": { - "@expo/config-types": "^45.0.0", - "@expo/json-file": "8.2.36", - "@expo/plist": "0.0.18", - "@expo/sdk-runtime-versions": "^1.0.0", - "@react-native/normalize-color": "^2.0.0", - "chalk": "^4.1.2", - "debug": "^4.3.1", - "find-up": "~5.0.0", - "getenv": "^1.0.0", - "glob": "7.1.6", - "resolve-from": "^5.0.0", - "semver": "^7.3.5", - "slash": "^3.0.0", - "xcode": "^3.0.1", - "xml2js": "0.4.23" - } - }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/@expo/config-plugins/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "semver": "bin/semver.js" + "@docsearch/react": "^3.5.2", + "@docusaurus/core": "3.4.0", + "@docusaurus/logger": "3.4.0", + "@docusaurus/plugin-content-docs": "3.4.0", + "@docusaurus/theme-common": "3.4.0", + "@docusaurus/theme-translations": "3.4.0", + "@docusaurus/utils": "3.4.0", + "@docusaurus/utils-validation": "3.4.0", + "algoliasearch": "^4.18.0", + "algoliasearch-helper": "^3.13.3", + "clsx": "^2.0.0", + "eta": "^2.2.0", + "fs-extra": "^11.1.1", + "lodash": "^4.17.21", + "tslib": "^2.6.0", + "utility-types": "^3.10.0" }, "engines": { - "node": ">=10" - } - }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/@expo/config-types": { - "version": "45.0.0", - "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-45.0.0.tgz", - "integrity": "sha512-/QGhhLWyaGautgEyU50UJr5YqKJix5t77ePTwreOVAhmZH+ff3nrrtYTTnccx+qF08ZNQmfAyYMCD3rQfzpiJA==", - "license": "MIT", - "optional": true, - "peer": true - }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/@expo/config/node_modules/semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "semver": "bin/semver.js" + "node": ">=18.0" }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/@expo/json-file": { - "version": "8.2.36", - "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-8.2.36.tgz", - "integrity": "sha512-tOZfTiIFA5KmMpdW9KF7bc6CFiGjb0xnbieJhTGlHrLL+ps2G0OkqmuZ3pFEXBOMnJYUVpnSy++52LFxvpa5ZQ==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@babel/code-frame": "~7.10.4", - "json5": "^1.0.1", - "write-file-atomic": "^2.3.0" + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/@expo/plist": { - "version": "0.0.18", - "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.0.18.tgz", - "integrity": "sha512-+48gRqUiz65R21CZ/IXa7RNBXgAI/uPSdvJqoN9x1hfL44DNbUoWHgHiEXTx7XelcATpDwNTz6sHLfy0iNqf+w==", - "license": "MIT", - "optional": true, - "peer": true, + "node_modules/@docusaurus/theme-translations": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.4.0.tgz", + "integrity": "sha512-zSxCSpmQCCdQU5Q4CnX/ID8CSUUI3fvmq4hU/GNP/XoAWtXo9SAVnM3TzpU8Gb//H3WCsT8mJcTfyOk3d9ftNg==", "dependencies": { - "@xmldom/xmldom": "~0.7.0", - "base64-js": "^1.2.3", - "xmlbuilder": "^14.0.0" + "fs-extra": "^11.1.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/@expo/vector-icons": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/@expo/vector-icons/-/vector-icons-13.0.0.tgz", - "integrity": "sha512-TI+l71+5aSKnShYclFa14Kum+hQMZ86b95SH6tQUG3qZEmLTarvWpKwqtTwQKqvlJSJrpFiSFu3eCuZokY6zWA==", - "license": "MIT", - "optional": true, - "peer": true + "node_modules/@docusaurus/tsconfig": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/tsconfig/-/tsconfig-3.5.2.tgz", + "integrity": "sha512-rQ7toURCFnWAIn8ubcquDs0ewhPwviMzxh6WpRjBW7sJVCXb6yzwUaY3HMNa0VXCFw+qkIbFywrMTf+Pb4uHWQ==", + "dev": true }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/@grpc/grpc-js": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.8.2.tgz", - "integrity": "sha512-5cqCjUvDKJWHGeu1prlrFOUmjuML0NequZKJ38PsCkfwIqPnZq4Q9burPP3It7/+46wpl0KsqVN3s6Te3B9Qtw==", - "license": "Apache-2.0", + "node_modules/@docusaurus/types": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.1.0.tgz", + "integrity": "sha512-VaczOZf7+re8aFBIWnex1XENomwHdsSTkrdX43zyor7G/FY4OIsP6X28Xc3o0jiY0YdNuvIDyA5TNwOtpgkCVw==", + "devOptional": true, "dependencies": { - "@grpc/proto-loader": "^0.7.0", - "@types/node": ">=12.12.47" + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "^1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1", + "webpack-merge": "^5.9.0" }, - "engines": { - "node": "^8.13.0 || >=10.10.0" + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/@hashgraph/cryptography": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/@hashgraph/cryptography/-/cryptography-1.4.6.tgz", - "integrity": "sha512-3HmnT1Lek71l6nHxc4GOyT/hSx/LmgusyWfE7hQda2dnE5vL2umydDw5TK2wq8gqmD9S3uRSMhz/BO55wtzxRA==", - "license": "Apache-2.0", + "node_modules/@docusaurus/utils": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.4.0.tgz", + "integrity": "sha512-fRwnu3L3nnWaXOgs88BVBmG1yGjcQqZNHG+vInhEa2Sz2oQB+ZjbEMO5Rh9ePFpZ0YDiDUhpaVjwmS+AU2F14g==", "dependencies": { - "bignumber.js": "^9.1.1", - "bn.js": "^5.1.1", - "crypto-js": "^4.1.1", - "elliptic": "^6.5.4", - "js-base64": "^3.7.4", - "tweetnacl": "^1.0.3", - "utf8": "^3.0.0" + "@docusaurus/logger": "3.4.0", + "@docusaurus/utils-common": "3.4.0", + "@svgr/webpack": "^8.1.0", + "escape-string-regexp": "^4.0.0", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "github-slugger": "^1.5.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "jiti": "^1.20.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "micromatch": "^4.0.5", + "prompts": "^2.4.2", + "resolve-pathname": "^3.0.0", + "shelljs": "^0.8.5", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" }, "engines": { - "node": ">=12.0.0" + "node": ">=18.0" }, "peerDependencies": { - "expo": "^45.0.3", - "expo-crypto": "^10.1.2", - "expo-random": "^12.1.2" + "@docusaurus/types": "*" }, "peerDependenciesMeta": { - "expo": { - "optional": true - }, - "expo-crypto": { - "optional": true - }, - "expo-random": { + "@docusaurus/types": { "optional": true } } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/@hashgraph/sdk": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/@hashgraph/sdk/-/sdk-2.29.0.tgz", - "integrity": "sha512-dMv2q7OCa2Xyi0ooGjo4JJRFxHKzKBvMd8G/n30j4jHx1JiSfI2ckPTAOwfCbYZ/o+EMDZzevyD5+Juf9iph+A==", - "license": "Apache-2.0", + "node_modules/@docusaurus/utils-common": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.4.0.tgz", + "integrity": "sha512-NVx54Wr4rCEKsjOH5QEVvxIqVvm+9kh7q8aYTU5WzUU9/Hctd6aTrcZ3G0Id4zYJ+AeaG5K5qHA4CY5Kcm2iyQ==", "dependencies": { - "@ethersproject/abi": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/rlp": "^5.7.0", - "@grpc/grpc-js": "1.8.2", - "@hashgraph/cryptography": "1.4.6", - "@hashgraph/proto": "2.12.0", - "axios": "^1.3.1", - "bignumber.js": "^9.1.1", - "crypto-js": "^4.1.1", - "js-base64": "^3.7.4", - "long": "^4.0.0", - "pino": "^8.14.1", - "pino-pretty": "^10.0.0", - "protobufjs": "^7.1.2", - "utf8": "^3.0.0" + "tslib": "^2.6.0" }, "engines": { - "node": ">=10.17.0" + "node": ">=18.0" }, "peerDependencies": { - "expo": "^45.0.3" + "@docusaurus/types": "*" }, "peerDependenciesMeta": { - "expo": { + "@docusaurus/types": { "optional": true } } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/@jest/types": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", - "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", - "license": "MIT", - "optional": true, - "peer": true, + "node_modules/@docusaurus/utils-validation": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.4.0.tgz", + "integrity": "sha512-hYQ9fM+AXYVTWxJOT1EuNaRnrR2WGpRdLDQG07O8UOpsvCPWUVOeo26Rbm0JWY2sGLfzAb+tvJ62yF+8F+TV0g==", "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^15.0.0", - "chalk": "^4.0.0" + "@docusaurus/logger": "3.4.0", + "@docusaurus/utils": "3.4.0", + "@docusaurus/utils-common": "3.4.0", + "fs-extra": "^11.2.0", + "joi": "^17.9.2", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "tslib": "^2.6.0" }, "engines": { - "node": ">= 10.14.2" + "node": ">=18.0" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/@types/yargs": { - "version": "15.0.19", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.19.tgz", - "integrity": "sha512-2XUaGVmyQjgyAZldf0D0c14vvo/yv0MhQBSTJcejMMaitsn3nxCB6TmH4G0ZQf+uxROOa9mpanoSm8h6SG/1ZA==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@types/yargs-parser": "*" + "node_modules/@ecies/ciphers": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@ecies/ciphers/-/ciphers-0.2.1.tgz", + "integrity": "sha512-ezMihhjW24VNK/2qQR7lH8xCQY24nk0XHF/kwJ1OuiiY5iEwQXOcKVSy47fSoHPRG8gVGXcK5SgtONDk5xMwtQ==", + "engines": { + "bun": ">=1", + "deno": ">=2", + "node": ">=16" + }, + "peerDependencies": { + "@noble/ciphers": "^1.0.0" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/babel-preset-expo": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/babel-preset-expo/-/babel-preset-expo-9.1.0.tgz", - "integrity": "sha512-dFcgT7AY5n15bLnfOM6R25f8Lh7YSALj4zeGze6aspYHfVrREYcovVG0eMGpY9V24fnwByNRv85lElc1jAj1Mw==", - "license": "MIT", - "optional": true, - "peer": true, + "node_modules/@emnapi/core": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.2.0.tgz", + "integrity": "sha512-E7Vgw78I93we4ZWdYCb4DGAwRROGkMIXk7/y87UmANR+J6qsWusmC3gLt0H+O0KOt5e6O38U8oJamgbudrES/w==", + "dev": true, "dependencies": { - "@babel/plugin-proposal-decorators": "^7.12.9", - "@babel/plugin-transform-react-jsx": "^7.12.17", - "@babel/preset-env": "^7.12.9", - "babel-plugin-module-resolver": "^4.1.0", - "babel-plugin-react-native-web": "~0.17.1", - "metro-react-native-babel-preset": "~0.67.0" + "@emnapi/wasi-threads": "1.0.1", + "tslib": "^2.4.0" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "license": "MIT", - "optional": true, - "peer": true, + "node_modules/@emnapi/runtime": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.2.0.tgz", + "integrity": "sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==", + "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "tslib": "^2.4.0" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", + "node_modules/@emnapi/wasi-threads": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.1.tgz", + "integrity": "sha512-iIBu7mwkq4UQGeMEM8bLwNK962nXdhodeScX4slfQnRhEMMzvYivHhutCIk8uojvmASXXPC2WNEjwxFWk72Oqw==", + "dev": true, "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" + "tslib": "^2.4.0" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "license": "MIT", - "optional": true, - "peer": true, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "devOptional": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, "engines": { - "node": ">= 10" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/compare-versions": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", - "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", - "license": "MIT", - "optional": true, - "peer": true - }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/cross-fetch": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", - "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "node-fetch": "^2.7.0" + "node_modules/@eslint-community/regexpp": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "devOptional": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/cross-spawn": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", - "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", - "license": "MIT", - "optional": true, - "peer": true, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "devOptional": true, "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": ">=4.8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/expo": { - "version": "45.0.8", - "resolved": "https://registry.npmjs.org/expo/-/expo-45.0.8.tgz", - "integrity": "sha512-1dSMiodS7t44+1jijPL6ky1CRR/L2pPhrDoaSDo4WBS9ntEa1hEBhC+qa1Th5VkjqG9qkR73AGRgx4h8ozRvsA==", - "license": "MIT", - "optional": true, - "peer": true, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "devOptional": true, "dependencies": { - "@babel/runtime": "^7.14.0", - "@expo/cli": "0.1.7", - "@expo/vector-icons": "^13.0.0", - "babel-preset-expo": "~9.1.0", - "cross-spawn": "^6.0.5", - "expo-application": "~4.1.0", - "expo-asset": "~8.5.0", - "expo-constants": "~13.1.1", - "expo-file-system": "~14.0.0", - "expo-font": "~10.1.0", - "expo-keep-awake": "~10.1.1", - "expo-modules-autolinking": "0.9.0", - "expo-modules-core": "0.9.2", - "fbemitter": "^3.0.0", - "getenv": "^1.0.0", - "invariant": "^2.2.4", - "md5-file": "^3.2.3", - "node-fetch": "^2.6.7", - "pretty-format": "^26.5.2", - "uuid": "^3.4.0" - }, - "bin": { - "expo": "bin/cli.js" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, - "optionalDependencies": { - "expo-error-recovery": "~3.1.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/expo-application": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/expo-application/-/expo-application-4.1.0.tgz", - "integrity": "sha512-Z2kctgVMpYZB1Iwaxd+XcMBq7h8EEY50GGrwxXsb1OHHQKN+WEVGBWxjvtPkAroqCdujLaB5HBay46gvUHRDQg==", - "license": "MIT", - "optional": true, - "peer": true, - "peerDependencies": { - "expo": "*" + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "devOptional": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/expo-asset": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/expo-asset/-/expo-asset-8.5.0.tgz", - "integrity": "sha512-k3QErZYxb6e6rPkJ1sG5yIJ7bhd4RFvnFStz0ZCO6SfktGygBAjTz5aTOLaaomiCIObRiBQ4byky/RLdli/NLw==", - "license": "MIT", - "optional": true, - "peer": true, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "devOptional": true, "dependencies": { - "blueimp-md5": "^2.10.0", - "invariant": "^2.2.4", - "md5-file": "^3.2.3", - "path-browserify": "^1.0.0", - "url-parse": "^1.5.9" + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/expo-constants": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-13.1.1.tgz", - "integrity": "sha512-QRVHrrMCLenBzWZ8M+EvCXM+jjdQzFMW27YQHRac3SGGoND1hWr81scOmGwlFo2wLZrYXm8HcYt1E6ry3IIwrA==", - "license": "MIT", - "optional": true, - "peer": true, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "devOptional": true + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "devOptional": true, "dependencies": { - "@expo/config": "^6.0.14", - "uuid": "^3.3.2" + "brace-expansion": "^1.1.7" }, - "peerDependencies": { - "expo": "*" + "engines": { + "node": "*" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/expo-error-recovery": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/expo-error-recovery/-/expo-error-recovery-3.1.0.tgz", - "integrity": "sha512-qUxCW7kPB6AVX5h3ZPVnxw4LLZWsRwAPBtRDlh1UDN7GWZ+CQN1SNk0w0BPotjNtSlXEZSFDqKqtoDDAUYjNmg==", - "license": "MIT", - "optional": true, - "peer": true, - "peerDependencies": { - "expo": "*" + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "devOptional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/expo-file-system": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-14.0.0.tgz", - "integrity": "sha512-Asva7ehLUq/PIem6Y+/OQvoIqhFqYDd7l4l49yDRDgLSbK2I7Fr8qGhDeDpnUXrMVamg2uwt9zRGhyrjFNRhVw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@expo/config-plugins": "^4.0.14", - "uuid": "^3.4.0" - }, - "peerDependencies": { - "expo": "*" + "node_modules/@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "devOptional": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/expo-font": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/expo-font/-/expo-font-10.1.0.tgz", - "integrity": "sha512-vmhzpE95Ym4iOj8IELof+C/3Weert2B3LyxV5rBjGosjzBdov+o+S6b5mN7Yc9kyEGykwB6k7npL45X3hFYDQA==", - "license": "MIT", - "optional": true, - "peer": true, + "node_modules/@ethereumjs/common": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-3.2.0.tgz", + "integrity": "sha512-pksvzI0VyLgmuEF2FA/JR/4/y6hcPq8OUail3/AvycBaW1d5VSauOZzqGvJ3RTmR4MU35lWE8KseKOsEhrFRBA==", "dependencies": { - "fontfaceobserver": "^2.1.0" - }, - "peerDependencies": { - "expo": "*" + "@ethereumjs/util": "^8.1.0", + "crc-32": "^1.2.0" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/expo-keep-awake": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-10.1.1.tgz", - "integrity": "sha512-9zC0sdhQljUeMr2yQ7o4kzEZXVAy82fFOAZE1+TwPL7qR0b0sphe7OJ5T1GX1qLcwuVaJ8YewaPoLSHRk79+Rg==", - "license": "MIT", - "optional": true, - "peer": true, - "peerDependencies": { - "expo": "*" + "node_modules/@ethereumjs/rlp": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-4.0.1.tgz", + "integrity": "sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==", + "bin": { + "rlp": "bin/rlp" + }, + "engines": { + "node": ">=14" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/expo-modules-autolinking": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-0.9.0.tgz", - "integrity": "sha512-brczklrHpWood7H2C4MjBfUD85NAyjotEhYs7hnHRtbnVgwwzXeAveDje/19kLaK8W40hvUN0LdBVxkZN3Hw6g==", - "license": "MIT", - "optional": true, - "peer": true, + "node_modules/@ethereumjs/tx": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-4.2.0.tgz", + "integrity": "sha512-1nc6VO4jtFd172BbSnTnDQVr9IYBFl1y4xPzZdtkrkKIncBCkdbgfdRV+MiTkJYAtTxvV12GRZLqBFT1PNK6Yw==", "dependencies": { - "chalk": "^4.1.0", - "commander": "^7.2.0", - "fast-glob": "^3.2.5", - "find-up": "^5.0.0", - "fs-extra": "^9.1.0" + "@ethereumjs/common": "^3.2.0", + "@ethereumjs/rlp": "^4.0.1", + "@ethereumjs/util": "^8.1.0", + "ethereum-cryptography": "^2.0.0" }, - "bin": { - "expo-modules-autolinking": "bin/expo-modules-autolinking.js" + "engines": { + "node": ">=14" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/expo-modules-core": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-0.9.2.tgz", - "integrity": "sha512-p/C0GJxFIIDGwmrWi70Q0ggfsgeUFS25ZkkBgoaHT7MVgiMjlKA/DCC3D6ZUkHl/JlzUm0aTftIGS8LWXsnZBw==", - "license": "MIT", - "optional": true, - "peer": true, + "node_modules/@ethereumjs/util": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@ethereumjs/util/-/util-8.1.0.tgz", + "integrity": "sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==", "dependencies": { - "compare-versions": "^3.4.0", - "invariant": "^2.2.4" + "@ethereumjs/rlp": "^4.0.1", + "ethereum-cryptography": "^2.0.0", + "micro-ftch": "^0.3.1" + }, + "engines": { + "node": ">=14" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/fbemitter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/fbemitter/-/fbemitter-3.0.0.tgz", - "integrity": "sha512-KWKaceCwKQU0+HPoop6gn4eOHk50bBv/VxjJtGMfwmJt3D29JpN4H4eisCtIPA+a8GVBam+ldMMpMjJUvpDyHw==", - "license": "BSD-3-Clause", - "optional": true, - "peer": true, + "node_modules/@faker-js/faker": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-9.0.1.tgz", + "integrity": "sha512-4mDeYIgM3By7X6t5E6eYwLAa+2h4DeZDF7thhzIg6XB76jeEvMwadYAMCFJL/R4AnEBcAUO9+gL0vhy3s+qvZA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/fakerjs" + } + ], + "engines": { + "node": ">=18.0.0", + "npm": ">=9.0.0" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.4.tgz", + "integrity": "sha512-a4IowK4QkXl4SCWTGUR0INAfEOX3wtsYw3rKK5InQEHMGObkR8Xk44qYQD9P4r6HHw0iIfK6GUKECmY8sTkqRA==", "dependencies": { - "fbjs": "^3.0.0" + "@floating-ui/utils": "^0.2.4" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/fbjs": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-3.0.5.tgz", - "integrity": "sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg==", - "license": "MIT", - "optional": true, - "peer": true, + "node_modules/@floating-ui/dom": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.7.tgz", + "integrity": "sha512-wmVfPG5o2xnKDU4jx/m4w5qva9FWHcnZ8BvzEe90D/RpwsJaTAVYPEPdQ8sbr/N8zZTAHlZUTQdqg8ZUbzHmng==", "dependencies": { - "cross-fetch": "^3.1.5", - "fbjs-css-vars": "^1.0.0", - "loose-envify": "^1.0.0", - "object-assign": "^4.1.0", - "promise": "^7.1.1", - "setimmediate": "^1.0.5", - "ua-parser-js": "^1.0.35" + "@floating-ui/core": "^1.6.0", + "@floating-ui/utils": "^0.2.4" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "license": "MIT", - "optional": true, - "peer": true, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.1.tgz", + "integrity": "sha512-4h84MJt3CHrtG18mGsXuLCHMrug49d7DFkU0RMIyshRveBeyV2hmV/pDaF2Uxtu8kgq5r46llp5E5FQiR0K2Yg==", "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" + "@floating-ui/dom": "^1.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } + "node_modules/@floating-ui/utils": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.4.tgz", + "integrity": "sha512-dWO2pw8hhi+WrXq1YJy2yCuWoL20PddgGaqTgVe4cOS9Q6qklXCiA1tJEqX6BEwRNSCP84/afac9hd4MS+zEUA==" }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, + "node_modules/@fortawesome/fontawesome-common-types": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.2.tgz", + "integrity": "sha512-gBxPg3aVO6J0kpfHNILc+NMhXnqHumFxOmjYCFfOiLZfwhnnfhtsdA2hfJlDnj+8PjAs6kKQPenOTKj3Rf7zHw==", + "hasInstallScript": true, "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=6" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "license": "MIT", - "optional": true, - "peer": true, + "node_modules/@fortawesome/fontawesome-svg-core": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.5.2.tgz", + "integrity": "sha512-5CdaCBGl8Rh9ohNdxeeTMxIj8oc3KNBgIeLMvJosBMdslK/UnEB8rzyDRrbKdL1kDweqBPo4GT9wvnakHWucZw==", + "hasInstallScript": true, "dependencies": { - "minimist": "^1.2.0" + "@fortawesome/fontawesome-common-types": "6.5.2" }, - "bin": { - "json5": "lib/cli.js" + "engines": { + "node": ">=6" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "license": "MIT", - "optional": true, - "peer": true, + "node_modules/@fortawesome/free-solid-svg-icons": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.5.2.tgz", + "integrity": "sha512-QWFZYXFE7O1Gr1dTIp+D6UcFUF0qElOnZptpi7PBUMylJh+vFmIedVe1Ir6RM1t2tEQLLSV1k7bR4o92M+uqlw==", + "hasInstallScript": true, "dependencies": { - "p-locate": "^5.0.0" + "@fortawesome/fontawesome-common-types": "6.5.2" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", - "license": "Apache-2.0" - }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/metro-react-native-babel-preset": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.67.0.tgz", - "integrity": "sha512-tgTG4j0SKwLHbLRELMmgkgkjV1biYkWlGGKOmM484/fJC6bpDikdaFhfjsyE+W+qt7I5szbCPCickMTNQ+zwig==", - "license": "MIT", - "optional": true, - "peer": true, + "node_modules/@fortawesome/react-fontawesome": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.2.tgz", + "integrity": "sha512-EnkrprPNqI6SXJl//m29hpaNzOp1bruISWaOiRtkMi/xSvHJlzc2j2JAYS7egxt/EbjSNV/k6Xy0AQI6vB2+1g==", "dependencies": { - "@babel/core": "^7.14.0", - "@babel/plugin-proposal-class-properties": "^7.0.0", - "@babel/plugin-proposal-export-default-from": "^7.0.0", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0", - "@babel/plugin-proposal-object-rest-spread": "^7.0.0", - "@babel/plugin-proposal-optional-catch-binding": "^7.0.0", - "@babel/plugin-proposal-optional-chaining": "^7.0.0", - "@babel/plugin-syntax-dynamic-import": "^7.0.0", - "@babel/plugin-syntax-export-default-from": "^7.0.0", - "@babel/plugin-syntax-flow": "^7.2.0", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.0.0", - "@babel/plugin-syntax-optional-chaining": "^7.0.0", - "@babel/plugin-transform-arrow-functions": "^7.0.0", - "@babel/plugin-transform-async-to-generator": "^7.0.0", - "@babel/plugin-transform-block-scoping": "^7.0.0", - "@babel/plugin-transform-classes": "^7.0.0", - "@babel/plugin-transform-computed-properties": "^7.0.0", - "@babel/plugin-transform-destructuring": "^7.0.0", - "@babel/plugin-transform-exponentiation-operator": "^7.0.0", - "@babel/plugin-transform-flow-strip-types": "^7.0.0", - "@babel/plugin-transform-for-of": "^7.0.0", - "@babel/plugin-transform-function-name": "^7.0.0", - "@babel/plugin-transform-literals": "^7.0.0", - "@babel/plugin-transform-modules-commonjs": "^7.0.0", - "@babel/plugin-transform-object-assign": "^7.0.0", - "@babel/plugin-transform-parameters": "^7.0.0", - "@babel/plugin-transform-react-display-name": "^7.0.0", - "@babel/plugin-transform-react-jsx": "^7.0.0", - "@babel/plugin-transform-react-jsx-self": "^7.0.0", - "@babel/plugin-transform-react-jsx-source": "^7.0.0", - "@babel/plugin-transform-regenerator": "^7.0.0", - "@babel/plugin-transform-runtime": "^7.0.0", - "@babel/plugin-transform-shorthand-properties": "^7.0.0", - "@babel/plugin-transform-spread": "^7.0.0", - "@babel/plugin-transform-sticky-regex": "^7.0.0", - "@babel/plugin-transform-template-literals": "^7.0.0", - "@babel/plugin-transform-typescript": "^7.5.0", - "@babel/plugin-transform-unicode-regex": "^7.0.0", - "@babel/template": "^7.0.0", - "react-refresh": "^0.4.0" + "prop-types": "^15.8.1" }, "peerDependencies": { - "@babel/core": "*" + "@fortawesome/fontawesome-svg-core": "~1 || ~6", + "react": ">=16.3" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "license": "ISC", - "optional": true, - "peer": true, + "node_modules/@grpc/grpc-js": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.12.2.tgz", + "integrity": "sha512-bgxdZmgTrJZX50OjyVwz3+mNEnCTNkh3cIqGPWVNeW9jX6bn1ZkU80uPd+67/ZpIJIjRQ9qaHCjhavyoWYxumg==", "dependencies": { - "brace-expansion": "^1.1.7" + "@grpc/proto-loader": "^0.7.13", + "@js-sdsl/ordered-map": "^4.4.2" }, "engines": { - "node": "*" - } - }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/on-exit-leak-free": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", - "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", - "license": "MIT", - "engines": { - "node": ">=14.0.0" + "node": ">=12.10.0" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "license": "MIT", - "optional": true, - "peer": true, + "node_modules/@grpc/proto-loader": { + "version": "0.7.13", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz", + "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==", "dependencies": { - "p-limit": "^3.0.2" + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.2.5", + "yargs": "^17.7.2" }, - "engines": { - "node": ">=10" + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=6" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "license": "MIT", - "optional": true, - "peer": true, + "node_modules/@grpc/proto-loader/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/@grpc/proto-loader/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/pino": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-8.21.0.tgz", - "integrity": "sha512-ip4qdzjkAyDDZklUaZkcRFb2iA118H9SgRh8yzTkSQK8HilsOJF7rSY8HoW5+I0M46AZgX/pxbprf2vvzQCE0Q==", - "license": "MIT", + "node_modules/@grpc/proto-loader/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dependencies": { - "atomic-sleep": "^1.0.0", - "fast-redact": "^3.1.1", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^1.2.0", - "pino-std-serializers": "^6.0.0", - "process-warning": "^3.0.0", - "quick-format-unescaped": "^4.0.3", - "real-require": "^0.2.0", - "safe-stable-stringify": "^2.3.1", - "sonic-boom": "^3.7.0", - "thread-stream": "^2.6.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, - "bin": { - "pino": "bin.js" - } - }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/pino-abstract-transport": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz", - "integrity": "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==", - "license": "MIT", - "dependencies": { - "readable-stream": "^4.0.0", - "split2": "^4.0.0" + "engines": { + "node": ">=8" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/pino-std-serializers": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz", - "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==", - "license": "MIT" - }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/pretty-format": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", - "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", - "license": "MIT", - "optional": true, - "peer": true, + "node_modules/@grpc/proto-loader/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dependencies": { - "@jest/types": "^26.6.2", - "ansi-regex": "^5.0.0", - "ansi-styles": "^4.0.0", - "react-is": "^17.0.1" + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" }, "engines": { - "node": ">= 10" + "node": ">=12" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/process-warning": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", - "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==", - "license": "MIT" + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/promise": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", - "license": "MIT", - "optional": true, - "peer": true, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", "dependencies": { - "asap": "~2.0.3" + "@hapi/hoek": "^9.0.0" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/protobufjs": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.5.tgz", - "integrity": "sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==", - "hasInstallScript": true, - "license": "BSD-3-Clause", + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "deprecated": "Use @eslint/config-array instead", + "devOptional": 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" + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" }, "engines": { - "node": ">=12.0.0" + "node": ">=10.10.0" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/protobufjs/node_modules/long": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/long/-/long-5.2.4.tgz", - "integrity": "sha512-qtzLbJE8hq7VabR3mISmVGtoXP8KGc2Z/AT8OuqlYD7JTR3oqrgwdjnk07wpj1twXxYmgDXgoKVWUG/fReSzHg==", - "license": "Apache-2.0" - }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/react-refresh": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.4.3.tgz", - "integrity": "sha512-Hwln1VNuGl/6bVwnd0Xdn1e84gT/8T9aYNL+HAKDArLCS7LWjwr7StE30IEYbIkx0Vi3vs+coQxe+SQDbGbbpA==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=0.10.0" + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "devOptional": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/readable-stream": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", - "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", - "license": "MIT", + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "devOptional": true, "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "*" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/real-require": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", - "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", - "license": "MIT", + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "devOptional": true, "engines": { - "node": ">= 12.13.0" + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "semver": "bin/semver" - } + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "devOptional": true }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "node_modules/@inquirer/confirm": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.0.tgz", + "integrity": "sha512-osaBbIMEqVFjTX5exoqPXs6PilWQdjaLhGtMDXMXg/yxkHXNq43GlxGyTA35lK2HpzUgDN+Cjh/2AmqCN0QJpw==", + "dev": true, "license": "MIT", - "optional": true, - "peer": true, "dependencies": { - "shebang-regex": "^1.0.0" + "@inquirer/core": "^10.1.1", + "@inquirer/type": "^3.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "node_modules/@inquirer/core": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.1.tgz", + "integrity": "sha512-rmZVXy9iZvO3ZStEe/ayuuwIJ23LSF13aPMlLMTQARX6lGUBDHGV8UB5i9MRrfy0+mZwt5/9bdy8llszSD3NQA==", + "dev": true, "license": "MIT", - "optional": true, - "peer": true, + "dependencies": { + "@inquirer/figures": "^1.0.8", + "@inquirer/type": "^3.0.1", + "ansi-escapes": "^4.3.2", + "cli-width": "^4.1.0", + "mute-stream": "^2.0.0", + "signal-exit": "^4.1.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.2" + }, "engines": { - "node": ">=0.10.0" + "node": ">=18" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/sonic-boom": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.1.tgz", - "integrity": "sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg==", - "license": "MIT", - "dependencies": { - "atomic-sleep": "^1.0.0" + "node_modules/@inquirer/core/node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 12" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/thread-stream": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.7.0.tgz", - "integrity": "sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw==", - "license": "MIT", - "dependencies": { - "real-require": "^0.2.0" - } + "node_modules/@inquirer/core/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/ua-parser-js": { - "version": "1.0.40", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.40.tgz", - "integrity": "sha512-z6PJ8Lml+v3ichVojCiB8toQJBuwR42ySM4ezjXIqXK3M0HczmKQ3LF4rhU55PfD99KEEXQG6yb7iOMyvYuHew==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/ua-parser-js" - }, - { - "type": "paypal", - "url": "https://paypal.me/faisalman" - }, - { - "type": "github", - "url": "https://github.com/sponsors/faisalman" - } - ], + "node_modules/@inquirer/core/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "license": "MIT", - "optional": true, - "peer": true, - "bin": { - "ua-parser-js": "script/cli.js" - }, "engines": { - "node": "*" - } - }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "license": "MIT", - "optional": true, - "peer": true, - "bin": { - "uuid": "bin/uuid" + "node": ">=8" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "node_modules/@inquirer/core/node_modules/mute-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", + "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", + "dev": true, "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" + "engines": { + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@bitgo/sdk-coin-hbar/node_modules/write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "node_modules/@inquirer/core/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@bitgo/sdk-coin-icp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-icp/-/sdk-coin-icp-1.1.0.tgz", - "integrity": "sha512-koLlZomvG92dC4Zn9BWMafj+H3TeUVxJSXsD00CNQOl9GBVp01Yt11cyIGDYHhqks2blK5QeYTMRuhaQD0vwRw==", + "node_modules/@inquirer/core/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "license": "MIT", "dependencies": { - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/statics": "^50.20.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=18 <21" + "node": ">=8" } }, - "node_modules/@bitgo/sdk-coin-injective": { - "version": "3.0.29", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-injective/-/sdk-coin-injective-3.0.29.tgz", - "integrity": "sha512-hmmkuU/cVaa/GxTygMTUJwXtbdccTydNSnVjq+zXFrk3gd/MpmcYDJECDzYO79D7Hl5QBv6Xaow2S+Vy7qmbmQ==", + "node_modules/@inquirer/core/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, "license": "MIT", "dependencies": { - "@bitgo/abstract-cosmos": "^11.2.16", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/sdk-lib-mpc": "^10.1.0", - "@bitgo/statics": "^50.20.0", - "@cosmjs/amino": "^0.29.5", - "@cosmjs/encoding": "^0.29.5", - "@cosmjs/stargate": "^0.29.5", - "bignumber.js": "^9.1.1" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=18 <21" + "node": ">=8" } }, - "node_modules/@bitgo/sdk-coin-islm": { - "version": "2.1.10", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-islm/-/sdk-coin-islm-2.1.10.tgz", - "integrity": "sha512-1qXAIwT18KSkUFIJqfTHm6bUlL48DaMCWjE/wJlH3Iptct8tzQc0EyHHJ38lqnH7B2ll5JM+4mKdDNOBJAT3Vg==", + "node_modules/@inquirer/figures": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.8.tgz", + "integrity": "sha512-tKd+jsmhq21AP1LhexC0pPwsCxEhGgAkg28byjJAd+xhmIs8LUX8JbUc3vBf3PhLxWiB5EvyBE5X7JSPAqMAqg==", + "dev": true, "license": "MIT", - "dependencies": { - "@bitgo/abstract-cosmos": "^11.2.16", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/statics": "^50.20.0", - "@cosmjs/amino": "^0.29.5", - "@cosmjs/encoding": "^0.29.5", - "@cosmjs/proto-signing": "^0.29.5", - "@cosmjs/stargate": "^0.29.5", - "bignumber.js": "^9.1.1", - "cosmjs-types": "^0.6.1", - "ethers": "^5.7.2", - "keccak": "3.0.3", - "protobufjs": "7.2.5" - }, "engines": { - "node": ">=18 <21" + "node": ">=18" } }, - "node_modules/@bitgo/sdk-coin-islm/node_modules/keccak": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.3.tgz", - "integrity": "sha512-JZrLIAJWuZxKbCilMpNz5Vj7Vtb4scDG3dMXLOsbzBmQGyjwE61BbW7bJkfKKCShXiQZt3T6sBgALRtmd+nZaQ==", - "hasInstallScript": true, + "node_modules/@inquirer/type": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.1.tgz", + "integrity": "sha512-+ksJMIy92sOAiAccGpcKZUc3bYO07cADnscIxHBknEm3uNts3movSmBofc1908BNy5edKscxYeAdaX1NXkHS6A==", + "dev": true, "license": "MIT", - "dependencies": { - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0", - "readable-stream": "^3.6.0" - }, "engines": { - "node": ">=10.0.0" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, - "node_modules/@bitgo/sdk-coin-islm/node_modules/protobufjs": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.5.tgz", - "integrity": "sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==", - "hasInstallScript": true, - "license": "BSD-3-Clause", + "node_modules/@ioredis/commands": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", + "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==" + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": 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" + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, "engines": { - "node": ">=12.0.0" + "node": ">=12" } }, - "node_modules/@bitgo/sdk-coin-lnbtc": { - "version": "1.1.38", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-lnbtc/-/sdk-coin-lnbtc-1.1.38.tgz", - "integrity": "sha512-pYou1qXEuuCuXX2vtZ7c1SKKtv5Glo1zdzmcFVSY38nA6hucbzko6lDt4Q1nVa1wgZZa7AAGXA+htxND7UweSA==", - "license": "MIT", - "dependencies": { - "@bitgo/abstract-lightning": "^1.2.38", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/utxo-lib": "^11.2.1" - }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, "engines": { - "node": ">=18 <21" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/@bitgo/sdk-coin-ltc": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-ltc/-/sdk-coin-ltc-3.1.10.tgz", - "integrity": "sha512-QVeBsxDYoGB7hRmAhEjkiChaVxuOp87TRwB0fhbVQoziT9yhNZiVZIhjQMwvHjY1fOp47TQ5M9AKgnwz6eiD8A==", - "license": "MIT", + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, "dependencies": { - "@bitgo/abstract-utxo": "^9.12.0", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/utxo-lib": "^11.2.1" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=18 <21" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/@bitgo/sdk-coin-near": { - "version": "2.0.60", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-near/-/sdk-coin-near-2.0.60.tgz", - "integrity": "sha512-DC7YofT5dzbiuTukeIlqMTXtvFPuUvuM6A4XRZF+GTVw1OCFItxXyomdHyO7kEDkbFxPrhg2FRFMh3rWEK2yDQ==", - "license": "MIT", - "dependencies": { - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/statics": "^50.20.0", - "@stablelib/hex": "^1.0.0", - "bignumber.js": "^9.0.0", - "bn.js": "^5.2.1", - "bs58": "^4.0.1", - "js-sha256": "^0.9.0", - "lodash": "^4.17.14", - "near-api-js": "^0.44.2", - "superagent": "^9.0.1", - "tweetnacl": "^1.0.3" - }, + "node_modules/@isaacs/ttlcache": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz", + "integrity": "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==", + "license": "ISC", + "peer": true, "engines": { - "node": ">=18 <21" + "node": ">=12" } }, - "node_modules/@bitgo/sdk-coin-oas": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-oas/-/sdk-coin-oas-1.1.13.tgz", - "integrity": "sha512-sEmz0yF1Dd/9w7wLY9KhXEejWq61GILQ1qrT9dAIdKiDYH9uuJanIenGXifi64UprN1D0bNokUg4l4XJvmFlSQ==", - "license": "MIT", + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dependencies": { - "@bitgo/abstract-eth": "^22.4.10", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/statics": "^50.20.0", - "@ethereumjs/common": "^2.6.5" + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" }, "engines": { - "node": ">=18 <21" + "node": ">=8" } }, - "node_modules/@bitgo/sdk-coin-oas/node_modules/@ethereumjs/common": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", - "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", - "license": "MIT", + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dependencies": { - "crc-32": "^1.2.0", - "ethereumjs-util": "^7.1.5" + "sprintf-js": "~1.0.2" } }, - "node_modules/@bitgo/sdk-coin-opeth": { - "version": "18.1.45", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-opeth/-/sdk-coin-opeth-18.1.45.tgz", - "integrity": "sha512-a7ltFrapsb3O5YubCT+m2xuU2/FjKsqZ42RddTgONmybKth/YAoZaBjaMQfCge/RU9fUhIdrb+Ux1ACx6mdvTA==", - "license": "MIT", - "dependencies": { - "@bitgo/abstract-eth": "^22.4.10", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/statics": "^50.20.0", - "@bitgo/utxo-lib": "^11.2.1", - "@ethereumjs/common": "^2.6.5", - "ethereumjs-abi": "^0.6.5", - "ethereumjs-util": "7.1.5" - }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "engines": { - "node": ">=18 <21" + "node": ">=6" } }, - "node_modules/@bitgo/sdk-coin-opeth/node_modules/@ethereumjs/common": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", - "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", - "license": "MIT", + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dependencies": { - "crc-32": "^1.2.0", - "ethereumjs-util": "^7.1.5" + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@bitgo/sdk-coin-osmo": { - "version": "3.0.29", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-osmo/-/sdk-coin-osmo-3.0.29.tgz", - "integrity": "sha512-FDDZuHUzYt0mI9ctuzEdWu7g0kB5jeJWzXHMuV2DwyqQEADRTuiJvbpF7wTusTuv3ClcMtmw5aqWPCI0SX4OVA==", - "license": "MIT", - "dependencies": { - "@bitgo/abstract-cosmos": "^11.2.16", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/sdk-lib-mpc": "^10.1.0", - "@bitgo/statics": "^50.20.0", - "@cosmjs/amino": "^0.29.5", - "@cosmjs/encoding": "^0.29.5", - "@cosmjs/stargate": "^0.29.5", - "bignumber.js": "^9.1.1" - }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "engines": { - "node": ">=18 <21" + "node": ">=8" } }, - "node_modules/@bitgo/sdk-coin-polygon": { - "version": "21.0.29", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-polygon/-/sdk-coin-polygon-21.0.29.tgz", - "integrity": "sha512-TfImxztWi82OXObvR0N+BUsP/M3GpegvN+mgYSy93JKjlPdNL1CtnQOoSUHn+qN4hpm4RIA1nGUQ8pVUb6HvCA==", - "license": "MIT", + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, "dependencies": { - "@bitgo/abstract-eth": "^22.4.10", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/sjcl": "^1.0.1", - "@bitgo/statics": "^50.20.0", - "@bitgo/utxo-lib": "^11.2.1", - "@ethereumjs/common": "^2.6.5", - "ethereumjs-util": "7.1.5", - "ethers": "^5.1.3" + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" }, "engines": { - "node": ">=18 <21" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@bitgo/sdk-coin-polygon/node_modules/@ethereumjs/common": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", - "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", - "license": "MIT", + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, "dependencies": { - "crc-32": "^1.2.0", - "ethereumjs-util": "^7.1.5" + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/@bitgo/sdk-coin-rbtc": { - "version": "2.0.60", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-rbtc/-/sdk-coin-rbtc-2.0.60.tgz", - "integrity": "sha512-HHmyV9ThmbWzH1Cm3UTKDqWSL7sQHl+q202qBHia4L4d9cpFrVGAkZGmeSbIytLke+QJKXetfV0/A5WecbXFvQ==", - "license": "MIT", + "node_modules/@jest/core/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, "dependencies": { - "@bitgo/abstract-eth": "^22.4.10", - "@bitgo/sdk-coin-eth": "^24.2.49", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/statics": "^50.20.0", - "@ethereumjs/common": "^2.6.5", - "ethereumjs-abi": "^0.6.5" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "engines": { - "node": ">=18 <21" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@bitgo/sdk-coin-rbtc/node_modules/@ethereumjs/common": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", - "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", - "license": "MIT", - "dependencies": { - "crc-32": "^1.2.0", - "ethereumjs-util": "^7.1.5" + "node_modules/@jest/core/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@bitgo/sdk-coin-rune": { - "version": "1.1.17", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-rune/-/sdk-coin-rune-1.1.17.tgz", - "integrity": "sha512-4WJ1EU+XH6ySSVEXXpKnmofQDwl9ug5rnBcQuiz/U9QBbCpkapLt052GY4YJ5UoRQTg0sZUq9Bqdauaj0o27rg==", + "node_modules/@jest/core/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, + "node_modules/@jest/create-cache-key-function": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz", + "integrity": "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==", "license": "MIT", + "peer": true, "dependencies": { - "@bitgo/abstract-cosmos": "^11.2.16", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/statics": "^50.20.0", - "@cosmjs/amino": "^0.29.5", - "@cosmjs/encoding": "^0.29.5", - "@cosmjs/proto-signing": "^0.29.5", - "@cosmjs/stargate": "^0.29.5", - "bech32-buffer": "^0.2.1", - "bignumber.js": "^9.1.1", - "lodash": "^4.17.21" + "@jest/types": "^29.6.3" }, "engines": { - "node": ">=18 <21" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@bitgo/sdk-coin-sei": { - "version": "3.0.29", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-sei/-/sdk-coin-sei-3.0.29.tgz", - "integrity": "sha512-9LYZtNMfk0VsmmT5YDnX+hr4Z7v9hJwll177ZoFmAFRlQZMV4vt/bmLb353nLGXX7Eg1OcUqkTI+bWhxut8OaQ==", - "license": "MIT", + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", "dependencies": { - "@bitgo/abstract-cosmos": "^11.2.16", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/sdk-lib-mpc": "^10.1.0", - "@bitgo/statics": "^50.20.0", - "@cosmjs/amino": "^0.29.5", - "@cosmjs/encoding": "^0.29.5", - "@cosmjs/stargate": "^0.29.5", - "bignumber.js": "^9.1.1" + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" }, "engines": { - "node": ">=18 <21" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@bitgo/sdk-coin-sol": { - "version": "4.7.17", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-sol/-/sdk-coin-sol-4.7.17.tgz", - "integrity": "sha512-uoQ40f23NrzitmwjVgJwWeFUDVLlgRnn0/sjfmzXOOIA1e++RBCIAAWyvVwtZEHdSilDt5iT/T/1Wc357x0m2g==", - "license": "MIT", + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, "dependencies": { - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/sdk-lib-mpc": "^10.1.0", - "@bitgo/statics": "^50.20.0", - "@solana/spl-token": "0.3.1", - "@solana/web3.js": "1.92.1", - "bignumber.js": "^9.0.0", - "bs58": "^4.0.1", - "lodash": "^4.17.14", - "superagent": "^9.0.1", - "tweetnacl": "^1.0.3" + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" }, "engines": { - "node": ">=18 <21" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@bitgo/sdk-coin-stx": { - "version": "3.3.17", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-stx/-/sdk-coin-stx-3.3.17.tgz", - "integrity": "sha512-cWVGjjYID6mSthQwqrLkw8RHeozFElfTy9xBfiYmp+T19RJGt0l57BZuOCVkbPWqFNH/uplTmN+vb+2f1CF8Dg==", - "license": "MIT", + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, "dependencies": { - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/statics": "^50.20.0", - "@bitgo/utxo-lib": "^11.2.1", - "@stacks/network": "^4.3.0", - "@stacks/transactions": "2.0.1", - "bignumber.js": "^9.0.0", - "bn.js": "^5.2.1", - "elliptic": "^6.5.2", - "ethereumjs-util": "7.1.5", - "lodash": "^4.17.15" + "jest-get-type": "^29.6.3" }, "engines": { - "node": ">=18 <21" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@bitgo/sdk-coin-tao": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-tao/-/sdk-coin-tao-1.0.2.tgz", - "integrity": "sha512-8O0ysGnQBJGobBRfwb2SerQ8NXjlkuXw9JeZghnoCg5JB4EkhfhJ5hVBdNwqo4z2aYEFGUI544Qvec9P5KYhpQ==", - "license": "MIT", + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", "dependencies": { - "@bitgo/abstract-substrate": "^1.0.2", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/statics": "^50.20.0", - "bignumber.js": "^9.1.2" + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": ">=16 <21" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@bitgo/sdk-coin-tia": { - "version": "3.0.29", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-tia/-/sdk-coin-tia-3.0.29.tgz", - "integrity": "sha512-s2pGn/cQ8s7dEEpf/FqjprocGtKknYKoy91WKWWFXikThLpcmV1/CDmTPVUk7MDn6caQIl+pYoCtlRWHwcmvVA==", - "license": "MIT", + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, "dependencies": { - "@bitgo/abstract-cosmos": "^11.2.16", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/sdk-lib-mpc": "^10.1.0", - "@bitgo/statics": "^50.20.0", - "@cosmjs/amino": "^0.29.5", - "@cosmjs/encoding": "^0.29.5", - "@cosmjs/stargate": "^0.29.5", - "bignumber.js": "^9.1.1" + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" }, "engines": { - "node": ">=18 <21" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@bitgo/sdk-coin-ton": { - "version": "3.4.17", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-ton/-/sdk-coin-ton-3.4.17.tgz", - "integrity": "sha512-mKwymowr/DTTyplkptQWWp0Tt/JaNdeP9YL8wwFjk/e2uJDIUBPc1U4/7Cq8E2QRlNC0rD+oTiTU9E4h17oV+Q==", - "license": "MIT", + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, "dependencies": { - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/sdk-lib-mpc": "^10.1.0", - "@bitgo/statics": "^50.20.0", - "bignumber.js": "^9.0.0", - "bn.js": "^5.2.1", - "lodash": "^4.17.21", - "tonweb": "^0.0.62", - "tweetnacl": "^1.0.3" + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" }, "engines": { - "node": ">=18 <21" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/@bitgo/sdk-coin-trx": { - "version": "2.0.60", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-trx/-/sdk-coin-trx-2.0.60.tgz", - "integrity": "sha512-OziYDAi4hAJ1hX+u6O2K6C0nvbyb+zhlgoSAto2L+ZQSeaUlqBKSh2utu6MnJwX9R7qVn7EOtVXVlOV7OEbVTQ==", - "license": "MIT", + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dependencies": { - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/statics": "^50.20.0", - "@bitgo/utxo-lib": "^11.2.1", - "@stablelib/hex": "^1.0.0", - "bignumber.js": "^9.0.0", - "ethers": "^5.7.2", - "lodash": "^4.17.14", - "protobufjs": "7.2.5", - "secp256k1": "5.0.1", - "superagent": "^9.0.1", - "tronweb": "5.1.0" + "@sinclair/typebox": "^0.27.8" }, "engines": { - "node": ">=18 <21" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@bitgo/sdk-coin-trx/node_modules/protobufjs": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.5.tgz", - "integrity": "sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==", - "hasInstallScript": true, - "license": "BSD-3-Clause", + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": 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" + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" }, "engines": { - "node": ">=12.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@bitgo/sdk-coin-xlm": { - "version": "3.2.34", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-xlm/-/sdk-coin-xlm-3.2.34.tgz", - "integrity": "sha512-9PiLJlo8gXDJ7SvanX4mnjUY17egVh/6LtsEoZGB5kJpkLugZXVxOZnTjJXMDJLxRud0unthZU52zA0gQFgCzw==", - "license": "MIT", + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, "dependencies": { - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/statics": "^50.20.0", - "bignumber.js": "^9.1.1", - "lodash": "^4.17.14", - "stellar-sdk": "^10.0.1", - "superagent": "^9.0.1" + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" }, "engines": { - "node": ">=18 <21" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@bitgo/sdk-coin-xrp": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-xrp/-/sdk-coin-xrp-3.7.2.tgz", - "integrity": "sha512-ketTWWs7qhkSCdDDEOfCL2uLRSHcqqNtICuk1U0+BHItKCAotjfMpA6rPmSxXZ8lCb78IdGycWKUeUQuWXbEzg==", - "license": "MIT", + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, "dependencies": { - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/statics": "^50.20.0", - "@bitgo/utxo-lib": "^11.2.1", - "bignumber.js": "^9.0.0", - "lodash": "^4.17.14", - "ripple-binary-codec": "2.1.0", - "ripple-keypairs": "2.0.0", - "xrpl": "4.0.0" + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" }, "engines": { - "node": ">=18 <21" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@bitgo/sdk-coin-xtz": { - "version": "2.1.58", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-xtz/-/sdk-coin-xtz-2.1.58.tgz", - "integrity": "sha512-hWRw4jl5kQ8G1S52L6Gfj2uZBQWmxnNzKwZDXzvPOKdVqjXFlAhvYwsXSLzI85LLliEaQQpLzFxdCJ97gzgKDw==", - "license": "MIT", + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dependencies": { - "@bitgo/blake2b": "^3.2.4", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/statics": "^50.20.0", - "@bitgo/utxo-lib": "^11.2.1", - "@taquito/local-forging": "6.3.5-beta.0", - "@taquito/signer": "6.3.5-beta.0", - "bignumber.js": "^9.0.0", - "bs58check": "^2.1.2", - "elliptic": "^6.5.2", - "libsodium-wrappers": "^0.7.6", - "lodash": "^4.17.15" + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" }, "engines": { - "node": ">=18 <21" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@bitgo/sdk-coin-zec": { - "version": "2.1.10", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-zec/-/sdk-coin-zec-2.1.10.tgz", - "integrity": "sha512-UTPMWv1okkj6ehbhDK9DRZyVJ22JrgFKkiRD/VF4movjhnEsV8uCtl2SOhIkbIRKXm2/5JiUu7sLuESfEXQLqQ==", - "license": "MIT", + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dependencies": { - "@bitgo/abstract-utxo": "^9.12.0", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/utxo-lib": "^11.2.1" + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" }, "engines": { - "node": ">=18 <21" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@bitgo/sdk-coin-zeta": { - "version": "3.0.29", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-zeta/-/sdk-coin-zeta-3.0.29.tgz", - "integrity": "sha512-PKL2e3jH6PhbjmD02Elp8OYh62tvyLqYXJtZo8EUmdBJxZ/9SIBatzNU9WG8B3Yen9nPlzhiHI1BCujPpPmVOw==", - "license": "MIT", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dependencies": { - "@bitgo/abstract-cosmos": "^11.2.16", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/sdk-lib-mpc": "^10.1.0", - "@bitgo/statics": "^50.20.0", - "@cosmjs/amino": "^0.29.5", - "@cosmjs/encoding": "^0.29.5", - "@cosmjs/stargate": "^0.29.5", - "bignumber.js": "^9.1.1" + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { - "node": ">=18 <21" + "node": ">=6.0.0" } }, - "node_modules/@bitgo/sdk-coin-zketh": { - "version": "2.0.52", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-zketh/-/sdk-coin-zketh-2.0.52.tgz", - "integrity": "sha512-PE1RQ8peAyqrsJXnlwxe8jdMwlTB/QGseAeJtKG1VDD1ayYaZoov8bTZvJWY9NSVL1H6p0o8Jqnsj6gahet83w==", - "license": "MIT", - "dependencies": { - "@bitgo/abstract-eth": "^22.4.10", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/statics": "^50.20.0", - "@bitgo/utxo-lib": "^11.2.1", - "@ethereumjs/common": "^2.6.5" - }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "engines": { - "node": ">=16 <21" + "node": ">=6.0.0" } }, - "node_modules/@bitgo/sdk-coin-zketh/node_modules/@ethereumjs/common": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", - "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", - "license": "MIT", - "dependencies": { - "crc-32": "^1.2.0", - "ethereumjs-util": "^7.1.5" + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "engines": { + "node": ">=6.0.0" } }, - "node_modules/@bitgo/sdk-core": { - "version": "28.20.0", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-core/-/sdk-core-28.20.0.tgz", - "integrity": "sha512-ieOAVMR1aOpYcpuG3sM4NBuFUeTMMO2TIKdbGQ1BHS4A3mgl+youFytYbbMRJsHE4NDyzyKD2+G+q2e4aWBJ0w==", - "license": "MIT", + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", "dependencies": { - "@bitgo/bls-dkg": "^1.3.1", - "@bitgo/public-types": "4.9.2", - "@bitgo/sdk-lib-mpc": "^10.1.0", - "@bitgo/sjcl": "^1.0.1", - "@bitgo/statics": "^50.20.0", - "@bitgo/utxo-lib": "^11.2.1", - "@noble/secp256k1": "1.6.3", - "@stablelib/hex": "^1.0.0", - "@types/elliptic": "^6.4.12", - "@types/superagent": "4.1.15", - "bech32": "^2.0.0", - "big.js": "^3.1.3", - "bigint-crypto-utils": "3.1.4", - "bignumber.js": "^9.1.1", - "bitcoinjs-message": "npm:@bitgo-forks/bitcoinjs-message@1.0.0-master.3", - "bolt11": "^1.4.0", - "bs58": "^4.0.1", - "bs58check": "^2.1.2", - "create-hmac": "^1.1.7", - "debug": "^3.1.0", - "elliptic": "^6.5.2", - "ethereumjs-util": "7.1.5", - "fp-ts": "^2.12.2", - "io-ts": "npm:@bitgo-forks/io-ts@2.1.4", - "io-ts-types": "^0.5.16", - "keccak": "3.0.3", - "libsodium-wrappers-sumo": "^0.7.9", - "lodash": "^4.17.15", - "macaroon": "^3.0.4", - "noble-bls12-381": "0.7.2", - "openpgp": "5.10.1", - "paillier-bigint": "3.3.0", - "secp256k1": "5.0.1", - "strip-hex-prefix": "^1.0.0", - "superagent": "^9.0.1", - "tweetnacl": "^1.0.3", - "uuid": "^8.3.2" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" } }, - "node_modules/@bitgo/sdk-core/node_modules/@bitgo/public-types": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/@bitgo/public-types/-/public-types-4.9.2.tgz", - "integrity": "sha512-yVP/duh0ION0pfSVMJt24qCQ66Vxjlg7eP9iewlaDpod1q1aGX4m0sP9GNcAWSVBHo1S0+r9YgWZIdcB/DHxTg==", - "license": "UNLICENSED", - "dependencies": { - "fp-ts": "^2.0.0", - "io-ts": "npm:@bitgo-forks/io-ts@2.1.4", - "io-ts-types": "^0.5.16", - "monocle-ts": "^2.3.13", - "newtype-ts": "^0.3.5" - } + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" }, - "node_modules/@bitgo/sdk-core/node_modules/@types/superagent": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.15.tgz", - "integrity": "sha512-mu/N4uvfDN2zVQQ5AYJI/g4qxn2bHB6521t1UuH09ShNWjebTqN0ZFuYK9uYjcgmI0dTQEs+Owi1EO6U0OkOZQ==", - "license": "MIT", + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dependencies": { - "@types/cookiejar": "*", - "@types/node": "*" - } - }, - "node_modules/@bitgo/sdk-core/node_modules/big.js": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", - "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", - "license": "MIT", - "engines": { - "node": "*" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@bitgo/sdk-core/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" + "node_modules/@js-sdsl/ordered-map": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", + "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" } }, - "node_modules/@bitgo/sdk-core/node_modules/keccak": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.3.tgz", - "integrity": "sha512-JZrLIAJWuZxKbCilMpNz5Vj7Vtb4scDG3dMXLOsbzBmQGyjwE61BbW7bJkfKKCShXiQZt3T6sBgALRtmd+nZaQ==", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0", - "readable-stream": "^3.6.0" - }, + "node_modules/@jsonjoy.com/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", + "dev": true, "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@bitgo/sdk-core/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" } }, - "node_modules/@bitgo/sdk-hmac": { + "node_modules/@jsonjoy.com/json-pack": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-hmac/-/sdk-hmac-1.1.0.tgz", - "integrity": "sha512-l6eq/ZQxahuWjESPQM/7JfoYJVeMFN8seKu9KTdzhajkVlHkoMSNAuulrFECtyySzGC5SHnoyubEceZANyZbXg==", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.1.0.tgz", + "integrity": "sha512-zlQONA+msXPPwHWZMKFVS78ewFczIll5lXiVPwFPCZUsrOKdxc2AvxU1HoNBmMRhqDZUR9HkC3UOm+6pME6Xsg==", + "dev": true, "dependencies": { - "@bitgo/sjcl": "^1.0.1" + "@jsonjoy.com/base64": "^1.1.1", + "@jsonjoy.com/util": "^1.1.2", + "hyperdyperid": "^1.2.0", + "thingies": "^1.20.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" } }, - "node_modules/@bitgo/sdk-lib-mpc": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-lib-mpc/-/sdk-lib-mpc-10.1.0.tgz", - "integrity": "sha512-0OtkLE01YLMoCl2nQvXygXx5Y5v0d3/F4Pl7DSN5tafMhZEuwXjID48mzQT2ukEbCLrBjg1bZc74zNsb0EDVdA==", - "license": "MIT", - "dependencies": { - "@noble/curves": "1.4.0", - "@silencelaboratories/dkls-wasm-ll-node": "1.1.2", - "@silencelaboratories/dkls-wasm-ll-web": "1.1.2", - "@types/superagent": "4.1.15", - "@wasmer/wasi": "^1.2.2", - "bigint-crypto-utils": "3.1.4", - "bigint-mod-arith": "3.1.2", - "cbor-x": "1.5.9", - "fp-ts": "2.16.2", - "io-ts": "npm:@bitgo-forks/io-ts@2.1.4", - "libsodium-wrappers-sumo": "^0.7.9", - "openpgp": "5.10.1", - "paillier-bigint": "3.3.0", - "secp256k1": "5.0.1" - }, - "peerDependencies": { - "@silencelaboratories/dkls-wasm-ll-bundler": "1.1.2" + "node_modules/@jsonjoy.com/util": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.3.0.tgz", + "integrity": "sha512-Cebt4Vk7k1xHy87kHY7KSPLT77A7Ev7IfOblyLZhtYEhrdQ6fX4EoLq3xOQ3O/DRMEh2ok5nyC180E+ABS8Wmw==", + "dev": true, + "engines": { + "node": ">=10.0" }, - "peerDependenciesMeta": { - "@silencelaboratories/dkls-wasm-ll-bundler": { - "optional": true - } + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" } }, - "node_modules/@bitgo/sdk-lib-mpc/node_modules/@noble/curves": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.0.tgz", - "integrity": "sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg==", + "node_modules/@keyv/serialize": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.0.2.tgz", + "integrity": "sha512-+E/LyaAeuABniD/RvUezWVXKpeuvwLEA9//nE9952zBaOdBd2mQ3pPoM8cUe2X6IcMByfuSLzmYqnYshG60+HQ==", "license": "MIT", "dependencies": { - "@noble/hashes": "1.4.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "buffer": "^6.0.3" } }, - "node_modules/@bitgo/sdk-lib-mpc/node_modules/@types/superagent": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.15.tgz", - "integrity": "sha512-mu/N4uvfDN2zVQQ5AYJI/g4qxn2bHB6521t1UuH09ShNWjebTqN0ZFuYK9uYjcgmI0dTQEs+Owi1EO6U0OkOZQ==", + "node_modules/@keyv/serialize/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "license": "MIT", "dependencies": { - "@types/cookiejar": "*", - "@types/node": "*" + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" } }, - "node_modules/@bitgo/sdk-lib-mpc/node_modules/fp-ts": { - "version": "2.16.2", - "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-2.16.2.tgz", - "integrity": "sha512-CkqAjnIKFqvo3sCyoBTqgJvF+bHrSik584S9nhTjtBESLx26cbtVMR/T9a6ApChOcSDAaM3JydDmWDUn4EEXng==", - "license": "MIT" + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==" }, - "node_modules/@bitgo/sjcl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@bitgo/sjcl/-/sjcl-1.0.1.tgz", - "integrity": "sha512-dBICMzShC8gXdpSj9cvl4wl9Jkt4h14wt4XQ+/6V6qcC2IObyKRJfaG5TYUU6RvVknhPBPyBx9v84vNKODM5fQ==", - "license": "(BSD-2-Clause OR GPL-2.0-only)" - }, - "node_modules/@bitgo/statics": { - "version": "50.20.0", - "resolved": "https://registry.npmjs.org/@bitgo/statics/-/statics-50.20.0.tgz", - "integrity": "sha512-smbJsJ7fFDMY2qdqikjKuMsuIKbUqRzlh04lIyMQFBs4KvQK/PpDzHnJqVdiTobvbjEf12aW8NgAO/FbP3ai/w==", - "license": "Apache-2.0" - }, - "node_modules/@bitgo/unspents": { - "version": "0.47.17", - "resolved": "https://registry.npmjs.org/@bitgo/unspents/-/unspents-0.47.17.tgz", - "integrity": "sha512-mWic5w/ATgfsg5AR+BPGNkSm8XPYha4z37GE4SeVAKzsKm2LiryAQBcP+Z+aIYUHXB9pK5++WtGY+AXNAUOU6A==", - "license": "Apache-2.0", - "dependencies": { - "@bitgo/utxo-lib": "^11.2.1", - "lodash": "~4.17.21", - "tcomb": "~3.2.29", - "varuint-bitcoin": "^1.0.4" - } + "node_modules/@lit-labs/ssr-dom-shim": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.2.1.tgz", + "integrity": "sha512-wx4aBmgeGvFmOKucFKY+8VFJSYZxs9poN3SDNQFF6lT6NrQUnHiPB2PWz2sc4ieEcAaYYzN+1uWahEeTq2aRIQ==" }, - "node_modules/@bitgo/utxo-lib": { - "version": "11.2.1", - "resolved": "https://registry.npmjs.org/@bitgo/utxo-lib/-/utxo-lib-11.2.1.tgz", - "integrity": "sha512-ko9twLjxurdcJHEtWXa2fDv3qBQEmVVq8zfzXvktt46R5Dc/jXGVE6puxbDduFvwlYgHRGj92JCqLWNKQvMpiw==", - "license": "MIT", + "node_modules/@lit/reactive-element": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.6.3.tgz", + "integrity": "sha512-QuTgnG52Poic7uM1AN5yJ09QMe0O28e10XzSvWDz02TJiiKee4stsiownEIadWm8nYzyDAyT+gKzUoZmiWQtsQ==", "dependencies": { - "@bitgo/blake2b": "^3.2.4", - "@brandonblack/musig": "^0.0.1-alpha.0", - "@noble/secp256k1": "1.6.3", - "bech32": "^2.0.0", - "bip174": "npm:@bitgo-forks/bip174@3.1.0-master.4", - "bip32": "^3.0.1", - "bitcoin-ops": "^1.3.0", - "bitcoinjs-lib": "npm:@bitgo-forks/bitcoinjs-lib@7.1.0-master.9", - "bn.js": "^5.2.1", - "bs58check": "^2.1.2", - "cashaddress": "^1.1.0", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "ecpair": "npm:@bitgo/ecpair@2.1.0-rc.0", - "elliptic": "^6.5.2", - "fastpriorityqueue": "^0.7.1", - "typeforce": "^1.11.3", - "varuint-bitcoin": "^1.1.2" - }, - "engines": { - "node": ">=10.22.0 <21", - "npm": ">=3.10.10" + "@lit-labs/ssr-dom-shim": "^1.0.0" } }, - "node_modules/@bitgo/utxo-ord": { - "version": "1.20.65", - "resolved": "https://registry.npmjs.org/@bitgo/utxo-ord/-/utxo-ord-1.20.65.tgz", - "integrity": "sha512-Ja82Ars/MJIzS18OG9gt46gqJfrgrewHa18bJCBA3Ha5zByawRlF2x6h2eyjMO6eOl4ChCIij40vjvOUiOJ7Mg==", - "license": "MIT", - "dependencies": { - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/unspents": "^0.47.17", - "@bitgo/utxo-lib": "^11.2.1" + "node_modules/@lukeed/csprng": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz", + "integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==", + "engines": { + "node": ">=8" } }, - "node_modules/@bitgo/wasm-miniscript": { - "version": "2.0.0-beta.2", - "resolved": "https://registry.npmjs.org/@bitgo/wasm-miniscript/-/wasm-miniscript-2.0.0-beta.2.tgz", - "integrity": "sha512-hh6R8NYTS6N1VdlgljkXAMRFNAsr2SGm1QcFjChHZ2bTotnNiCLlOlVR6EYhwtGr5eWLItye3iZG10m/li0xKA==" - }, - "node_modules/@brandonblack/musig": { - "version": "0.0.1-alpha.1", - "resolved": "https://registry.npmjs.org/@brandonblack/musig/-/musig-0.0.1-alpha.1.tgz", - "integrity": "sha512-00RbByQG85lSzrkDjCblzrUc2n1LJAPPrEMHS4oMg+QckE0kzjd26JytT6yx6tNU2+aOXfK7O4kGW/sKVL67cw==", - "license": "MIT" + "node_modules/@mdx-js/mdx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.0.1.tgz", + "integrity": "sha512-eIQ4QTrOWyL3LWEe/bu6Taqzq2HQvHcyTMaOrI95P2/LmJE7AsfPfgJGuFLPVqBUE1BC1rik3VIhU+s9u72arA==", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdx": "^2.0.0", + "collapse-white-space": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-build-jsx": "^3.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-util-to-js": "^2.0.0", + "estree-walker": "^3.0.0", + "hast-util-to-estree": "^3.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "markdown-extensions": "^2.0.0", + "periscopic": "^3.0.0", + "remark-mdx": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "source-map": "^0.7.0", + "unified": "^11.0.0", + "unist-util-position-from-estree": "^2.0.0", + "unist-util-stringify-position": "^4.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } }, - "node_modules/@bull-board/api": { - "version": "5.20.1", - "resolved": "https://registry.npmjs.org/@bull-board/api/-/api-5.20.1.tgz", - "integrity": "sha512-45aDhnOzWRrtUUAKHxdClSnLIus5f8BK3ATzb2IwI/BRgOi1lWTe1YG266hVqDdWXsUDxKzf75DAANKfAoEsRA==", + "node_modules/@mdx-js/react": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.1.tgz", + "integrity": "sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A==", "dependencies": { - "redis-info": "^3.0.8" + "@types/mdx": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" }, "peerDependencies": { - "@bull-board/ui": "5.20.1" + "@types/react": ">=16", + "react": ">=16" } }, - "node_modules/@bull-board/express": { - "version": "5.20.1", - "resolved": "https://registry.npmjs.org/@bull-board/express/-/express-5.20.1.tgz", - "integrity": "sha512-980wGA8kjMyw7MrYNN25l7lJNlLz22ln3jW/H3ef98BXhTeBnPR16XhXu1Z6471X5Aor9WXZ6FRQ5pJhP4iXuA==", + "node_modules/@metamask/eth-json-rpc-provider": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@metamask/eth-json-rpc-provider/-/eth-json-rpc-provider-1.0.1.tgz", + "integrity": "sha512-whiUMPlAOrVGmX8aKYVPvlKyG4CpQXiNNyt74vE1xb5sPvmx5oA7B/kOi/JdBvhGQq97U1/AVdXEdk2zkP8qyA==", "dependencies": { - "@bull-board/api": "5.20.1", - "@bull-board/ui": "5.20.1", - "ejs": "^3.1.10", - "express": "^4.19.2" + "@metamask/json-rpc-engine": "^7.0.0", + "@metamask/safe-event-emitter": "^3.0.0", + "@metamask/utils": "^5.0.1" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@bull-board/nestjs": { - "version": "5.20.1", - "resolved": "https://registry.npmjs.org/@bull-board/nestjs/-/nestjs-5.20.1.tgz", - "integrity": "sha512-6WREzrJdrAuJ3LcZVETzfEpQxUSF2xxC7plPiSj11jyO30i/moKkc7gUVuP2h6YgQnhhH3ppFxECVduXWRBDLQ==", + "node_modules/@metamask/eth-json-rpc-provider/node_modules/@metamask/json-rpc-engine": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@metamask/json-rpc-engine/-/json-rpc-engine-7.3.3.tgz", + "integrity": "sha512-dwZPq8wx9yV3IX2caLi9q9xZBw2XeIoYqdyihDDDpuHVCEiqadJLwqM3zy+uwf6F1QYQ65A8aOMQg1Uw7LMLNg==", "dependencies": { - "@nestjs/bull-shared": "^10.0.0" + "@metamask/rpc-errors": "^6.2.1", + "@metamask/safe-event-emitter": "^3.0.0", + "@metamask/utils": "^8.3.0" }, - "peerDependencies": { - "@bull-board/api": "^5.20.1", - "@bull-board/express": "^5.20.1", - "@nestjs/common": "^9.0.0 || ^10.0.0", - "@nestjs/core": "^9.0.0 || ^10.0.0", - "reflect-metadata": "^0.1.13 || ^0.2.0", - "rxjs": "^7.8.1" + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@bull-board/ui": { - "version": "5.20.1", - "resolved": "https://registry.npmjs.org/@bull-board/ui/-/ui-5.20.1.tgz", - "integrity": "sha512-RzNinC4FKHNuxzkIRsCL+n9iO5RxmF5YM7byCuuv1/UeFjtCtsLHFi6TI9ZgJsXETA2Uxq9Mg7ppncojUjrINw==", + "node_modules/@metamask/eth-json-rpc-provider/node_modules/@metamask/json-rpc-engine/node_modules/@metamask/utils": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-8.5.0.tgz", + "integrity": "sha512-I6bkduevXb72TIM9q2LRO63JSsF9EXduh3sBr9oybNX2hNNpr/j1tEjXrsG0Uabm4MJ1xkGAQEMwifvKZIkyxQ==", "dependencies": { - "@bull-board/api": "5.20.1" + "@ethereumjs/tx": "^4.2.0", + "@metamask/superstruct": "^3.0.0", + "@noble/hashes": "^1.3.1", + "@scure/base": "^1.1.3", + "@types/debug": "^4.1.7", + "debug": "^4.3.4", + "pony-cause": "^2.1.10", + "semver": "^7.5.4", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@bundled-es-modules/cookie": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@bundled-es-modules/cookie/-/cookie-2.0.1.tgz", - "integrity": "sha512-8o+5fRPLNbjbdGRRmJj3h6Hh1AQJf2dk3qQ/5ZFb+PXkRNiSoMGGUKlsgLfrxneb72axVJyIYji64E2+nNfYyw==", - "dev": true, - "license": "ISC", + "node_modules/@metamask/eth-json-rpc-provider/node_modules/@metamask/utils": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-5.0.2.tgz", + "integrity": "sha512-yfmE79bRQtnMzarnKfX7AEJBwFTxvTyw3nBQlu/5rmGXrjAeAMltoGxO62TFurxrQAFMNa/fEjIHNvungZp0+g==", "dependencies": { - "cookie": "^0.7.2" + "@ethereumjs/tx": "^4.1.2", + "@types/debug": "^4.1.7", + "debug": "^4.3.4", + "semver": "^7.3.8", + "superstruct": "^1.0.3" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@bundled-es-modules/cookie/node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "dev": true, - "license": "MIT", + "node_modules/@metamask/eth-json-rpc-provider/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">= 0.6" + "node": ">=10" } }, - "node_modules/@bundled-es-modules/statuses": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@bundled-es-modules/statuses/-/statuses-1.0.1.tgz", - "integrity": "sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==", - "dev": true, - "license": "ISC", + "node_modules/@metamask/json-rpc-engine": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@metamask/json-rpc-engine/-/json-rpc-engine-8.0.2.tgz", + "integrity": "sha512-IoQPmql8q7ABLruW7i4EYVHWUbF74yrp63bRuXV5Zf9BQwcn5H9Ww1eLtROYvI1bUXwOiHZ6qT5CWTrDc/t/AA==", "dependencies": { - "statuses": "^2.0.1" + "@metamask/rpc-errors": "^6.2.1", + "@metamask/safe-event-emitter": "^3.0.0", + "@metamask/utils": "^8.3.0" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@bundled-es-modules/tough-cookie": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@bundled-es-modules/tough-cookie/-/tough-cookie-0.1.6.tgz", - "integrity": "sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw==", - "dev": true, - "license": "ISC", + "node_modules/@metamask/json-rpc-middleware-stream": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@metamask/json-rpc-middleware-stream/-/json-rpc-middleware-stream-7.0.2.tgz", + "integrity": "sha512-yUdzsJK04Ev98Ck4D7lmRNQ8FPioXYhEUZOMS01LXW8qTvPGiRVXmVltj2p4wrLkh0vW7u6nv0mNl5xzC5Qmfg==", "dependencies": { - "@types/tough-cookie": "^4.0.5", - "tough-cookie": "^4.1.4" + "@metamask/json-rpc-engine": "^8.0.2", + "@metamask/safe-event-emitter": "^3.0.0", + "@metamask/utils": "^8.3.0", + "readable-stream": "^3.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@cbor-extract/cbor-extract-darwin-arm64": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-darwin-arm64/-/cbor-extract-darwin-arm64-2.2.0.tgz", - "integrity": "sha512-P7swiOAdF7aSi0H+tHtHtr6zrpF3aAq/W9FXx5HektRvLTM2O89xCyXF3pk7pLc7QpaY7AoaE8UowVf9QBdh3w==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@cbor-extract/cbor-extract-darwin-x64": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-darwin-x64/-/cbor-extract-darwin-x64-2.2.0.tgz", - "integrity": "sha512-1liF6fgowph0JxBbYnAS7ZlqNYLf000Qnj4KjqPNW4GViKrEql2MgZnAsExhY9LSy8dnvA4C0qHEBgPrll0z0w==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@cbor-extract/cbor-extract-linux-arm": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-linux-arm/-/cbor-extract-linux-arm-2.2.0.tgz", - "integrity": "sha512-QeBcBXk964zOytiedMPQNZr7sg0TNavZeuUCD6ON4vEOU/25+pLhNN6EDIKJ9VLTKaZ7K7EaAriyYQ1NQ05s/Q==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@cbor-extract/cbor-extract-linux-arm64": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-linux-arm64/-/cbor-extract-linux-arm64-2.2.0.tgz", - "integrity": "sha512-rQvhNmDuhjTVXSPFLolmQ47/ydGOFXtbR7+wgkSY0bdOxCFept1hvg59uiLPT2fVDuJFuEy16EImo5tE2x3RsQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@cbor-extract/cbor-extract-linux-x64": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-linux-x64/-/cbor-extract-linux-x64-2.2.0.tgz", - "integrity": "sha512-cWLAWtT3kNLHSvP4RKDzSTX9o0wvQEEAj4SKvhWuOVZxiDAeQazr9A+PSiRILK1VYMLeDml89ohxCnUNQNQNCw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@cbor-extract/cbor-extract-win32-x64": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-win32-x64/-/cbor-extract-win32-x64-2.2.0.tgz", - "integrity": "sha512-l2M+Z8DO2vbvADOBNLbbh9y5ST1RY5sqkWOg/58GkUPBYou/cuNZ68SGQ644f1CvZ8kcOxyZtw06+dxWHIoN/w==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@celo/base": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@celo/base/-/base-2.3.0.tgz", - "integrity": "sha512-Jo81eVGCPcKpUw9G4/uFE2x2TeYpS6BhEpmzmrkL86AU+EC93ES9UUlCcCpFSVRfoiHldIGp2QzyU+kAYap//Q==", - "license": "Apache-2.0" - }, - "node_modules/@celo/connect": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@celo/connect/-/connect-2.3.0.tgz", - "integrity": "sha512-p4oPU7ZafhaBXlX189I2jDTC9t5O9ayUywTsJMkSbsfz/q3RalTl+/YWM1m8twF2VdilAjOR1GiObbVVkYQLNQ==", - "deprecated": "Versions less than 5.1 are deprecated and will no longer be able to submit transactions to celo in a future hardfork", - "license": "Apache-2.0", + "node_modules/@metamask/object-multiplex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@metamask/object-multiplex/-/object-multiplex-2.1.0.tgz", + "integrity": "sha512-4vKIiv0DQxljcXwfpnbsXcfa5glMj5Zg9mqn4xpIWqkv6uJ2ma5/GtUfLFSxhlxnR8asRMv8dDmWya1Tc1sDFA==", "dependencies": { - "@celo/base": "2.3.0", - "@celo/utils": "2.3.0", - "@types/debug": "^4.1.5", - "@types/utf8": "^2.1.6", - "bignumber.js": "^9.0.0", - "debug": "^4.1.1", - "utf8": "3.0.0" + "once": "^1.4.0", + "readable-stream": "^3.6.2" }, "engines": { - "node": ">=8.13.0" - }, - "peerDependencies": { - "web3": "1.3.6" + "node": "^16.20 || ^18.16 || >=20" } }, - "node_modules/@celo/contractkit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@celo/contractkit/-/contractkit-2.3.0.tgz", - "integrity": "sha512-mctnQBp7GZAsuV4I47kTK3fBtjoL4uqd0LZ8wUmck+COJT9yW3DuQjPQwQvBxN6InKET9IeUmTuoTW4oAbW/FQ==", - "deprecated": "Versions less than 5.1 are deprecated and will no longer be able to submit transactions to celo in a future hardfork", - "license": "Apache-2.0", + "node_modules/@metamask/onboarding": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@metamask/onboarding/-/onboarding-1.0.1.tgz", + "integrity": "sha512-FqHhAsCI+Vacx2qa5mAFcWNSrTcVGMNjzxVgaX8ECSny/BJ9/vgXP9V7WF/8vb9DltPeQkxr+Fnfmm6GHfmdTQ==", "dependencies": { - "@celo/base": "2.3.0", - "@celo/connect": "2.3.0", - "@celo/utils": "2.3.0", - "@celo/wallet-local": "2.3.0", - "@types/bn.js": "^5.1.0", - "@types/debug": "^4.1.5", - "bignumber.js": "^9.0.0", - "cross-fetch": "^3.0.6", - "debug": "^4.1.1", - "fp-ts": "2.1.1", - "io-ts": "2.0.1", - "semver": "^7.3.5", - "web3": "1.3.6" + "bowser": "^2.9.0" + } + }, + "node_modules/@metamask/providers": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@metamask/providers/-/providers-16.1.0.tgz", + "integrity": "sha512-znVCvux30+3SaUwcUGaSf+pUckzT5ukPRpcBmy+muBLC0yaWnBcvDqGfcsw6CBIenUdFrVoAFa8B6jsuCY/a+g==", + "dependencies": { + "@metamask/json-rpc-engine": "^8.0.1", + "@metamask/json-rpc-middleware-stream": "^7.0.1", + "@metamask/object-multiplex": "^2.0.0", + "@metamask/rpc-errors": "^6.2.1", + "@metamask/safe-event-emitter": "^3.1.1", + "@metamask/utils": "^8.3.0", + "detect-browser": "^5.2.0", + "extension-port-stream": "^3.0.0", + "fast-deep-equal": "^3.1.3", + "is-stream": "^2.0.0", + "readable-stream": "^3.6.2", + "webextension-polyfill": "^0.10.0" }, "engines": { - "node": ">=8.13.0" + "node": "^18.18 || >=20" } }, - "node_modules/@celo/contractkit/node_modules/cross-fetch": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", - "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", - "license": "MIT", + "node_modules/@metamask/rpc-errors": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@metamask/rpc-errors/-/rpc-errors-6.4.0.tgz", + "integrity": "sha512-1ugFO1UoirU2esS3juZanS/Fo8C8XYocCuBpfZI5N7ECtoG+zu0wF+uWZASik6CkO6w9n/Iebt4iI4pT0vptpg==", "dependencies": { - "node-fetch": "^2.7.0" + "@metamask/utils": "^9.0.0", + "fast-safe-stringify": "^2.0.6" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@celo/contractkit/node_modules/fp-ts": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-2.1.1.tgz", - "integrity": "sha512-YcWhMdDCFCja0MmaDroTgNu+NWWrrnUEn92nvDgrtVy9Z71YFnhNVIghoHPt8gs82ijoMzFGeWKvArbyICiJgw==", - "license": "MIT" - }, - "node_modules/@celo/contractkit/node_modules/io-ts": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/io-ts/-/io-ts-2.0.1.tgz", - "integrity": "sha512-RezD+WcCfW4VkMkEcQWL/Nmy/nqsWTvTYg7oUmTGzglvSSV2P9h2z1PVeREPFf0GWNzruYleAt1XCMQZSg1xxQ==", - "license": "MIT", - "peerDependencies": { - "fp-ts": "^2.0.0" + "node_modules/@metamask/rpc-errors/node_modules/@metamask/utils": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-9.3.0.tgz", + "integrity": "sha512-w8CVbdkDrVXFJbfBSlDfafDR6BAkpDmv1bC1UJVCoVny5tW2RKAdn9i68Xf7asYT4TnUhl/hN4zfUiKQq9II4g==", + "dependencies": { + "@ethereumjs/tx": "^4.2.0", + "@metamask/superstruct": "^3.1.0", + "@noble/hashes": "^1.3.1", + "@scure/base": "^1.1.3", + "@types/debug": "^4.1.7", + "debug": "^4.3.4", + "pony-cause": "^2.1.10", + "semver": "^7.5.4", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@celo/contractkit/node_modules/semver": { + "node_modules/@metamask/rpc-errors/node_modules/semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -7079,12189 +5823,1401 @@ "node": ">=10" } }, - "node_modules/@celo/utils": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@celo/utils/-/utils-2.3.0.tgz", - "integrity": "sha512-K4Ga1rpYyFTTyhopHUHdeNehJN4qYT+cdf2BPgc6wS4AsI/G8vq91tmXOBJNL1oPVIbnW7MOp51IKJP51/zdhA==", - "license": "Apache-2.0", - "dependencies": { - "@celo/base": "2.3.0", - "@types/bn.js": "^5.1.0", - "@types/elliptic": "^6.4.9", - "@types/ethereumjs-util": "^5.2.0", - "@types/node": "^10.12.18", - "bignumber.js": "^9.0.0", - "elliptic": "^6.5.4", - "ethereumjs-util": "^5.2.0", - "io-ts": "2.0.1", - "web3-eth-abi": "1.3.6", - "web3-utils": "1.3.6" + "node_modules/@metamask/safe-event-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@metamask/safe-event-emitter/-/safe-event-emitter-3.1.2.tgz", + "integrity": "sha512-5yb2gMI1BDm0JybZezeoX/3XhPDOtTbcFvpTXM9kxsoZjPZFh4XciqRbpD6N86HYZqWDhEaKUDuOyR0sQHEjMA==", + "engines": { + "node": ">=12.0.0" } }, - "node_modules/@celo/utils/node_modules/@types/node": { - "version": "10.17.60", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", - "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==", - "license": "MIT" - }, - "node_modules/@celo/utils/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", - "license": "MIT" - }, - "node_modules/@celo/utils/node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "license": "MIT", - "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" - } - }, - "node_modules/@celo/utils/node_modules/ethereumjs-util": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", - "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", - "license": "MPL-2.0", + "node_modules/@metamask/sdk": { + "version": "0.30.1", + "resolved": "https://registry.npmjs.org/@metamask/sdk/-/sdk-0.30.1.tgz", + "integrity": "sha512-NelEjJZsF5wVpSQELpmvXtnS9+C6HdxGQ4GB9jMRzeejphmPyKqmrIGM6XtaPrJtlpX+40AcJ2dtBQcjJVzpbQ==", "dependencies": { - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "^0.1.3", - "rlp": "^2.0.0", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/@celo/utils/node_modules/io-ts": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/io-ts/-/io-ts-2.0.1.tgz", - "integrity": "sha512-RezD+WcCfW4VkMkEcQWL/Nmy/nqsWTvTYg7oUmTGzglvSSV2P9h2z1PVeREPFf0GWNzruYleAt1XCMQZSg1xxQ==", - "license": "MIT", + "@metamask/onboarding": "^1.0.1", + "@metamask/providers": "16.1.0", + "@metamask/sdk-communication-layer": "0.30.0", + "@metamask/sdk-install-modal-web": "0.30.0", + "bowser": "^2.9.0", + "cross-fetch": "^4.0.0", + "debug": "^4.3.4", + "eciesjs": "^0.4.8", + "eth-rpc-errors": "^4.0.3", + "eventemitter2": "^6.4.7", + "i18next": "23.11.5", + "i18next-browser-languagedetector": "7.1.0", + "obj-multiplex": "^1.0.0", + "pump": "^3.0.0", + "qrcode-terminal-nooctal": "^0.12.1", + "react-native-webview": "^11.26.0", + "readable-stream": "^3.6.2", + "socket.io-client": "^4.5.1", + "util": "^0.12.4", + "uuid": "^8.3.2" + }, "peerDependencies": { - "fp-ts": "^2.0.0" + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } } }, - "node_modules/@celo/utils/node_modules/node-addon-api": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", - "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", - "license": "MIT" - }, - "node_modules/@celo/utils/node_modules/secp256k1": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.4.tgz", - "integrity": "sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==", - "hasInstallScript": true, - "license": "MIT", + "node_modules/@metamask/sdk-communication-layer": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/@metamask/sdk-communication-layer/-/sdk-communication-layer-0.30.0.tgz", + "integrity": "sha512-q5nbdYkAf76MsZxi1l5MJEAyd8sY9jLRapC8a7x1Q1BNV4rzQeFeux/d0mJ/jTR2LAwbnLZs2rL226AM75oK4w==", "dependencies": { - "elliptic": "^6.5.7", - "node-addon-api": "^5.0.0", - "node-gyp-build": "^4.2.0" + "bufferutil": "^4.0.8", + "date-fns": "^2.29.3", + "debug": "^4.3.4", + "utf-8-validate": "^5.0.2", + "uuid": "^8.3.2" }, - "engines": { - "node": ">=18.0.0" + "peerDependencies": { + "cross-fetch": "^4.0.0", + "eciesjs": "^0.3.16", + "eventemitter2": "^6.4.7", + "readable-stream": "^3.6.2", + "socket.io-client": "^4.5.1" } }, - "node_modules/@celo/wallet-base": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@celo/wallet-base/-/wallet-base-2.3.0.tgz", - "integrity": "sha512-C5+t5Sx39Riul1EATPMq0bqWyHCAqoIRW4fU/5FrML+OYvpH+3SAIjJuxoD4vdj3gZZBWockg32PFp0TNb6e4g==", - "deprecated": "Versions less than 5.1 are deprecated and will no longer be able to submit transactions to celo in a future hardfork", - "license": "Apache-2.0", + "node_modules/@metamask/sdk-communication-layer/node_modules/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", "dependencies": { - "@celo/base": "2.3.0", - "@celo/connect": "2.3.0", - "@celo/utils": "2.3.0", - "@types/debug": "^4.1.5", - "@types/ethereumjs-util": "^5.2.0", - "bignumber.js": "^9.0.0", - "debug": "^4.1.1", - "eth-lib": "^0.2.8", - "ethereumjs-util": "^5.2.0" + "@babel/runtime": "^7.21.0" }, "engines": { - "node": ">=8.13.0" + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" } }, - "node_modules/@celo/wallet-base/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", - "license": "MIT" - }, - "node_modules/@celo/wallet-base/node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "license": "MIT", - "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" - } - }, - "node_modules/@celo/wallet-base/node_modules/ethereumjs-util": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", - "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", - "license": "MPL-2.0", - "dependencies": { - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "^0.1.3", - "rlp": "^2.0.0", - "safe-buffer": "^5.1.1" + "node_modules/@metamask/sdk-communication-layer/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" } }, - "node_modules/@celo/wallet-base/node_modules/node-addon-api": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", - "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", - "license": "MIT" - }, - "node_modules/@celo/wallet-base/node_modules/secp256k1": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.4.tgz", - "integrity": "sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==", - "hasInstallScript": true, - "license": "MIT", + "node_modules/@metamask/sdk-install-modal-web": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/@metamask/sdk-install-modal-web/-/sdk-install-modal-web-0.30.0.tgz", + "integrity": "sha512-1gT533Huja9tK3cmttvcpZirRAtWJ7vnYH+lnNRKEj2xIP335Df2cOwS+zqNC4GlRCZw7A3IsTjIzlKoxBY1uQ==", "dependencies": { - "elliptic": "^6.5.7", - "node-addon-api": "^5.0.0", - "node-gyp-build": "^4.2.0" + "qr-code-styling": "^1.6.0-rc.1" + }, + "peerDependencies": { + "i18next": "23.11.5", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-native": "*" }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, + "node_modules/@metamask/sdk/node_modules/@noble/hashes": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.5.0.tgz", + "integrity": "sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==", "engines": { - "node": ">=18.0.0" + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@celo/wallet-local": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@celo/wallet-local/-/wallet-local-2.3.0.tgz", - "integrity": "sha512-B2rg6DmKnHP98ixkIRH7I4aNFZVcj4e7wmB9z2LB08wAiuBFS4qsGp4ciplLb+AQuwbUSe8SpRSuKYxKUTQmFA==", - "license": "Apache-2.0", + "node_modules/@metamask/sdk/node_modules/eciesjs": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/eciesjs/-/eciesjs-0.4.11.tgz", + "integrity": "sha512-SmUG449n1w1YGvJD9R30tBGvpxTxA0cnn0rfvpFIBvmezfIhagLjsH2JG8HBHOLS8slXsPh48II7IDUTH/J3Mg==", "dependencies": { - "@celo/connect": "2.3.0", - "@celo/utils": "2.3.0", - "@celo/wallet-base": "2.3.0", - "@types/ethereumjs-util": "^5.2.0", - "eth-lib": "^0.2.8", - "ethereumjs-util": "^5.2.0" + "@ecies/ciphers": "^0.2.1", + "@noble/ciphers": "^1.0.0", + "@noble/curves": "^1.6.0", + "@noble/hashes": "^1.5.0" }, "engines": { - "node": ">=8.13.0" + "bun": ">=1", + "deno": ">=2", + "node": ">=16" } }, - "node_modules/@celo/wallet-local/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", - "license": "MIT" - }, - "node_modules/@celo/wallet-local/node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "license": "MIT", - "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" - } - }, - "node_modules/@celo/wallet-local/node_modules/ethereumjs-util": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", - "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", - "license": "MPL-2.0", - "dependencies": { - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "^0.1.3", - "rlp": "^2.0.0", - "safe-buffer": "^5.1.1" + "node_modules/@metamask/sdk/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" } }, - "node_modules/@celo/wallet-local/node_modules/node-addon-api": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", - "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", - "license": "MIT" - }, - "node_modules/@celo/wallet-local/node_modules/secp256k1": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.4.tgz", - "integrity": "sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "elliptic": "^6.5.7", - "node-addon-api": "^5.0.0", - "node-gyp-build": "^4.2.0" - }, + "node_modules/@metamask/superstruct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@metamask/superstruct/-/superstruct-3.1.0.tgz", + "integrity": "sha512-N08M56HdOgBfRKkrgCMZvQppkZGcArEop3kixNEtVbJKm6P9Cfg0YkI6X0s1g78sNrj2fWUwvJADdZuzJgFttA==", "engines": { - "node": ">=18.0.0" + "node": ">=16.0.0" } }, - "node_modules/@coinbase/wallet-sdk": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/@coinbase/wallet-sdk/-/wallet-sdk-4.2.3.tgz", - "integrity": "sha512-BcyHZ/Ec84z0emORzqdXDv4P0oV+tV3a0OirfA8Ko1JGBIAVvB+hzLvZzCDvnuZx7MTK+Dd8Y9Tjlo446BpCIg==", + "node_modules/@metamask/utils": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-8.5.0.tgz", + "integrity": "sha512-I6bkduevXb72TIM9q2LRO63JSsF9EXduh3sBr9oybNX2hNNpr/j1tEjXrsG0Uabm4MJ1xkGAQEMwifvKZIkyxQ==", "dependencies": { - "@noble/hashes": "^1.4.0", - "clsx": "^1.2.1", - "eventemitter3": "^5.0.1", - "preact": "^10.24.2" + "@ethereumjs/tx": "^4.2.0", + "@metamask/superstruct": "^3.0.0", + "@noble/hashes": "^1.3.1", + "@scure/base": "^1.1.3", + "@types/debug": "^4.1.7", + "debug": "^4.3.4", + "pony-cause": "^2.1.10", + "semver": "^7.5.4", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@coinbase/wallet-sdk/node_modules/clsx": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", - "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "node_modules/@metamask/utils/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">=6" + "node": ">=10" } }, - "node_modules/@coinbase/wallet-sdk/node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" + "node_modules/@microsoft/tsdoc": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.15.0.tgz", + "integrity": "sha512-HZpPoABogPvjeJOdzCOSJsXeL/SMCBgBZMVC3X3d7YYp2gf31MfxhUoYUNwf1ERPJOnQc0wkFn9trqI6ZEdZuA==" }, - "node_modules/@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "optional": true, - "engines": { - "node": ">=0.1.90" + "node_modules/@module-federation/bridge-react-webpack-plugin": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@module-federation/bridge-react-webpack-plugin/-/bridge-react-webpack-plugin-0.2.8.tgz", + "integrity": "sha512-6G1qTo1HWvRcN5fzE+SZgvgzSPoq5YqNx8hFL8BttJmnd3wj4SUOFiikAsXhdVrzSK+Zuzg6pipkiLH1m+pbtw==", + "dev": true, + "dependencies": { + "@module-federation/sdk": "0.2.8" } }, - "node_modules/@confio/ics23": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/@confio/ics23/-/ics23-0.6.8.tgz", - "integrity": "sha512-wB6uo+3A50m0sW/EWcU64xpV/8wShZ6bMTa7pF8eYsTrSkQA7oLUIJcs/wb8g4y2Oyq701BaGiO6n/ak5WXO1w==", - "deprecated": "Unmaintained. The codebase for this package was moved to https://github.com/cosmos/ics23 but then the JS implementation was removed in https://github.com/cosmos/ics23/pull/353. Please consult the maintainers of https://github.com/cosmos for further assistance.", - "license": "Apache-2.0", + "node_modules/@module-federation/dts-plugin": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@module-federation/dts-plugin/-/dts-plugin-0.2.8.tgz", + "integrity": "sha512-qY1Wbqo0yu9nh6KR8K19t5T4tYtlUbmcNdcaCweISCyAbH99TrhpQkJ89NY0TLtnxQ6uayIYayqAWS7vzyDXVw==", + "dev": true, "dependencies": { - "@noble/hashes": "^1.0.0", - "protobufjs": "^6.8.8" + "@module-federation/managers": "0.2.8", + "@module-federation/sdk": "0.2.8", + "@module-federation/third-party-dts-extractor": "0.2.8", + "adm-zip": "^0.5.10", + "ansi-colors": "^4.1.3", + "axios": "^1.6.7", + "chalk": "3.0.0", + "fs-extra": "9.1.0", + "isomorphic-ws": "5.0.0", + "koa": "2.11.0", + "lodash.clonedeepwith": "4.5.0", + "log4js": "6.9.1", + "node-schedule": "2.1.1", + "rambda": "^9.1.0", + "ws": "8.17.1" + }, + "peerDependencies": { + "typescript": "^4.9.0 || ^5.0.0", + "vue-tsc": ">=1.0.24" + }, + "peerDependenciesMeta": { + "vue-tsc": { + "optional": true + } } }, - "node_modules/@confio/ics23/node_modules/long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", - "license": "Apache-2.0" - }, - "node_modules/@confio/ics23/node_modules/protobufjs": { - "version": "6.11.4", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.4.tgz", - "integrity": "sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw==", - "hasInstallScript": true, - "license": "BSD-3-Clause", + "node_modules/@module-federation/dts-plugin/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": 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/long": "^4.0.1", - "@types/node": ">=13.7.0", - "long": "^4.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, - "bin": { - "pbjs": "bin/pbjs", - "pbts": "bin/pbts" + "engines": { + "node": ">=8" } }, - "node_modules/@cosmjs/amino": { - "version": "0.29.5", - "resolved": "https://registry.npmjs.org/@cosmjs/amino/-/amino-0.29.5.tgz", - "integrity": "sha512-Qo8jpC0BiziTSUqpkNatBcwtKNhCovUnFul9SlT/74JUCdLYaeG5hxr3q1cssQt++l4LvlcpF+OUXL48XjNjLw==", - "license": "Apache-2.0", + "node_modules/@module-federation/dts-plugin/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, "dependencies": { - "@cosmjs/crypto": "^0.29.5", - "@cosmjs/encoding": "^0.29.5", - "@cosmjs/math": "^0.29.5", - "@cosmjs/utils": "^0.29.5" + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" } }, - "node_modules/@cosmjs/amino/node_modules/@cosmjs/crypto": { - "version": "0.29.5", - "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.29.5.tgz", - "integrity": "sha512-2bKkaLGictaNL0UipQCL6C1afaisv6k8Wr/GCLx9FqiyFkh9ZgRHDyetD64ZsjnWV/N/D44s/esI+k6oPREaiQ==", - "license": "Apache-2.0", - "dependencies": { - "@cosmjs/encoding": "^0.29.5", - "@cosmjs/math": "^0.29.5", - "@cosmjs/utils": "^0.29.5", - "@noble/hashes": "^1", - "bn.js": "^5.2.0", - "elliptic": "^6.5.4", - "libsodium-wrappers": "^0.7.6" + "node_modules/@module-federation/dts-plugin/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, - "node_modules/@cosmjs/crypto": { - "version": "0.30.1", - "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.30.1.tgz", - "integrity": "sha512-rAljUlake3MSXs9xAm87mu34GfBLN0h/1uPPV6jEwClWjNkAMotzjC0ab9MARy5FFAvYHL3lWb57bhkbt2GtzQ==", - "license": "Apache-2.0", + "node_modules/@module-federation/enhanced": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@module-federation/enhanced/-/enhanced-0.2.8.tgz", + "integrity": "sha512-6fGM/GiKw6LZiBe6DF8Petz6ih/Yyf3q2htLrx+hrWoDWfWEoWlLvoCUsVkY2UgMCLKid7Fm3Auc4w8A4aRjvQ==", + "dev": true, "dependencies": { - "@cosmjs/encoding": "^0.30.1", - "@cosmjs/math": "^0.30.1", - "@cosmjs/utils": "^0.30.1", - "@noble/hashes": "^1", - "bn.js": "^5.2.0", - "elliptic": "^6.5.4", - "libsodium-wrappers": "^0.7.6" + "@module-federation/bridge-react-webpack-plugin": "0.2.8", + "@module-federation/dts-plugin": "0.2.8", + "@module-federation/managers": "0.2.8", + "@module-federation/manifest": "0.2.8", + "@module-federation/rspack": "0.2.8", + "@module-federation/runtime-tools": "0.2.8", + "@module-federation/sdk": "0.2.8", + "btoa": "^1.2.1", + "upath": "2.0.1" + }, + "peerDependencies": { + "typescript": "^4.9.0 || ^5.0.0", + "vue-tsc": ">=1.0.24", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "vue-tsc": { + "optional": true + }, + "webpack": { + "optional": true + } } }, - "node_modules/@cosmjs/crypto/node_modules/@cosmjs/encoding": { - "version": "0.30.1", - "resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.30.1.tgz", - "integrity": "sha512-rXmrTbgqwihORwJ3xYhIgQFfMSrwLu1s43RIK9I8EBudPx3KmnmyAKzMOVsRDo9edLFNuZ9GIvysUCwQfq3WlQ==", - "license": "Apache-2.0", + "node_modules/@module-federation/managers": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@module-federation/managers/-/managers-0.2.8.tgz", + "integrity": "sha512-S5GXqt2Vrs1+uNXHw7UzZ7m3fs8H3nxNsNGQ0j5+HiT5yA7uRTY1AZJZCGAHzG6XImJ1DzL/SW1acM2Hwj0aAw==", + "dev": true, "dependencies": { - "base64-js": "^1.3.0", - "bech32": "^1.1.4", - "readonly-date": "^1.0.0" + "@module-federation/sdk": "0.2.8", + "find-pkg": "2.0.0", + "fs-extra": "9.1.0" } }, - "node_modules/@cosmjs/crypto/node_modules/@cosmjs/math": { - "version": "0.30.1", - "resolved": "https://registry.npmjs.org/@cosmjs/math/-/math-0.30.1.tgz", - "integrity": "sha512-yaoeI23pin9ZiPHIisa6qqLngfnBR/25tSaWpkTm8Cy10MX70UF5oN4+/t1heLaM6SSmRrhk3psRkV4+7mH51Q==", - "license": "Apache-2.0", + "node_modules/@module-federation/managers/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, "dependencies": { - "bn.js": "^5.2.0" + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" } }, - "node_modules/@cosmjs/crypto/node_modules/@cosmjs/utils": { - "version": "0.30.1", - "resolved": "https://registry.npmjs.org/@cosmjs/utils/-/utils-0.30.1.tgz", - "integrity": "sha512-KvvX58MGMWh7xA+N+deCfunkA/ZNDvFLw4YbOmX3f/XBIkqrVY7qlotfy2aNb1kgp6h4B6Yc8YawJPDTfvWX7g==", - "license": "Apache-2.0" - }, - "node_modules/@cosmjs/crypto/node_modules/bech32": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", - "license": "MIT" - }, - "node_modules/@cosmjs/encoding": { - "version": "0.29.5", - "resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.29.5.tgz", - "integrity": "sha512-G4rGl/Jg4dMCw5u6PEZHZcoHnUBlukZODHbm/wcL4Uu91fkn5jVo5cXXZcvs4VCkArVGrEj/52eUgTZCmOBGWQ==", - "license": "Apache-2.0", + "node_modules/@module-federation/manifest": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@module-federation/manifest/-/manifest-0.2.8.tgz", + "integrity": "sha512-kw4PeAldkOuGCWfCnDzZwPHUx5qv9+WztY5+TEbsgXc5E+/e2NDA6Gg3eT8zUGeexeGdab3f+DuN9ZClZJYVGA==", + "dev": true, "dependencies": { - "base64-js": "^1.3.0", - "bech32": "^1.1.4", - "readonly-date": "^1.0.0" + "@module-federation/dts-plugin": "0.2.8", + "@module-federation/managers": "0.2.8", + "@module-federation/sdk": "0.2.8", + "chalk": "3.0.0", + "find-pkg": "2.0.0" } }, - "node_modules/@cosmjs/encoding/node_modules/bech32": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", - "license": "MIT" - }, - "node_modules/@cosmjs/json-rpc": { - "version": "0.29.5", - "resolved": "https://registry.npmjs.org/@cosmjs/json-rpc/-/json-rpc-0.29.5.tgz", - "integrity": "sha512-C78+X06l+r9xwdM1yFWIpGl03LhB9NdM1xvZpQHwgCOl0Ir/WV8pw48y3Ez2awAoUBRfTeejPe4KvrE6NoIi/w==", - "license": "Apache-2.0", + "node_modules/@module-federation/manifest/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, "dependencies": { - "@cosmjs/stream": "^0.29.5", - "xstream": "^11.14.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@cosmjs/math": { - "version": "0.29.5", - "resolved": "https://registry.npmjs.org/@cosmjs/math/-/math-0.29.5.tgz", - "integrity": "sha512-2GjKcv+A9f86MAWYLUkjhw1/WpRl2R1BTb3m9qPG7lzMA7ioYff9jY5SPCfafKdxM4TIQGxXQlYGewQL16O68Q==", - "license": "Apache-2.0", + "node_modules/@module-federation/rspack": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@module-federation/rspack/-/rspack-0.2.8.tgz", + "integrity": "sha512-5Bofm3cY7OOwO2DT5TevITd+HAA03zsY1wwsMb1BP6NkS/ukUtsjuRo2Anua0RkHBEIx+Dv5rpqOn7qSlOm1Fg==", + "dev": true, "dependencies": { - "bn.js": "^5.2.0" + "@module-federation/bridge-react-webpack-plugin": "0.2.8", + "@module-federation/dts-plugin": "0.2.8", + "@module-federation/managers": "0.2.8", + "@module-federation/manifest": "0.2.8", + "@module-federation/runtime-tools": "0.2.8", + "@module-federation/sdk": "0.2.8" + }, + "peerDependencies": { + "typescript": "^4.9.0 || ^5.0.0", + "vue-tsc": ">=1.0.24" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "vue-tsc": { + "optional": true + } } }, - "node_modules/@cosmjs/proto-signing": { - "version": "0.29.5", - "resolved": "https://registry.npmjs.org/@cosmjs/proto-signing/-/proto-signing-0.29.5.tgz", - "integrity": "sha512-QRrS7CiKaoETdgIqvi/7JC2qCwCR7lnWaUsTzh/XfRy3McLkEd+cXbKAW3cygykv7IN0VAEIhZd2lyIfT8KwNA==", - "license": "Apache-2.0", + "node_modules/@module-federation/runtime": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@module-federation/runtime/-/runtime-0.2.8.tgz", + "integrity": "sha512-8xmA/+z1zD09F5qU8VnSWLExqTCVWoHOguXsCX79kkqp7i0c+D2YaebWzlQ2kku+DU+0VIzXpQ3BBcumZ3v3wQ==", + "dev": true, "dependencies": { - "@cosmjs/amino": "^0.29.5", - "@cosmjs/crypto": "^0.29.5", - "@cosmjs/encoding": "^0.29.5", - "@cosmjs/math": "^0.29.5", - "@cosmjs/utils": "^0.29.5", - "cosmjs-types": "^0.5.2", - "long": "^4.0.0" + "@module-federation/sdk": "0.2.8" } }, - "node_modules/@cosmjs/proto-signing/node_modules/@cosmjs/crypto": { - "version": "0.29.5", - "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.29.5.tgz", - "integrity": "sha512-2bKkaLGictaNL0UipQCL6C1afaisv6k8Wr/GCLx9FqiyFkh9ZgRHDyetD64ZsjnWV/N/D44s/esI+k6oPREaiQ==", - "license": "Apache-2.0", + "node_modules/@module-federation/runtime-tools": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@module-federation/runtime-tools/-/runtime-tools-0.2.8.tgz", + "integrity": "sha512-RSNtyhcNvnTQIdzRUIOGue6WQA/9mL9cY/n0dEd357L/lmLCvfHiZbowlkacckDzyApariUHxzkHrU2Q6kzoew==", + "dev": true, "dependencies": { - "@cosmjs/encoding": "^0.29.5", - "@cosmjs/math": "^0.29.5", - "@cosmjs/utils": "^0.29.5", - "@noble/hashes": "^1", - "bn.js": "^5.2.0", - "elliptic": "^6.5.4", - "libsodium-wrappers": "^0.7.6" + "@module-federation/runtime": "0.2.8", + "@module-federation/webpack-bundler-runtime": "0.2.8" } }, - "node_modules/@cosmjs/proto-signing/node_modules/cosmjs-types": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/cosmjs-types/-/cosmjs-types-0.5.2.tgz", - "integrity": "sha512-zxCtIJj8v3Di7s39uN4LNcN3HIE1z0B9Z0SPE8ZNQR0oSzsuSe1ACgxoFkvhkS7WBasCAFcglS11G2hyfd5tPg==", - "license": "Apache-2.0", + "node_modules/@module-federation/sdk": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@module-federation/sdk/-/sdk-0.2.8.tgz", + "integrity": "sha512-eGMnJxdRDgt6dtMv8gkAlzEbTPWVHb3AHUNUG0w56wcbIF0RHC6kmvpHpSQyq4DVGWv3U4g/ZiH5BvBlqEelDQ==", + "dev": true + }, + "node_modules/@module-federation/third-party-dts-extractor": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@module-federation/third-party-dts-extractor/-/third-party-dts-extractor-0.2.8.tgz", + "integrity": "sha512-VGXvdsRlljbFUfGeA448CxR7i6fLWJN07ViRuNXYYXc19e4bQVhBHzrf7eCv9ahcf/tA/8YYCS2h11ixbD691A==", + "dev": true, "dependencies": { - "long": "^4.0.0", - "protobufjs": "~6.11.2" + "find-pkg": "2.0.0", + "fs-extra": "9.1.0", + "resolve": "1.22.8" } }, - "node_modules/@cosmjs/proto-signing/node_modules/long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", - "license": "Apache-2.0" - }, - "node_modules/@cosmjs/proto-signing/node_modules/protobufjs": { - "version": "6.11.4", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.4.tgz", - "integrity": "sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw==", - "hasInstallScript": true, - "license": "BSD-3-Clause", + "node_modules/@module-federation/third-party-dts-extractor/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": 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/long": "^4.0.1", - "@types/node": ">=13.7.0", - "long": "^4.0.0" + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, - "bin": { - "pbjs": "bin/pbjs", - "pbts": "bin/pbts" + "engines": { + "node": ">=10" } }, - "node_modules/@cosmjs/socket": { - "version": "0.29.5", - "resolved": "https://registry.npmjs.org/@cosmjs/socket/-/socket-0.29.5.tgz", - "integrity": "sha512-5VYDupIWbIXq3ftPV1LkS5Ya/T7Ol/AzWVhNxZ79hPe/mBfv1bGau/LqIYOm2zxGlgm9hBHOTmWGqNYDwr9LNQ==", - "license": "Apache-2.0", + "node_modules/@module-federation/webpack-bundler-runtime": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@module-federation/webpack-bundler-runtime/-/webpack-bundler-runtime-0.2.8.tgz", + "integrity": "sha512-tiW1kD/V3QNul1/O3Y3lwQv/r4sUU4jvWZykrLvHYt2vuoGe1d4tHnSIFEVEAi9FSpuDwdRK2+NaWBr92gIS7Q==", + "dev": true, "dependencies": { - "@cosmjs/stream": "^0.29.5", - "isomorphic-ws": "^4.0.1", - "ws": "^7", - "xstream": "^11.14.0" + "@module-federation/runtime": "0.2.8", + "@module-federation/sdk": "0.2.8" } }, - "node_modules/@cosmjs/socket/node_modules/isomorphic-ws": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", - "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", - "license": "MIT", + "node_modules/@monaco-editor/loader": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.4.0.tgz", + "integrity": "sha512-00ioBig0x642hytVspPl7DbQyaSWRaolYie/UFNjoTdvoKPzo6xrXLhTk9ixgIKcLH5b5vDOjVNiGyY+uDCUlg==", + "dependencies": { + "state-local": "^1.0.6" + }, "peerDependencies": { - "ws": "*" + "monaco-editor": ">= 0.21.0 < 1" } }, - "node_modules/@cosmjs/socket/node_modules/ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "license": "MIT", - "engines": { - "node": ">=8.3.0" + "node_modules/@monaco-editor/react": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.6.0.tgz", + "integrity": "sha512-RFkU9/i7cN2bsq/iTkurMWOEErmYcY6JiQI3Jn+WeR/FGISH8JbHERjpS9oRuSOPvDMJI0Z8nJeKkbOs9sBYQw==", + "dependencies": { + "@monaco-editor/loader": "^1.4.0" }, "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "monaco-editor": ">= 0.25.0 < 1", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/@cosmjs/stargate": { - "version": "0.29.5", - "resolved": "https://registry.npmjs.org/@cosmjs/stargate/-/stargate-0.29.5.tgz", - "integrity": "sha512-hjEv8UUlJruLrYGJcUZXM/CziaINOKwfVm2BoSdUnNTMxGvY/jC1ABHKeZUYt9oXHxEJ1n9+pDqzbKc8pT0nBw==", - "license": "Apache-2.0", - "dependencies": { - "@confio/ics23": "^0.6.8", - "@cosmjs/amino": "^0.29.5", - "@cosmjs/encoding": "^0.29.5", - "@cosmjs/math": "^0.29.5", - "@cosmjs/proto-signing": "^0.29.5", - "@cosmjs/stream": "^0.29.5", - "@cosmjs/tendermint-rpc": "^0.29.5", - "@cosmjs/utils": "^0.29.5", - "cosmjs-types": "^0.5.2", - "long": "^4.0.0", - "protobufjs": "~6.11.3", - "xstream": "^11.14.0" - } - }, - "node_modules/@cosmjs/stargate/node_modules/cosmjs-types": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/cosmjs-types/-/cosmjs-types-0.5.2.tgz", - "integrity": "sha512-zxCtIJj8v3Di7s39uN4LNcN3HIE1z0B9Z0SPE8ZNQR0oSzsuSe1ACgxoFkvhkS7WBasCAFcglS11G2hyfd5tPg==", - "license": "Apache-2.0", + "node_modules/@motionone/animation": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/animation/-/animation-10.18.0.tgz", + "integrity": "sha512-9z2p5GFGCm0gBsZbi8rVMOAJCtw1WqBTIPw3ozk06gDvZInBPIsQcHgYogEJ4yuHJ+akuW8g1SEIOpTOvYs8hw==", "dependencies": { - "long": "^4.0.0", - "protobufjs": "~6.11.2" + "@motionone/easing": "^10.18.0", + "@motionone/types": "^10.17.1", + "@motionone/utils": "^10.18.0", + "tslib": "^2.3.1" } }, - "node_modules/@cosmjs/stargate/node_modules/long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", - "license": "Apache-2.0" - }, - "node_modules/@cosmjs/stargate/node_modules/protobufjs": { - "version": "6.11.4", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.4.tgz", - "integrity": "sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw==", - "hasInstallScript": true, - "license": "BSD-3-Clause", + "node_modules/@motionone/dom": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/dom/-/dom-10.18.0.tgz", + "integrity": "sha512-bKLP7E0eyO4B2UaHBBN55tnppwRnaE3KFfh3Ps9HhnAkar3Cb69kUCJY9as8LrccVYKgHA+JY5dOQqJLOPhF5A==", "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/long": "^4.0.1", - "@types/node": ">=13.7.0", - "long": "^4.0.0" - }, - "bin": { - "pbjs": "bin/pbjs", - "pbts": "bin/pbts" + "@motionone/animation": "^10.18.0", + "@motionone/generators": "^10.18.0", + "@motionone/types": "^10.17.1", + "@motionone/utils": "^10.18.0", + "hey-listen": "^1.0.8", + "tslib": "^2.3.1" } }, - "node_modules/@cosmjs/stream": { - "version": "0.29.5", - "resolved": "https://registry.npmjs.org/@cosmjs/stream/-/stream-0.29.5.tgz", - "integrity": "sha512-TToTDWyH1p05GBtF0Y8jFw2C+4783ueDCmDyxOMM6EU82IqpmIbfwcdMOCAm0JhnyMh+ocdebbFvnX/sGKzRAA==", - "license": "Apache-2.0", + "node_modules/@motionone/easing": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/easing/-/easing-10.18.0.tgz", + "integrity": "sha512-VcjByo7XpdLS4o9T8t99JtgxkdMcNWD3yHU/n6CLEz3bkmKDRZyYQ/wmSf6daum8ZXqfUAgFeCZSpJZIMxaCzg==", "dependencies": { - "xstream": "^11.14.0" + "@motionone/utils": "^10.18.0", + "tslib": "^2.3.1" } }, - "node_modules/@cosmjs/tendermint-rpc": { - "version": "0.29.5", - "resolved": "https://registry.npmjs.org/@cosmjs/tendermint-rpc/-/tendermint-rpc-0.29.5.tgz", - "integrity": "sha512-ar80twieuAxsy0x2za/aO3kBr2DFPAXDmk2ikDbmkda+qqfXgl35l9CVAAjKRqd9d+cRvbQyb5M4wy6XQpEV6w==", - "license": "Apache-2.0", - "dependencies": { - "@cosmjs/crypto": "^0.29.5", - "@cosmjs/encoding": "^0.29.5", - "@cosmjs/json-rpc": "^0.29.5", - "@cosmjs/math": "^0.29.5", - "@cosmjs/socket": "^0.29.5", - "@cosmjs/stream": "^0.29.5", - "@cosmjs/utils": "^0.29.5", - "axios": "^0.21.2", - "readonly-date": "^1.0.0", - "xstream": "^11.14.0" - } - }, - "node_modules/@cosmjs/tendermint-rpc/node_modules/@cosmjs/crypto": { - "version": "0.29.5", - "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.29.5.tgz", - "integrity": "sha512-2bKkaLGictaNL0UipQCL6C1afaisv6k8Wr/GCLx9FqiyFkh9ZgRHDyetD64ZsjnWV/N/D44s/esI+k6oPREaiQ==", - "license": "Apache-2.0", + "node_modules/@motionone/generators": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/generators/-/generators-10.18.0.tgz", + "integrity": "sha512-+qfkC2DtkDj4tHPu+AFKVfR/C30O1vYdvsGYaR13W/1cczPrrcjdvYCj0VLFuRMN+lP1xvpNZHCRNM4fBzn1jg==", "dependencies": { - "@cosmjs/encoding": "^0.29.5", - "@cosmjs/math": "^0.29.5", - "@cosmjs/utils": "^0.29.5", - "@noble/hashes": "^1", - "bn.js": "^5.2.0", - "elliptic": "^6.5.4", - "libsodium-wrappers": "^0.7.6" + "@motionone/types": "^10.17.1", + "@motionone/utils": "^10.18.0", + "tslib": "^2.3.1" } }, - "node_modules/@cosmjs/tendermint-rpc/node_modules/axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", - "license": "MIT", + "node_modules/@motionone/svelte": { + "version": "10.16.4", + "resolved": "https://registry.npmjs.org/@motionone/svelte/-/svelte-10.16.4.tgz", + "integrity": "sha512-zRVqk20lD1xqe+yEDZhMYgftsuHc25+9JSo+r0a0OWUJFocjSV9D/+UGhX4xgJsuwB9acPzXLr20w40VnY2PQA==", "dependencies": { - "follow-redirects": "^1.14.0" + "@motionone/dom": "^10.16.4", + "tslib": "^2.3.1" } }, - "node_modules/@cosmjs/utils": { - "version": "0.29.5", - "resolved": "https://registry.npmjs.org/@cosmjs/utils/-/utils-0.29.5.tgz", - "integrity": "sha512-m7h+RXDUxOzEOGt4P+3OVPX7PuakZT3GBmaM/Y2u+abN3xZkziykD/NvedYFvvCCdQo714XcGl33bwifS9FZPQ==", - "license": "Apache-2.0" - }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" - } + "node_modules/@motionone/types": { + "version": "10.17.1", + "resolved": "https://registry.npmjs.org/@motionone/types/-/types-10.17.1.tgz", + "integrity": "sha512-KaC4kgiODDz8hswCrS0btrVrzyU2CSQKO7Ps90ibBVSQmjkrt2teqta6/sOG59v7+dPnKMAg13jyqtMKV2yJ7A==" }, - "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, + "node_modules/@motionone/utils": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/utils/-/utils-10.18.0.tgz", + "integrity": "sha512-3XVF7sgyTSI2KWvTf6uLlBJ5iAgRgmvp3bpuOiQJvInd4nZ19ET8lX5unn30SlmRH7hXbBbH+Gxd0m0klJ3Xtw==", "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@motionone/types": "^10.17.1", + "hey-listen": "^1.0.8", + "tslib": "^2.3.1" } }, - "node_modules/@dabh/diagnostics": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", - "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", + "node_modules/@motionone/vue": { + "version": "10.16.4", + "resolved": "https://registry.npmjs.org/@motionone/vue/-/vue-10.16.4.tgz", + "integrity": "sha512-z10PF9JV6SbjFq+/rYabM+8CVlMokgl8RFGvieSGNTmrkQanfHn+15XBrhG3BgUfvmTeSeyShfOHpG0i9zEdcg==", + "deprecated": "Motion One for Vue is deprecated. Use Oku Motion instead https://oku-ui.com/motion", "dependencies": { - "colorspace": "1.1.x", - "enabled": "2.0.x", - "kuler": "^2.0.0" - } - }, - "node_modules/@discoveryjs/json-ext": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", - "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", - "engines": { - "node": ">=10.0.0" + "@motionone/dom": "^10.16.4", + "tslib": "^2.3.1" } }, - "node_modules/@docsearch/css": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.6.1.tgz", - "integrity": "sha512-VtVb5DS+0hRIprU2CO6ZQjK2Zg4QU5HrDM1+ix6rT0umsYvFvatMAnf97NHZlVWDaaLlx7GRfR/7FikANiM2Fg==" + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz", + "integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@docsearch/react": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.6.1.tgz", - "integrity": "sha512-qXZkEPvybVhSXj0K7U3bXc233tk5e8PfhoZ6MhPOiik/qUQxYC+Dn9DnoS7CxHQQhHfCvTiN0eY9M12oRghEXw==", - "dependencies": { - "@algolia/autocomplete-core": "1.9.3", - "@algolia/autocomplete-preset-algolia": "1.9.3", - "@docsearch/css": "3.6.1", - "algoliasearch": "^4.19.1" - }, - "peerDependencies": { - "@types/react": ">= 16.8.0 < 19.0.0", - "react": ">= 16.8.0 < 19.0.0", - "react-dom": ">= 16.8.0 < 19.0.0", - "search-insights": ">= 1 < 3" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "react": { - "optional": true - }, - "react-dom": { - "optional": true - }, - "search-insights": { - "optional": true - } - } - }, - "node_modules/@docusaurus/core": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.4.0.tgz", - "integrity": "sha512-g+0wwmN2UJsBqy2fQRQ6fhXruoEa62JDeEa5d8IdTJlMoaDaEDfHh7WjwGRn4opuTQWpjAwP/fbcgyHKlE+64w==", - "dependencies": { - "@babel/core": "^7.23.3", - "@babel/generator": "^7.23.3", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-runtime": "^7.22.9", - "@babel/preset-env": "^7.22.9", - "@babel/preset-react": "^7.22.5", - "@babel/preset-typescript": "^7.22.5", - "@babel/runtime": "^7.22.6", - "@babel/runtime-corejs3": "^7.22.6", - "@babel/traverse": "^7.22.8", - "@docusaurus/cssnano-preset": "3.4.0", - "@docusaurus/logger": "3.4.0", - "@docusaurus/mdx-loader": "3.4.0", - "@docusaurus/utils": "3.4.0", - "@docusaurus/utils-common": "3.4.0", - "@docusaurus/utils-validation": "3.4.0", - "autoprefixer": "^10.4.14", - "babel-loader": "^9.1.3", - "babel-plugin-dynamic-import-node": "^2.3.3", - "boxen": "^6.2.1", - "chalk": "^4.1.2", - "chokidar": "^3.5.3", - "clean-css": "^5.3.2", - "cli-table3": "^0.6.3", - "combine-promises": "^1.1.0", - "commander": "^5.1.0", - "copy-webpack-plugin": "^11.0.0", - "core-js": "^3.31.1", - "css-loader": "^6.8.1", - "css-minimizer-webpack-plugin": "^5.0.1", - "cssnano": "^6.1.2", - "del": "^6.1.1", - "detect-port": "^1.5.1", - "escape-html": "^1.0.3", - "eta": "^2.2.0", - "eval": "^0.1.8", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "html-minifier-terser": "^7.2.0", - "html-tags": "^3.3.1", - "html-webpack-plugin": "^5.5.3", - "leven": "^3.1.0", - "lodash": "^4.17.21", - "mini-css-extract-plugin": "^2.7.6", - "p-map": "^4.0.0", - "postcss": "^8.4.26", - "postcss-loader": "^7.3.3", - "prompts": "^2.4.2", - "react-dev-utils": "^12.0.1", - "react-helmet-async": "^1.3.0", - "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", - "react-loadable-ssr-addon-v5-slorber": "^1.0.1", - "react-router": "^5.3.4", - "react-router-config": "^5.1.1", - "react-router-dom": "^5.3.4", - "rtl-detect": "^1.0.4", - "semver": "^7.5.4", - "serve-handler": "^6.1.5", - "shelljs": "^0.8.5", - "terser-webpack-plugin": "^5.3.9", - "tslib": "^2.6.0", - "update-notifier": "^6.0.2", - "url-loader": "^4.1.1", - "webpack": "^5.88.1", - "webpack-bundle-analyzer": "^4.9.0", - "webpack-dev-server": "^4.15.1", - "webpack-merge": "^5.9.0", - "webpackbar": "^5.0.2" - }, - "bin": { - "docusaurus": "bin/docusaurus.mjs" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/core/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@docusaurus/cssnano-preset": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.4.0.tgz", - "integrity": "sha512-qwLFSz6v/pZHy/UP32IrprmH5ORce86BGtN0eBtG75PpzQJAzp9gefspox+s8IEOr0oZKuQ/nhzZ3xwyc3jYJQ==", - "dependencies": { - "cssnano-preset-advanced": "^6.1.2", - "postcss": "^8.4.38", - "postcss-sort-media-queries": "^5.2.0", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=18.0" - } - }, - "node_modules/@docusaurus/logger": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.4.0.tgz", - "integrity": "sha512-bZwkX+9SJ8lB9kVRkXw+xvHYSMGG4bpYHKGXeXFvyVc79NMeeBSGgzd4TQLHH+DYeOJoCdl8flrFJVxlZ0wo/Q==", - "dependencies": { - "chalk": "^4.1.2", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=18.0" - } - }, - "node_modules/@docusaurus/mdx-loader": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.4.0.tgz", - "integrity": "sha512-kSSbrrk4nTjf4d+wtBA9H+FGauf2gCax89kV8SUSJu3qaTdSIKdWERlngsiHaCFgZ7laTJ8a67UFf+xlFPtuTw==", - "dependencies": { - "@docusaurus/logger": "3.4.0", - "@docusaurus/utils": "3.4.0", - "@docusaurus/utils-validation": "3.4.0", - "@mdx-js/mdx": "^3.0.0", - "@slorber/remark-comment": "^1.0.0", - "escape-html": "^1.0.3", - "estree-util-value-to-estree": "^3.0.1", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "image-size": "^1.0.2", - "mdast-util-mdx": "^3.0.0", - "mdast-util-to-string": "^4.0.0", - "rehype-raw": "^7.0.0", - "remark-directive": "^3.0.0", - "remark-emoji": "^4.0.0", - "remark-frontmatter": "^5.0.0", - "remark-gfm": "^4.0.0", - "stringify-object": "^3.3.0", - "tslib": "^2.6.0", - "unified": "^11.0.3", - "unist-util-visit": "^5.0.0", - "url-loader": "^4.1.1", - "vfile": "^6.0.1", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/module-type-aliases": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.4.0.tgz", - "integrity": "sha512-A1AyS8WF5Bkjnb8s+guTDuYmUiwJzNrtchebBHpc0gz0PyHJNMaybUlSrmJjHVcGrya0LKI4YcR3lBDQfXRYLw==", - "dependencies": { - "@docusaurus/types": "3.4.0", - "@types/history": "^4.7.11", - "@types/react": "*", - "@types/react-router-config": "*", - "@types/react-router-dom": "*", - "react-helmet-async": "*", - "react-loadable": "npm:@docusaurus/react-loadable@6.0.0" - }, - "peerDependencies": { - "react": "*", - "react-dom": "*" - } - }, - "node_modules/@docusaurus/module-type-aliases/node_modules/@docusaurus/types": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", - "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", - "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "^1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/plugin-content-blog": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.4.0.tgz", - "integrity": "sha512-vv6ZAj78ibR5Jh7XBUT4ndIjmlAxkijM3Sx5MAAzC1gyv0vupDQNhzuFg1USQmQVj3P5I6bquk12etPV3LJ+Xw==", - "dependencies": { - "@docusaurus/core": "3.4.0", - "@docusaurus/logger": "3.4.0", - "@docusaurus/mdx-loader": "3.4.0", - "@docusaurus/types": "3.4.0", - "@docusaurus/utils": "3.4.0", - "@docusaurus/utils-common": "3.4.0", - "@docusaurus/utils-validation": "3.4.0", - "cheerio": "^1.0.0-rc.12", - "feed": "^4.2.2", - "fs-extra": "^11.1.1", - "lodash": "^4.17.21", - "reading-time": "^1.5.0", - "srcset": "^4.0.0", - "tslib": "^2.6.0", - "unist-util-visit": "^5.0.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/plugin-content-blog/node_modules/@docusaurus/types": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", - "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", - "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "^1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/plugin-content-docs": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.4.0.tgz", - "integrity": "sha512-HkUCZffhBo7ocYheD9oZvMcDloRnGhBMOZRyVcAQRFmZPmNqSyISlXA1tQCIxW+r478fty97XXAGjNYzBjpCsg==", - "dependencies": { - "@docusaurus/core": "3.4.0", - "@docusaurus/logger": "3.4.0", - "@docusaurus/mdx-loader": "3.4.0", - "@docusaurus/module-type-aliases": "3.4.0", - "@docusaurus/types": "3.4.0", - "@docusaurus/utils": "3.4.0", - "@docusaurus/utils-common": "3.4.0", - "@docusaurus/utils-validation": "3.4.0", - "@types/react-router-config": "^5.0.7", - "combine-promises": "^1.1.0", - "fs-extra": "^11.1.1", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "tslib": "^2.6.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/plugin-content-docs/node_modules/@docusaurus/types": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", - "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", - "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "^1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/plugin-content-pages": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.4.0.tgz", - "integrity": "sha512-h2+VN/0JjpR8fIkDEAoadNjfR3oLzB+v1qSXbIAKjQ46JAHx3X22n9nqS+BWSQnTnp1AjkjSvZyJMekmcwxzxg==", - "dependencies": { - "@docusaurus/core": "3.4.0", - "@docusaurus/mdx-loader": "3.4.0", - "@docusaurus/types": "3.4.0", - "@docusaurus/utils": "3.4.0", - "@docusaurus/utils-validation": "3.4.0", - "fs-extra": "^11.1.1", - "tslib": "^2.6.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/plugin-content-pages/node_modules/@docusaurus/types": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", - "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", - "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "^1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/plugin-debug": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.4.0.tgz", - "integrity": "sha512-uV7FDUNXGyDSD3PwUaf5YijX91T5/H9SX4ErEcshzwgzWwBtK37nUWPU3ZLJfeTavX3fycTOqk9TglpOLaWkCg==", - "dependencies": { - "@docusaurus/core": "3.4.0", - "@docusaurus/types": "3.4.0", - "@docusaurus/utils": "3.4.0", - "fs-extra": "^11.1.1", - "react-json-view-lite": "^1.2.0", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/plugin-debug/node_modules/@docusaurus/types": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", - "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", - "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "^1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/plugin-google-analytics": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.4.0.tgz", - "integrity": "sha512-mCArluxEGi3cmYHqsgpGGt3IyLCrFBxPsxNZ56Mpur0xSlInnIHoeLDH7FvVVcPJRPSQ9/MfRqLsainRw+BojA==", - "dependencies": { - "@docusaurus/core": "3.4.0", - "@docusaurus/types": "3.4.0", - "@docusaurus/utils-validation": "3.4.0", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/plugin-google-analytics/node_modules/@docusaurus/types": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", - "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", - "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "^1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/plugin-google-gtag": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.4.0.tgz", - "integrity": "sha512-Dsgg6PLAqzZw5wZ4QjUYc8Z2KqJqXxHxq3vIoyoBWiLEEfigIs7wHR+oiWUQy3Zk9MIk6JTYj7tMoQU0Jm3nqA==", - "dependencies": { - "@docusaurus/core": "3.4.0", - "@docusaurus/types": "3.4.0", - "@docusaurus/utils-validation": "3.4.0", - "@types/gtag.js": "^0.0.12", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/plugin-google-gtag/node_modules/@docusaurus/types": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", - "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", - "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "^1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/plugin-google-tag-manager": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.4.0.tgz", - "integrity": "sha512-O9tX1BTwxIhgXpOLpFDueYA9DWk69WCbDRrjYoMQtFHSkTyE7RhNgyjSPREUWJb9i+YUg3OrsvrBYRl64FCPCQ==", - "dependencies": { - "@docusaurus/core": "3.4.0", - "@docusaurus/types": "3.4.0", - "@docusaurus/utils-validation": "3.4.0", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/plugin-google-tag-manager/node_modules/@docusaurus/types": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", - "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", - "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "^1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/plugin-sitemap": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.4.0.tgz", - "integrity": "sha512-+0VDvx9SmNrFNgwPoeoCha+tRoAjopwT0+pYO1xAbyLcewXSemq+eLxEa46Q1/aoOaJQ0qqHELuQM7iS2gp33Q==", - "dependencies": { - "@docusaurus/core": "3.4.0", - "@docusaurus/logger": "3.4.0", - "@docusaurus/types": "3.4.0", - "@docusaurus/utils": "3.4.0", - "@docusaurus/utils-common": "3.4.0", - "@docusaurus/utils-validation": "3.4.0", - "fs-extra": "^11.1.1", - "sitemap": "^7.1.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/plugin-sitemap/node_modules/@docusaurus/types": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", - "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", - "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "^1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/preset-classic": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.4.0.tgz", - "integrity": "sha512-Ohj6KB7siKqZaQhNJVMBBUzT3Nnp6eTKqO+FXO3qu/n1hJl3YLwVKTWBg28LF7MWrKu46UuYavwMRxud0VyqHg==", - "dependencies": { - "@docusaurus/core": "3.4.0", - "@docusaurus/plugin-content-blog": "3.4.0", - "@docusaurus/plugin-content-docs": "3.4.0", - "@docusaurus/plugin-content-pages": "3.4.0", - "@docusaurus/plugin-debug": "3.4.0", - "@docusaurus/plugin-google-analytics": "3.4.0", - "@docusaurus/plugin-google-gtag": "3.4.0", - "@docusaurus/plugin-google-tag-manager": "3.4.0", - "@docusaurus/plugin-sitemap": "3.4.0", - "@docusaurus/theme-classic": "3.4.0", - "@docusaurus/theme-common": "3.4.0", - "@docusaurus/theme-search-algolia": "3.4.0", - "@docusaurus/types": "3.4.0" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/preset-classic/node_modules/@docusaurus/types": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", - "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", - "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "^1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/theme-classic": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.4.0.tgz", - "integrity": "sha512-0IPtmxsBYv2adr1GnZRdMkEQt1YW6tpzrUPj02YxNpvJ5+ju4E13J5tB4nfdaen/tfR1hmpSPlTFPvTf4kwy8Q==", - "dependencies": { - "@docusaurus/core": "3.4.0", - "@docusaurus/mdx-loader": "3.4.0", - "@docusaurus/module-type-aliases": "3.4.0", - "@docusaurus/plugin-content-blog": "3.4.0", - "@docusaurus/plugin-content-docs": "3.4.0", - "@docusaurus/plugin-content-pages": "3.4.0", - "@docusaurus/theme-common": "3.4.0", - "@docusaurus/theme-translations": "3.4.0", - "@docusaurus/types": "3.4.0", - "@docusaurus/utils": "3.4.0", - "@docusaurus/utils-common": "3.4.0", - "@docusaurus/utils-validation": "3.4.0", - "@mdx-js/react": "^3.0.0", - "clsx": "^2.0.0", - "copy-text-to-clipboard": "^3.2.0", - "infima": "0.2.0-alpha.43", - "lodash": "^4.17.21", - "nprogress": "^0.2.0", - "postcss": "^8.4.26", - "prism-react-renderer": "^2.3.0", - "prismjs": "^1.29.0", - "react-router-dom": "^5.3.4", - "rtlcss": "^4.1.0", - "tslib": "^2.6.0", - "utility-types": "^3.10.0" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/types": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", - "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", - "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "^1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/theme-common": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.4.0.tgz", - "integrity": "sha512-0A27alXuv7ZdCg28oPE8nH/Iz73/IUejVaCazqu9elS4ypjiLhK3KfzdSQBnL/g7YfHSlymZKdiOHEo8fJ0qMA==", - "dependencies": { - "@docusaurus/mdx-loader": "3.4.0", - "@docusaurus/module-type-aliases": "3.4.0", - "@docusaurus/plugin-content-blog": "3.4.0", - "@docusaurus/plugin-content-docs": "3.4.0", - "@docusaurus/plugin-content-pages": "3.4.0", - "@docusaurus/utils": "3.4.0", - "@docusaurus/utils-common": "3.4.0", - "@types/history": "^4.7.11", - "@types/react": "*", - "@types/react-router-config": "*", - "clsx": "^2.0.0", - "parse-numeric-range": "^1.3.0", - "prism-react-renderer": "^2.3.0", - "tslib": "^2.6.0", - "utility-types": "^3.10.0" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/theme-search-algolia": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.4.0.tgz", - "integrity": "sha512-aiHFx7OCw4Wck1z6IoShVdUWIjntC8FHCw9c5dR8r3q4Ynh+zkS8y2eFFunN/DL6RXPzpnvKCg3vhLQYJDmT9Q==", - "dependencies": { - "@docsearch/react": "^3.5.2", - "@docusaurus/core": "3.4.0", - "@docusaurus/logger": "3.4.0", - "@docusaurus/plugin-content-docs": "3.4.0", - "@docusaurus/theme-common": "3.4.0", - "@docusaurus/theme-translations": "3.4.0", - "@docusaurus/utils": "3.4.0", - "@docusaurus/utils-validation": "3.4.0", - "algoliasearch": "^4.18.0", - "algoliasearch-helper": "^3.13.3", - "clsx": "^2.0.0", - "eta": "^2.2.0", - "fs-extra": "^11.1.1", - "lodash": "^4.17.21", - "tslib": "^2.6.0", - "utility-types": "^3.10.0" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/theme-translations": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.4.0.tgz", - "integrity": "sha512-zSxCSpmQCCdQU5Q4CnX/ID8CSUUI3fvmq4hU/GNP/XoAWtXo9SAVnM3TzpU8Gb//H3WCsT8mJcTfyOk3d9ftNg==", - "dependencies": { - "fs-extra": "^11.1.1", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=18.0" - } - }, - "node_modules/@docusaurus/tsconfig": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docusaurus/tsconfig/-/tsconfig-3.5.2.tgz", - "integrity": "sha512-rQ7toURCFnWAIn8ubcquDs0ewhPwviMzxh6WpRjBW7sJVCXb6yzwUaY3HMNa0VXCFw+qkIbFywrMTf+Pb4uHWQ==", - "dev": true - }, - "node_modules/@docusaurus/types": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.1.0.tgz", - "integrity": "sha512-VaczOZf7+re8aFBIWnex1XENomwHdsSTkrdX43zyor7G/FY4OIsP6X28Xc3o0jiY0YdNuvIDyA5TNwOtpgkCVw==", - "devOptional": true, - "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "@types/history": "^4.7.11", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.9.2", - "react-helmet-async": "^1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.88.1", - "webpack-merge": "^5.9.0" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@docusaurus/utils": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.4.0.tgz", - "integrity": "sha512-fRwnu3L3nnWaXOgs88BVBmG1yGjcQqZNHG+vInhEa2Sz2oQB+ZjbEMO5Rh9ePFpZ0YDiDUhpaVjwmS+AU2F14g==", - "dependencies": { - "@docusaurus/logger": "3.4.0", - "@docusaurus/utils-common": "3.4.0", - "@svgr/webpack": "^8.1.0", - "escape-string-regexp": "^4.0.0", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.1", - "github-slugger": "^1.5.0", - "globby": "^11.1.0", - "gray-matter": "^4.0.3", - "jiti": "^1.20.0", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "micromatch": "^4.0.5", - "prompts": "^2.4.2", - "resolve-pathname": "^3.0.0", - "shelljs": "^0.8.5", - "tslib": "^2.6.0", - "url-loader": "^4.1.1", - "utility-types": "^3.10.0", - "webpack": "^5.88.1" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "@docusaurus/types": "*" - }, - "peerDependenciesMeta": { - "@docusaurus/types": { - "optional": true - } - } - }, - "node_modules/@docusaurus/utils-common": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.4.0.tgz", - "integrity": "sha512-NVx54Wr4rCEKsjOH5QEVvxIqVvm+9kh7q8aYTU5WzUU9/Hctd6aTrcZ3G0Id4zYJ+AeaG5K5qHA4CY5Kcm2iyQ==", - "dependencies": { - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "@docusaurus/types": "*" - }, - "peerDependenciesMeta": { - "@docusaurus/types": { - "optional": true - } - } - }, - "node_modules/@docusaurus/utils-validation": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.4.0.tgz", - "integrity": "sha512-hYQ9fM+AXYVTWxJOT1EuNaRnrR2WGpRdLDQG07O8UOpsvCPWUVOeo26Rbm0JWY2sGLfzAb+tvJ62yF+8F+TV0g==", - "dependencies": { - "@docusaurus/logger": "3.4.0", - "@docusaurus/utils": "3.4.0", - "@docusaurus/utils-common": "3.4.0", - "fs-extra": "^11.2.0", - "joi": "^17.9.2", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "tslib": "^2.6.0" - }, - "engines": { - "node": ">=18.0" - } - }, - "node_modules/@ecies/ciphers": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@ecies/ciphers/-/ciphers-0.2.1.tgz", - "integrity": "sha512-ezMihhjW24VNK/2qQR7lH8xCQY24nk0XHF/kwJ1OuiiY5iEwQXOcKVSy47fSoHPRG8gVGXcK5SgtONDk5xMwtQ==", - "engines": { - "bun": ">=1", - "deno": ">=2", - "node": ">=16" - }, - "peerDependencies": { - "@noble/ciphers": "^1.0.0" - } - }, - "node_modules/@emnapi/core": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.2.0.tgz", - "integrity": "sha512-E7Vgw78I93we4ZWdYCb4DGAwRROGkMIXk7/y87UmANR+J6qsWusmC3gLt0H+O0KOt5e6O38U8oJamgbudrES/w==", - "dev": true, - "dependencies": { - "@emnapi/wasi-threads": "1.0.1", - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/runtime": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.2.0.tgz", - "integrity": "sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==", - "dev": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/wasi-threads": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.1.tgz", - "integrity": "sha512-iIBu7mwkq4UQGeMEM8bLwNK962nXdhodeScX4slfQnRhEMMzvYivHhutCIk8uojvmASXXPC2WNEjwxFWk72Oqw==", - "dev": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@emurgo/cardano-serialization-lib-browser": { - "version": "12.1.1", - "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-browser/-/cardano-serialization-lib-browser-12.1.1.tgz", - "integrity": "sha512-DANl1Jr3LdmA0aDW/meEgnF6JLGjIZ3rgo4KLFNGtch0cuG53uzj3LXzslHLofYTEuNBRaBJFPMmG2xnd1uQAg==", - "license": "MIT" - }, - "node_modules/@emurgo/cardano-serialization-lib-nodejs": { - "version": "12.1.1", - "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-nodejs/-/cardano-serialization-lib-nodejs-12.1.1.tgz", - "integrity": "sha512-zXJNbtCrurlQtNvGaXjEjqCzVeCQ92mQgxwPziKZAxqd5w+Lb7iJ+48Brl58BQS9KTrtennlVIZ/R90aP2WFqw==", - "license": "MIT" - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", - "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@ethereumjs/common": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-3.2.0.tgz", - "integrity": "sha512-pksvzI0VyLgmuEF2FA/JR/4/y6hcPq8OUail3/AvycBaW1d5VSauOZzqGvJ3RTmR4MU35lWE8KseKOsEhrFRBA==", - "dependencies": { - "@ethereumjs/util": "^8.1.0", - "crc-32": "^1.2.0" - } - }, - "node_modules/@ethereumjs/rlp": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-4.0.1.tgz", - "integrity": "sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==", - "bin": { - "rlp": "bin/rlp" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@ethereumjs/tx": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-4.2.0.tgz", - "integrity": "sha512-1nc6VO4jtFd172BbSnTnDQVr9IYBFl1y4xPzZdtkrkKIncBCkdbgfdRV+MiTkJYAtTxvV12GRZLqBFT1PNK6Yw==", - "dependencies": { - "@ethereumjs/common": "^3.2.0", - "@ethereumjs/rlp": "^4.0.1", - "@ethereumjs/util": "^8.1.0", - "ethereum-cryptography": "^2.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@ethereumjs/util": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@ethereumjs/util/-/util-8.1.0.tgz", - "integrity": "sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==", - "dependencies": { - "@ethereumjs/rlp": "^4.0.1", - "ethereum-cryptography": "^2.0.0", - "micro-ftch": "^0.3.1" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@ethersproject/abi": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz", - "integrity": "sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "node_modules/@ethersproject/abstract-provider": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz", - "integrity": "sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/networks": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/web": "^5.7.0" - } - }, - "node_modules/@ethersproject/abstract-signer": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz", - "integrity": "sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0" - } - }, - "node_modules/@ethersproject/address": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz", - "integrity": "sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/rlp": "^5.7.0" - } - }, - "node_modules/@ethersproject/base64": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz", - "integrity": "sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bytes": "^5.7.0" - } - }, - "node_modules/@ethersproject/basex": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.7.0.tgz", - "integrity": "sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/properties": "^5.7.0" - } - }, - "node_modules/@ethersproject/bignumber": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz", - "integrity": "sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "bn.js": "^5.2.1" - } - }, - "node_modules/@ethersproject/bytes": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz", - "integrity": "sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/constants": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz", - "integrity": "sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bignumber": "^5.7.0" - } - }, - "node_modules/@ethersproject/contracts": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.7.0.tgz", - "integrity": "sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/abi": "^5.7.0", - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/transactions": "^5.7.0" - } - }, - "node_modules/@ethersproject/hash": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz", - "integrity": "sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/base64": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "node_modules/@ethersproject/hdnode": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.7.0.tgz", - "integrity": "sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/basex": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/pbkdf2": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/sha2": "^5.7.0", - "@ethersproject/signing-key": "^5.7.0", - "@ethersproject/strings": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/wordlists": "^5.7.0" - } - }, - "node_modules/@ethersproject/json-wallets": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz", - "integrity": "sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/hdnode": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/pbkdf2": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/random": "^5.7.0", - "@ethersproject/strings": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "aes-js": "3.0.0", - "scrypt-js": "3.0.1" - } - }, - "node_modules/@ethersproject/keccak256": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz", - "integrity": "sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "js-sha3": "0.8.0" - } - }, - "node_modules/@ethersproject/logger": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz", - "integrity": "sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT" - }, - "node_modules/@ethersproject/networks": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz", - "integrity": "sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/pbkdf2": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz", - "integrity": "sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/sha2": "^5.7.0" - } - }, - "node_modules/@ethersproject/properties": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz", - "integrity": "sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/providers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.7.2.tgz", - "integrity": "sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/base64": "^5.7.0", - "@ethersproject/basex": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/networks": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/random": "^5.7.0", - "@ethersproject/rlp": "^5.7.0", - "@ethersproject/sha2": "^5.7.0", - "@ethersproject/strings": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/web": "^5.7.0", - "bech32": "1.1.4", - "ws": "7.4.6" - } - }, - "node_modules/@ethersproject/providers/node_modules/bech32": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", - "license": "MIT" - }, - "node_modules/@ethersproject/providers/node_modules/ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", - "license": "MIT", - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/@ethersproject/random": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.7.0.tgz", - "integrity": "sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/rlp": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz", - "integrity": "sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/sha2": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.7.0.tgz", - "integrity": "sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "hash.js": "1.1.7" - } - }, - "node_modules/@ethersproject/signing-key": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz", - "integrity": "sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "bn.js": "^5.2.1", - "elliptic": "6.5.4", - "hash.js": "1.1.7" - } - }, - "node_modules/@ethersproject/signing-key/node_modules/elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "license": "MIT", - "dependencies": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/@ethersproject/signing-key/node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", - "license": "MIT" - }, - "node_modules/@ethersproject/solidity": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.7.0.tgz", - "integrity": "sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/sha2": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "node_modules/@ethersproject/strings": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz", - "integrity": "sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/transactions": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz", - "integrity": "sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/rlp": "^5.7.0", - "@ethersproject/signing-key": "^5.7.0" - } - }, - "node_modules/@ethersproject/units": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.7.0.tgz", - "integrity": "sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/wallet": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.7.0.tgz", - "integrity": "sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/hdnode": "^5.7.0", - "@ethersproject/json-wallets": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/random": "^5.7.0", - "@ethersproject/signing-key": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/wordlists": "^5.7.0" - } - }, - "node_modules/@ethersproject/web": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz", - "integrity": "sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/base64": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "node_modules/@ethersproject/wordlists": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.7.0.tgz", - "integrity": "sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "node_modules/@expo/bunyan": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@expo/bunyan/-/bunyan-4.0.0.tgz", - "integrity": "sha512-Ydf4LidRB/EBI+YrB+cVLqIseiRfjUI/AeHBgjGMtq3GroraDu81OV7zqophRgupngoL3iS3JUMDMnxO7g39qA==", - "engines": [ - "node >=0.10.0" - ], - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "uuid": "^8.0.0" - }, - "optionalDependencies": { - "mv": "~2", - "safe-json-stringify": "~1" - } - }, - "node_modules/@expo/bunyan/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "license": "MIT", - "optional": true, - "peer": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@expo/cli": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/@expo/cli/-/cli-0.1.7.tgz", - "integrity": "sha512-F81fPthpT7QtVu1P7QeZMezGn0tCcalCh3ANIzWBaQZNG4vly7mo2dp3PMGzNdmXq6yt93bJ4HbfS+0/NpKl7g==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@babel/runtime": "^7.14.0", - "@expo/code-signing-certificates": "^0.0.2", - "@expo/config": "~6.0.23", - "@expo/config-plugins": "~4.1.4", - "@expo/dev-server": "0.1.116", - "@expo/devcert": "^1.0.0", - "@expo/json-file": "^8.2.35", - "@expo/metro-config": "0.3.19", - "@expo/osascript": "^2.0.31", - "@expo/package-manager": "~0.0.52", - "@expo/plist": "^0.0.18", - "@expo/prebuild-config": "~4.0.0", - "@expo/rudder-sdk-node": "1.1.1", - "@expo/spawn-async": "1.5.0", - "@expo/xcpretty": "^4.1.1", - "@urql/core": "2.3.6", - "@urql/exchange-retry": "0.3.0", - "accepts": "^1.3.8", - "arg": "4.1.0", - "better-opn": "~3.0.2", - "bplist-parser": "^0.3.1", - "cacache": "^15.3.0", - "chalk": "^4.0.0", - "ci-info": "^3.3.0", - "env-editor": "^0.4.1", - "form-data": "^3.0.1", - "freeport-async": "2.0.0", - "fs-extra": "~8.1.0", - "getenv": "^1.0.0", - "graphql": "15.8.0", - "graphql-tag": "^2.10.1", - "internal-ip": "4.3.0", - "is-root": "^2.1.0", - "js-yaml": "^3.13.1", - "json-schema-deref-sync": "^0.13.0", - "md5-file": "^3.2.3", - "md5hex": "^1.0.0", - "minipass": "3.1.6", - "node-fetch": "^2.6.7", - "node-forge": "^1.3.1", - "npm-package-arg": "^7.0.0", - "ora": "3.4.0", - "pretty-bytes": "5.6.0", - "progress": "2.0.3", - "prompts": "^2.3.2", - "qrcode-terminal": "0.11.0", - "requireg": "^0.2.2", - "resolve-from": "^5.0.0", - "semver": "^6.3.0", - "slugify": "^1.3.4", - "structured-headers": "^0.4.1", - "tar": "^6.0.5", - "tempy": "^0.7.1", - "terminal-link": "^2.1.1", - "text-table": "^0.2.0", - "url-join": "4.0.0", - "uuid": "^3.4.0", - "wrap-ansi": "^7.0.0" - }, - "bin": { - "expo-internal": "build/bin/cli" - } - }, - "node_modules/@expo/cli/node_modules/@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, - "node_modules/@expo/cli/node_modules/@expo/config": { - "version": "6.0.26", - "resolved": "https://registry.npmjs.org/@expo/config/-/config-6.0.26.tgz", - "integrity": "sha512-nMQaZl69r6CMJFhCj0xcGJN9bIi4Uws0k9K6q6rGFPFNarS0z0aexeyNLv93/J+hsTJVn0GEYtGz5Y/R8boXxw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@babel/code-frame": "~7.10.4", - "@expo/config-plugins": "4.1.5", - "@expo/config-types": "^45.0.0", - "@expo/json-file": "8.2.36", - "getenv": "^1.0.0", - "glob": "7.1.6", - "require-from-string": "^2.0.2", - "resolve-from": "^5.0.0", - "semver": "7.3.2", - "slugify": "^1.3.4", - "sucrase": "^3.20.0" - } - }, - "node_modules/@expo/cli/node_modules/@expo/config-plugins": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-4.1.5.tgz", - "integrity": "sha512-RVvU40RtZt12HavuDAe+LDIq9lHj7sheOfMEHdmpJ/uTA8pgvkbc56XF6JHQD+yRr6+uhhb+JnAasGq49dsQbw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@expo/config-types": "^45.0.0", - "@expo/json-file": "8.2.36", - "@expo/plist": "0.0.18", - "@expo/sdk-runtime-versions": "^1.0.0", - "@react-native/normalize-color": "^2.0.0", - "chalk": "^4.1.2", - "debug": "^4.3.1", - "find-up": "~5.0.0", - "getenv": "^1.0.0", - "glob": "7.1.6", - "resolve-from": "^5.0.0", - "semver": "^7.3.5", - "slash": "^3.0.0", - "xcode": "^3.0.1", - "xml2js": "0.4.23" - } - }, - "node_modules/@expo/cli/node_modules/@expo/config-plugins/node_modules/@expo/json-file": { - "version": "8.2.36", - "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-8.2.36.tgz", - "integrity": "sha512-tOZfTiIFA5KmMpdW9KF7bc6CFiGjb0xnbieJhTGlHrLL+ps2G0OkqmuZ3pFEXBOMnJYUVpnSy++52LFxvpa5ZQ==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@babel/code-frame": "~7.10.4", - "json5": "^1.0.1", - "write-file-atomic": "^2.3.0" - } - }, - "node_modules/@expo/cli/node_modules/@expo/config-plugins/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/@expo/cli/node_modules/@expo/config-plugins/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@expo/cli/node_modules/@expo/config-types": { - "version": "45.0.0", - "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-45.0.0.tgz", - "integrity": "sha512-/QGhhLWyaGautgEyU50UJr5YqKJix5t77ePTwreOVAhmZH+ff3nrrtYTTnccx+qF08ZNQmfAyYMCD3rQfzpiJA==", - "license": "MIT", - "optional": true, - "peer": true - }, - "node_modules/@expo/cli/node_modules/@expo/config/node_modules/@expo/json-file": { - "version": "8.2.36", - "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-8.2.36.tgz", - "integrity": "sha512-tOZfTiIFA5KmMpdW9KF7bc6CFiGjb0xnbieJhTGlHrLL+ps2G0OkqmuZ3pFEXBOMnJYUVpnSy++52LFxvpa5ZQ==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@babel/code-frame": "~7.10.4", - "json5": "^1.0.1", - "write-file-atomic": "^2.3.0" - } - }, - "node_modules/@expo/cli/node_modules/@expo/config/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/@expo/cli/node_modules/@expo/config/node_modules/semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@expo/cli/node_modules/@expo/json-file": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-8.3.3.tgz", - "integrity": "sha512-eZ5dld9AD0PrVRiIWpRkm5aIoWBw3kAyd8VkuWEy92sEthBKDDDHAnK2a0dw0Eil6j7rK7lS/Qaq/Zzngv2h5A==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@babel/code-frame": "~7.10.4", - "json5": "^2.2.2", - "write-file-atomic": "^2.3.0" - } - }, - "node_modules/@expo/cli/node_modules/@expo/metro-config": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@expo/metro-config/-/metro-config-0.3.19.tgz", - "integrity": "sha512-UZlwnD0g/7uAx/AZ5ulC7Y4unfJFJywXy3Ozu40dhQnSciOU/nkzK94XpKbxHuRZJ3crZxvL2EDwQ8jguDjASw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@expo/config": "6.0.26", - "@expo/json-file": "8.2.36", - "chalk": "^4.1.0", - "debug": "^4.3.2", - "find-yarn-workspace-root": "~2.0.0", - "getenv": "^1.0.0", - "resolve-from": "^5.0.0", - "sucrase": "^3.20.0" - } - }, - "node_modules/@expo/cli/node_modules/@expo/metro-config/node_modules/@expo/json-file": { - "version": "8.2.36", - "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-8.2.36.tgz", - "integrity": "sha512-tOZfTiIFA5KmMpdW9KF7bc6CFiGjb0xnbieJhTGlHrLL+ps2G0OkqmuZ3pFEXBOMnJYUVpnSy++52LFxvpa5ZQ==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@babel/code-frame": "~7.10.4", - "json5": "^1.0.1", - "write-file-atomic": "^2.3.0" - } - }, - "node_modules/@expo/cli/node_modules/@expo/metro-config/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/@expo/cli/node_modules/@expo/plist": { - "version": "0.0.18", - "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.0.18.tgz", - "integrity": "sha512-+48gRqUiz65R21CZ/IXa7RNBXgAI/uPSdvJqoN9x1hfL44DNbUoWHgHiEXTx7XelcATpDwNTz6sHLfy0iNqf+w==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@xmldom/xmldom": "~0.7.0", - "base64-js": "^1.2.3", - "xmlbuilder": "^14.0.0" - } - }, - "node_modules/@expo/cli/node_modules/@urql/exchange-retry": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@urql/exchange-retry/-/exchange-retry-0.3.0.tgz", - "integrity": "sha512-hHqer2mcdVC0eYnVNbWyi28AlGOPb2vjH3lP3/Bc8Lc8BjhMsDwFMm7WhoP5C1+cfbr/QJ6Er3H/L08wznXxfg==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@urql/core": ">=2.3.1", - "wonka": "^4.0.14" - }, - "peerDependencies": { - "graphql": "^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0" - } - }, - "node_modules/@expo/cli/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/@expo/cli/node_modules/arg": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.0.tgz", - "integrity": "sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg==", - "license": "MIT", - "optional": true, - "peer": true - }, - "node_modules/@expo/cli/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/@expo/cli/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@expo/cli/node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "license": "ISC", - "optional": true, - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@expo/cli/node_modules/cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "restore-cursor": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@expo/cli/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT", - "optional": true, - "peer": true - }, - "node_modules/@expo/cli/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@expo/cli/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@expo/cli/node_modules/form-data": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.2.tgz", - "integrity": "sha512-sJe+TQb2vIaIyO783qN6BlMYWMw3WBOHA1Ay2qxsnjuafEOQFJ2JakedOQirT6D5XPRxDvS7AHYyem9fTpb4LQ==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@expo/cli/node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/@expo/cli/node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@expo/cli/node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@expo/cli/node_modules/graphql": { - "version": "15.8.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.8.0.tgz", - "integrity": "sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 10.x" - } - }, - "node_modules/@expo/cli/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@expo/cli/node_modules/hosted-git-info": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz", - "integrity": "sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@expo/cli/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@expo/cli/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@expo/cli/node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "license": "MIT", - "optional": true, - "peer": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@expo/cli/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@expo/cli/node_modules/log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "chalk": "^2.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@expo/cli/node_modules/log-symbols/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@expo/cli/node_modules/log-symbols/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@expo/cli/node_modules/mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@expo/cli/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@expo/cli/node_modules/minipass": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz", - "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@expo/cli/node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@expo/cli/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "license": "MIT", - "optional": true, - "peer": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@expo/cli/node_modules/npm-package-arg": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-7.0.0.tgz", - "integrity": "sha512-xXxr8y5U0kl8dVkz2oK7yZjPBvqM2fwaO5l3Yg13p03v8+E3qQcD0JNhHzjL1vyGgxcKkD0cco+NLR72iuPk3g==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "hosted-git-info": "^3.0.2", - "osenv": "^0.1.5", - "semver": "^5.6.0", - "validate-npm-package-name": "^3.0.0" - } - }, - "node_modules/@expo/cli/node_modules/npm-package-arg/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/@expo/cli/node_modules/onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "mimic-fn": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@expo/cli/node_modules/ora": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-3.4.0.tgz", - "integrity": "sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "chalk": "^2.4.2", - "cli-cursor": "^2.1.0", - "cli-spinners": "^2.0.0", - "log-symbols": "^2.2.0", - "strip-ansi": "^5.2.0", - "wcwidth": "^1.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@expo/cli/node_modules/ora/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@expo/cli/node_modules/ora/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@expo/cli/node_modules/ora/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@expo/cli/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@expo/cli/node_modules/restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@expo/cli/node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "license": "BSD-3-Clause", - "optional": true, - "peer": true - }, - "node_modules/@expo/cli/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@expo/cli/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@expo/cli/node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@expo/cli/node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "license": "ISC", - "optional": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@expo/cli/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/@expo/cli/node_modules/url-join": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.0.tgz", - "integrity": "sha512-EGXjXJZhIHiQMK2pQukuFcL303nskqIRzWvPvV5O8miOfwoUb9G+a/Cld60kUyeaybEI94wvVClT10DtfeAExA==", - "license": "MIT", - "optional": true, - "peer": true - }, - "node_modules/@expo/cli/node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "license": "MIT", - "optional": true, - "peer": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/@expo/cli/node_modules/validate-npm-package-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", - "integrity": "sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "builtins": "^1.0.3" - } - }, - "node_modules/@expo/cli/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/@expo/cli/node_modules/write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - }, - "node_modules/@expo/code-signing-certificates": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/@expo/code-signing-certificates/-/code-signing-certificates-0.0.2.tgz", - "integrity": "sha512-vnPHFjwOqxQ1VLztktY+fYCfwvLzjqpzKn09rchcQE7Sdf0wtW5fFtIZBEFOOY5wasp8tXSnp627zrAwazPHzg==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "node-forge": "^1.2.1", - "nullthrows": "^1.1.1" - } - }, - "node_modules/@expo/config": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/@expo/config/-/config-6.0.6.tgz", - "integrity": "sha512-GPI8EIdMAtZ5VaB4p5GcfuX50xyfGFdpEqLi0QmcfrCfTsGry1/j/Qy28hovHM1oJYHlaZylTcbGy+1ET+AO2w==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/code-frame": "~7.10.4", - "@expo/config-plugins": "4.0.6", - "@expo/config-types": "^43.0.1", - "@expo/json-file": "8.2.33", - "getenv": "^1.0.0", - "glob": "7.1.6", - "require-from-string": "^2.0.2", - "resolve-from": "^5.0.0", - "semver": "7.3.2", - "slugify": "^1.3.4", - "sucrase": "^3.20.0" - } - }, - "node_modules/@expo/config-plugins": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-4.0.6.tgz", - "integrity": "sha512-K/KQaw/CU8uLQgk7sFnZC54YGHoGucKFfdjYeZx5ds2eyzbuMAiKzGFcxZ/S+1dVBZ8QHzwowsVBW3kuYhnQ3Q==", - "license": "MIT", - "peer": true, - "dependencies": { - "@expo/config-types": "^43.0.1", - "@expo/json-file": "8.2.33", - "@expo/plist": "0.0.15", - "@react-native/normalize-color": "^2.0.0", - "chalk": "^4.1.2", - "debug": "^4.3.1", - "find-up": "~5.0.0", - "fs-extra": "9.0.0", - "getenv": "^1.0.0", - "glob": "7.1.6", - "resolve-from": "^5.0.0", - "semver": "^7.3.5", - "slash": "^3.0.0", - "xcode": "^3.0.1", - "xml2js": "0.4.23" - } - }, - "node_modules/@expo/config-plugins/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "license": "MIT", - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@expo/config-plugins/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "license": "MIT", - "peer": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@expo/config-plugins/node_modules/fs-extra": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.0.tgz", - "integrity": "sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==", - "license": "MIT", - "peer": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^1.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@expo/config-plugins/node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "license": "ISC", - "peer": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@expo/config-plugins/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "license": "MIT", - "peer": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@expo/config-plugins/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "license": "ISC", - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@expo/config-plugins/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "license": "MIT", - "peer": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@expo/config-plugins/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@expo/config-plugins/node_modules/universalify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", - "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@expo/config-types": { - "version": "43.0.1", - "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-43.0.1.tgz", - "integrity": "sha512-EtllpCGDdB/UdwAIs5YXJwBLpbFQNdlLLrxIvoILA9cXrpQMWkeDCT9lQPJzFRMFcLUaMuGvkzX2tR4tx5EQFQ==", - "license": "MIT", - "peer": true - }, - "node_modules/@expo/config/node_modules/@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, - "node_modules/@expo/config/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "license": "MIT", - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@expo/config/node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "license": "ISC", - "peer": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@expo/config/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "license": "ISC", - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@expo/config/node_modules/semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@expo/dev-server": { - "version": "0.1.116", - "resolved": "https://registry.npmjs.org/@expo/dev-server/-/dev-server-0.1.116.tgz", - "integrity": "sha512-jUyOv3S55wBsYiFhiYVz35Ui8QTnUGVKlsPRgQHnKU70Ey4jxJqObtGkNnrgazzDfy9S7qFJKiyJQro7621ipA==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@expo/bunyan": "4.0.0", - "@expo/metro-config": "0.3.19", - "@expo/osascript": "2.0.33", - "body-parser": "1.19.0", - "chalk": "^4.0.0", - "connect": "^3.7.0", - "fs-extra": "9.0.0", - "node-fetch": "^2.6.0", - "open": "^8.3.0", - "resolve-from": "^5.0.0", - "semver": "7.3.2", - "serialize-error": "6.0.0", - "temp-dir": "^2.0.0" - } - }, - "node_modules/@expo/dev-server/node_modules/@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, - "node_modules/@expo/dev-server/node_modules/@expo/config": { - "version": "6.0.26", - "resolved": "https://registry.npmjs.org/@expo/config/-/config-6.0.26.tgz", - "integrity": "sha512-nMQaZl69r6CMJFhCj0xcGJN9bIi4Uws0k9K6q6rGFPFNarS0z0aexeyNLv93/J+hsTJVn0GEYtGz5Y/R8boXxw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@babel/code-frame": "~7.10.4", - "@expo/config-plugins": "4.1.5", - "@expo/config-types": "^45.0.0", - "@expo/json-file": "8.2.36", - "getenv": "^1.0.0", - "glob": "7.1.6", - "require-from-string": "^2.0.2", - "resolve-from": "^5.0.0", - "semver": "7.3.2", - "slugify": "^1.3.4", - "sucrase": "^3.20.0" - } - }, - "node_modules/@expo/dev-server/node_modules/@expo/config-plugins": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-4.1.5.tgz", - "integrity": "sha512-RVvU40RtZt12HavuDAe+LDIq9lHj7sheOfMEHdmpJ/uTA8pgvkbc56XF6JHQD+yRr6+uhhb+JnAasGq49dsQbw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@expo/config-types": "^45.0.0", - "@expo/json-file": "8.2.36", - "@expo/plist": "0.0.18", - "@expo/sdk-runtime-versions": "^1.0.0", - "@react-native/normalize-color": "^2.0.0", - "chalk": "^4.1.2", - "debug": "^4.3.1", - "find-up": "~5.0.0", - "getenv": "^1.0.0", - "glob": "7.1.6", - "resolve-from": "^5.0.0", - "semver": "^7.3.5", - "slash": "^3.0.0", - "xcode": "^3.0.1", - "xml2js": "0.4.23" - } - }, - "node_modules/@expo/dev-server/node_modules/@expo/config-plugins/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@expo/dev-server/node_modules/@expo/config-types": { - "version": "45.0.0", - "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-45.0.0.tgz", - "integrity": "sha512-/QGhhLWyaGautgEyU50UJr5YqKJix5t77ePTwreOVAhmZH+ff3nrrtYTTnccx+qF08ZNQmfAyYMCD3rQfzpiJA==", - "license": "MIT", - "optional": true, - "peer": true - }, - "node_modules/@expo/dev-server/node_modules/@expo/json-file": { - "version": "8.2.36", - "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-8.2.36.tgz", - "integrity": "sha512-tOZfTiIFA5KmMpdW9KF7bc6CFiGjb0xnbieJhTGlHrLL+ps2G0OkqmuZ3pFEXBOMnJYUVpnSy++52LFxvpa5ZQ==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@babel/code-frame": "~7.10.4", - "json5": "^1.0.1", - "write-file-atomic": "^2.3.0" - } - }, - "node_modules/@expo/dev-server/node_modules/@expo/metro-config": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@expo/metro-config/-/metro-config-0.3.19.tgz", - "integrity": "sha512-UZlwnD0g/7uAx/AZ5ulC7Y4unfJFJywXy3Ozu40dhQnSciOU/nkzK94XpKbxHuRZJ3crZxvL2EDwQ8jguDjASw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@expo/config": "6.0.26", - "@expo/json-file": "8.2.36", - "chalk": "^4.1.0", - "debug": "^4.3.2", - "find-yarn-workspace-root": "~2.0.0", - "getenv": "^1.0.0", - "resolve-from": "^5.0.0", - "sucrase": "^3.20.0" - } - }, - "node_modules/@expo/dev-server/node_modules/@expo/osascript": { - "version": "2.0.33", - "resolved": "https://registry.npmjs.org/@expo/osascript/-/osascript-2.0.33.tgz", - "integrity": "sha512-FQinlwHrTlJbntp8a7NAlCKedVXe06Va/0DSLXRO8lZVtgbEMrYYSUZWQNcOlNtc58c2elNph6z9dMOYwSo3JQ==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@expo/spawn-async": "^1.5.0", - "exec-async": "^2.2.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@expo/dev-server/node_modules/@expo/plist": { - "version": "0.0.18", - "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.0.18.tgz", - "integrity": "sha512-+48gRqUiz65R21CZ/IXa7RNBXgAI/uPSdvJqoN9x1hfL44DNbUoWHgHiEXTx7XelcATpDwNTz6sHLfy0iNqf+w==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@xmldom/xmldom": "~0.7.0", - "base64-js": "^1.2.3", - "xmlbuilder": "^14.0.0" - } - }, - "node_modules/@expo/dev-server/node_modules/body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@expo/dev-server/node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/@expo/dev-server/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@expo/dev-server/node_modules/bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@expo/dev-server/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@expo/dev-server/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@expo/dev-server/node_modules/fs-extra": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.0.tgz", - "integrity": "sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^1.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@expo/dev-server/node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@expo/dev-server/node_modules/http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@expo/dev-server/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", - "license": "ISC", - "optional": true, - "peer": true - }, - "node_modules/@expo/dev-server/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/@expo/dev-server/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@expo/dev-server/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@expo/dev-server/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT", - "optional": true, - "peer": true - }, - "node_modules/@expo/dev-server/node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@expo/dev-server/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@expo/dev-server/node_modules/qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", - "license": "BSD-3-Clause", - "optional": true, - "peer": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/@expo/dev-server/node_modules/raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@expo/dev-server/node_modules/semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@expo/dev-server/node_modules/serialize-error": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-6.0.0.tgz", - "integrity": "sha512-3vmBkMZLQO+BR4RPHcyRGdE09XCF6cvxzk2N2qn8Er3F91cy8Qt7VvEbZBOpaL53qsBbe2cFOefU6tRY6WDelA==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "type-fest": "^0.12.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@expo/dev-server/node_modules/setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", - "license": "ISC", - "optional": true, - "peer": true - }, - "node_modules/@expo/dev-server/node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@expo/dev-server/node_modules/toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/@expo/dev-server/node_modules/type-fest": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.12.0.tgz", - "integrity": "sha512-53RyidyjvkGpnWPMF9bQgFtWp+Sl8O2Rp13VavmJgfAP9WWG6q6TkrKU8iyJdnwnfgHI6k2hTlgqH4aSdjoTbg==", - "license": "(MIT OR CC0-1.0)", - "optional": true, - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@expo/dev-server/node_modules/universalify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", - "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@expo/dev-server/node_modules/write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - }, - "node_modules/@expo/devcert": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@expo/devcert/-/devcert-1.1.4.tgz", - "integrity": "sha512-fqBODr8c72+gBSX5Ty3SIzaY4bXainlpab78+vEYEKL3fXmsOswMLf0+KE36mUEAa36BYabX7K3EiXOXX5OPMw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "application-config-path": "^0.1.0", - "command-exists": "^1.2.4", - "debug": "^3.1.0", - "eol": "^0.9.1", - "get-port": "^3.2.0", - "glob": "^10.4.2", - "lodash": "^4.17.21", - "mkdirp": "^0.5.1", - "password-prompt": "^1.0.4", - "sudo-prompt": "^8.2.0", - "tmp": "^0.0.33", - "tslib": "^2.4.0" - } - }, - "node_modules/@expo/devcert/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/@expo/devcert/node_modules/eol": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/eol/-/eol-0.9.1.tgz", - "integrity": "sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg==", - "license": "MIT", - "optional": true, - "peer": true - }, - "node_modules/@expo/devcert/node_modules/get-port": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", - "integrity": "sha512-x5UJKlgeUiNT8nyo/AcnwLnZuZNcSjSw0kogRB+Whd1fjjFq4B1hySFxSFWWSn4mIBzg3sRNUDFYc4g5gjPoLg==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@expo/devcert/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@expo/devcert/node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "license": "BlueOak-1.0.0", - "optional": true, - "peer": true, - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/@expo/devcert/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@expo/devcert/node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "os-tmpdir": "~1.0.2" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/@expo/image-utils": { - "version": "0.3.21", - "resolved": "https://registry.npmjs.org/@expo/image-utils/-/image-utils-0.3.21.tgz", - "integrity": "sha512-Ha7pNcpl52RJIeYz3gR1ajOgPPl7WLZWiLqtLi94s9J0a7FvmNBMqd/VKrfHNj8QmtZxXcmXr7y7tPhZbVFg7w==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@expo/spawn-async": "1.5.0", - "chalk": "^4.0.0", - "fs-extra": "9.0.0", - "getenv": "^1.0.0", - "jimp-compact": "0.16.1", - "mime": "^2.4.4", - "node-fetch": "^2.6.0", - "parse-png": "^2.1.0", - "resolve-from": "^5.0.0", - "semver": "7.3.2", - "tempy": "0.3.0" - } - }, - "node_modules/@expo/image-utils/node_modules/crypto-random-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", - "integrity": "sha512-GsVpkFPlycH7/fRR7Dhcmnoii54gV1nz7y4CWyeFS14N+JVBBhY+r8amRHE4BwSYal7BPTDp8isvAlCxyFt3Hg==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@expo/image-utils/node_modules/fs-extra": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.0.tgz", - "integrity": "sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^1.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@expo/image-utils/node_modules/mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", - "license": "MIT", - "optional": true, - "peer": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/@expo/image-utils/node_modules/semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@expo/image-utils/node_modules/temp-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", - "integrity": "sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@expo/image-utils/node_modules/tempy": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.3.0.tgz", - "integrity": "sha512-WrH/pui8YCwmeiAoxV+lpRH9HpRtgBhSR2ViBPgpGb/wnYDzp21R4MN45fsCGvLROvY67o3byhJRYRONJyImVQ==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "temp-dir": "^1.0.0", - "type-fest": "^0.3.1", - "unique-string": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@expo/image-utils/node_modules/type-fest": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", - "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", - "license": "(MIT OR CC0-1.0)", - "optional": true, - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/@expo/image-utils/node_modules/unique-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", - "integrity": "sha512-ODgiYu03y5g76A1I9Gt0/chLCzQjvzDy7DsZGsLOE/1MrF6wriEskSncj1+/C58Xk/kPZDppSctDybCwOSaGAg==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "crypto-random-string": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@expo/image-utils/node_modules/universalify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", - "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@expo/json-file": { - "version": "8.2.33", - "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-8.2.33.tgz", - "integrity": "sha512-CDnhjdirUs6OdN5hOSTJ2y3i9EiJMk7Z5iDljC5xyCHCrUex7oyI8vbRsZEojAahxZccgL/PrO+CjakiFFWurg==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/code-frame": "~7.10.4", - "json5": "^1.0.1", - "write-file-atomic": "^2.3.0" - } - }, - "node_modules/@expo/json-file/node_modules/@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, - "node_modules/@expo/json-file/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "license": "MIT", - "peer": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/@expo/json-file/node_modules/write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", - "license": "ISC", - "peer": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - }, - "node_modules/@expo/metro-config": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@expo/metro-config/-/metro-config-0.2.8.tgz", - "integrity": "sha512-8g0QrHfvSgTLzryuE4JXRwFwBZ7EmqE55zR39Yy7jEVR3epYL0JbBK0/IDFmf6auwsDFtMjAZjFL4WEhRN5bEQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "@expo/config": "6.0.6", - "chalk": "^4.1.0", - "debug": "^4.3.2", - "getenv": "^1.0.0", - "sucrase": "^3.20.0" - } - }, - "node_modules/@expo/osascript": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@expo/osascript/-/osascript-2.1.5.tgz", - "integrity": "sha512-Cp7YF7msGiTAIbFdzNovwHBfecdMLVL5XzSqq4xQz72ALFCQ3uSIUXRph1QV2r61ugH7Yem0gY8yi7RcDlI4qg==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@expo/spawn-async": "^1.7.2", - "exec-async": "^2.2.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@expo/osascript/node_modules/@expo/spawn-async": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@expo/spawn-async/-/spawn-async-1.7.2.tgz", - "integrity": "sha512-QdWi16+CHB9JYP7gma19OVVg0BFkvU8zNj9GjWorYI8Iv8FUxjOCcYRuAmX4s/h91e4e7BPsskc8cSrZYho9Ew==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "cross-spawn": "^7.0.3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@expo/package-manager": { - "version": "0.0.60", - "resolved": "https://registry.npmjs.org/@expo/package-manager/-/package-manager-0.0.60.tgz", - "integrity": "sha512-MdV7dpFA4aI8HIW0xsW2DBUem5aFKL8+/v5LXKPZuXmYW02/EXPSp7DBJAwow8ULpa3Q2VlYfb46hWPre3hw4A==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@expo/json-file": "^8.2.37", - "@expo/spawn-async": "^1.5.0", - "ansi-regex": "^5.0.0", - "chalk": "^4.0.0", - "find-up": "^5.0.0", - "find-yarn-workspace-root": "~2.0.0", - "npm-package-arg": "^7.0.0", - "rimraf": "^3.0.2", - "split": "^1.0.1", - "sudo-prompt": "9.1.1" - } - }, - "node_modules/@expo/package-manager/node_modules/@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, - "node_modules/@expo/package-manager/node_modules/@expo/json-file": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-8.3.3.tgz", - "integrity": "sha512-eZ5dld9AD0PrVRiIWpRkm5aIoWBw3kAyd8VkuWEy92sEthBKDDDHAnK2a0dw0Eil6j7rK7lS/Qaq/Zzngv2h5A==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@babel/code-frame": "~7.10.4", - "json5": "^2.2.2", - "write-file-atomic": "^2.3.0" - } - }, - "node_modules/@expo/package-manager/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@expo/package-manager/node_modules/hosted-git-info": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz", - "integrity": "sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@expo/package-manager/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@expo/package-manager/node_modules/npm-package-arg": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-7.0.0.tgz", - "integrity": "sha512-xXxr8y5U0kl8dVkz2oK7yZjPBvqM2fwaO5l3Yg13p03v8+E3qQcD0JNhHzjL1vyGgxcKkD0cco+NLR72iuPk3g==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "hosted-git-info": "^3.0.2", - "osenv": "^0.1.5", - "semver": "^5.6.0", - "validate-npm-package-name": "^3.0.0" - } - }, - "node_modules/@expo/package-manager/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@expo/package-manager/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/@expo/package-manager/node_modules/sudo-prompt": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/sudo-prompt/-/sudo-prompt-9.1.1.tgz", - "integrity": "sha512-es33J1g2HjMpyAhz8lOR+ICmXXAqTuKbuXuUWLhOLew20oN9oUCgCJx615U/v7aioZg7IX5lIh9x34vwneu4pA==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "license": "MIT", - "optional": true, - "peer": true - }, - "node_modules/@expo/package-manager/node_modules/validate-npm-package-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", - "integrity": "sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "builtins": "^1.0.3" - } - }, - "node_modules/@expo/package-manager/node_modules/write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - }, - "node_modules/@expo/plist": { - "version": "0.0.15", - "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.0.15.tgz", - "integrity": "sha512-LDxiS0KNZAGJu4fIJhbEKczmb+zeftl1NU0LE0tj0mozoMI5HSKdMUchgvnBm35bwBl8ekKkAfJJ0ONxljWQjQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "@xmldom/xmldom": "~0.7.0", - "base64-js": "^1.2.3", - "xmlbuilder": "^14.0.0" - } - }, - "node_modules/@expo/prebuild-config": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@expo/prebuild-config/-/prebuild-config-4.0.4.tgz", - "integrity": "sha512-yvoc2w4zwiq1wko8FE8/N3e1HSrXQP8XUvX8nIJtQ2mrSLGktbg9SzNM8+s8aBVTd4j1Zp3bcMzTsYnG9ygYbA==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@expo/config": "6.0.26", - "@expo/config-plugins": "4.1.5", - "@expo/config-types": "^45.0.0", - "@expo/image-utils": "0.3.21", - "@expo/json-file": "8.2.36", - "debug": "^4.3.1", - "expo-modules-autolinking": "0.8.1", - "fs-extra": "^9.0.0", - "resolve-from": "^5.0.0", - "semver": "7.3.2", - "xml2js": "0.4.23" - } - }, - "node_modules/@expo/prebuild-config/node_modules/@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, - "node_modules/@expo/prebuild-config/node_modules/@expo/config": { - "version": "6.0.26", - "resolved": "https://registry.npmjs.org/@expo/config/-/config-6.0.26.tgz", - "integrity": "sha512-nMQaZl69r6CMJFhCj0xcGJN9bIi4Uws0k9K6q6rGFPFNarS0z0aexeyNLv93/J+hsTJVn0GEYtGz5Y/R8boXxw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@babel/code-frame": "~7.10.4", - "@expo/config-plugins": "4.1.5", - "@expo/config-types": "^45.0.0", - "@expo/json-file": "8.2.36", - "getenv": "^1.0.0", - "glob": "7.1.6", - "require-from-string": "^2.0.2", - "resolve-from": "^5.0.0", - "semver": "7.3.2", - "slugify": "^1.3.4", - "sucrase": "^3.20.0" - } - }, - "node_modules/@expo/prebuild-config/node_modules/@expo/config-plugins": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-4.1.5.tgz", - "integrity": "sha512-RVvU40RtZt12HavuDAe+LDIq9lHj7sheOfMEHdmpJ/uTA8pgvkbc56XF6JHQD+yRr6+uhhb+JnAasGq49dsQbw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@expo/config-types": "^45.0.0", - "@expo/json-file": "8.2.36", - "@expo/plist": "0.0.18", - "@expo/sdk-runtime-versions": "^1.0.0", - "@react-native/normalize-color": "^2.0.0", - "chalk": "^4.1.2", - "debug": "^4.3.1", - "find-up": "~5.0.0", - "getenv": "^1.0.0", - "glob": "7.1.6", - "resolve-from": "^5.0.0", - "semver": "^7.3.5", - "slash": "^3.0.0", - "xcode": "^3.0.1", - "xml2js": "0.4.23" - } - }, - "node_modules/@expo/prebuild-config/node_modules/@expo/config-plugins/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@expo/prebuild-config/node_modules/@expo/config-types": { - "version": "45.0.0", - "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-45.0.0.tgz", - "integrity": "sha512-/QGhhLWyaGautgEyU50UJr5YqKJix5t77ePTwreOVAhmZH+ff3nrrtYTTnccx+qF08ZNQmfAyYMCD3rQfzpiJA==", - "license": "MIT", - "optional": true, - "peer": true - }, - "node_modules/@expo/prebuild-config/node_modules/@expo/json-file": { - "version": "8.2.36", - "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-8.2.36.tgz", - "integrity": "sha512-tOZfTiIFA5KmMpdW9KF7bc6CFiGjb0xnbieJhTGlHrLL+ps2G0OkqmuZ3pFEXBOMnJYUVpnSy++52LFxvpa5ZQ==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@babel/code-frame": "~7.10.4", - "json5": "^1.0.1", - "write-file-atomic": "^2.3.0" - } - }, - "node_modules/@expo/prebuild-config/node_modules/@expo/plist": { - "version": "0.0.18", - "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.0.18.tgz", - "integrity": "sha512-+48gRqUiz65R21CZ/IXa7RNBXgAI/uPSdvJqoN9x1hfL44DNbUoWHgHiEXTx7XelcATpDwNTz6sHLfy0iNqf+w==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@xmldom/xmldom": "~0.7.0", - "base64-js": "^1.2.3", - "xmlbuilder": "^14.0.0" - } - }, - "node_modules/@expo/prebuild-config/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@expo/prebuild-config/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@expo/prebuild-config/node_modules/expo-modules-autolinking": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-0.8.1.tgz", - "integrity": "sha512-S8qfaXCv//7tQWV9M+JKx3CF7ypYhDdSUbkUQdaVO/r8D76/aRTArY/aRw1yEfaAOzyK8C8diDToV1itl51DfQ==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "chalk": "^4.1.0", - "commander": "^7.2.0", - "fast-glob": "^3.2.5", - "find-up": "^5.0.0", - "fs-extra": "^9.1.0" - }, - "bin": { - "expo-modules-autolinking": "bin/expo-modules-autolinking.js" - } - }, - "node_modules/@expo/prebuild-config/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@expo/prebuild-config/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@expo/prebuild-config/node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@expo/prebuild-config/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/@expo/prebuild-config/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@expo/prebuild-config/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@expo/prebuild-config/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@expo/prebuild-config/node_modules/semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@expo/prebuild-config/node_modules/write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - }, - "node_modules/@expo/rudder-sdk-node": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@expo/rudder-sdk-node/-/rudder-sdk-node-1.1.1.tgz", - "integrity": "sha512-uy/hS/awclDJ1S88w9UGpc6Nm9XnNUjzOAAib1A3PVAnGQIwebg8DpFqOthFBTlZxeuV/BKbZ5jmTbtNZkp1WQ==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@expo/bunyan": "^4.0.0", - "@segment/loosely-validate-event": "^2.0.0", - "fetch-retry": "^4.1.1", - "md5": "^2.2.1", - "node-fetch": "^2.6.1", - "remove-trailing-slash": "^0.1.0", - "uuid": "^8.3.2" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@expo/rudder-sdk-node/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "license": "MIT", - "optional": true, - "peer": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@expo/sdk-runtime-versions": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@expo/sdk-runtime-versions/-/sdk-runtime-versions-1.0.0.tgz", - "integrity": "sha512-Doz2bfiPndXYFPMRwPyGa1k5QaKDVpY806UJj570epIiMzWaYyCtobasyfC++qfIXVb5Ocy7r3tP9d62hAQ7IQ==", - "license": "MIT", - "optional": true, - "peer": true - }, - "node_modules/@expo/spawn-async": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@expo/spawn-async/-/spawn-async-1.5.0.tgz", - "integrity": "sha512-LB7jWkqrHo+5fJHNrLAFdimuSXQ2MQ4lA7SQW5bf/HbsXuV2VrT/jN/M8f/KoWt0uJMGN4k/j7Opx4AvOOxSew==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "cross-spawn": "^6.0.5" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@expo/spawn-async/node_modules/cross-spawn": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", - "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/@expo/spawn-async/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@expo/spawn-async/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/@expo/spawn-async/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@expo/spawn-async/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@expo/spawn-async/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/@expo/vector-icons": { - "version": "12.0.5", - "resolved": "https://registry.npmjs.org/@expo/vector-icons/-/vector-icons-12.0.5.tgz", - "integrity": "sha512-zWvHBmkpbi1KrPma6Y+r/bsGI6MjbM1MBSe6W9A4uYMLhNI5NR4JtTnqxhf7g1XdpaDtBdv5aOWKEx4d5rxnhg==", - "license": "MIT", - "peer": true, - "dependencies": { - "lodash.frompairs": "^4.0.1", - "lodash.isequal": "^4.5.0", - "lodash.isstring": "^4.0.1", - "lodash.omit": "^4.5.0", - "lodash.pick": "^4.4.0", - "lodash.template": "^4.5.0" - } - }, - "node_modules/@expo/xcpretty": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@expo/xcpretty/-/xcpretty-4.3.2.tgz", - "integrity": "sha512-ReZxZ8pdnoI3tP/dNnJdnmAk7uLT4FjsKDGW7YeDdvdOMz2XCQSmSCM9IWlrXuWtMF9zeSB6WJtEhCQ41gQOfw==", - "license": "BSD-3-Clause", - "optional": true, - "peer": true, - "dependencies": { - "@babel/code-frame": "7.10.4", - "chalk": "^4.1.0", - "find-up": "^5.0.0", - "js-yaml": "^4.1.0" - }, - "bin": { - "excpretty": "build/cli.js" - } - }, - "node_modules/@expo/xcpretty/node_modules/@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, - "node_modules/@expo/xcpretty/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@expo/xcpretty/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@expo/xcpretty/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@faker-js/faker": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-9.0.1.tgz", - "integrity": "sha512-4mDeYIgM3By7X6t5E6eYwLAa+2h4DeZDF7thhzIg6XB76jeEvMwadYAMCFJL/R4AnEBcAUO9+gL0vhy3s+qvZA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/fakerjs" - } - ], - "engines": { - "node": ">=18.0.0", - "npm": ">=9.0.0" - } - }, - "node_modules/@floating-ui/core": { - "version": "1.6.4", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.4.tgz", - "integrity": "sha512-a4IowK4QkXl4SCWTGUR0INAfEOX3wtsYw3rKK5InQEHMGObkR8Xk44qYQD9P4r6HHw0iIfK6GUKECmY8sTkqRA==", - "dependencies": { - "@floating-ui/utils": "^0.2.4" - } - }, - "node_modules/@floating-ui/dom": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.7.tgz", - "integrity": "sha512-wmVfPG5o2xnKDU4jx/m4w5qva9FWHcnZ8BvzEe90D/RpwsJaTAVYPEPdQ8sbr/N8zZTAHlZUTQdqg8ZUbzHmng==", - "dependencies": { - "@floating-ui/core": "^1.6.0", - "@floating-ui/utils": "^0.2.4" - } - }, - "node_modules/@floating-ui/react-dom": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.1.tgz", - "integrity": "sha512-4h84MJt3CHrtG18mGsXuLCHMrug49d7DFkU0RMIyshRveBeyV2hmV/pDaF2Uxtu8kgq5r46llp5E5FQiR0K2Yg==", - "dependencies": { - "@floating-ui/dom": "^1.0.0" - }, - "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" - } - }, - "node_modules/@floating-ui/utils": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.4.tgz", - "integrity": "sha512-dWO2pw8hhi+WrXq1YJy2yCuWoL20PddgGaqTgVe4cOS9Q6qklXCiA1tJEqX6BEwRNSCP84/afac9hd4MS+zEUA==" - }, - "node_modules/@fortawesome/fontawesome-common-types": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.2.tgz", - "integrity": "sha512-gBxPg3aVO6J0kpfHNILc+NMhXnqHumFxOmjYCFfOiLZfwhnnfhtsdA2hfJlDnj+8PjAs6kKQPenOTKj3Rf7zHw==", - "hasInstallScript": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/@fortawesome/fontawesome-svg-core": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.5.2.tgz", - "integrity": "sha512-5CdaCBGl8Rh9ohNdxeeTMxIj8oc3KNBgIeLMvJosBMdslK/UnEB8rzyDRrbKdL1kDweqBPo4GT9wvnakHWucZw==", - "hasInstallScript": true, - "dependencies": { - "@fortawesome/fontawesome-common-types": "6.5.2" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@fortawesome/free-solid-svg-icons": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.5.2.tgz", - "integrity": "sha512-QWFZYXFE7O1Gr1dTIp+D6UcFUF0qElOnZptpi7PBUMylJh+vFmIedVe1Ir6RM1t2tEQLLSV1k7bR4o92M+uqlw==", - "hasInstallScript": true, - "dependencies": { - "@fortawesome/fontawesome-common-types": "6.5.2" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@fortawesome/react-fontawesome": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.2.tgz", - "integrity": "sha512-EnkrprPNqI6SXJl//m29hpaNzOp1bruISWaOiRtkMi/xSvHJlzc2j2JAYS7egxt/EbjSNV/k6Xy0AQI6vB2+1g==", - "dependencies": { - "prop-types": "^15.8.1" - }, - "peerDependencies": { - "@fortawesome/fontawesome-svg-core": "~1 || ~6", - "react": ">=16.3" - } - }, - "node_modules/@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", - "license": "MIT", - "optional": true, - "peer": true - }, - "node_modules/@graphql-typed-document-node/core": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz", - "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==", - "license": "MIT", - "optional": true, - "peer": true, - "peerDependencies": { - "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@grpc/grpc-js": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.12.2.tgz", - "integrity": "sha512-bgxdZmgTrJZX50OjyVwz3+mNEnCTNkh3cIqGPWVNeW9jX6bn1ZkU80uPd+67/ZpIJIjRQ9qaHCjhavyoWYxumg==", - "dependencies": { - "@grpc/proto-loader": "^0.7.13", - "@js-sdsl/ordered-map": "^4.4.2" - }, - "engines": { - "node": ">=12.10.0" - } - }, - "node_modules/@grpc/proto-loader": { - "version": "0.7.13", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz", - "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==", - "dependencies": { - "lodash.camelcase": "^4.3.0", - "long": "^5.0.0", - "protobufjs": "^7.2.5", - "yargs": "^17.7.2" - }, - "bin": { - "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@grpc/proto-loader/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/@grpc/proto-loader/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/@grpc/proto-loader/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@grpc/proto-loader/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@hapi/hoek": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", - "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" - }, - "node_modules/@hapi/topo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", - "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", - "dependencies": { - "@hapi/hoek": "^9.0.0" - } - }, - "node_modules/@hashgraph/cryptography": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@hashgraph/cryptography/-/cryptography-1.1.2.tgz", - "integrity": "sha512-oSnDDs5foNq6Yni4kCwbA01NuVY2mewVr1jhkJG7yNDT6+xIBCztRWDeINb1JuShXe57Cuf88M1zmN5iFN7JgA==", - "license": "Apache-2.0", - "dependencies": { - "bignumber.js": "^9.0.2", - "crypto-js": "^4.1.1", - "elliptic": "^6.5.4", - "expo-crypto": "^10.1.2", - "expo-random": "^12.1.2", - "js-base64": "^3.7.2", - "tweetnacl": "^1.0.3", - "utf8": "^3.0.0" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "expo": "^44.0.5" - } - }, - "node_modules/@hashgraph/proto": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@hashgraph/proto/-/proto-2.12.0.tgz", - "integrity": "sha512-IIN6K3b2X8ih7V14IDH8rsVJ1DE9ud25FfKUpr+lDNnQdBfdZdG2AGlHRhc9iDAz4vCHoHc6F3Ao6yYKMceeTg==", - "license": "Apache-2.0", - "dependencies": { - "long": "^4.0.0", - "protobufjs": "^7.1.2", - "protobufjs-cli": "^1.0.2" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@hashgraph/proto/node_modules/long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", - "license": "Apache-2.0" - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "deprecated": "Use @eslint/config-array instead", - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead" - }, - "node_modules/@inquirer/confirm": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.0.tgz", - "integrity": "sha512-osaBbIMEqVFjTX5exoqPXs6PilWQdjaLhGtMDXMXg/yxkHXNq43GlxGyTA35lK2HpzUgDN+Cjh/2AmqCN0QJpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.1.1", - "@inquirer/type": "^3.0.1" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - } - }, - "node_modules/@inquirer/core": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.1.tgz", - "integrity": "sha512-rmZVXy9iZvO3ZStEe/ayuuwIJ23LSF13aPMlLMTQARX6lGUBDHGV8UB5i9MRrfy0+mZwt5/9bdy8llszSD3NQA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/figures": "^1.0.8", - "@inquirer/type": "^3.0.1", - "ansi-escapes": "^4.3.2", - "cli-width": "^4.1.0", - "mute-stream": "^2.0.0", - "signal-exit": "^4.1.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^6.2.0", - "yoctocolors-cjs": "^2.1.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@inquirer/core/node_modules/cli-width": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", - "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">= 12" - } - }, - "node_modules/@inquirer/core/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/@inquirer/core/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@inquirer/core/node_modules/mute-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", - "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/@inquirer/core/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@inquirer/core/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@inquirer/core/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@inquirer/figures": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.8.tgz", - "integrity": "sha512-tKd+jsmhq21AP1LhexC0pPwsCxEhGgAkg28byjJAd+xhmIs8LUX8JbUc3vBf3PhLxWiB5EvyBE5X7JSPAqMAqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@inquirer/type": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.1.tgz", - "integrity": "sha512-+ksJMIy92sOAiAccGpcKZUc3bYO07cADnscIxHBknEm3uNts3movSmBofc1908BNy5edKscxYeAdaX1NXkHS6A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - } - }, - "node_modules/@ioredis/commands": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", - "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==" - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/ttlcache": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz", - "integrity": "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==", - "license": "ISC", - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/console": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/core": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", - "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", - "dev": true, - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/reporters": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.7.0", - "jest-config": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-resolve-dependencies": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "jest-watcher": "^29.7.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/core/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/core/node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@jest/core/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true - }, - "node_modules/@jest/create-cache-key-function": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz", - "integrity": "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==", - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/types": "^29.6.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", - "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", - "dev": true, - "dependencies": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/expect-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", - "dev": true, - "dependencies": { - "jest-get-type": "^29.6.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/fake-timers": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", - "dependencies": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/globals": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", - "dev": true, - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/reporters": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", - "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", - "dev": true, - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/source-map": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", - "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/test-result": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", - "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", - "dev": true, - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/test-sequencer": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", - "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", - "dev": true, - "dependencies": { - "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", - "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@js-sdsl/ordered-map": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", - "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/js-sdsl" - } - }, - "node_modules/@jsdoc/salty": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.9.tgz", - "integrity": "sha512-yYxMVH7Dqw6nO0d5NIV8OQWnitU8k6vXH8NtgqAfIa/IUqRMxRv/NUJJ08VEKbAakwxlgBl5PJdrU0dMPStsnw==", - "license": "Apache-2.0", - "dependencies": { - "lodash": "^4.17.21" - }, - "engines": { - "node": ">=v12.0.0" - } - }, - "node_modules/@jsonjoy.com/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", - "dev": true, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/@jsonjoy.com/json-pack": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.1.0.tgz", - "integrity": "sha512-zlQONA+msXPPwHWZMKFVS78ewFczIll5lXiVPwFPCZUsrOKdxc2AvxU1HoNBmMRhqDZUR9HkC3UOm+6pME6Xsg==", - "dev": true, - "dependencies": { - "@jsonjoy.com/base64": "^1.1.1", - "@jsonjoy.com/util": "^1.1.2", - "hyperdyperid": "^1.2.0", - "thingies": "^1.20.0" - }, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/@jsonjoy.com/util": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.3.0.tgz", - "integrity": "sha512-Cebt4Vk7k1xHy87kHY7KSPLT77A7Ev7IfOblyLZhtYEhrdQ6fX4EoLq3xOQ3O/DRMEh2ok5nyC180E+ABS8Wmw==", - "dev": true, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/@keyv/serialize": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.0.2.tgz", - "integrity": "sha512-+E/LyaAeuABniD/RvUezWVXKpeuvwLEA9//nE9952zBaOdBd2mQ3pPoM8cUe2X6IcMByfuSLzmYqnYshG60+HQ==", - "license": "MIT", - "dependencies": { - "buffer": "^6.0.3" - } - }, - "node_modules/@keyv/serialize/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/@ledgerhq/devices": { - "version": "5.51.1", - "resolved": "https://registry.npmjs.org/@ledgerhq/devices/-/devices-5.51.1.tgz", - "integrity": "sha512-4w+P0VkbjzEXC7kv8T1GJ/9AVaP9I6uasMZ/JcdwZBS3qwvKo5A5z9uGhP5c7TvItzcmPb44b5Mw2kT+WjUuAA==", - "license": "Apache-2.0", - "dependencies": { - "@ledgerhq/errors": "^5.50.0", - "@ledgerhq/logs": "^5.50.0", - "rxjs": "6", - "semver": "^7.3.5" - } - }, - "node_modules/@ledgerhq/devices/node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" - } - }, - "node_modules/@ledgerhq/devices/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@ledgerhq/devices/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "license": "0BSD" - }, - "node_modules/@ledgerhq/errors": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@ledgerhq/errors/-/errors-5.50.0.tgz", - "integrity": "sha512-gu6aJ/BHuRlpU7kgVpy2vcYk6atjB4iauP2ymF7Gk0ez0Y/6VSMVSJvubeEQN+IV60+OBK0JgeIZG7OiHaw8ow==", - "license": "Apache-2.0" - }, - "node_modules/@ledgerhq/hw-transport": { - "version": "5.51.1", - "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport/-/hw-transport-5.51.1.tgz", - "integrity": "sha512-6wDYdbWrw9VwHIcoDnqWBaDFyviyjZWv6H9vz9Vyhe4Qd7TIFmbTl/eWs6hZvtZBza9K8y7zD8ChHwRI4s9tSw==", - "license": "Apache-2.0", - "dependencies": { - "@ledgerhq/devices": "^5.51.1", - "@ledgerhq/errors": "^5.50.0", - "events": "^3.3.0" - } - }, - "node_modules/@ledgerhq/hw-transport-web-ble": { - "version": "5.48.0", - "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-web-ble/-/hw-transport-web-ble-5.48.0.tgz", - "integrity": "sha512-ezgssFvxc4/UbfwIxwg9jEn0/yiND8TW6bDkaE3kAqKCa8ZYYgFtms8iRqjTOJlqcbSYkudbNhP74jtY0NxfdA==", - "license": "Apache-2.0", - "dependencies": { - "@ledgerhq/devices": "^5.48.0", - "@ledgerhq/errors": "^5.48.0", - "@ledgerhq/hw-transport": "^5.48.0", - "@ledgerhq/logs": "^5.48.0", - "rxjs": "^6.6.7" - } - }, - "node_modules/@ledgerhq/hw-transport-web-ble/node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" - } - }, - "node_modules/@ledgerhq/hw-transport-web-ble/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "license": "0BSD" - }, - "node_modules/@ledgerhq/hw-transport-webhid": { - "version": "5.48.0", - "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-webhid/-/hw-transport-webhid-5.48.0.tgz", - "integrity": "sha512-g6TYxgPX3MqP3jQ4SJaJjlM+2SwUSk4Si/9MeKLwz5ySbiD3bSTh/Gbzv8VBCaHPO4fILujc5vW/xejJuMzR8w==", - "license": "Apache-2.0", - "dependencies": { - "@ledgerhq/devices": "^5.48.0", - "@ledgerhq/errors": "^5.48.0", - "@ledgerhq/hw-transport": "^5.48.0", - "@ledgerhq/logs": "^5.48.0" - } - }, - "node_modules/@ledgerhq/hw-transport-webusb": { - "version": "5.48.0", - "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-webusb/-/hw-transport-webusb-5.48.0.tgz", - "integrity": "sha512-tO+p11aRQx9q9ifmi/NCbCBKQ738lp+PROy1BWSzjCJcUEz1sKTLeRTLE2Xze25KebhuM2YR1NgkX5LN1z4upA==", - "license": "Apache-2.0", - "dependencies": { - "@ledgerhq/devices": "^5.48.0", - "@ledgerhq/errors": "^5.48.0", - "@ledgerhq/hw-transport": "^5.48.0", - "@ledgerhq/logs": "^5.48.0" - } - }, - "node_modules/@ledgerhq/logs": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@ledgerhq/logs/-/logs-5.50.0.tgz", - "integrity": "sha512-swKHYCOZUGyVt4ge0u8a7AwNcA//h4nx5wIi0sruGye1IJ5Cva0GyK9L2/WdX+kWVTKp92ZiEo1df31lrWGPgA==", - "license": "Apache-2.0" - }, - "node_modules/@leichtgewicht/ip-codec": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", - "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==" - }, - "node_modules/@lit-labs/ssr-dom-shim": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.2.1.tgz", - "integrity": "sha512-wx4aBmgeGvFmOKucFKY+8VFJSYZxs9poN3SDNQFF6lT6NrQUnHiPB2PWz2sc4ieEcAaYYzN+1uWahEeTq2aRIQ==" - }, - "node_modules/@lit/reactive-element": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.6.3.tgz", - "integrity": "sha512-QuTgnG52Poic7uM1AN5yJ09QMe0O28e10XzSvWDz02TJiiKee4stsiownEIadWm8nYzyDAyT+gKzUoZmiWQtsQ==", - "dependencies": { - "@lit-labs/ssr-dom-shim": "^1.0.0" - } - }, - "node_modules/@lukeed/csprng": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz", - "integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/@mdx-js/mdx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.0.1.tgz", - "integrity": "sha512-eIQ4QTrOWyL3LWEe/bu6Taqzq2HQvHcyTMaOrI95P2/LmJE7AsfPfgJGuFLPVqBUE1BC1rik3VIhU+s9u72arA==", - "dependencies": { - "@types/estree": "^1.0.0", - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdx": "^2.0.0", - "collapse-white-space": "^2.0.0", - "devlop": "^1.0.0", - "estree-util-build-jsx": "^3.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "estree-util-to-js": "^2.0.0", - "estree-walker": "^3.0.0", - "hast-util-to-estree": "^3.0.0", - "hast-util-to-jsx-runtime": "^2.0.0", - "markdown-extensions": "^2.0.0", - "periscopic": "^3.0.0", - "remark-mdx": "^3.0.0", - "remark-parse": "^11.0.0", - "remark-rehype": "^11.0.0", - "source-map": "^0.7.0", - "unified": "^11.0.0", - "unist-util-position-from-estree": "^2.0.0", - "unist-util-stringify-position": "^4.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/@mdx-js/react": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.1.tgz", - "integrity": "sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A==", - "dependencies": { - "@types/mdx": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - }, - "peerDependencies": { - "@types/react": ">=16", - "react": ">=16" - } - }, - "node_modules/@metamask/eth-json-rpc-provider": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@metamask/eth-json-rpc-provider/-/eth-json-rpc-provider-1.0.1.tgz", - "integrity": "sha512-whiUMPlAOrVGmX8aKYVPvlKyG4CpQXiNNyt74vE1xb5sPvmx5oA7B/kOi/JdBvhGQq97U1/AVdXEdk2zkP8qyA==", - "dependencies": { - "@metamask/json-rpc-engine": "^7.0.0", - "@metamask/safe-event-emitter": "^3.0.0", - "@metamask/utils": "^5.0.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@metamask/eth-json-rpc-provider/node_modules/@metamask/json-rpc-engine": { - "version": "7.3.3", - "resolved": "https://registry.npmjs.org/@metamask/json-rpc-engine/-/json-rpc-engine-7.3.3.tgz", - "integrity": "sha512-dwZPq8wx9yV3IX2caLi9q9xZBw2XeIoYqdyihDDDpuHVCEiqadJLwqM3zy+uwf6F1QYQ65A8aOMQg1Uw7LMLNg==", - "dependencies": { - "@metamask/rpc-errors": "^6.2.1", - "@metamask/safe-event-emitter": "^3.0.0", - "@metamask/utils": "^8.3.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@metamask/eth-json-rpc-provider/node_modules/@metamask/json-rpc-engine/node_modules/@metamask/utils": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-8.5.0.tgz", - "integrity": "sha512-I6bkduevXb72TIM9q2LRO63JSsF9EXduh3sBr9oybNX2hNNpr/j1tEjXrsG0Uabm4MJ1xkGAQEMwifvKZIkyxQ==", - "dependencies": { - "@ethereumjs/tx": "^4.2.0", - "@metamask/superstruct": "^3.0.0", - "@noble/hashes": "^1.3.1", - "@scure/base": "^1.1.3", - "@types/debug": "^4.1.7", - "debug": "^4.3.4", - "pony-cause": "^2.1.10", - "semver": "^7.5.4", - "uuid": "^9.0.1" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@metamask/eth-json-rpc-provider/node_modules/@metamask/utils": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-5.0.2.tgz", - "integrity": "sha512-yfmE79bRQtnMzarnKfX7AEJBwFTxvTyw3nBQlu/5rmGXrjAeAMltoGxO62TFurxrQAFMNa/fEjIHNvungZp0+g==", - "dependencies": { - "@ethereumjs/tx": "^4.1.2", - "@types/debug": "^4.1.7", - "debug": "^4.3.4", - "semver": "^7.3.8", - "superstruct": "^1.0.3" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@metamask/eth-json-rpc-provider/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@metamask/eth-sig-util": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@metamask/eth-sig-util/-/eth-sig-util-5.1.0.tgz", - "integrity": "sha512-mlgziIHYlA9pi/XZerChqg4NocdOgBPB9NmxgXWQO2U2hH8RGOJQrz6j/AIKkYxgCMIE2PY000+joOwXfzeTDQ==", - "license": "ISC", - "dependencies": { - "@ethereumjs/util": "^8.0.6", - "bn.js": "^4.12.0", - "ethereum-cryptography": "^2.0.0", - "ethjs-util": "^0.1.6", - "tweetnacl": "^1.0.3", - "tweetnacl-util": "^0.15.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@metamask/eth-sig-util/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", - "license": "MIT" - }, - "node_modules/@metamask/json-rpc-engine": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@metamask/json-rpc-engine/-/json-rpc-engine-8.0.2.tgz", - "integrity": "sha512-IoQPmql8q7ABLruW7i4EYVHWUbF74yrp63bRuXV5Zf9BQwcn5H9Ww1eLtROYvI1bUXwOiHZ6qT5CWTrDc/t/AA==", - "dependencies": { - "@metamask/rpc-errors": "^6.2.1", - "@metamask/safe-event-emitter": "^3.0.0", - "@metamask/utils": "^8.3.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@metamask/json-rpc-middleware-stream": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@metamask/json-rpc-middleware-stream/-/json-rpc-middleware-stream-7.0.2.tgz", - "integrity": "sha512-yUdzsJK04Ev98Ck4D7lmRNQ8FPioXYhEUZOMS01LXW8qTvPGiRVXmVltj2p4wrLkh0vW7u6nv0mNl5xzC5Qmfg==", - "dependencies": { - "@metamask/json-rpc-engine": "^8.0.2", - "@metamask/safe-event-emitter": "^3.0.0", - "@metamask/utils": "^8.3.0", - "readable-stream": "^3.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@metamask/object-multiplex": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@metamask/object-multiplex/-/object-multiplex-2.1.0.tgz", - "integrity": "sha512-4vKIiv0DQxljcXwfpnbsXcfa5glMj5Zg9mqn4xpIWqkv6uJ2ma5/GtUfLFSxhlxnR8asRMv8dDmWya1Tc1sDFA==", - "dependencies": { - "once": "^1.4.0", - "readable-stream": "^3.6.2" - }, - "engines": { - "node": "^16.20 || ^18.16 || >=20" - } - }, - "node_modules/@metamask/onboarding": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@metamask/onboarding/-/onboarding-1.0.1.tgz", - "integrity": "sha512-FqHhAsCI+Vacx2qa5mAFcWNSrTcVGMNjzxVgaX8ECSny/BJ9/vgXP9V7WF/8vb9DltPeQkxr+Fnfmm6GHfmdTQ==", - "dependencies": { - "bowser": "^2.9.0" - } - }, - "node_modules/@metamask/providers": { - "version": "16.1.0", - "resolved": "https://registry.npmjs.org/@metamask/providers/-/providers-16.1.0.tgz", - "integrity": "sha512-znVCvux30+3SaUwcUGaSf+pUckzT5ukPRpcBmy+muBLC0yaWnBcvDqGfcsw6CBIenUdFrVoAFa8B6jsuCY/a+g==", - "dependencies": { - "@metamask/json-rpc-engine": "^8.0.1", - "@metamask/json-rpc-middleware-stream": "^7.0.1", - "@metamask/object-multiplex": "^2.0.0", - "@metamask/rpc-errors": "^6.2.1", - "@metamask/safe-event-emitter": "^3.1.1", - "@metamask/utils": "^8.3.0", - "detect-browser": "^5.2.0", - "extension-port-stream": "^3.0.0", - "fast-deep-equal": "^3.1.3", - "is-stream": "^2.0.0", - "readable-stream": "^3.6.2", - "webextension-polyfill": "^0.10.0" - }, - "engines": { - "node": "^18.18 || >=20" - } - }, - "node_modules/@metamask/rpc-errors": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/@metamask/rpc-errors/-/rpc-errors-6.4.0.tgz", - "integrity": "sha512-1ugFO1UoirU2esS3juZanS/Fo8C8XYocCuBpfZI5N7ECtoG+zu0wF+uWZASik6CkO6w9n/Iebt4iI4pT0vptpg==", - "dependencies": { - "@metamask/utils": "^9.0.0", - "fast-safe-stringify": "^2.0.6" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@metamask/rpc-errors/node_modules/@metamask/utils": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-9.3.0.tgz", - "integrity": "sha512-w8CVbdkDrVXFJbfBSlDfafDR6BAkpDmv1bC1UJVCoVny5tW2RKAdn9i68Xf7asYT4TnUhl/hN4zfUiKQq9II4g==", - "dependencies": { - "@ethereumjs/tx": "^4.2.0", - "@metamask/superstruct": "^3.1.0", - "@noble/hashes": "^1.3.1", - "@scure/base": "^1.1.3", - "@types/debug": "^4.1.7", - "debug": "^4.3.4", - "pony-cause": "^2.1.10", - "semver": "^7.5.4", - "uuid": "^9.0.1" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@metamask/rpc-errors/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@metamask/safe-event-emitter": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@metamask/safe-event-emitter/-/safe-event-emitter-3.1.2.tgz", - "integrity": "sha512-5yb2gMI1BDm0JybZezeoX/3XhPDOtTbcFvpTXM9kxsoZjPZFh4XciqRbpD6N86HYZqWDhEaKUDuOyR0sQHEjMA==", - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@metamask/sdk": { - "version": "0.30.1", - "resolved": "https://registry.npmjs.org/@metamask/sdk/-/sdk-0.30.1.tgz", - "integrity": "sha512-NelEjJZsF5wVpSQELpmvXtnS9+C6HdxGQ4GB9jMRzeejphmPyKqmrIGM6XtaPrJtlpX+40AcJ2dtBQcjJVzpbQ==", - "dependencies": { - "@metamask/onboarding": "^1.0.1", - "@metamask/providers": "16.1.0", - "@metamask/sdk-communication-layer": "0.30.0", - "@metamask/sdk-install-modal-web": "0.30.0", - "bowser": "^2.9.0", - "cross-fetch": "^4.0.0", - "debug": "^4.3.4", - "eciesjs": "^0.4.8", - "eth-rpc-errors": "^4.0.3", - "eventemitter2": "^6.4.7", - "i18next": "23.11.5", - "i18next-browser-languagedetector": "7.1.0", - "obj-multiplex": "^1.0.0", - "pump": "^3.0.0", - "qrcode-terminal-nooctal": "^0.12.1", - "react-native-webview": "^11.26.0", - "readable-stream": "^3.6.2", - "socket.io-client": "^4.5.1", - "util": "^0.12.4", - "uuid": "^8.3.2" - }, - "peerDependencies": { - "react": "^18.2.0", - "react-dom": "^18.2.0" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } - }, - "node_modules/@metamask/sdk-communication-layer": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/@metamask/sdk-communication-layer/-/sdk-communication-layer-0.30.0.tgz", - "integrity": "sha512-q5nbdYkAf76MsZxi1l5MJEAyd8sY9jLRapC8a7x1Q1BNV4rzQeFeux/d0mJ/jTR2LAwbnLZs2rL226AM75oK4w==", - "dependencies": { - "bufferutil": "^4.0.8", - "date-fns": "^2.29.3", - "debug": "^4.3.4", - "utf-8-validate": "^5.0.2", - "uuid": "^8.3.2" - }, - "peerDependencies": { - "cross-fetch": "^4.0.0", - "eciesjs": "^0.3.16", - "eventemitter2": "^6.4.7", - "readable-stream": "^3.6.2", - "socket.io-client": "^4.5.1" - } - }, - "node_modules/@metamask/sdk-communication-layer/node_modules/date-fns": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", - "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", - "dependencies": { - "@babel/runtime": "^7.21.0" - }, - "engines": { - "node": ">=0.11" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/date-fns" - } - }, - "node_modules/@metamask/sdk-communication-layer/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@metamask/sdk-install-modal-web": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/@metamask/sdk-install-modal-web/-/sdk-install-modal-web-0.30.0.tgz", - "integrity": "sha512-1gT533Huja9tK3cmttvcpZirRAtWJ7vnYH+lnNRKEj2xIP335Df2cOwS+zqNC4GlRCZw7A3IsTjIzlKoxBY1uQ==", - "dependencies": { - "qr-code-styling": "^1.6.0-rc.1" - }, - "peerDependencies": { - "i18next": "23.11.5", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-native": "*" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-dom": { - "optional": true - }, - "react-native": { - "optional": true - } - } - }, - "node_modules/@metamask/sdk/node_modules/@noble/hashes": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.5.0.tgz", - "integrity": "sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==", - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@metamask/sdk/node_modules/eciesjs": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/eciesjs/-/eciesjs-0.4.11.tgz", - "integrity": "sha512-SmUG449n1w1YGvJD9R30tBGvpxTxA0cnn0rfvpFIBvmezfIhagLjsH2JG8HBHOLS8slXsPh48II7IDUTH/J3Mg==", - "dependencies": { - "@ecies/ciphers": "^0.2.1", - "@noble/ciphers": "^1.0.0", - "@noble/curves": "^1.6.0", - "@noble/hashes": "^1.5.0" - }, - "engines": { - "bun": ">=1", - "deno": ">=2", - "node": ">=16" - } - }, - "node_modules/@metamask/sdk/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@metamask/superstruct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@metamask/superstruct/-/superstruct-3.1.0.tgz", - "integrity": "sha512-N08M56HdOgBfRKkrgCMZvQppkZGcArEop3kixNEtVbJKm6P9Cfg0YkI6X0s1g78sNrj2fWUwvJADdZuzJgFttA==", - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@metamask/utils": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-8.5.0.tgz", - "integrity": "sha512-I6bkduevXb72TIM9q2LRO63JSsF9EXduh3sBr9oybNX2hNNpr/j1tEjXrsG0Uabm4MJ1xkGAQEMwifvKZIkyxQ==", - "dependencies": { - "@ethereumjs/tx": "^4.2.0", - "@metamask/superstruct": "^3.0.0", - "@noble/hashes": "^1.3.1", - "@scure/base": "^1.1.3", - "@types/debug": "^4.1.7", - "debug": "^4.3.4", - "pony-cause": "^2.1.10", - "semver": "^7.5.4", - "uuid": "^9.0.1" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@metamask/utils/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@microsoft/tsdoc": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.15.0.tgz", - "integrity": "sha512-HZpPoABogPvjeJOdzCOSJsXeL/SMCBgBZMVC3X3d7YYp2gf31MfxhUoYUNwf1ERPJOnQc0wkFn9trqI6ZEdZuA==" - }, - "node_modules/@module-federation/bridge-react-webpack-plugin": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@module-federation/bridge-react-webpack-plugin/-/bridge-react-webpack-plugin-0.2.8.tgz", - "integrity": "sha512-6G1qTo1HWvRcN5fzE+SZgvgzSPoq5YqNx8hFL8BttJmnd3wj4SUOFiikAsXhdVrzSK+Zuzg6pipkiLH1m+pbtw==", - "dev": true, - "dependencies": { - "@module-federation/sdk": "0.2.8" - } - }, - "node_modules/@module-federation/dts-plugin": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@module-federation/dts-plugin/-/dts-plugin-0.2.8.tgz", - "integrity": "sha512-qY1Wbqo0yu9nh6KR8K19t5T4tYtlUbmcNdcaCweISCyAbH99TrhpQkJ89NY0TLtnxQ6uayIYayqAWS7vzyDXVw==", - "dev": true, - "dependencies": { - "@module-federation/managers": "0.2.8", - "@module-federation/sdk": "0.2.8", - "@module-federation/third-party-dts-extractor": "0.2.8", - "adm-zip": "^0.5.10", - "ansi-colors": "^4.1.3", - "axios": "^1.6.7", - "chalk": "3.0.0", - "fs-extra": "9.1.0", - "isomorphic-ws": "5.0.0", - "koa": "2.11.0", - "lodash.clonedeepwith": "4.5.0", - "log4js": "6.9.1", - "node-schedule": "2.1.1", - "rambda": "^9.1.0", - "ws": "8.17.1" - }, - "peerDependencies": { - "typescript": "^4.9.0 || ^5.0.0", - "vue-tsc": ">=1.0.24" - }, - "peerDependenciesMeta": { - "vue-tsc": { - "optional": true - } - } - }, - "node_modules/@module-federation/dts-plugin/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@module-federation/dts-plugin/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@module-federation/dts-plugin/node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/@module-federation/enhanced": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@module-federation/enhanced/-/enhanced-0.2.8.tgz", - "integrity": "sha512-6fGM/GiKw6LZiBe6DF8Petz6ih/Yyf3q2htLrx+hrWoDWfWEoWlLvoCUsVkY2UgMCLKid7Fm3Auc4w8A4aRjvQ==", - "dev": true, - "dependencies": { - "@module-federation/bridge-react-webpack-plugin": "0.2.8", - "@module-federation/dts-plugin": "0.2.8", - "@module-federation/managers": "0.2.8", - "@module-federation/manifest": "0.2.8", - "@module-federation/rspack": "0.2.8", - "@module-federation/runtime-tools": "0.2.8", - "@module-federation/sdk": "0.2.8", - "btoa": "^1.2.1", - "upath": "2.0.1" - }, - "peerDependencies": { - "typescript": "^4.9.0 || ^5.0.0", - "vue-tsc": ">=1.0.24", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - }, - "vue-tsc": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/@module-federation/managers": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@module-federation/managers/-/managers-0.2.8.tgz", - "integrity": "sha512-S5GXqt2Vrs1+uNXHw7UzZ7m3fs8H3nxNsNGQ0j5+HiT5yA7uRTY1AZJZCGAHzG6XImJ1DzL/SW1acM2Hwj0aAw==", - "dev": true, - "dependencies": { - "@module-federation/sdk": "0.2.8", - "find-pkg": "2.0.0", - "fs-extra": "9.1.0" - } - }, - "node_modules/@module-federation/managers/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@module-federation/manifest": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@module-federation/manifest/-/manifest-0.2.8.tgz", - "integrity": "sha512-kw4PeAldkOuGCWfCnDzZwPHUx5qv9+WztY5+TEbsgXc5E+/e2NDA6Gg3eT8zUGeexeGdab3f+DuN9ZClZJYVGA==", - "dev": true, - "dependencies": { - "@module-federation/dts-plugin": "0.2.8", - "@module-federation/managers": "0.2.8", - "@module-federation/sdk": "0.2.8", - "chalk": "3.0.0", - "find-pkg": "2.0.0" - } - }, - "node_modules/@module-federation/manifest/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@module-federation/rspack": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@module-federation/rspack/-/rspack-0.2.8.tgz", - "integrity": "sha512-5Bofm3cY7OOwO2DT5TevITd+HAA03zsY1wwsMb1BP6NkS/ukUtsjuRo2Anua0RkHBEIx+Dv5rpqOn7qSlOm1Fg==", - "dev": true, - "dependencies": { - "@module-federation/bridge-react-webpack-plugin": "0.2.8", - "@module-federation/dts-plugin": "0.2.8", - "@module-federation/managers": "0.2.8", - "@module-federation/manifest": "0.2.8", - "@module-federation/runtime-tools": "0.2.8", - "@module-federation/sdk": "0.2.8" - }, - "peerDependencies": { - "typescript": "^4.9.0 || ^5.0.0", - "vue-tsc": ">=1.0.24" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - }, - "vue-tsc": { - "optional": true - } - } - }, - "node_modules/@module-federation/runtime": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@module-federation/runtime/-/runtime-0.2.8.tgz", - "integrity": "sha512-8xmA/+z1zD09F5qU8VnSWLExqTCVWoHOguXsCX79kkqp7i0c+D2YaebWzlQ2kku+DU+0VIzXpQ3BBcumZ3v3wQ==", - "dev": true, - "dependencies": { - "@module-federation/sdk": "0.2.8" - } - }, - "node_modules/@module-federation/runtime-tools": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@module-federation/runtime-tools/-/runtime-tools-0.2.8.tgz", - "integrity": "sha512-RSNtyhcNvnTQIdzRUIOGue6WQA/9mL9cY/n0dEd357L/lmLCvfHiZbowlkacckDzyApariUHxzkHrU2Q6kzoew==", - "dev": true, - "dependencies": { - "@module-federation/runtime": "0.2.8", - "@module-federation/webpack-bundler-runtime": "0.2.8" - } - }, - "node_modules/@module-federation/sdk": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@module-federation/sdk/-/sdk-0.2.8.tgz", - "integrity": "sha512-eGMnJxdRDgt6dtMv8gkAlzEbTPWVHb3AHUNUG0w56wcbIF0RHC6kmvpHpSQyq4DVGWv3U4g/ZiH5BvBlqEelDQ==", - "dev": true - }, - "node_modules/@module-federation/third-party-dts-extractor": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@module-federation/third-party-dts-extractor/-/third-party-dts-extractor-0.2.8.tgz", - "integrity": "sha512-VGXvdsRlljbFUfGeA448CxR7i6fLWJN07ViRuNXYYXc19e4bQVhBHzrf7eCv9ahcf/tA/8YYCS2h11ixbD691A==", - "dev": true, - "dependencies": { - "find-pkg": "2.0.0", - "fs-extra": "9.1.0", - "resolve": "1.22.8" - } - }, - "node_modules/@module-federation/third-party-dts-extractor/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@module-federation/webpack-bundler-runtime": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@module-federation/webpack-bundler-runtime/-/webpack-bundler-runtime-0.2.8.tgz", - "integrity": "sha512-tiW1kD/V3QNul1/O3Y3lwQv/r4sUU4jvWZykrLvHYt2vuoGe1d4tHnSIFEVEAi9FSpuDwdRK2+NaWBr92gIS7Q==", - "dev": true, - "dependencies": { - "@module-federation/runtime": "0.2.8", - "@module-federation/sdk": "0.2.8" - } - }, - "node_modules/@monaco-editor/loader": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.4.0.tgz", - "integrity": "sha512-00ioBig0x642hytVspPl7DbQyaSWRaolYie/UFNjoTdvoKPzo6xrXLhTk9ixgIKcLH5b5vDOjVNiGyY+uDCUlg==", - "dependencies": { - "state-local": "^1.0.6" - }, - "peerDependencies": { - "monaco-editor": ">= 0.21.0 < 1" - } - }, - "node_modules/@monaco-editor/react": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.6.0.tgz", - "integrity": "sha512-RFkU9/i7cN2bsq/iTkurMWOEErmYcY6JiQI3Jn+WeR/FGISH8JbHERjpS9oRuSOPvDMJI0Z8nJeKkbOs9sBYQw==", - "dependencies": { - "@monaco-editor/loader": "^1.4.0" - }, - "peerDependencies": { - "monaco-editor": ">= 0.25.0 < 1", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@motionone/animation": { - "version": "10.18.0", - "resolved": "https://registry.npmjs.org/@motionone/animation/-/animation-10.18.0.tgz", - "integrity": "sha512-9z2p5GFGCm0gBsZbi8rVMOAJCtw1WqBTIPw3ozk06gDvZInBPIsQcHgYogEJ4yuHJ+akuW8g1SEIOpTOvYs8hw==", - "dependencies": { - "@motionone/easing": "^10.18.0", - "@motionone/types": "^10.17.1", - "@motionone/utils": "^10.18.0", - "tslib": "^2.3.1" - } - }, - "node_modules/@motionone/dom": { - "version": "10.18.0", - "resolved": "https://registry.npmjs.org/@motionone/dom/-/dom-10.18.0.tgz", - "integrity": "sha512-bKLP7E0eyO4B2UaHBBN55tnppwRnaE3KFfh3Ps9HhnAkar3Cb69kUCJY9as8LrccVYKgHA+JY5dOQqJLOPhF5A==", - "dependencies": { - "@motionone/animation": "^10.18.0", - "@motionone/generators": "^10.18.0", - "@motionone/types": "^10.17.1", - "@motionone/utils": "^10.18.0", - "hey-listen": "^1.0.8", - "tslib": "^2.3.1" - } - }, - "node_modules/@motionone/easing": { - "version": "10.18.0", - "resolved": "https://registry.npmjs.org/@motionone/easing/-/easing-10.18.0.tgz", - "integrity": "sha512-VcjByo7XpdLS4o9T8t99JtgxkdMcNWD3yHU/n6CLEz3bkmKDRZyYQ/wmSf6daum8ZXqfUAgFeCZSpJZIMxaCzg==", - "dependencies": { - "@motionone/utils": "^10.18.0", - "tslib": "^2.3.1" - } - }, - "node_modules/@motionone/generators": { - "version": "10.18.0", - "resolved": "https://registry.npmjs.org/@motionone/generators/-/generators-10.18.0.tgz", - "integrity": "sha512-+qfkC2DtkDj4tHPu+AFKVfR/C30O1vYdvsGYaR13W/1cczPrrcjdvYCj0VLFuRMN+lP1xvpNZHCRNM4fBzn1jg==", - "dependencies": { - "@motionone/types": "^10.17.1", - "@motionone/utils": "^10.18.0", - "tslib": "^2.3.1" - } - }, - "node_modules/@motionone/svelte": { - "version": "10.16.4", - "resolved": "https://registry.npmjs.org/@motionone/svelte/-/svelte-10.16.4.tgz", - "integrity": "sha512-zRVqk20lD1xqe+yEDZhMYgftsuHc25+9JSo+r0a0OWUJFocjSV9D/+UGhX4xgJsuwB9acPzXLr20w40VnY2PQA==", - "dependencies": { - "@motionone/dom": "^10.16.4", - "tslib": "^2.3.1" - } - }, - "node_modules/@motionone/types": { - "version": "10.17.1", - "resolved": "https://registry.npmjs.org/@motionone/types/-/types-10.17.1.tgz", - "integrity": "sha512-KaC4kgiODDz8hswCrS0btrVrzyU2CSQKO7Ps90ibBVSQmjkrt2teqta6/sOG59v7+dPnKMAg13jyqtMKV2yJ7A==" - }, - "node_modules/@motionone/utils": { - "version": "10.18.0", - "resolved": "https://registry.npmjs.org/@motionone/utils/-/utils-10.18.0.tgz", - "integrity": "sha512-3XVF7sgyTSI2KWvTf6uLlBJ5iAgRgmvp3bpuOiQJvInd4nZ19ET8lX5unn30SlmRH7hXbBbH+Gxd0m0klJ3Xtw==", - "dependencies": { - "@motionone/types": "^10.17.1", - "hey-listen": "^1.0.8", - "tslib": "^2.3.1" - } - }, - "node_modules/@motionone/vue": { - "version": "10.16.4", - "resolved": "https://registry.npmjs.org/@motionone/vue/-/vue-10.16.4.tgz", - "integrity": "sha512-z10PF9JV6SbjFq+/rYabM+8CVlMokgl8RFGvieSGNTmrkQanfHn+15XBrhG3BgUfvmTeSeyShfOHpG0i9zEdcg==", - "deprecated": "Motion One for Vue is deprecated. Use Oku Motion instead https://oku-ui.com/motion", - "dependencies": { - "@motionone/dom": "^10.16.4", - "tslib": "^2.3.1" - } - }, - "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz", - "integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz", - "integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz", - "integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz", - "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz", - "integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz", - "integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@mswjs/interceptors": { - "version": "0.37.3", - "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.37.3.tgz", - "integrity": "sha512-USvgCL/uOGFtVa6SVyRrC8kIAedzRohxIXN5LISlg5C5vLZCn7dgMFVSNhSF9cuBEFrm/O2spDWEZeMnw4ZXYg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@open-draft/deferred-promise": "^2.2.0", - "@open-draft/logger": "^0.3.0", - "@open-draft/until": "^2.0.0", - "is-node-process": "^1.2.0", - "outvariant": "^1.4.3", - "strict-event-emitter": "^0.5.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@mysten/bcs": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/@mysten/bcs/-/bcs-0.7.4.tgz", - "integrity": "sha512-6DKzM4L10Au3Og5EJRBqJZmXWZ7hS/clVjbVUH4sA0aFtS3AZo2xc+r5fUFfdJbaWZUxVaDiQ8BNiEZWkAnEOw==", - "license": "Apache-2.0", - "dependencies": { - "bs58": "^5.0.0" - } - }, - "node_modules/@mysten/bcs/node_modules/base-x": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.0.tgz", - "integrity": "sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw==", - "license": "MIT" - }, - "node_modules/@mysten/bcs/node_modules/bs58": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-5.0.0.tgz", - "integrity": "sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==", - "license": "MIT", - "dependencies": { - "base-x": "^4.0.0" - } - }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.4.tgz", - "integrity": "sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==", - "dev": true, - "dependencies": { - "@emnapi/core": "^1.1.0", - "@emnapi/runtime": "^1.1.0", - "@tybys/wasm-util": "^0.9.0" - } - }, - "node_modules/@narval-xyz/armory-mpc-module": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/@narval-xyz/armory-mpc-module/-/armory-mpc-module-0.0.1.tgz", - "integrity": "sha512-jAUKXB4tf5KgcNeqpcpVNzivvB4IiOMKpVufdhaRx+JHQDSxfCkFYcghtoWavZGA5csryrGMFHwPUZnA7q594g==", - "bundleDependencies": [ - "@narval-xyz/armory-sdk" - ], - "optional": true, - "dependencies": { - "@narval-xyz/armory-sdk": "^0.0.5", - "@nestjs/common": "^10.0.0", - "@nestjs/core": "^10.0.0", - "@nestjs/platform-express": "^10.0.0", - "@noble/curves": "^1.4.2", - "@sepior/tsmsdkv2": "^63.0.0", - "reflect-metadata": "^0.1.13", - "rxjs": "^7.8.1" - } - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/@adraffy/ens-normalize": { - "version": "1.10.0", - "inBundle": true, - "license": "MIT", - "optional": true - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/@narval-xyz/armory-sdk": { - "version": "0.0.5", - "inBundle": true, - "license": "MPL-2.0", - "optional": true, - "dependencies": { - "@noble/curves": "1.4.0", - "axios": "1.7.2", - "jose": "5.5.0", - "lodash": "4.17.21", - "tslib": "2.6.3", - "uuid": "9.0.1", - "viem": "2.16.2", - "zod": "3.23.8" - } - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/@narval-xyz/armory-sdk/node_modules/@noble/curves": { - "version": "1.4.0", - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@noble/hashes": "1.4.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/@narval-xyz/armory-sdk/node_modules/tslib": { - "version": "2.6.3", - "inBundle": true, - "license": "0BSD", - "optional": true - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/@noble/hashes": { - "version": "1.4.0", - "inBundle": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/@scure/base": { - "version": "1.1.7", - "inBundle": true, - "license": "MIT", - "optional": true, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/@scure/bip32": { - "version": "1.3.2", - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@noble/curves": "~1.2.0", - "@noble/hashes": "~1.3.2", - "@scure/base": "~1.1.2" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/@scure/bip32/node_modules/@noble/curves": { - "version": "1.2.0", - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@noble/hashes": "1.3.2" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/@scure/bip32/node_modules/@noble/curves/node_modules/@noble/hashes": { - "version": "1.3.2", - "inBundle": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/@scure/bip32/node_modules/@noble/hashes": { - "version": "1.3.3", - "inBundle": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/@scure/bip39": { - "version": "1.2.1", - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@noble/hashes": "~1.3.0", - "@scure/base": "~1.1.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/@scure/bip39/node_modules/@noble/hashes": { - "version": "1.3.3", - "inBundle": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/abitype": { - "version": "1.0.4", - "inBundle": true, - "license": "MIT", - "optional": true, - "funding": { - "url": "https://github.com/sponsors/wevm" - }, - "peerDependencies": { - "typescript": ">=5.0.4", - "zod": "^3 >=3.22.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - }, - "zod": { - "optional": true - } - } - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/asynckit": { - "version": "0.4.0", - "inBundle": true, - "license": "MIT", - "optional": true - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/axios": { - "version": "1.7.2", - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/combined-stream": { - "version": "1.0.8", - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/delayed-stream": { - "version": "1.0.0", - "inBundle": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/follow-redirects": { - "version": "1.15.6", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "inBundle": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/form-data": { - "version": "4.0.0", - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/isows": { - "version": "1.0.4", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wagmi-dev" - } - ], - "inBundle": true, - "license": "MIT", - "optional": true, - "peerDependencies": { - "ws": "*" - } - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/jose": { - "version": "5.5.0", - "inBundle": true, - "license": "MIT", - "optional": true, - "funding": { - "url": "https://github.com/sponsors/panva" - } - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/lodash": { - "version": "4.17.21", - "inBundle": true, - "license": "MIT", - "optional": true - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/mime-db": { - "version": "1.52.0", - "inBundle": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/mime-types": { - "version": "2.1.35", - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/proxy-from-env": { - "version": "1.1.0", - "inBundle": true, - "license": "MIT", - "optional": true - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/uuid": { - "version": "9.0.1", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "inBundle": true, - "license": "MIT", - "optional": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/viem": { - "version": "2.16.2", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wevm" - } - ], - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@adraffy/ens-normalize": "1.10.0", - "@noble/curves": "1.2.0", - "@noble/hashes": "1.3.2", - "@scure/bip32": "1.3.2", - "@scure/bip39": "1.2.1", - "abitype": "1.0.4", - "isows": "1.0.4", - "ws": "8.17.1" - }, - "peerDependencies": { - "typescript": ">=5.0.4" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/viem/node_modules/@noble/curves": { - "version": "1.2.0", - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@noble/hashes": "1.3.2" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/viem/node_modules/@noble/hashes": { - "version": "1.3.2", - "inBundle": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/ws": { - "version": "8.17.1", - "inBundle": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/@narval-xyz/armory-mpc-module/node_modules/zod": { - "version": "3.23.8", - "inBundle": true, - "license": "MIT", - "optional": true, - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/@narval-xyz/armory-sdk": { - "resolved": "packages/armory-sdk", - "link": true - }, - "node_modules/@nestjs/axios": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-3.0.2.tgz", - "integrity": "sha512-Z6GuOUdNQjP7FX+OuV2Ybyamse+/e0BFdTWBX5JxpBDKA+YkdLynDgG6HTF04zy6e9zPa19UX0WA2VDoehwhXQ==", - "peerDependencies": { - "@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0", - "axios": "^1.3.1", - "rxjs": "^6.0.0 || ^7.0.0" - } - }, - "node_modules/@nestjs/bull": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/@nestjs/bull/-/bull-10.2.0.tgz", - "integrity": "sha512-byQI3cgAVP8BNa71h5g33D1pNwOaK2O9+zYmT98eU8LxxJHh53aWMwEUrCHrwgSz4P8bD+jY8ObQ5vtU4SsidA==", - "dependencies": { - "@nestjs/bull-shared": "^10.2.0", - "tslib": "2.6.3" - }, - "peerDependencies": { - "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", - "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0", - "bull": "^3.3 || ^4.0.0" - } - }, - "node_modules/@nestjs/bull-shared": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/@nestjs/bull-shared/-/bull-shared-10.2.0.tgz", - "integrity": "sha512-cSi6CyPECHDFumnHWWfwLCnbc6hm5jXt7FqzJ0Id6EhGqdz5ja0FmgRwXoS4xoMA2RRjlxn2vGXr4YOaHBAeig==", - "dependencies": { - "tslib": "2.6.3" - }, - "peerDependencies": { - "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", - "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0" - } - }, - "node_modules/@nestjs/cache-manager": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@nestjs/cache-manager/-/cache-manager-3.0.0.tgz", - "integrity": "sha512-csKvxHSQWfC0OiDo0bNEhLqrmYDopHEvRyC81MxV9xFj1AO+rOKocpHa4M1ZGH//6uKFIPGN9oiR0mvZY77APA==", - "license": "MIT", - "peerDependencies": { - "@nestjs/common": "^9.0.0 || ^10.0.0 || ^11.0.0", - "@nestjs/core": "^9.0.0 || ^10.0.0 || ^11.0.0", - "cache-manager": ">=6", - "rxjs": "^7.8.1" - } - }, - "node_modules/@nestjs/common": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.3.10.tgz", - "integrity": "sha512-H8k0jZtxk1IdtErGDmxFRy0PfcOAUg41Prrqpx76DQusGGJjsaovs1zjXVD1rZWaVYchfT1uczJ6L4Kio10VNg==", - "dependencies": { - "iterare": "1.2.1", - "tslib": "2.6.3", - "uid": "2.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nest" - }, - "peerDependencies": { - "class-transformer": "*", - "class-validator": "*", - "reflect-metadata": "^0.1.12 || ^0.2.0", - "rxjs": "^7.1.0" - }, - "peerDependenciesMeta": { - "class-transformer": { - "optional": true - }, - "class-validator": { - "optional": true - } - } - }, - "node_modules/@nestjs/config": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-3.1.1.tgz", - "integrity": "sha512-qu5QlNiJdqQtOsnB6lx4JCXPQ96jkKUsOGd+JXfXwqJqZcOSAq6heNFg0opW4pq4J/VZoNwoo87TNnx9wthnqQ==", - "dependencies": { - "dotenv": "16.3.1", - "dotenv-expand": "10.0.0", - "lodash": "4.17.21", - "uuid": "9.0.0" - }, - "peerDependencies": { - "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", - "reflect-metadata": "^0.1.13" - } - }, - "node_modules/@nestjs/config/node_modules/dotenv": { - "version": "16.3.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", - "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/motdotla/dotenv?sponsor=1" - } - }, - "node_modules/@nestjs/config/node_modules/uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@nestjs/core": { - "version": "10.4.7", - "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.4.7.tgz", - "integrity": "sha512-AIpQzW/vGGqSLkKvll1R7uaSNv99AxZI2EFyVJPNGDgFsfXaohfV1Ukl6f+s75Km+6Fj/7aNl80EqzNWQCS8Ig==", - "hasInstallScript": true, - "dependencies": { - "@nuxtjs/opencollective": "0.3.2", - "fast-safe-stringify": "2.1.1", - "iterare": "1.2.1", - "path-to-regexp": "3.3.0", - "tslib": "2.7.0", - "uid": "2.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nest" - }, - "peerDependencies": { - "@nestjs/common": "^10.0.0", - "@nestjs/microservices": "^10.0.0", - "@nestjs/platform-express": "^10.0.0", - "@nestjs/websockets": "^10.0.0", - "reflect-metadata": "^0.1.12 || ^0.2.0", - "rxjs": "^7.1.0" - }, - "peerDependenciesMeta": { - "@nestjs/microservices": { - "optional": true - }, - "@nestjs/platform-express": { - "optional": true - }, - "@nestjs/websockets": { - "optional": true - } - } - }, - "node_modules/@nestjs/core/node_modules/path-to-regexp": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.3.0.tgz", - "integrity": "sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==" - }, - "node_modules/@nestjs/core/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" - }, - "node_modules/@nestjs/event-emitter": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@nestjs/event-emitter/-/event-emitter-2.1.1.tgz", - "integrity": "sha512-6L6fBOZTyfFlL7Ih/JDdqlCzZeCW0RjCX28wnzGyg/ncv5F/EOeT1dfopQr1loBRQ3LTgu8OWM7n4zLN4xigsg==", - "license": "MIT", - "dependencies": { - "eventemitter2": "6.4.9" - }, - "peerDependencies": { - "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", - "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0" - } - }, - "node_modules/@nestjs/mapped-types": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-2.0.5.tgz", - "integrity": "sha512-bSJv4pd6EY99NX9CjBIyn4TVDoSit82DUZlL4I3bqNfy5Gt+gXTa86i3I/i0iIV9P4hntcGM5GyO+FhZAhxtyg==", - "peerDependencies": { - "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", - "class-transformer": "^0.4.0 || ^0.5.0", - "class-validator": "^0.13.0 || ^0.14.0", - "reflect-metadata": "^0.1.12 || ^0.2.0" - }, - "peerDependenciesMeta": { - "class-transformer": { - "optional": true - }, - "class-validator": { - "optional": true - } - } - }, - "node_modules/@nestjs/platform-express": { - "version": "10.3.9", - "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.3.9.tgz", - "integrity": "sha512-si/UzobP6YUtYtCT1cSyQYHHzU3yseqYT6l7OHSMVvfG1+TqxaAqI6nmrix02LO+l1YntHRXEs3p+v9a7EfrSQ==", - "license": "MIT", - "dependencies": { - "body-parser": "1.20.2", - "cors": "2.8.5", - "express": "4.19.2", - "multer": "1.4.4-lts.1", - "tslib": "2.6.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nest" - }, - "peerDependencies": { - "@nestjs/common": "^10.0.0", - "@nestjs/core": "^10.0.0" - } - }, - "node_modules/@nestjs/platform-express/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "license": "0BSD" - }, - "node_modules/@nestjs/schematics": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-9.2.0.tgz", - "integrity": "sha512-wHpNJDPzM6XtZUOB3gW0J6mkFCSJilzCM3XrHI1o0C8vZmFE1snbmkIXNyoi1eV0Nxh1BMymcgz5vIMJgQtTqw==", - "dev": true, - "dependencies": { - "@angular-devkit/core": "16.0.1", - "@angular-devkit/schematics": "16.0.1", - "jsonc-parser": "3.2.0", - "pluralize": "8.0.0" - }, - "peerDependencies": { - "typescript": ">=4.3.5" - } - }, - "node_modules/@nestjs/swagger": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-7.4.0.tgz", - "integrity": "sha512-dCiwKkRxcR7dZs5jtrGspBAe/nqJd1AYzOBTzw9iCdbq3BGrLpwokelk6lFZPe4twpTsPQqzNKBwKzVbI6AR/g==", - "dependencies": { - "@microsoft/tsdoc": "^0.15.0", - "@nestjs/mapped-types": "2.0.5", - "js-yaml": "4.1.0", - "lodash": "4.17.21", - "path-to-regexp": "3.2.0", - "swagger-ui-dist": "5.17.14" - }, - "peerDependencies": { - "@fastify/static": "^6.0.0 || ^7.0.0", - "@nestjs/common": "^9.0.0 || ^10.0.0", - "@nestjs/core": "^9.0.0 || ^10.0.0", - "class-transformer": "*", - "class-validator": "*", - "reflect-metadata": "^0.1.12 || ^0.2.0" - }, - "peerDependenciesMeta": { - "@fastify/static": { - "optional": true - }, - "class-transformer": { - "optional": true - }, - "class-validator": { - "optional": true - } - } - }, - "node_modules/@nestjs/testing": { - "version": "10.4.1", - "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.4.1.tgz", - "integrity": "sha512-pR+su5+YGqCLH0RhhVkPowQK7FCORU0/PWAywPK7LScAOtD67ZoviZ7hAU4vnGdwkg4HCB0D7W8Bkg19CGU8Xw==", - "dev": true, - "dependencies": { - "tslib": "2.6.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nest" - }, - "peerDependencies": { - "@nestjs/common": "^10.0.0", - "@nestjs/core": "^10.0.0", - "@nestjs/microservices": "^10.0.0", - "@nestjs/platform-express": "^10.0.0" - }, - "peerDependenciesMeta": { - "@nestjs/microservices": { - "optional": true - }, - "@nestjs/platform-express": { - "optional": true - } - } - }, - "node_modules/@next/env": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.4.tgz", - "integrity": "sha512-3EtkY5VDkuV2+lNmKlbkibIJxcO4oIHEhBWne6PaAp+76J9KoSsGvNikp6ivzAT8dhhBMYrm6op2pS1ApG0Hzg==" - }, - "node_modules/@next/eslint-plugin-next": { - "version": "14.2.6", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.6.tgz", - "integrity": "sha512-d3+p4AjIYmhqzYHhhmkRYYN6ZU35TwZAKX08xKRfnHkz72KhWL2kxMFsDptpZs5e8bBGdepn7vn1+9DaF8iX+A==", - "dev": true, - "dependencies": { - "glob": "10.3.10" - } - }, - "node_modules/@next/eslint-plugin-next/node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "dev": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@next/swc-darwin-arm64": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.4.tgz", - "integrity": "sha512-AH3mO4JlFUqsYcwFUHb1wAKlebHU/Hv2u2kb1pAuRanDZ7pD/A/KPD98RHZmwsJpdHQwfEc/06mgpSzwrJYnNg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-darwin-x64": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.4.tgz", - "integrity": "sha512-QVadW73sWIO6E2VroyUjuAxhWLZWEpiFqHdZdoQ/AMpN9YWGuHV8t2rChr0ahy+irKX5mlDU7OY68k3n4tAZTg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-gnu": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.4.tgz", - "integrity": "sha512-KT6GUrb3oyCfcfJ+WliXuJnD6pCpZiosx2X3k66HLR+DMoilRb76LpWPGb4tZprawTtcnyrv75ElD6VncVamUQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-musl": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.4.tgz", - "integrity": "sha512-Alv8/XGSs/ytwQcbCHwze1HmiIkIVhDHYLjczSVrf0Wi2MvKn/blt7+S6FJitj3yTlMwMxII1gIJ9WepI4aZ/A==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-gnu": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.4.tgz", - "integrity": "sha512-ze0ShQDBPCqxLImzw4sCdfnB3lRmN3qGMB2GWDRlq5Wqy4G36pxtNOo2usu/Nm9+V2Rh/QQnrRc2l94kYFXO6Q==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-musl": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.4.tgz", - "integrity": "sha512-8dwC0UJoc6fC7PX70csdaznVMNr16hQrTDAMPvLPloazlcaWfdPogq+UpZX6Drqb1OBlwowz8iG7WR0Tzk/diQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-arm64-msvc": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.4.tgz", - "integrity": "sha512-jxyg67NbEWkDyvM+O8UDbPAyYRZqGLQDTPwvrBBeOSyVWW/jFQkQKQ70JDqDSYg1ZDdl+E3nkbFbq8xM8E9x8A==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-ia32-msvc": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.4.tgz", - "integrity": "sha512-twrmN753hjXRdcrZmZttb/m5xaCBFa48Dt3FbeEItpJArxriYDunWxJn+QFXdJ3hPkm4u7CKxncVvnmgQMY1ag==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-x64-msvc": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.4.tgz", - "integrity": "sha512-tkLrjBzqFTP8DVrAAQmZelEahfR9OxWpFR++vAI9FBhCiIxtwHwBHC23SBHCTURBtwB4kc/x44imVOnkKGNVGg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@noble/ciphers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.0.0.tgz", - "integrity": "sha512-wH5EHOmLi0rEazphPbecAzmjd12I6/Yv/SiHdkA9LSycsQk7RuuTp7am5/o62qYr0RScE7Pc9icXGBbsr6cesA==", - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@noble/curves": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.6.0.tgz", - "integrity": "sha512-TlaHRXDehJuRNR9TfZDNQ45mMEd5dwUwmicsafcIX4SsNiqnCHKjE/1alYPd/lDRVhxdhUAlv8uEhMCI5zjIJQ==", - "dependencies": { - "@noble/hashes": "1.5.0" - }, - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@noble/curves/node_modules/@noble/hashes": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.5.0.tgz", - "integrity": "sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==", - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@noble/ed25519": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@noble/ed25519/-/ed25519-1.7.1.tgz", - "integrity": "sha512-Rk4SkJFaXZiznFyC/t77Q0NKS4FL7TLJJsVG2V2oiEq3kJVeTdxysEe/yRWSpnWMe808XRDJ+VFh5pt/FN5plw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ] - }, - "node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@noble/secp256k1": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.6.3.tgz", - "integrity": "sha512-T04e4iTurVy7I8Sw4+c5OSN9/RkPlo1uKxAomtxQNLq8j1uPAqnsqG1bqvY3Jv7c13gyr6dui0zmh/I3+f/JaQ==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "license": "MIT" - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@npmcli/fs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", - "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "@gar/promisify": "^1.0.1", - "semver": "^7.3.5" - } - }, - "node_modules/@npmcli/fs/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@npmcli/move-file": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", - "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", - "deprecated": "This functionality has been moved to @npmcli/fs", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@npmcli/move-file/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "license": "MIT", - "optional": true, - "peer": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@nrwl/devkit": { - "version": "19.5.1", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.5.1.tgz", - "integrity": "sha512-ZsckDZszLTv3oshNsY5fZ86g8a/VcGvgDpdiP/z/A/krtOHL8iUjdT/72Eo5DIult5WcSFjnifyWcyWIGe1PeA==", - "dev": true, - "dependencies": { - "@nx/devkit": "19.5.1" - } - }, - "node_modules/@nrwl/eslint-plugin-nx": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nrwl/eslint-plugin-nx/-/eslint-plugin-nx-19.3.2.tgz", - "integrity": "sha512-OD9WYOpTCgMQWTwUKRUuXlVfegkbkqNqkVQ3hsftjTn1dkB8QbvMa9ajqDGU+pbQDLeMMwtjc4itVpUimvmudQ==", - "dev": true, - "dependencies": { - "@nx/eslint-plugin": "19.3.2" - } - }, - "node_modules/@nrwl/jest": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/jest/-/jest-19.2.0.tgz", - "integrity": "sha512-s3qb0AblY+wqPUJFraWP9MYVyv3EA8bbEsMRCuvDDbhoe2nnyd/7PmluyPsWgJVdgbY9Ajgs3ZjuBEfFQ3VV9A==", - "dev": true, - "dependencies": { - "@nx/jest": "19.2.0" - } - }, - "node_modules/@nrwl/jest/node_modules/@nrwl/devkit": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.2.0.tgz", - "integrity": "sha512-Ew5AJZkLXJwt15HjaIbHve8FOXmZ3HK8KPqTXqwKHX8jQW+fDUCaSXKe/lCZMNg0RvY+jMNecuC86uGdiIbLMg==", - "dev": true, - "dependencies": { - "@nx/devkit": "19.2.0" - } - }, - "node_modules/@nrwl/jest/node_modules/@nx/devkit": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.2.0.tgz", - "integrity": "sha512-fK3zRUE2SLp9BUomFiyCuAX2E1yfWYE/hKimniscsvM34/u/xLZYVmmZ0/jfpGPbyaonXKZr2KTb7RimX/hyqg==", - "dev": true, - "dependencies": { - "@nrwl/devkit": "19.2.0", - "ejs": "^3.1.7", - "enquirer": "~2.3.6", - "ignore": "^5.0.4", - "minimatch": "9.0.3", - "semver": "^7.5.3", - "tmp": "~0.2.1", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" - }, - "peerDependencies": { - "nx": ">= 17 <= 20" - } - }, - "node_modules/@nrwl/jest/node_modules/@nx/jest": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/jest/-/jest-19.2.0.tgz", - "integrity": "sha512-iJMqfwkIB4T7NRYAQe3nZWFEAQGGblMGcxWczMKEixCIZWcAz4up74eb0H6Yv+tUVOQHrFTm6J1OnrW3BqvOZA==", - "dev": true, - "dependencies": { - "@jest/reporters": "^29.4.1", - "@jest/test-result": "^29.4.1", - "@nrwl/jest": "19.2.0", - "@nx/devkit": "19.2.0", - "@nx/js": "19.2.0", - "@phenomnomnominal/tsquery": "~5.0.1", - "chalk": "^4.1.0", - "identity-obj-proxy": "3.0.0", - "jest-config": "^29.4.1", - "jest-resolve": "^29.4.1", - "jest-util": "^29.4.1", - "minimatch": "9.0.3", - "resolve.exports": "1.1.0", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" - } - }, - "node_modules/@nrwl/jest/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@nrwl/js": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/js/-/js-19.2.0.tgz", - "integrity": "sha512-i6CyQvTP1etmTxjFhUIw/HAtoZCENbhkc7UmAsyCgTX5IJeo0U3YoHsmDI0TE45yu+4x4gcKLqOHs2zqWj7WCw==", - "dev": true, - "dependencies": { - "@nx/js": "19.2.0" - } - }, - "node_modules/@nrwl/nest": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/nest/-/nest-19.2.0.tgz", - "integrity": "sha512-JjhGurz1neZHyrRtmstBHpIAfh/TE3h/untSMqiixrRg8k+qPZBi2dpcV6HZxWVoDkgKrL6ro7olmiXvWMQdqw==", - "dev": true, - "dependencies": { - "@nx/nest": "19.2.0" - } - }, - "node_modules/@nrwl/next": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/next/-/next-19.2.0.tgz", - "integrity": "sha512-+DFtnuB33w/x5A5c1EuSjnKE0i2YKJT5tltZ1bX7fyDcqukwESmTL+CNpYNlp5VuejDzV/3wp1pNdeqt+85/YA==", - "dev": true, - "dependencies": { - "@nx/next": "19.2.0" - } - }, - "node_modules/@nrwl/node": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/node/-/node-19.2.0.tgz", - "integrity": "sha512-fy4GPMGRT7/t3sUljOot2h9CVq0QWOv/nPxyK7YVk2jkwkjo9gTovVoZrjacv8DOOL4DE1tRr7yHfEQY6fnDig==", - "dev": true, - "dependencies": { - "@nx/node": "19.2.0" - } - }, - "node_modules/@nrwl/react": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/react/-/react-19.2.0.tgz", - "integrity": "sha512-Zz4lJK1S511s8F1OmbH0HiMz9xX/OCL8UQ5FJ9uViMNnkaLPx0NUGzrAbliDUq2XGYDBZ8ZtGFgC1DTlL9iK+w==", - "dev": true, - "dependencies": { - "@nx/react": "19.2.0" - } - }, - "node_modules/@nrwl/tao": { - "version": "19.4.4", - "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.4.4.tgz", - "integrity": "sha512-iwswcp7fW5GiIeAFvA/Ssr9fe2ZZHcuOS20bQx+mLEnEgBaARkgWqNdYMZ594NRqXQ1CrOEy5jncahS6K+pRbw==", - "dev": true, - "dependencies": { - "nx": "19.4.4", - "tslib": "^2.3.0" - }, - "bin": { - "tao": "index.js" - } - }, - "node_modules/@nrwl/web": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/web/-/web-19.2.0.tgz", - "integrity": "sha512-s6fEyic1cCwZAoKxZ64RMdCfG2jQGZC/FTyO4J7a8iB8oRD8mRLw0lWamXIcW10O0KPrE0zO63+kpjfKJ/ZK+w==", - "dev": true, - "dependencies": { - "@nx/web": "19.2.0" - } - }, - "node_modules/@nrwl/webpack": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nrwl/webpack/-/webpack-19.6.3.tgz", - "integrity": "sha512-e1Y493FBdNPO3TrXNAJSzbeGWAZiLUsDUfQDXjlAboQRL5n3bn1W/zc98DGMxobJWAzw2vWW7UEm2ZyYyeU/lA==", - "dev": true, - "dependencies": { - "@nx/webpack": "19.6.3" - } - }, - "node_modules/@nrwl/workspace": { - "version": "19.7.3", - "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-19.7.3.tgz", - "integrity": "sha512-2ffUbLzBYGQte6zQ6dDLefgU9X812Uh7v61yTV7z4zfYbUtjwInkWqlkTvRuK08DRhD5vWo9xyUDp7acAdZaxw==", - "dev": true, - "dependencies": { - "@nx/workspace": "19.7.3" - } - }, - "node_modules/@nuxtjs/opencollective": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz", - "integrity": "sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==", - "dependencies": { - "chalk": "^4.1.0", - "consola": "^2.15.0", - "node-fetch": "^2.6.1" - }, - "bin": { - "opencollective": "bin/opencollective.js" - }, - "engines": { - "node": ">=8.0.0", - "npm": ">=5.0.0" - } - }, - "node_modules/@nx/devkit": { - "version": "19.5.1", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.5.1.tgz", - "integrity": "sha512-Vj8wwzNIR5VIWmuLHhOi4aUVq7eVV5YTbctnEewKT+V/O4LZj+hClGyVNyT8s6b8JIjNWoIO4HXStLnH8rDOlw==", - "dev": true, - "dependencies": { - "@nrwl/devkit": "19.5.1", - "ejs": "^3.1.7", - "enquirer": "~2.3.6", - "ignore": "^5.0.4", - "minimatch": "9.0.3", - "semver": "^7.5.3", - "tmp": "~0.2.1", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" - }, - "peerDependencies": { - "nx": ">= 17 <= 20" - } - }, - "node_modules/@nx/devkit/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@nx/eslint": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/eslint/-/eslint-19.3.2.tgz", - "integrity": "sha512-ICUX8ADAIj9xA7Yc6hY9pfeC55ZxRjiAaqslsK3h4pCrFADVFDluShhrxSpUkp4doBzGUR7s1K7GIbeRrwD4qA==", - "dev": true, - "dependencies": { - "@nx/devkit": "19.3.2", - "@nx/js": "19.3.2", - "@nx/linter": "19.3.2", - "semver": "^7.5.3", - "tslib": "^2.3.0", - "typescript": "~5.4.2" - }, - "peerDependencies": { - "@zkochan/js-yaml": "0.0.7", - "eslint": "^8.0.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "@zkochan/js-yaml": { - "optional": true - } - } - }, - "node_modules/@nx/eslint-plugin": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/eslint-plugin/-/eslint-plugin-19.3.2.tgz", - "integrity": "sha512-ZhnFrnAKILA29EwiHQhUQnLfXleUH/YrDS3FUYBpwKnICAPXARsgb7Qi+3Uick0q4HlkL6xGRkkQSfA5cZ9Qtw==", - "dev": true, - "dependencies": { - "@nrwl/eslint-plugin-nx": "19.3.2", - "@nx/devkit": "19.3.2", - "@nx/js": "19.3.2", - "@typescript-eslint/type-utils": "^7.3.0", - "@typescript-eslint/utils": "^7.3.0", - "chalk": "^4.1.0", - "confusing-browser-globals": "^1.0.9", - "jsonc-eslint-parser": "^2.1.0", - "semver": "^7.5.3", - "tslib": "^2.3.0" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^6.13.2 || ^7.0.0", - "eslint-config-prettier": "^9.0.0" - }, - "peerDependenciesMeta": { - "eslint-config-prettier": { - "optional": true - } - } - }, - "node_modules/@nx/eslint-plugin/node_modules/@nrwl/devkit": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.3.2.tgz", - "integrity": "sha512-n3tFalVPUk1HAJ2VYNnF34yzB9j2+6swFUi4Y92PxD1vN7vrIXnNeaTx2qcee7JDjBpiJ7Zn0KLg2jwiH6hNwA==", - "dev": true, - "dependencies": { - "@nx/devkit": "19.3.2" - } - }, - "node_modules/@nx/eslint-plugin/node_modules/@nrwl/js": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nrwl/js/-/js-19.3.2.tgz", - "integrity": "sha512-ZgCoLsASIlp1xtYpWW/1ZxvKSb6BY3ZNXBmjoUW4LyN7Pk6su55gPAVt6JWIxSMm+HC+v+Cb4XFKZLdtuvE7bg==", - "dev": true, - "dependencies": { - "@nx/js": "19.3.2" - } - }, - "node_modules/@nx/eslint-plugin/node_modules/@nrwl/tao": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.3.2.tgz", - "integrity": "sha512-I1gW7woqwU6rdlgwj6XXAKcreJ5ptRKI2WpLdZErkrPmaRG/jMZx/yjZrG4PWdIEuZ4ZmYnRsoXbKN6ilCknQw==", - "dev": true, - "dependencies": { - "nx": "19.3.2", - "tslib": "^2.3.0" - }, - "bin": { - "tao": "index.js" - } - }, - "node_modules/@nx/eslint-plugin/node_modules/@nrwl/workspace": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-19.3.2.tgz", - "integrity": "sha512-6gV4qa38t3GyRKmO2PLcamDcFRD7I3wl6/R0/E1eC8Wm6K2oBzjOIV5ALpz4iC4LOln88IL+AjuQdG6kdtfXlA==", - "dev": true, - "dependencies": { - "@nx/workspace": "19.3.2" - } - }, - "node_modules/@nx/eslint-plugin/node_modules/@nx/devkit": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.3.2.tgz", - "integrity": "sha512-uD3jaJ1Jvf7B6jqH2t2GH0L6REwcCGBLXq1qs1HRQF5SZrEtuUeusn8wvCKP7dftPK3byLHAG0xHRW4+IUAz/g==", - "dev": true, - "dependencies": { - "@nrwl/devkit": "19.3.2", - "ejs": "^3.1.7", - "enquirer": "~2.3.6", - "ignore": "^5.0.4", - "minimatch": "9.0.3", - "semver": "^7.5.3", - "tmp": "~0.2.1", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" - }, - "peerDependencies": { - "nx": ">= 17 <= 20" - } - }, - "node_modules/@nx/eslint-plugin/node_modules/@nx/js": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/js/-/js-19.3.2.tgz", - "integrity": "sha512-WXULhOHYDIAvs+SyDiRaNrpn1DmBAl3u7F5Jpu2VIyrcXgllrYGqUAykUqSu6Oyc2J+asfEtiG67I7UucTHLhA==", - "dev": true, - "dependencies": { - "@babel/core": "^7.23.2", - "@babel/plugin-proposal-decorators": "^7.22.7", - "@babel/plugin-transform-class-properties": "^7.22.5", - "@babel/plugin-transform-runtime": "^7.23.2", - "@babel/preset-env": "^7.23.2", - "@babel/preset-typescript": "^7.22.5", - "@babel/runtime": "^7.22.6", - "@nrwl/js": "19.3.2", - "@nx/devkit": "19.3.2", - "@nx/workspace": "19.3.2", - "babel-plugin-const-enum": "^1.0.1", - "babel-plugin-macros": "^2.8.0", - "babel-plugin-transform-typescript-metadata": "^0.3.1", - "chalk": "^4.1.0", - "columnify": "^1.6.0", - "detect-port": "^1.5.1", - "fast-glob": "3.2.7", - "fs-extra": "^11.1.0", - "ignore": "^5.0.4", - "js-tokens": "^4.0.0", - "minimatch": "9.0.3", - "npm-package-arg": "11.0.1", - "npm-run-path": "^4.0.1", - "ora": "5.3.0", - "semver": "^7.5.3", - "source-map-support": "0.5.19", - "ts-node": "10.9.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0" - }, - "peerDependencies": { - "verdaccio": "^5.0.4" - }, - "peerDependenciesMeta": { - "verdaccio": { - "optional": true - } - } - }, - "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-darwin-arm64": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.3.2.tgz", - "integrity": "sha512-MTqPTR1FwfVfIkHKUw95dFlPBN6mbqfJ+KzLHvUSPcqLKelhi82tsisjMoB5sNK0YWcNNVqYW72ojCnHVB0TUg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-darwin-x64": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.3.2.tgz", - "integrity": "sha512-C8s9X5AlVgl3V5PycLdX+75lpAWq0qQs6QUEAnyxrLM9l+/HRecgoW6uZ7tX6Fnd8WGfMIwyahBw4LyZgk6zTw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-freebsd-x64": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.3.2.tgz", - "integrity": "sha512-XeEpEU0iqJ/5cAPMmjqJ0Sdz89ZtDRj4NdksioyhAHri94X5/3lm3lDs4tB3nObT7p3QL7r/HP1itq5DHYmMSQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.3.2.tgz", - "integrity": "sha512-r4Wl0P94QRBUyiexUcfwKxqFXp48avMG3L0no/ZuNWGODbw1w8ppA4vhnkXtXbIaMdaTGx9eIYO7kFJ2SwMCng==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-linux-arm64-gnu": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.3.2.tgz", - "integrity": "sha512-oaTC4iS1fXnc61ZgSxwCQ2GGIqY64G22udRqNsX9TOtgrT7UA/mjE3Si01r+0xODimOiB525ueyxdIh1MAu6Vg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-linux-arm64-musl": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.3.2.tgz", - "integrity": "sha512-yyO9bTM7FW7HTYsSQlL4lgbAexUBpzfhdK+RkgsCiW+U/5bi+jFRxo/SbqGUL+IVliFavWyRXahMqOOM6nBq/w==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-linux-x64-gnu": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.3.2.tgz", - "integrity": "sha512-DC+llVdL4toLjQkDGBgzoCe26FWIOT+SzRdVcKePoNliZ4jDhkOh3+p75NEIOEcDUgoE9M2iCWEBUjkV978ogw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-linux-x64-musl": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.3.2.tgz", - "integrity": "sha512-Wun4v+kuuqv20tJiCENkHGisDqfx029bFufqxx2IOe9TvD6vK4rMMkFVPUoK3FP8EBdaMW4nrR0ZucTFnStl6w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-win32-arm64-msvc": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.3.2.tgz", - "integrity": "sha512-bNVf6eu5rWFjHvn0rKHeZYlHUcs3naXvvbduW1g0DPkHG6mt8FYffQmyboN+CSeBd/uWDPNyTUekVWwU7PjtLA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-win32-x64-msvc": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.3.2.tgz", - "integrity": "sha512-8DD5BPa5YrxTOKL3HTAgEd+IXNqRtJfwvbrn2MbOMNMyoMG9Zi5yhFvTH/HTT9Tz6VUHvXP16QWYA3R7eFi7Gg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/eslint-plugin/node_modules/@nx/workspace": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-19.3.2.tgz", - "integrity": "sha512-gam41l0hFftYIYTt8eTvZjh+ZWo62HO2p/efqZuFIa/1ZsXF1XG8MDRkCSh5Wfjh1f0jS2ma8HwPV3e8TJm2lw==", - "dev": true, - "dependencies": { - "@nrwl/workspace": "19.3.2", - "@nx/devkit": "19.3.2", - "chalk": "^4.1.0", - "enquirer": "~2.3.6", - "nx": "19.3.2", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" - } - }, - "node_modules/@nx/eslint-plugin/node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "node_modules/@nx/eslint-plugin/node_modules/dotenv-expand": { - "version": "11.0.6", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.6.tgz", - "integrity": "sha512-8NHi73otpWsZGBSZwwknTXS5pqMOrk9+Ssrna8xCaxkzEpU9OTf9R5ArQGVw03//Zmk9MOwLPng9WwndvpAJ5g==", - "dev": true, - "dependencies": { - "dotenv": "^16.4.4" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/@nx/eslint-plugin/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/@nx/eslint-plugin/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@nx/eslint-plugin/node_modules/nx": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/nx/-/nx-19.3.2.tgz", - "integrity": "sha512-eKWs+ahkTKnq9EeWJCE4u8JLeq1cOHnq5DKoiisy2nwUg4KGy1odReegxUMLeEgNBcMI40EUtEJFiTMJSXZQeg==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@nrwl/tao": "19.3.2", - "@yarnpkg/lockfile": "^1.1.0", - "@yarnpkg/parsers": "3.0.0-rc.46", - "@zkochan/js-yaml": "0.0.7", - "axios": "^1.6.0", - "chalk": "^4.1.0", - "cli-cursor": "3.1.0", - "cli-spinners": "2.6.1", - "cliui": "^8.0.1", - "dotenv": "~16.4.5", - "dotenv-expand": "~11.0.6", - "enquirer": "~2.3.6", - "figures": "3.2.0", - "flat": "^5.0.2", - "front-matter": "^4.0.2", - "fs-extra": "^11.1.0", - "ignore": "^5.0.4", - "jest-diff": "^29.4.1", - "jsonc-parser": "3.2.0", - "lines-and-columns": "~2.0.3", - "minimatch": "9.0.3", - "node-machine-id": "1.1.12", - "npm-run-path": "^4.0.1", - "open": "^8.4.0", - "ora": "5.3.0", - "semver": "^7.5.3", - "string-width": "^4.2.3", - "strong-log-transformer": "^2.1.0", - "tar-stream": "~2.2.0", - "tmp": "~0.2.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0", - "yargs": "^17.6.2", - "yargs-parser": "21.1.1" - }, - "bin": { - "nx": "bin/nx.js", - "nx-cloud": "bin/nx-cloud.js" - }, - "optionalDependencies": { - "@nx/nx-darwin-arm64": "19.3.2", - "@nx/nx-darwin-x64": "19.3.2", - "@nx/nx-freebsd-x64": "19.3.2", - "@nx/nx-linux-arm-gnueabihf": "19.3.2", - "@nx/nx-linux-arm64-gnu": "19.3.2", - "@nx/nx-linux-arm64-musl": "19.3.2", - "@nx/nx-linux-x64-gnu": "19.3.2", - "@nx/nx-linux-x64-musl": "19.3.2", - "@nx/nx-win32-arm64-msvc": "19.3.2", - "@nx/nx-win32-x64-msvc": "19.3.2" - }, - "peerDependencies": { - "@swc-node/register": "^1.8.0", - "@swc/core": "^1.3.85" - }, - "peerDependenciesMeta": { - "@swc-node/register": { - "optional": true - }, - "@swc/core": { - "optional": true - } - } - }, - "node_modules/@nx/eslint-plugin/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@nx/eslint-plugin/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@nx/eslint-plugin/node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", - "dev": true, - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "node_modules/@nx/eslint-plugin/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@nx/eslint/node_modules/@nrwl/devkit": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.3.2.tgz", - "integrity": "sha512-n3tFalVPUk1HAJ2VYNnF34yzB9j2+6swFUi4Y92PxD1vN7vrIXnNeaTx2qcee7JDjBpiJ7Zn0KLg2jwiH6hNwA==", - "dev": true, - "dependencies": { - "@nx/devkit": "19.3.2" - } - }, - "node_modules/@nx/eslint/node_modules/@nrwl/js": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nrwl/js/-/js-19.3.2.tgz", - "integrity": "sha512-ZgCoLsASIlp1xtYpWW/1ZxvKSb6BY3ZNXBmjoUW4LyN7Pk6su55gPAVt6JWIxSMm+HC+v+Cb4XFKZLdtuvE7bg==", - "dev": true, - "dependencies": { - "@nx/js": "19.3.2" - } - }, - "node_modules/@nx/eslint/node_modules/@nrwl/tao": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.3.2.tgz", - "integrity": "sha512-I1gW7woqwU6rdlgwj6XXAKcreJ5ptRKI2WpLdZErkrPmaRG/jMZx/yjZrG4PWdIEuZ4ZmYnRsoXbKN6ilCknQw==", - "dev": true, - "dependencies": { - "nx": "19.3.2", - "tslib": "^2.3.0" - }, - "bin": { - "tao": "index.js" - } - }, - "node_modules/@nx/eslint/node_modules/@nrwl/tao/node_modules/nx": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/nx/-/nx-19.3.2.tgz", - "integrity": "sha512-eKWs+ahkTKnq9EeWJCE4u8JLeq1cOHnq5DKoiisy2nwUg4KGy1odReegxUMLeEgNBcMI40EUtEJFiTMJSXZQeg==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@nrwl/tao": "19.3.2", - "@yarnpkg/lockfile": "^1.1.0", - "@yarnpkg/parsers": "3.0.0-rc.46", - "@zkochan/js-yaml": "0.0.7", - "axios": "^1.6.0", - "chalk": "^4.1.0", - "cli-cursor": "3.1.0", - "cli-spinners": "2.6.1", - "cliui": "^8.0.1", - "dotenv": "~16.4.5", - "dotenv-expand": "~11.0.6", - "enquirer": "~2.3.6", - "figures": "3.2.0", - "flat": "^5.0.2", - "front-matter": "^4.0.2", - "fs-extra": "^11.1.0", - "ignore": "^5.0.4", - "jest-diff": "^29.4.1", - "jsonc-parser": "3.2.0", - "lines-and-columns": "~2.0.3", - "minimatch": "9.0.3", - "node-machine-id": "1.1.12", - "npm-run-path": "^4.0.1", - "open": "^8.4.0", - "ora": "5.3.0", - "semver": "^7.5.3", - "string-width": "^4.2.3", - "strong-log-transformer": "^2.1.0", - "tar-stream": "~2.2.0", - "tmp": "~0.2.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0", - "yargs": "^17.6.2", - "yargs-parser": "21.1.1" - }, - "bin": { - "nx": "bin/nx.js", - "nx-cloud": "bin/nx-cloud.js" - }, - "optionalDependencies": { - "@nx/nx-darwin-arm64": "19.3.2", - "@nx/nx-darwin-x64": "19.3.2", - "@nx/nx-freebsd-x64": "19.3.2", - "@nx/nx-linux-arm-gnueabihf": "19.3.2", - "@nx/nx-linux-arm64-gnu": "19.3.2", - "@nx/nx-linux-arm64-musl": "19.3.2", - "@nx/nx-linux-x64-gnu": "19.3.2", - "@nx/nx-linux-x64-musl": "19.3.2", - "@nx/nx-win32-arm64-msvc": "19.3.2", - "@nx/nx-win32-x64-msvc": "19.3.2" - }, - "peerDependencies": { - "@swc-node/register": "^1.8.0", - "@swc/core": "^1.3.85" - }, - "peerDependenciesMeta": { - "@swc-node/register": { - "optional": true - }, - "@swc/core": { - "optional": true - } - } - }, - "node_modules/@nx/eslint/node_modules/@nrwl/workspace": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-19.3.2.tgz", - "integrity": "sha512-6gV4qa38t3GyRKmO2PLcamDcFRD7I3wl6/R0/E1eC8Wm6K2oBzjOIV5ALpz4iC4LOln88IL+AjuQdG6kdtfXlA==", - "dev": true, - "dependencies": { - "@nx/workspace": "19.3.2" - } - }, - "node_modules/@nx/eslint/node_modules/@nx/devkit": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.3.2.tgz", - "integrity": "sha512-uD3jaJ1Jvf7B6jqH2t2GH0L6REwcCGBLXq1qs1HRQF5SZrEtuUeusn8wvCKP7dftPK3byLHAG0xHRW4+IUAz/g==", - "dev": true, - "dependencies": { - "@nrwl/devkit": "19.3.2", - "ejs": "^3.1.7", - "enquirer": "~2.3.6", - "ignore": "^5.0.4", - "minimatch": "9.0.3", - "semver": "^7.5.3", - "tmp": "~0.2.1", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" - }, - "peerDependencies": { - "nx": ">= 17 <= 20" - } - }, - "node_modules/@nx/eslint/node_modules/@nx/js": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/js/-/js-19.3.2.tgz", - "integrity": "sha512-WXULhOHYDIAvs+SyDiRaNrpn1DmBAl3u7F5Jpu2VIyrcXgllrYGqUAykUqSu6Oyc2J+asfEtiG67I7UucTHLhA==", - "dev": true, - "dependencies": { - "@babel/core": "^7.23.2", - "@babel/plugin-proposal-decorators": "^7.22.7", - "@babel/plugin-transform-class-properties": "^7.22.5", - "@babel/plugin-transform-runtime": "^7.23.2", - "@babel/preset-env": "^7.23.2", - "@babel/preset-typescript": "^7.22.5", - "@babel/runtime": "^7.22.6", - "@nrwl/js": "19.3.2", - "@nx/devkit": "19.3.2", - "@nx/workspace": "19.3.2", - "babel-plugin-const-enum": "^1.0.1", - "babel-plugin-macros": "^2.8.0", - "babel-plugin-transform-typescript-metadata": "^0.3.1", - "chalk": "^4.1.0", - "columnify": "^1.6.0", - "detect-port": "^1.5.1", - "fast-glob": "3.2.7", - "fs-extra": "^11.1.0", - "ignore": "^5.0.4", - "js-tokens": "^4.0.0", - "minimatch": "9.0.3", - "npm-package-arg": "11.0.1", - "npm-run-path": "^4.0.1", - "ora": "5.3.0", - "semver": "^7.5.3", - "source-map-support": "0.5.19", - "ts-node": "10.9.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0" - }, - "peerDependencies": { - "verdaccio": "^5.0.4" - }, - "peerDependenciesMeta": { - "verdaccio": { - "optional": true - } - } - }, - "node_modules/@nx/eslint/node_modules/@nx/js/node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", - "dev": true, - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "node_modules/@nx/eslint/node_modules/@nx/nx-darwin-arm64": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.3.2.tgz", - "integrity": "sha512-MTqPTR1FwfVfIkHKUw95dFlPBN6mbqfJ+KzLHvUSPcqLKelhi82tsisjMoB5sNK0YWcNNVqYW72ojCnHVB0TUg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/eslint/node_modules/@nx/nx-darwin-x64": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.3.2.tgz", - "integrity": "sha512-C8s9X5AlVgl3V5PycLdX+75lpAWq0qQs6QUEAnyxrLM9l+/HRecgoW6uZ7tX6Fnd8WGfMIwyahBw4LyZgk6zTw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/eslint/node_modules/@nx/nx-freebsd-x64": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.3.2.tgz", - "integrity": "sha512-XeEpEU0iqJ/5cAPMmjqJ0Sdz89ZtDRj4NdksioyhAHri94X5/3lm3lDs4tB3nObT7p3QL7r/HP1itq5DHYmMSQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/eslint/node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.3.2.tgz", - "integrity": "sha512-r4Wl0P94QRBUyiexUcfwKxqFXp48avMG3L0no/ZuNWGODbw1w8ppA4vhnkXtXbIaMdaTGx9eIYO7kFJ2SwMCng==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/eslint/node_modules/@nx/nx-linux-arm64-gnu": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.3.2.tgz", - "integrity": "sha512-oaTC4iS1fXnc61ZgSxwCQ2GGIqY64G22udRqNsX9TOtgrT7UA/mjE3Si01r+0xODimOiB525ueyxdIh1MAu6Vg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/eslint/node_modules/@nx/nx-linux-arm64-musl": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.3.2.tgz", - "integrity": "sha512-yyO9bTM7FW7HTYsSQlL4lgbAexUBpzfhdK+RkgsCiW+U/5bi+jFRxo/SbqGUL+IVliFavWyRXahMqOOM6nBq/w==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/eslint/node_modules/@nx/nx-linux-x64-gnu": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.3.2.tgz", - "integrity": "sha512-DC+llVdL4toLjQkDGBgzoCe26FWIOT+SzRdVcKePoNliZ4jDhkOh3+p75NEIOEcDUgoE9M2iCWEBUjkV978ogw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/eslint/node_modules/@nx/nx-linux-x64-musl": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.3.2.tgz", - "integrity": "sha512-Wun4v+kuuqv20tJiCENkHGisDqfx029bFufqxx2IOe9TvD6vK4rMMkFVPUoK3FP8EBdaMW4nrR0ZucTFnStl6w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/eslint/node_modules/@nx/nx-win32-arm64-msvc": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.3.2.tgz", - "integrity": "sha512-bNVf6eu5rWFjHvn0rKHeZYlHUcs3naXvvbduW1g0DPkHG6mt8FYffQmyboN+CSeBd/uWDPNyTUekVWwU7PjtLA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/eslint/node_modules/@nx/nx-win32-x64-msvc": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.3.2.tgz", - "integrity": "sha512-8DD5BPa5YrxTOKL3HTAgEd+IXNqRtJfwvbrn2MbOMNMyoMG9Zi5yhFvTH/HTT9Tz6VUHvXP16QWYA3R7eFi7Gg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/eslint/node_modules/@nx/workspace": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-19.3.2.tgz", - "integrity": "sha512-gam41l0hFftYIYTt8eTvZjh+ZWo62HO2p/efqZuFIa/1ZsXF1XG8MDRkCSh5Wfjh1f0jS2ma8HwPV3e8TJm2lw==", - "dev": true, - "dependencies": { - "@nrwl/workspace": "19.3.2", - "@nx/devkit": "19.3.2", - "chalk": "^4.1.0", - "enquirer": "~2.3.6", - "nx": "19.3.2", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" - } - }, - "node_modules/@nx/eslint/node_modules/@nx/workspace/node_modules/nx": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/nx/-/nx-19.3.2.tgz", - "integrity": "sha512-eKWs+ahkTKnq9EeWJCE4u8JLeq1cOHnq5DKoiisy2nwUg4KGy1odReegxUMLeEgNBcMI40EUtEJFiTMJSXZQeg==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@nrwl/tao": "19.3.2", - "@yarnpkg/lockfile": "^1.1.0", - "@yarnpkg/parsers": "3.0.0-rc.46", - "@zkochan/js-yaml": "0.0.7", - "axios": "^1.6.0", - "chalk": "^4.1.0", - "cli-cursor": "3.1.0", - "cli-spinners": "2.6.1", - "cliui": "^8.0.1", - "dotenv": "~16.4.5", - "dotenv-expand": "~11.0.6", - "enquirer": "~2.3.6", - "figures": "3.2.0", - "flat": "^5.0.2", - "front-matter": "^4.0.2", - "fs-extra": "^11.1.0", - "ignore": "^5.0.4", - "jest-diff": "^29.4.1", - "jsonc-parser": "3.2.0", - "lines-and-columns": "~2.0.3", - "minimatch": "9.0.3", - "node-machine-id": "1.1.12", - "npm-run-path": "^4.0.1", - "open": "^8.4.0", - "ora": "5.3.0", - "semver": "^7.5.3", - "string-width": "^4.2.3", - "strong-log-transformer": "^2.1.0", - "tar-stream": "~2.2.0", - "tmp": "~0.2.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0", - "yargs": "^17.6.2", - "yargs-parser": "21.1.1" - }, - "bin": { - "nx": "bin/nx.js", - "nx-cloud": "bin/nx-cloud.js" - }, - "optionalDependencies": { - "@nx/nx-darwin-arm64": "19.3.2", - "@nx/nx-darwin-x64": "19.3.2", - "@nx/nx-freebsd-x64": "19.3.2", - "@nx/nx-linux-arm-gnueabihf": "19.3.2", - "@nx/nx-linux-arm64-gnu": "19.3.2", - "@nx/nx-linux-arm64-musl": "19.3.2", - "@nx/nx-linux-x64-gnu": "19.3.2", - "@nx/nx-linux-x64-musl": "19.3.2", - "@nx/nx-win32-arm64-msvc": "19.3.2", - "@nx/nx-win32-x64-msvc": "19.3.2" - }, - "peerDependencies": { - "@swc-node/register": "^1.8.0", - "@swc/core": "^1.3.85" - }, - "peerDependenciesMeta": { - "@swc-node/register": { - "optional": true - }, - "@swc/core": { - "optional": true - } - } - }, - "node_modules/@nx/eslint/node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "node_modules/@nx/eslint/node_modules/dotenv-expand": { - "version": "11.0.6", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.6.tgz", - "integrity": "sha512-8NHi73otpWsZGBSZwwknTXS5pqMOrk9+Ssrna8xCaxkzEpU9OTf9R5ArQGVw03//Zmk9MOwLPng9WwndvpAJ5g==", - "dev": true, - "dependencies": { - "dotenv": "^16.4.4" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/@nx/eslint/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/@nx/eslint/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@nx/eslint/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@nx/eslint/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@nx/eslint/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@nx/jest": { - "version": "20.0.8", - "resolved": "https://registry.npmjs.org/@nx/jest/-/jest-20.0.8.tgz", - "integrity": "sha512-LEs1EKl0RezDycGKxCaJivvKKXXHL5HUGp9dxE2FuS2nzimYhYldxlOH+zr73J5SWEZtxnMHHjRPkbDffnoxug==", - "dev": true, - "dependencies": { - "@jest/reporters": "^29.4.1", - "@jest/test-result": "^29.4.1", - "@nx/devkit": "20.0.8", - "@nx/js": "20.0.8", - "@phenomnomnominal/tsquery": "~5.0.1", - "chalk": "^4.1.0", - "identity-obj-proxy": "3.0.0", - "jest-config": "^29.4.1", - "jest-resolve": "^29.4.1", - "jest-util": "^29.4.1", - "minimatch": "9.0.3", - "resolve.exports": "1.1.0", - "semver": "^7.5.3", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" - } - }, - "node_modules/@nx/jest/node_modules/@nx/devkit": { - "version": "20.0.8", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-20.0.8.tgz", - "integrity": "sha512-MRUGgWSMzYtdwtolvWL5EZlX+7xYgu7JIXf1+3rmZU5adMmlqWKrIbyvDf53XocQlT8oxx/xXTEFHhIymGTQCg==", - "dev": true, - "dependencies": { - "ejs": "^3.1.7", - "enquirer": "~2.3.6", - "ignore": "^5.0.4", - "minimatch": "9.0.3", - "semver": "^7.5.3", - "tmp": "~0.2.1", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" - }, - "peerDependencies": { - "nx": ">= 19 <= 21" - } - }, - "node_modules/@nx/jest/node_modules/@nx/js": { - "version": "20.0.8", - "resolved": "https://registry.npmjs.org/@nx/js/-/js-20.0.8.tgz", - "integrity": "sha512-PDkjhen4Gl1bMw65XfgebSceNH7HOeTr1f5C+WY/II+7pcAx2lqWj4n6t0XkzBMWlOyfHt/H+O/F4GuZ/hjIyg==", - "dev": true, - "dependencies": { - "@babel/core": "^7.23.2", - "@babel/plugin-proposal-decorators": "^7.22.7", - "@babel/plugin-transform-class-properties": "^7.22.5", - "@babel/plugin-transform-runtime": "^7.23.2", - "@babel/preset-env": "^7.23.2", - "@babel/preset-typescript": "^7.22.5", - "@babel/runtime": "^7.22.6", - "@nx/devkit": "20.0.8", - "@nx/workspace": "20.0.8", - "@zkochan/js-yaml": "0.0.7", - "babel-plugin-const-enum": "^1.0.1", - "babel-plugin-macros": "^2.8.0", - "babel-plugin-transform-typescript-metadata": "^0.3.1", - "chalk": "^4.1.0", - "columnify": "^1.6.0", - "detect-port": "^1.5.1", - "enquirer": "~2.3.6", - "fast-glob": "3.2.7", - "ignore": "^5.0.4", - "js-tokens": "^4.0.0", - "jsonc-parser": "3.2.0", - "minimatch": "9.0.3", - "npm-package-arg": "11.0.1", - "npm-run-path": "^4.0.1", - "ora": "5.3.0", - "semver": "^7.5.3", - "source-map-support": "0.5.19", - "ts-node": "10.9.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0" - }, - "peerDependencies": { - "verdaccio": "^5.0.4" - }, - "peerDependenciesMeta": { - "verdaccio": { - "optional": true - } - } - }, - "node_modules/@nx/jest/node_modules/@nx/nx-darwin-arm64": { - "version": "20.0.8", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-20.0.8.tgz", - "integrity": "sha512-tDoafq5YUyOwxR1Y796WXA6j49OLJRO7TA/Fym52SSuD3AULbgo3/X5XeY6oL2PWM044CuUVrp3V4cIDUtyJpA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/jest/node_modules/@nx/nx-darwin-x64": { - "version": "20.0.8", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-20.0.8.tgz", - "integrity": "sha512-bvfZ6VhSvOpPV00veaJDO1a4X+f0dn8S1A73/2ThbGZrZLAQIFrA8v+ysax+bfCGRHNdtlAL+f7TG2buh/4BRg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/jest/node_modules/@nx/nx-freebsd-x64": { - "version": "20.0.8", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-20.0.8.tgz", - "integrity": "sha512-AdOme0o/pTFy+TutIOAamuGTqbh6nOLrkNEX8f4ogfDRH+k/WvjRQ4z4ne58wf/2EVXua4jKTIEipIZAP/Ad1w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/jest/node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "20.0.8", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-20.0.8.tgz", - "integrity": "sha512-PYf7Z30A1TCZq9HVUP6JjT3ghTLYkaBpR6vDwiGWUV/exuNmhUgfYW6TiTpiSArXwnAgSIbaoGe537iEvYzA7A==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/jest/node_modules/@nx/nx-linux-arm64-gnu": { - "version": "20.0.8", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-20.0.8.tgz", - "integrity": "sha512-3VpvhjmNR78HVxGzpWiwqZsG5sNvLUv2Qfohtxyc3561o8VU41R9Onf/LJmbbZvmdDaPvvXQp3rs0OXT4i7T1g==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/jest/node_modules/@nx/nx-linux-arm64-musl": { - "version": "20.0.8", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-20.0.8.tgz", - "integrity": "sha512-3Z7fTJGG8h4VCHhD8Ix0zr6eFMfa1y3YDlzm8Clxu4Enzz0pEsUrT+ph6qrsArnIyUgiCowSi8+xgHFg7V/F1Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/jest/node_modules/@nx/nx-linux-x64-gnu": { - "version": "20.0.8", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-20.0.8.tgz", - "integrity": "sha512-Uttl1RHzWpjZgdzowCUNjC6/b3YhZR31wyXWgVF4PDWpDVgy4EigGc19tdrvv8pUVKQFuj0uaSTPUklguN7c3A==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/jest/node_modules/@nx/nx-linux-x64-musl": { - "version": "20.0.8", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-20.0.8.tgz", - "integrity": "sha512-llc6ywSPaOWQzEzD73USyAXd/y3Slu+GHS02IsQqZeA23EIOEzhvEeeeKgs4F8LKuFW/TpV6T5IhvSHw9/mvBg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/jest/node_modules/@nx/nx-win32-arm64-msvc": { - "version": "20.0.8", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-20.0.8.tgz", - "integrity": "sha512-GhPVVNrL0QcQ3B6r0P0Dta3TIesJz7uso7iI5rCZ/oOGa02UsT4NkQBpIhxYQZ4TnHYNy84g4rHtYHrSlpDlEw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/jest/node_modules/@nx/nx-win32-x64-msvc": { - "version": "20.0.8", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-20.0.8.tgz", - "integrity": "sha512-yLlcgM0zFdmsExdLv8O2g5FWQ6d2vyN5OynKV+F5BrWHC4LvrqyYJ99y++5bLFoEi19RYIK6sLnzGIRSF6dHGg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/jest/node_modules/@nx/workspace": { - "version": "20.0.8", - "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-20.0.8.tgz", - "integrity": "sha512-G7nON6s3KDWNAH9P8IBvvAmTGgTsFZPuWH7We9px0ZwsRcURDDP1OqZsYmfr0zTHTS58wu4Uax/uQLwnTVC1xQ==", - "dev": true, - "dependencies": { - "@nx/devkit": "20.0.8", - "chalk": "^4.1.0", - "enquirer": "~2.3.6", - "nx": "20.0.8", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" - } - }, - "node_modules/@nx/jest/node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "node_modules/@nx/jest/node_modules/axios": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", - "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", - "dev": true, - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/@nx/jest/node_modules/dotenv-expand": { - "version": "11.0.6", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.6.tgz", - "integrity": "sha512-8NHi73otpWsZGBSZwwknTXS5pqMOrk9+Ssrna8xCaxkzEpU9OTf9R5ArQGVw03//Zmk9MOwLPng9WwndvpAJ5g==", - "dev": true, - "dependencies": { - "dotenv": "^16.4.4" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/@nx/jest/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/@nx/jest/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@nx/jest/node_modules/lines-and-columns": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.3.tgz", - "integrity": "sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/@nx/jest/node_modules/nx": { - "version": "20.0.8", - "resolved": "https://registry.npmjs.org/nx/-/nx-20.0.8.tgz", - "integrity": "sha512-cMtb+u5Eji7Xm9xMHZkRXMcO8GH6FFqS2+nMgtLUZ/+ZmquEgoV8mbsKVw1u1sJ6osOpWAu9OwXcilwtvSOoBw==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@napi-rs/wasm-runtime": "0.2.4", - "@yarnpkg/lockfile": "^1.1.0", - "@yarnpkg/parsers": "3.0.0-rc.46", - "@zkochan/js-yaml": "0.0.7", - "axios": "^1.7.4", - "chalk": "^4.1.0", - "cli-cursor": "3.1.0", - "cli-spinners": "2.6.1", - "cliui": "^8.0.1", - "dotenv": "~16.4.5", - "dotenv-expand": "~11.0.6", - "enquirer": "~2.3.6", - "figures": "3.2.0", - "flat": "^5.0.2", - "front-matter": "^4.0.2", - "ignore": "^5.0.4", - "jest-diff": "^29.4.1", - "jsonc-parser": "3.2.0", - "lines-and-columns": "2.0.3", - "minimatch": "9.0.3", - "node-machine-id": "1.1.12", - "npm-run-path": "^4.0.1", - "open": "^8.4.0", - "ora": "5.3.0", - "semver": "^7.5.3", - "string-width": "^4.2.3", - "tar-stream": "~2.2.0", - "tmp": "~0.2.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0", - "yargs": "^17.6.2", - "yargs-parser": "21.1.1" - }, - "bin": { - "nx": "bin/nx.js", - "nx-cloud": "bin/nx-cloud.js" - }, - "optionalDependencies": { - "@nx/nx-darwin-arm64": "20.0.8", - "@nx/nx-darwin-x64": "20.0.8", - "@nx/nx-freebsd-x64": "20.0.8", - "@nx/nx-linux-arm-gnueabihf": "20.0.8", - "@nx/nx-linux-arm64-gnu": "20.0.8", - "@nx/nx-linux-arm64-musl": "20.0.8", - "@nx/nx-linux-x64-gnu": "20.0.8", - "@nx/nx-linux-x64-musl": "20.0.8", - "@nx/nx-win32-arm64-msvc": "20.0.8", - "@nx/nx-win32-x64-msvc": "20.0.8" - }, - "peerDependencies": { - "@swc-node/register": "^1.8.0", - "@swc/core": "^1.3.85" - }, - "peerDependenciesMeta": { - "@swc-node/register": { - "optional": true - }, - "@swc/core": { - "optional": true - } - } - }, - "node_modules/@nx/jest/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@nx/jest/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@nx/jest/node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", - "dev": true, - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "node_modules/@nx/jest/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@nx/js": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/js/-/js-19.2.0.tgz", - "integrity": "sha512-cLz1OSfWpm/y0bZtdv5INlCo9/ED9tC45e6OKBc2ClW5Gz2+IoZz/dK/bCXg7dpEBtF1Y9mHihKisPOmUhaLwQ==", - "dev": true, - "dependencies": { - "@babel/core": "^7.23.2", - "@babel/plugin-proposal-decorators": "^7.22.7", - "@babel/plugin-transform-class-properties": "^7.22.5", - "@babel/plugin-transform-runtime": "^7.23.2", - "@babel/preset-env": "^7.23.2", - "@babel/preset-typescript": "^7.22.5", - "@babel/runtime": "^7.22.6", - "@nrwl/js": "19.2.0", - "@nx/devkit": "19.2.0", - "@nx/workspace": "19.2.0", - "babel-plugin-const-enum": "^1.0.1", - "babel-plugin-macros": "^2.8.0", - "babel-plugin-transform-typescript-metadata": "^0.3.1", - "chalk": "^4.1.0", - "columnify": "^1.6.0", - "detect-port": "^1.5.1", - "fast-glob": "3.2.7", - "fs-extra": "^11.1.0", - "ignore": "^5.0.4", - "js-tokens": "^4.0.0", - "minimatch": "9.0.3", - "npm-package-arg": "11.0.1", - "npm-run-path": "^4.0.1", - "ora": "5.3.0", - "semver": "^7.5.3", - "source-map-support": "0.5.19", - "ts-node": "10.9.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0" - }, - "peerDependencies": { - "verdaccio": "^5.0.4" - }, - "peerDependenciesMeta": { - "verdaccio": { - "optional": true - } - } - }, - "node_modules/@nx/js/node_modules/@nrwl/devkit": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.2.0.tgz", - "integrity": "sha512-Ew5AJZkLXJwt15HjaIbHve8FOXmZ3HK8KPqTXqwKHX8jQW+fDUCaSXKe/lCZMNg0RvY+jMNecuC86uGdiIbLMg==", - "dev": true, - "dependencies": { - "@nx/devkit": "19.2.0" - } - }, - "node_modules/@nx/js/node_modules/@nrwl/tao": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.2.0.tgz", - "integrity": "sha512-9AOwbY/E7OlLCFu+6jhJGUIs+qurE2/3Pldooe7cJPqQmSQeJuVZuL6A2xHtbSG7VsXTq5Yj8dVvK1KmT45SIA==", - "dev": true, - "dependencies": { - "nx": "19.2.0", - "tslib": "^2.3.0" - }, - "bin": { - "tao": "index.js" - } - }, - "node_modules/@nx/js/node_modules/@nrwl/workspace": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-19.2.0.tgz", - "integrity": "sha512-/3p9KNpGHgEVjM5aMFhzdp0Vh+Bt16OnlSA+eSKPd5r0eQyLY+T4zTQ1kjyHGYa/xcN8vsWKEnbZW2fD/HWSng==", - "dev": true, - "dependencies": { - "@nx/workspace": "19.2.0" - } - }, - "node_modules/@nx/js/node_modules/@nx/devkit": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.2.0.tgz", - "integrity": "sha512-fK3zRUE2SLp9BUomFiyCuAX2E1yfWYE/hKimniscsvM34/u/xLZYVmmZ0/jfpGPbyaonXKZr2KTb7RimX/hyqg==", - "dev": true, - "dependencies": { - "@nrwl/devkit": "19.2.0", - "ejs": "^3.1.7", - "enquirer": "~2.3.6", - "ignore": "^5.0.4", - "minimatch": "9.0.3", - "semver": "^7.5.3", - "tmp": "~0.2.1", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" - }, - "peerDependencies": { - "nx": ">= 17 <= 20" - } - }, - "node_modules/@nx/js/node_modules/@nx/nx-darwin-arm64": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.2.0.tgz", - "integrity": "sha512-W+OpGyzr10oaycf4atPc5uH2wN1G6LJGHkWDN3LGSQhoDWuj13idFpjSy6rJ8WxtL8kIvPXq78GEi1yAADsakA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/js/node_modules/@nx/nx-darwin-x64": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.2.0.tgz", - "integrity": "sha512-4l1BDn29R0ugf7ATcGcZGEwK0frZSCtiyXnX3JFq55dNS4Bv3FiZLew7JULjdumXEXr773bH326FQlocLVlcXg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/js/node_modules/@nx/nx-freebsd-x64": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.2.0.tgz", - "integrity": "sha512-9zdwLRSkEg/H7bbIVWATn0H8QNgnHaTe23tciZPaBr95J6CXVJWWpC4wn9duURhvbscnqUSSSfKK1f+MSEDTbw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/js/node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.2.0.tgz", - "integrity": "sha512-KNVnqRPegJza3kU4q3pY8m0pT8OSQZnLGsDZti6morhXh2sE79f/zeevOrbhf8JnaJfQtyrXfGvjYAiL3+I8bw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/js/node_modules/@nx/nx-linux-arm64-gnu": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.2.0.tgz", - "integrity": "sha512-UXIl90l+cDecU17OOLlI+uzbjzQucnNu4Mee67EqE3TyfpSvuU1l3FWZ9sbE0effp8IwKpbL7Gt5KirJKtWzIA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/js/node_modules/@nx/nx-linux-arm64-musl": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.2.0.tgz", - "integrity": "sha512-4Z8XO3WljS2GWOL2SQ1p8SRNn2Kn6FU1FWClh7KBzMtpzjsHdmOXenMP9UOGZ6gBnfBIknCEDjE3uJUHmuShGg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/js/node_modules/@nx/nx-linux-x64-gnu": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.2.0.tgz", - "integrity": "sha512-EwAkZEp0KB99VEPTskW2feCpSKqWScKdRd6UaIM9Vmqqtb5hSk6yR6p0mprjytbDtFVoKQJMOFa35qe+2R8mKQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/js/node_modules/@nx/nx-linux-x64-musl": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.2.0.tgz", - "integrity": "sha512-LbFcHe83YZUS/my/8nBxQ2i3JWakcXd7zbzZ0cSAQk6DuJVCUk8PLdgZzhrVcmT82Pv7H0fM/4jgEl+oHGoc/g==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/js/node_modules/@nx/nx-win32-arm64-msvc": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.2.0.tgz", - "integrity": "sha512-BxOveRfRCdhuCs2GWbsdzGsjtLC3N+MuUlVaXSWADksF6/QKuCHM/2Kq3RYkLVVtlls6NCBp410RSx/XsbSEug==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/js/node_modules/@nx/nx-win32-x64-msvc": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.2.0.tgz", - "integrity": "sha512-QiDxtOHIiRka9Bz7tSpBvQgQPrX5grLhoz6miD6LX1WjO56bZIkEAVefGnMc3WZ1PacS1ZECtymHwUy+WpEqAQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/js/node_modules/@nx/workspace": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-19.2.0.tgz", - "integrity": "sha512-0wdv8jrGIGcf/ZF4r2/xWz/jrQjwftgLPmh7BawYPFbDZlRXkzb7a4MTJOxXH8QcR3ZJNhRjkFfHRPbB0luf1A==", - "dev": true, - "dependencies": { - "@nrwl/workspace": "19.2.0", - "@nx/devkit": "19.2.0", - "chalk": "^4.1.0", - "enquirer": "~2.3.6", - "nx": "19.2.0", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" - } - }, - "node_modules/@nx/js/node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "node_modules/@nx/js/node_modules/dotenv": { - "version": "16.3.2", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.2.tgz", - "integrity": "sha512-HTlk5nmhkm8F6JcdXvHIzaorzCoziNQT9mGxLPVXW8wJF1TiGSL60ZGB4gHWabHOaMmWmhvk2/lPHfnBiT78AQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/motdotla/dotenv?sponsor=1" - } - }, - "node_modules/@nx/js/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/@nx/js/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@nx/js/node_modules/nx": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/nx/-/nx-19.2.0.tgz", - "integrity": "sha512-IewqV0eGOpp569TSjfQVIQODxkRYKSDTP0e0j20GKkMTvCAmdbJRYZxyTr6Aw6gSM7lEVgK/4yESRO5YidfV2Q==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@nrwl/tao": "19.2.0", - "@yarnpkg/lockfile": "^1.1.0", - "@yarnpkg/parsers": "3.0.0-rc.46", - "@zkochan/js-yaml": "0.0.7", - "axios": "^1.6.0", - "chalk": "^4.1.0", - "cli-cursor": "3.1.0", - "cli-spinners": "2.6.1", - "cliui": "^8.0.1", - "dotenv": "~16.3.1", - "dotenv-expand": "~10.0.0", - "enquirer": "~2.3.6", - "figures": "3.2.0", - "flat": "^5.0.2", - "front-matter": "^4.0.2", - "fs-extra": "^11.1.0", - "ignore": "^5.0.4", - "jest-diff": "^29.4.1", - "jsonc-parser": "3.2.0", - "lines-and-columns": "~2.0.3", - "minimatch": "9.0.3", - "node-machine-id": "1.1.12", - "npm-run-path": "^4.0.1", - "open": "^8.4.0", - "ora": "5.3.0", - "semver": "^7.5.3", - "string-width": "^4.2.3", - "strong-log-transformer": "^2.1.0", - "tar-stream": "~2.2.0", - "tmp": "~0.2.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0", - "yargs": "^17.6.2", - "yargs-parser": "21.1.1" - }, - "bin": { - "nx": "bin/nx.js", - "nx-cloud": "bin/nx-cloud.js" - }, - "optionalDependencies": { - "@nx/nx-darwin-arm64": "19.2.0", - "@nx/nx-darwin-x64": "19.2.0", - "@nx/nx-freebsd-x64": "19.2.0", - "@nx/nx-linux-arm-gnueabihf": "19.2.0", - "@nx/nx-linux-arm64-gnu": "19.2.0", - "@nx/nx-linux-arm64-musl": "19.2.0", - "@nx/nx-linux-x64-gnu": "19.2.0", - "@nx/nx-linux-x64-musl": "19.2.0", - "@nx/nx-win32-arm64-msvc": "19.2.0", - "@nx/nx-win32-x64-msvc": "19.2.0" - }, - "peerDependencies": { - "@swc-node/register": "^1.8.0", - "@swc/core": "^1.3.85" - }, - "peerDependenciesMeta": { - "@swc-node/register": { - "optional": true - }, - "@swc/core": { - "optional": true - } - } - }, - "node_modules/@nx/js/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@nx/js/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@nx/js/node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", - "dev": true, - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "node_modules/@nx/js/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@nx/linter": { - "version": "19.3.2", - "resolved": "https://registry.npmjs.org/@nx/linter/-/linter-19.3.2.tgz", - "integrity": "sha512-ODGoo0Xcl+zjRrAfcNrMoOk8m/RnDSF7kr1nXLwfNv7VnMm4gcqmwLePfvA/nQZdaNQjaweQ22OOVEAfyrmqFw==", - "dev": true, - "dependencies": { - "@nx/eslint": "19.3.2" - } - }, - "node_modules/@nx/nest": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nest/-/nest-19.2.0.tgz", - "integrity": "sha512-soFP2FpznJuGQ5+MoCdBft2I4ldU0kvkoluGn9bt89D1K3NJGbnp6YS8Hu19nlsgovN27SZXCK0AtVFmxLFfHQ==", - "dev": true, - "dependencies": { - "@nestjs/schematics": "^9.1.0", - "@nrwl/nest": "19.2.0", - "@nx/devkit": "19.2.0", - "@nx/eslint": "19.2.0", - "@nx/js": "19.2.0", - "@nx/node": "19.2.0", - "@phenomnomnominal/tsquery": "~5.0.1", - "tslib": "^2.3.0" - } - }, - "node_modules/@nx/nest/node_modules/@nrwl/devkit": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.2.0.tgz", - "integrity": "sha512-Ew5AJZkLXJwt15HjaIbHve8FOXmZ3HK8KPqTXqwKHX8jQW+fDUCaSXKe/lCZMNg0RvY+jMNecuC86uGdiIbLMg==", - "dev": true, - "dependencies": { - "@nx/devkit": "19.2.0" - } - }, - "node_modules/@nx/nest/node_modules/@nx/devkit": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.2.0.tgz", - "integrity": "sha512-fK3zRUE2SLp9BUomFiyCuAX2E1yfWYE/hKimniscsvM34/u/xLZYVmmZ0/jfpGPbyaonXKZr2KTb7RimX/hyqg==", - "dev": true, - "dependencies": { - "@nrwl/devkit": "19.2.0", - "ejs": "^3.1.7", - "enquirer": "~2.3.6", - "ignore": "^5.0.4", - "minimatch": "9.0.3", - "semver": "^7.5.3", - "tmp": "~0.2.1", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" - }, - "peerDependencies": { - "nx": ">= 17 <= 20" - } - }, - "node_modules/@nx/nest/node_modules/@nx/eslint": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/eslint/-/eslint-19.2.0.tgz", - "integrity": "sha512-9OIMntrLDPrQNZjYxOncIX+65r4RhV2dJ3PrjJ9lwCVqJKZGxfCn6f8JK8ubeLoWFPVjKEtfLTHK529vvfXifQ==", - "dev": true, - "dependencies": { - "@nx/devkit": "19.2.0", - "@nx/js": "19.2.0", - "@nx/linter": "19.2.0", - "semver": "^7.5.3", - "tslib": "^2.3.0", - "typescript": "~5.4.2" - }, - "peerDependencies": { - "@zkochan/js-yaml": "0.0.7", - "eslint": "^8.0.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "@zkochan/js-yaml": { - "optional": true - } - } - }, - "node_modules/@nx/nest/node_modules/@nx/linter": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/linter/-/linter-19.2.0.tgz", - "integrity": "sha512-Rahjy3+OLc4aXT8VNXpwyMozeU4RB6HIQOh5NAdcA6PoOH8cG1VtbyjryIZE8l5HT1hrpI5EkONZt1UXiIGw3w==", - "dev": true, - "dependencies": { - "@nx/eslint": "19.2.0" - } - }, - "node_modules/@nx/nest/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@nx/next": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/next/-/next-19.2.0.tgz", - "integrity": "sha512-GL/5J80rKL5ZWmsyUxiB8aEeKy4XC8Gb+9xhV6RunCF/hOQI+B/ScHQW0N7mgYoD86QL40HhvFIa7qYbKjQwnw==", - "dev": true, - "dependencies": { - "@babel/plugin-proposal-decorators": "^7.22.7", - "@nrwl/next": "19.2.0", - "@nx/devkit": "19.2.0", - "@nx/eslint": "19.2.0", - "@nx/js": "19.2.0", - "@nx/react": "19.2.0", - "@nx/web": "19.2.0", - "@nx/webpack": "19.2.0", - "@nx/workspace": "19.2.0", - "@svgr/webpack": "^8.0.1", - "chalk": "^4.1.0", - "copy-webpack-plugin": "^10.2.4", - "file-loader": "^6.2.0", - "fs-extra": "^11.1.0", - "ignore": "^5.0.4", - "semver": "^7.5.3", - "tslib": "^2.3.0", - "webpack-merge": "^5.8.0" - }, - "peerDependencies": { - "next": ">=14.0.0" - } - }, - "node_modules/@nx/next/node_modules/@nrwl/devkit": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.2.0.tgz", - "integrity": "sha512-Ew5AJZkLXJwt15HjaIbHve8FOXmZ3HK8KPqTXqwKHX8jQW+fDUCaSXKe/lCZMNg0RvY+jMNecuC86uGdiIbLMg==", - "dev": true, - "dependencies": { - "@nx/devkit": "19.2.0" - } - }, - "node_modules/@nx/next/node_modules/@nrwl/tao": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.2.0.tgz", - "integrity": "sha512-9AOwbY/E7OlLCFu+6jhJGUIs+qurE2/3Pldooe7cJPqQmSQeJuVZuL6A2xHtbSG7VsXTq5Yj8dVvK1KmT45SIA==", - "dev": true, - "dependencies": { - "nx": "19.2.0", - "tslib": "^2.3.0" - }, - "bin": { - "tao": "index.js" - } - }, - "node_modules/@nx/next/node_modules/@nrwl/tao/node_modules/nx": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/nx/-/nx-19.2.0.tgz", - "integrity": "sha512-IewqV0eGOpp569TSjfQVIQODxkRYKSDTP0e0j20GKkMTvCAmdbJRYZxyTr6Aw6gSM7lEVgK/4yESRO5YidfV2Q==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@nrwl/tao": "19.2.0", - "@yarnpkg/lockfile": "^1.1.0", - "@yarnpkg/parsers": "3.0.0-rc.46", - "@zkochan/js-yaml": "0.0.7", - "axios": "^1.6.0", - "chalk": "^4.1.0", - "cli-cursor": "3.1.0", - "cli-spinners": "2.6.1", - "cliui": "^8.0.1", - "dotenv": "~16.3.1", - "dotenv-expand": "~10.0.0", - "enquirer": "~2.3.6", - "figures": "3.2.0", - "flat": "^5.0.2", - "front-matter": "^4.0.2", - "fs-extra": "^11.1.0", - "ignore": "^5.0.4", - "jest-diff": "^29.4.1", - "jsonc-parser": "3.2.0", - "lines-and-columns": "~2.0.3", - "minimatch": "9.0.3", - "node-machine-id": "1.1.12", - "npm-run-path": "^4.0.1", - "open": "^8.4.0", - "ora": "5.3.0", - "semver": "^7.5.3", - "string-width": "^4.2.3", - "strong-log-transformer": "^2.1.0", - "tar-stream": "~2.2.0", - "tmp": "~0.2.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0", - "yargs": "^17.6.2", - "yargs-parser": "21.1.1" - }, - "bin": { - "nx": "bin/nx.js", - "nx-cloud": "bin/nx-cloud.js" - }, - "optionalDependencies": { - "@nx/nx-darwin-arm64": "19.2.0", - "@nx/nx-darwin-x64": "19.2.0", - "@nx/nx-freebsd-x64": "19.2.0", - "@nx/nx-linux-arm-gnueabihf": "19.2.0", - "@nx/nx-linux-arm64-gnu": "19.2.0", - "@nx/nx-linux-arm64-musl": "19.2.0", - "@nx/nx-linux-x64-gnu": "19.2.0", - "@nx/nx-linux-x64-musl": "19.2.0", - "@nx/nx-win32-arm64-msvc": "19.2.0", - "@nx/nx-win32-x64-msvc": "19.2.0" - }, - "peerDependencies": { - "@swc-node/register": "^1.8.0", - "@swc/core": "^1.3.85" - }, - "peerDependenciesMeta": { - "@swc-node/register": { - "optional": true - }, - "@swc/core": { - "optional": true - } - } - }, - "node_modules/@nx/next/node_modules/@nrwl/webpack": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/webpack/-/webpack-19.2.0.tgz", - "integrity": "sha512-lYj7T967iCgo6fWzZ727oYnmtdKHhM/6A8Li945iWLg+wY/IJdTevaU+0uEvmeSsGFyr0a0DZJ1todk0gHs0Kw==", - "dev": true, - "dependencies": { - "@nx/webpack": "19.2.0" - } - }, - "node_modules/@nx/next/node_modules/@nrwl/workspace": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-19.2.0.tgz", - "integrity": "sha512-/3p9KNpGHgEVjM5aMFhzdp0Vh+Bt16OnlSA+eSKPd5r0eQyLY+T4zTQ1kjyHGYa/xcN8vsWKEnbZW2fD/HWSng==", - "dev": true, - "dependencies": { - "@nx/workspace": "19.2.0" - } - }, - "node_modules/@nx/next/node_modules/@nx/devkit": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.2.0.tgz", - "integrity": "sha512-fK3zRUE2SLp9BUomFiyCuAX2E1yfWYE/hKimniscsvM34/u/xLZYVmmZ0/jfpGPbyaonXKZr2KTb7RimX/hyqg==", - "dev": true, - "dependencies": { - "@nrwl/devkit": "19.2.0", - "ejs": "^3.1.7", - "enquirer": "~2.3.6", - "ignore": "^5.0.4", - "minimatch": "9.0.3", - "semver": "^7.5.3", - "tmp": "~0.2.1", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" - }, - "peerDependencies": { - "nx": ">= 17 <= 20" - } - }, - "node_modules/@nx/next/node_modules/@nx/eslint": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/eslint/-/eslint-19.2.0.tgz", - "integrity": "sha512-9OIMntrLDPrQNZjYxOncIX+65r4RhV2dJ3PrjJ9lwCVqJKZGxfCn6f8JK8ubeLoWFPVjKEtfLTHK529vvfXifQ==", - "dev": true, - "dependencies": { - "@nx/devkit": "19.2.0", - "@nx/js": "19.2.0", - "@nx/linter": "19.2.0", - "semver": "^7.5.3", - "tslib": "^2.3.0", - "typescript": "~5.4.2" - }, - "peerDependencies": { - "@zkochan/js-yaml": "0.0.7", - "eslint": "^8.0.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "@zkochan/js-yaml": { - "optional": true - } - } - }, - "node_modules/@nx/next/node_modules/@nx/linter": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/linter/-/linter-19.2.0.tgz", - "integrity": "sha512-Rahjy3+OLc4aXT8VNXpwyMozeU4RB6HIQOh5NAdcA6PoOH8cG1VtbyjryIZE8l5HT1hrpI5EkONZt1UXiIGw3w==", - "dev": true, - "dependencies": { - "@nx/eslint": "19.2.0" - } - }, - "node_modules/@nx/next/node_modules/@nx/nx-darwin-arm64": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.2.0.tgz", - "integrity": "sha512-W+OpGyzr10oaycf4atPc5uH2wN1G6LJGHkWDN3LGSQhoDWuj13idFpjSy6rJ8WxtL8kIvPXq78GEi1yAADsakA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/next/node_modules/@nx/nx-darwin-x64": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.2.0.tgz", - "integrity": "sha512-4l1BDn29R0ugf7ATcGcZGEwK0frZSCtiyXnX3JFq55dNS4Bv3FiZLew7JULjdumXEXr773bH326FQlocLVlcXg==", + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz", + "integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==", "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/next/node_modules/@nx/nx-freebsd-x64": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.2.0.tgz", - "integrity": "sha512-9zdwLRSkEg/H7bbIVWATn0H8QNgnHaTe23tciZPaBr95J6CXVJWWpC4wn9duURhvbscnqUSSSfKK1f+MSEDTbw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" - } + ] }, - "node_modules/@nx/next/node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.2.0.tgz", - "integrity": "sha512-KNVnqRPegJza3kU4q3pY8m0pT8OSQZnLGsDZti6morhXh2sE79f/zeevOrbhf8JnaJfQtyrXfGvjYAiL3+I8bw==", + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz", + "integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==", "cpu": [ "arm" ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/next/node_modules/@nx/nx-linux-arm64-gnu": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.2.0.tgz", - "integrity": "sha512-UXIl90l+cDecU17OOLlI+uzbjzQucnNu4Mee67EqE3TyfpSvuU1l3FWZ9sbE0effp8IwKpbL7Gt5KirJKtWzIA==", - "cpu": [ - "arm64" - ], - "dev": true, "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">= 10" - } + ] }, - "node_modules/@nx/next/node_modules/@nx/nx-linux-arm64-musl": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.2.0.tgz", - "integrity": "sha512-4Z8XO3WljS2GWOL2SQ1p8SRNn2Kn6FU1FWClh7KBzMtpzjsHdmOXenMP9UOGZ6gBnfBIknCEDjE3uJUHmuShGg==", + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz", + "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==", "cpu": [ "arm64" ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/next/node_modules/@nx/nx-linux-x64-gnu": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.2.0.tgz", - "integrity": "sha512-EwAkZEp0KB99VEPTskW2feCpSKqWScKdRd6UaIM9Vmqqtb5hSk6yR6p0mprjytbDtFVoKQJMOFa35qe+2R8mKQ==", - "cpu": [ - "x64" - ], - "dev": true, "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">= 10" - } + ] }, - "node_modules/@nx/next/node_modules/@nx/nx-linux-x64-musl": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.2.0.tgz", - "integrity": "sha512-LbFcHe83YZUS/my/8nBxQ2i3JWakcXd7zbzZ0cSAQk6DuJVCUk8PLdgZzhrVcmT82Pv7H0fM/4jgEl+oHGoc/g==", + "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz", + "integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==", "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/next/node_modules/@nx/nx-win32-arm64-msvc": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.2.0.tgz", - "integrity": "sha512-BxOveRfRCdhuCs2GWbsdzGsjtLC3N+MuUlVaXSWADksF6/QKuCHM/2Kq3RYkLVVtlls6NCBp410RSx/XsbSEug==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/next/node_modules/@nx/nx-win32-x64-msvc": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.2.0.tgz", - "integrity": "sha512-QiDxtOHIiRka9Bz7tSpBvQgQPrX5grLhoz6miD6LX1WjO56bZIkEAVefGnMc3WZ1PacS1ZECtymHwUy+WpEqAQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/next/node_modules/@nx/webpack": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/webpack/-/webpack-19.2.0.tgz", - "integrity": "sha512-/YGLknUIOmYd2r1DOUcyDnHJ4tZeVU6iHnuqUx2zv6pVZYnBs2cW6JjejH6s+n6y8hMQ7H/mXa7RR2eQI2KgaQ==", - "dev": true, - "dependencies": { - "@babel/core": "^7.23.2", - "@nrwl/webpack": "19.2.0", - "@nx/devkit": "19.2.0", - "@nx/js": "19.2.0", - "ajv": "^8.12.0", - "autoprefixer": "^10.4.9", - "babel-loader": "^9.1.2", - "browserslist": "^4.21.4", - "chalk": "^4.1.0", - "copy-webpack-plugin": "^10.2.4", - "css-loader": "^6.4.0", - "css-minimizer-webpack-plugin": "^5.0.0", - "fork-ts-checker-webpack-plugin": "7.2.13", - "less": "4.1.3", - "less-loader": "11.1.0", - "license-webpack-plugin": "^4.0.2", - "loader-utils": "^2.0.3", - "mini-css-extract-plugin": "~2.4.7", - "parse5": "4.0.0", - "postcss": "^8.4.38", - "postcss-import": "~14.1.0", - "postcss-loader": "^6.1.1", - "rxjs": "^7.8.0", - "sass": "^1.42.1", - "sass-loader": "^12.2.0", - "source-map-loader": "^3.0.0", - "style-loader": "^3.3.0", - "stylus": "^0.59.0", - "stylus-loader": "^7.1.0", - "terser-webpack-plugin": "^5.3.3", - "ts-loader": "^9.3.1", - "tsconfig-paths-webpack-plugin": "4.0.0", - "tslib": "^2.3.0", - "webpack": "^5.80.0", - "webpack-dev-server": "^4.9.3", - "webpack-node-externals": "^3.0.0", - "webpack-subresource-integrity": "^5.1.0" - } - }, - "node_modules/@nx/next/node_modules/@nx/workspace": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-19.2.0.tgz", - "integrity": "sha512-0wdv8jrGIGcf/ZF4r2/xWz/jrQjwftgLPmh7BawYPFbDZlRXkzb7a4MTJOxXH8QcR3ZJNhRjkFfHRPbB0luf1A==", - "dev": true, - "dependencies": { - "@nrwl/workspace": "19.2.0", - "@nx/devkit": "19.2.0", - "chalk": "^4.1.0", - "enquirer": "~2.3.6", - "nx": "19.2.0", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" - } - }, - "node_modules/@nx/next/node_modules/@nx/workspace/node_modules/nx": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/nx/-/nx-19.2.0.tgz", - "integrity": "sha512-IewqV0eGOpp569TSjfQVIQODxkRYKSDTP0e0j20GKkMTvCAmdbJRYZxyTr6Aw6gSM7lEVgK/4yESRO5YidfV2Q==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@nrwl/tao": "19.2.0", - "@yarnpkg/lockfile": "^1.1.0", - "@yarnpkg/parsers": "3.0.0-rc.46", - "@zkochan/js-yaml": "0.0.7", - "axios": "^1.6.0", - "chalk": "^4.1.0", - "cli-cursor": "3.1.0", - "cli-spinners": "2.6.1", - "cliui": "^8.0.1", - "dotenv": "~16.3.1", - "dotenv-expand": "~10.0.0", - "enquirer": "~2.3.6", - "figures": "3.2.0", - "flat": "^5.0.2", - "front-matter": "^4.0.2", - "fs-extra": "^11.1.0", - "ignore": "^5.0.4", - "jest-diff": "^29.4.1", - "jsonc-parser": "3.2.0", - "lines-and-columns": "~2.0.3", - "minimatch": "9.0.3", - "node-machine-id": "1.1.12", - "npm-run-path": "^4.0.1", - "open": "^8.4.0", - "ora": "5.3.0", - "semver": "^7.5.3", - "string-width": "^4.2.3", - "strong-log-transformer": "^2.1.0", - "tar-stream": "~2.2.0", - "tmp": "~0.2.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0", - "yargs": "^17.6.2", - "yargs-parser": "21.1.1" - }, - "bin": { - "nx": "bin/nx.js", - "nx-cloud": "bin/nx-cloud.js" - }, - "optionalDependencies": { - "@nx/nx-darwin-arm64": "19.2.0", - "@nx/nx-darwin-x64": "19.2.0", - "@nx/nx-freebsd-x64": "19.2.0", - "@nx/nx-linux-arm-gnueabihf": "19.2.0", - "@nx/nx-linux-arm64-gnu": "19.2.0", - "@nx/nx-linux-arm64-musl": "19.2.0", - "@nx/nx-linux-x64-gnu": "19.2.0", - "@nx/nx-linux-x64-musl": "19.2.0", - "@nx/nx-win32-arm64-msvc": "19.2.0", - "@nx/nx-win32-x64-msvc": "19.2.0" - }, - "peerDependencies": { - "@swc-node/register": "^1.8.0", - "@swc/core": "^1.3.85" - }, - "peerDependenciesMeta": { - "@swc-node/register": { - "optional": true - }, - "@swc/core": { - "optional": true - } - } - }, - "node_modules/@nx/next/node_modules/array-union": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz", - "integrity": "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@nx/next/node_modules/copy-webpack-plugin": { - "version": "10.2.4", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz", - "integrity": "sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg==", - "dev": true, - "dependencies": { - "fast-glob": "^3.2.7", - "glob-parent": "^6.0.1", - "globby": "^12.0.2", - "normalize-path": "^3.0.0", - "schema-utils": "^4.0.0", - "serialize-javascript": "^6.0.0" - }, - "engines": { - "node": ">= 12.20.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - } - }, - "node_modules/@nx/next/node_modules/cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", - "dev": true, - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@nx/next/node_modules/dotenv": { - "version": "16.3.2", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.2.tgz", - "integrity": "sha512-HTlk5nmhkm8F6JcdXvHIzaorzCoziNQT9mGxLPVXW8wJF1TiGSL60ZGB4gHWabHOaMmWmhvk2/lPHfnBiT78AQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/motdotla/dotenv?sponsor=1" - } + ] }, - "node_modules/@nx/next/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz", + "integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/@nx/next/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "node_modules/@mswjs/interceptors": { + "version": "0.37.3", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.37.3.tgz", + "integrity": "sha512-USvgCL/uOGFtVa6SVyRrC8kIAedzRohxIXN5LISlg5C5vLZCn7dgMFVSNhSF9cuBEFrm/O2spDWEZeMnw4ZXYg==", "dev": true, + "license": "MIT", "dependencies": { - "is-glob": "^4.0.3" + "@open-draft/deferred-promise": "^2.2.0", + "@open-draft/logger": "^0.3.0", + "@open-draft/until": "^2.0.0", + "is-node-process": "^1.2.0", + "outvariant": "^1.4.3", + "strict-event-emitter": "^0.5.1" }, "engines": { - "node": ">=10.13.0" + "node": ">=18" } }, - "node_modules/@nx/next/node_modules/globby": { - "version": "12.2.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-12.2.0.tgz", - "integrity": "sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA==", + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.4.tgz", + "integrity": "sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==", "dev": true, "dependencies": { - "array-union": "^3.0.1", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.7", - "ignore": "^5.1.9", - "merge2": "^1.4.1", - "slash": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "@emnapi/core": "^1.1.0", + "@emnapi/runtime": "^1.1.0", + "@tybys/wasm-util": "^0.9.0" } }, - "node_modules/@nx/next/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, + "node_modules/@narval-xyz/armory-mpc-module": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@narval-xyz/armory-mpc-module/-/armory-mpc-module-0.0.1.tgz", + "integrity": "sha512-jAUKXB4tf5KgcNeqpcpVNzivvB4IiOMKpVufdhaRx+JHQDSxfCkFYcghtoWavZGA5csryrGMFHwPUZnA7q594g==", + "bundleDependencies": [ + "@narval-xyz/armory-sdk" + ], + "optional": true, "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" + "@narval-xyz/armory-sdk": "^0.0.5", + "@nestjs/common": "^10.0.0", + "@nestjs/core": "^10.0.0", + "@nestjs/platform-express": "^10.0.0", + "@noble/curves": "^1.4.2", + "@sepior/tsmsdkv2": "^63.0.0", + "reflect-metadata": "^0.1.13", + "rxjs": "^7.8.1" } }, - "node_modules/@nx/next/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } + "node_modules/@narval-xyz/armory-mpc-module/node_modules/@adraffy/ens-normalize": { + "version": "1.10.0", + "inBundle": true, + "license": "MIT", + "optional": true }, - "node_modules/@nx/next/node_modules/mini-css-extract-plugin": { - "version": "2.4.7", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.4.7.tgz", - "integrity": "sha512-euWmddf0sk9Nv1O0gfeeUAvAkoSlWncNLF77C0TP2+WoPvy8mAHKOzMajcCz2dzvyt3CNgxb1obIEVFIRxaipg==", - "dev": true, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/@narval-xyz/armory-sdk": { + "version": "0.0.5", + "inBundle": true, + "license": "MPL-2.0", + "optional": true, "dependencies": { - "schema-utils": "^4.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" + "@noble/curves": "1.4.0", + "axios": "1.7.2", + "jose": "5.5.0", + "lodash": "4.17.21", + "tslib": "2.6.3", + "uuid": "9.0.1", + "viem": "2.16.2", + "zod": "3.23.8" } }, - "node_modules/@nx/next/node_modules/postcss-loader": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", - "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", - "dev": true, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/@narval-xyz/armory-sdk/node_modules/@noble/curves": { + "version": "1.4.0", + "inBundle": true, + "license": "MIT", + "optional": true, "dependencies": { - "cosmiconfig": "^7.0.0", - "klona": "^2.0.5", - "semver": "^7.3.5" - }, - "engines": { - "node": ">= 12.13.0" + "@noble/hashes": "1.4.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "postcss": "^7.0.0 || ^8.0.1", - "webpack": "^5.0.0" + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@nx/next/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } + "node_modules/@narval-xyz/armory-mpc-module/node_modules/@narval-xyz/armory-sdk/node_modules/tslib": { + "version": "2.6.3", + "inBundle": true, + "license": "0BSD", + "optional": true }, - "node_modules/@nx/next/node_modules/slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", - "dev": true, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/@noble/hashes": { + "version": "1.4.0", + "inBundle": true, + "license": "MIT", + "optional": true, "engines": { - "node": ">=12" + "node": ">= 16" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@nx/next/node_modules/source-map-loader": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-3.0.2.tgz", - "integrity": "sha512-BokxPoLjyl3iOrgkWaakaxqnelAJSS+0V+De0kKIq6lyWrXuiPgYTGp6z3iHmqljKAaLXwZa+ctD8GccRJeVvg==", - "dev": true, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/@scure/base": { + "version": "1.1.7", + "inBundle": true, + "license": "MIT", + "optional": true, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/@scure/bip32": { + "version": "1.3.2", + "inBundle": true, + "license": "MIT", + "optional": true, "dependencies": { - "abab": "^2.0.5", - "iconv-lite": "^0.6.3", - "source-map-js": "^1.0.1" - }, - "engines": { - "node": ">= 12.13.0" + "@noble/curves": "~1.2.0", + "@noble/hashes": "~1.3.2", + "@scure/base": "~1.1.2" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@nx/next/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/@scure/bip32/node_modules/@noble/curves": { + "version": "1.2.0", + "inBundle": true, + "license": "MIT", + "optional": true, "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "@noble/hashes": "1.3.2" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@nx/next/node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, - "license": "ISC", + "node_modules/@narval-xyz/armory-mpc-module/node_modules/@scure/bip32/node_modules/@noble/curves/node_modules/@noble/hashes": { + "version": "1.3.2", + "inBundle": true, + "license": "MIT", + "optional": true, "engines": { - "node": ">= 6" - } - }, - "node_modules/@nx/next/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" + "node": ">= 16" }, - "engines": { - "node": ">=12" + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@nx/node": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/node/-/node-19.2.0.tgz", - "integrity": "sha512-d4VnUY5i4nWw2dIkc3OJx4tiBNPsym9Xvq0XyyHjCn3DXTFOH9UiYpVR3kOL/22DeQs8hGOkb3jaSNdi2W8Dlg==", - "dev": true, - "dependencies": { - "@nrwl/node": "19.2.0", - "@nx/devkit": "19.2.0", - "@nx/eslint": "19.2.0", - "@nx/jest": "19.2.0", - "@nx/js": "19.2.0", - "tslib": "^2.3.0" + "node_modules/@narval-xyz/armory-mpc-module/node_modules/@scure/bip32/node_modules/@noble/hashes": { + "version": "1.3.3", + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@nx/node/node_modules/@nrwl/devkit": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.2.0.tgz", - "integrity": "sha512-Ew5AJZkLXJwt15HjaIbHve8FOXmZ3HK8KPqTXqwKHX8jQW+fDUCaSXKe/lCZMNg0RvY+jMNecuC86uGdiIbLMg==", - "dev": true, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/@scure/bip39": { + "version": "1.2.1", + "inBundle": true, + "license": "MIT", + "optional": true, "dependencies": { - "@nx/devkit": "19.2.0" + "@noble/hashes": "~1.3.0", + "@scure/base": "~1.1.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@nx/node/node_modules/@nx/devkit": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.2.0.tgz", - "integrity": "sha512-fK3zRUE2SLp9BUomFiyCuAX2E1yfWYE/hKimniscsvM34/u/xLZYVmmZ0/jfpGPbyaonXKZr2KTb7RimX/hyqg==", - "dev": true, - "dependencies": { - "@nrwl/devkit": "19.2.0", - "ejs": "^3.1.7", - "enquirer": "~2.3.6", - "ignore": "^5.0.4", - "minimatch": "9.0.3", - "semver": "^7.5.3", - "tmp": "~0.2.1", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" + "node_modules/@narval-xyz/armory-mpc-module/node_modules/@scure/bip39/node_modules/@noble/hashes": { + "version": "1.3.3", + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 16" }, - "peerDependencies": { - "nx": ">= 17 <= 20" + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@nx/node/node_modules/@nx/eslint": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/eslint/-/eslint-19.2.0.tgz", - "integrity": "sha512-9OIMntrLDPrQNZjYxOncIX+65r4RhV2dJ3PrjJ9lwCVqJKZGxfCn6f8JK8ubeLoWFPVjKEtfLTHK529vvfXifQ==", - "dev": true, - "dependencies": { - "@nx/devkit": "19.2.0", - "@nx/js": "19.2.0", - "@nx/linter": "19.2.0", - "semver": "^7.5.3", - "tslib": "^2.3.0", - "typescript": "~5.4.2" + "node_modules/@narval-xyz/armory-mpc-module/node_modules/abitype": { + "version": "1.0.4", + "inBundle": true, + "license": "MIT", + "optional": true, + "funding": { + "url": "https://github.com/sponsors/wevm" }, "peerDependencies": { - "@zkochan/js-yaml": "0.0.7", - "eslint": "^8.0.0 || ^9.0.0" + "typescript": ">=5.0.4", + "zod": "^3 >=3.22.0" }, "peerDependenciesMeta": { - "@zkochan/js-yaml": { + "typescript": { + "optional": true + }, + "zod": { "optional": true } } }, - "node_modules/@nx/node/node_modules/@nx/jest": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/jest/-/jest-19.2.0.tgz", - "integrity": "sha512-iJMqfwkIB4T7NRYAQe3nZWFEAQGGblMGcxWczMKEixCIZWcAz4up74eb0H6Yv+tUVOQHrFTm6J1OnrW3BqvOZA==", - "dev": true, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/asynckit": { + "version": "0.4.0", + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/axios": { + "version": "1.7.2", + "inBundle": true, + "license": "MIT", + "optional": true, "dependencies": { - "@jest/reporters": "^29.4.1", - "@jest/test-result": "^29.4.1", - "@nrwl/jest": "19.2.0", - "@nx/devkit": "19.2.0", - "@nx/js": "19.2.0", - "@phenomnomnominal/tsquery": "~5.0.1", - "chalk": "^4.1.0", - "identity-obj-proxy": "3.0.0", - "jest-config": "^29.4.1", - "jest-resolve": "^29.4.1", - "jest-util": "^29.4.1", - "minimatch": "9.0.3", - "resolve.exports": "1.1.0", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" } }, - "node_modules/@nx/node/node_modules/@nx/linter": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/linter/-/linter-19.2.0.tgz", - "integrity": "sha512-Rahjy3+OLc4aXT8VNXpwyMozeU4RB6HIQOh5NAdcA6PoOH8cG1VtbyjryIZE8l5HT1hrpI5EkONZt1UXiIGw3w==", - "dev": true, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/combined-stream": { + "version": "1.0.8", + "inBundle": true, + "license": "MIT", + "optional": true, "dependencies": { - "@nx/eslint": "19.2.0" + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" } }, - "node_modules/@nx/node/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/delayed-stream": { + "version": "1.0.0", + "inBundle": true, + "license": "MIT", + "optional": true, "engines": { - "node": ">=10" + "node": ">=0.4.0" } }, - "node_modules/@nx/nx-darwin-arm64": { - "version": "19.4.4", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.4.4.tgz", - "integrity": "sha512-qmPz1PYsV1zlpSWBHLmy3J7Hw5H5pPWAps6ObcxwUuQwli6uySi4OKFKCLnmWgi1ICvB2NviChK45OIDtxJ2Iw==", - "cpu": [ - "arm64" + "node_modules/@narval-xyz/armory-mpc-module/node_modules/follow-redirects": { + "version": "1.15.6", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } ], - "dev": true, + "inBundle": true, + "license": "MIT", "optional": true, - "os": [ - "darwin" - ], "engines": { - "node": ">= 10" + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } } }, - "node_modules/@nx/nx-darwin-x64": { - "version": "19.4.4", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.4.4.tgz", - "integrity": "sha512-/M+KQrjaIovhTP81BGMQ3AezSy9ZYhubXg7G3ltcMfox07yw5Pj10Ip9ZwkE5zF6CuJXNAoLesmNhbqMXodsag==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/form-data": { + "version": "4.0.0", + "inBundle": true, + "license": "MIT", "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, "engines": { - "node": ">= 10" + "node": ">= 6" } }, - "node_modules/@nx/nx-freebsd-x64": { - "version": "19.4.4", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.4.4.tgz", - "integrity": "sha512-PegR8GgHn24/eXqVRme3iRPHVYmH94rSBNoKOrWHJ8RTA/Dw+ZoOmhdLssOSs6z7JQ0S63MKo8x/HILI3+WyXw==", - "cpu": [ - "x64" + "node_modules/@narval-xyz/armory-mpc-module/node_modules/isows": { + "version": "1.0.4", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wagmi-dev" + } ], - "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/jose": { + "version": "5.5.0", + "inBundle": true, + "license": "MIT", + "optional": true, + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/lodash": { + "version": "4.17.21", + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/mime-db": { + "version": "1.52.0", + "inBundle": true, + "license": "MIT", "optional": true, - "os": [ - "freebsd" - ], "engines": { - "node": ">= 10" + "node": ">= 0.6" } }, - "node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "19.4.4", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.4.4.tgz", - "integrity": "sha512-6Yz0aTR8XE/MXpjbQ5HRlGcngYXUv156tJeynO8lyiZ0HK1RkUq+MsbSLw0zvqBUljWQwQwK20rsAx9AUqM9kQ==", - "cpu": [ - "arm" - ], - "dev": true, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/mime-types": { + "version": "2.1.35", + "inBundle": true, + "license": "MIT", "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "mime-db": "1.52.0" + }, "engines": { - "node": ">= 10" + "node": ">= 0.6" } }, - "node_modules/@nx/nx-linux-arm64-gnu": { - "version": "19.4.4", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.4.4.tgz", - "integrity": "sha512-33zZ+ytnRgXnx7Ls8hoEtXSRDJF8PuZaJBbGocrpfXku58fHj7+AJtQZWjQe3STGJuVUbmIZNfGJ/st+3Zeccg==", - "cpu": [ - "arm64" + "node_modules/@narval-xyz/armory-mpc-module/node_modules/proxy-from-env": { + "version": "1.1.0", + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/uuid": { + "version": "9.0.1", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" ], - "dev": true, + "inBundle": true, + "license": "MIT", "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" + "bin": { + "uuid": "dist/bin/uuid" } }, - "node_modules/@nx/nx-linux-arm64-musl": { - "version": "19.4.4", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.4.4.tgz", - "integrity": "sha512-00qPmFs0LGmeudYSwhcuMLNRb4/Eaaf6SMkqdbJU2iKEbq6rY7clORAJlOn3FQPmxi/j2uEfbkONMfO8pqsu3A==", - "cpu": [ - "arm64" + "node_modules/@narval-xyz/armory-mpc-module/node_modules/viem": { + "version": "2.16.2", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } ], - "dev": true, + "inBundle": true, + "license": "MIT", "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" + "dependencies": { + "@adraffy/ens-normalize": "1.10.0", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.2", + "@scure/bip32": "1.3.2", + "@scure/bip39": "1.2.1", + "abitype": "1.0.4", + "isows": "1.0.4", + "ws": "8.17.1" + }, + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@nx/nx-linux-x64-gnu": { - "version": "19.4.4", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.4.4.tgz", - "integrity": "sha512-R7wIdVzSVvKTsLPRBIo9eouEik4ZiYhR4eG2XybhdWNhv8vC+VzOdbWWUyxQzzxj2Lo5o7d4UlFxvblTftQJJw==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/viem/node_modules/@noble/curves": { + "version": "1.2.0", + "inBundle": true, + "license": "MIT", "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" + "dependencies": { + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@nx/nx-linux-x64-musl": { - "version": "19.4.4", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.4.4.tgz", - "integrity": "sha512-2Xu71Jwa0Ti2fwvvGXb21kpMaga4eZeS5+2MKMJnE2hzW6NWSx68xnw6TPJIdEKbkJUHWk32vF4vob79puunHQ==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/viem/node_modules/@noble/hashes": { + "version": "1.3.2", + "inBundle": true, + "license": "MIT", "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">= 10" + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@nx/nx-win32-arm64-msvc": { - "version": "19.4.4", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.4.4.tgz", - "integrity": "sha512-ztF1MhxB+IdLIqwx1DbAdqJvTHrFstUavinFTxTaGBTu9AtFwziRP567XB8TiyzyCSmY9H8JJHGByQ0Mr6cUbQ==", - "cpu": [ - "arm64" - ], - "dev": true, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/ws": { + "version": "8.17.1", + "inBundle": true, + "license": "MIT", "optional": true, - "os": [ - "win32" - ], "engines": { - "node": ">= 10" + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, - "node_modules/@nx/nx-win32-x64-msvc": { - "version": "19.4.4", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.4.4.tgz", - "integrity": "sha512-AdcjRiQ3MXlhpwCt5QprxtwAvG+VcYymF6ZI37aHZ9EkSEkD77iFgpkAhfhhHEgbTmnGBcMZMwJ5MENXjwdW8A==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/@narval-xyz/armory-mpc-module/node_modules/zod": { + "version": "3.23.8", + "inBundle": true, + "license": "MIT", "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" + "funding": { + "url": "https://github.com/sponsors/colinhacks" } }, - "node_modules/@nx/react": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/react/-/react-19.2.0.tgz", - "integrity": "sha512-G9PSRnX8X4lCaJ7808xwL+kfZ/LWLi/Rph6mGJFnSS+0Y89WyHNcQTIWdvzabQy2RwXgi/eDy1FToDx/5rTZbA==", - "dev": true, - "dependencies": { - "@nrwl/react": "19.2.0", - "@nx/devkit": "19.2.0", - "@nx/eslint": "19.2.0", - "@nx/js": "19.2.0", - "@nx/web": "19.2.0", - "@phenomnomnominal/tsquery": "~5.0.1", - "@svgr/webpack": "^8.0.1", - "chalk": "^4.1.0", - "file-loader": "^6.2.0", - "minimatch": "9.0.3", - "tslib": "^2.3.0" + "node_modules/@narval-xyz/armory-sdk": { + "resolved": "packages/armory-sdk", + "link": true + }, + "node_modules/@nestjs/axios": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-3.0.2.tgz", + "integrity": "sha512-Z6GuOUdNQjP7FX+OuV2Ybyamse+/e0BFdTWBX5JxpBDKA+YkdLynDgG6HTF04zy6e9zPa19UX0WA2VDoehwhXQ==", + "peerDependencies": { + "@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0", + "axios": "^1.3.1", + "rxjs": "^6.0.0 || ^7.0.0" } }, - "node_modules/@nx/react/node_modules/@nrwl/devkit": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.2.0.tgz", - "integrity": "sha512-Ew5AJZkLXJwt15HjaIbHve8FOXmZ3HK8KPqTXqwKHX8jQW+fDUCaSXKe/lCZMNg0RvY+jMNecuC86uGdiIbLMg==", - "dev": true, + "node_modules/@nestjs/bull": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/@nestjs/bull/-/bull-10.2.0.tgz", + "integrity": "sha512-byQI3cgAVP8BNa71h5g33D1pNwOaK2O9+zYmT98eU8LxxJHh53aWMwEUrCHrwgSz4P8bD+jY8ObQ5vtU4SsidA==", "dependencies": { - "@nx/devkit": "19.2.0" + "@nestjs/bull-shared": "^10.2.0", + "tslib": "2.6.3" + }, + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", + "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0", + "bull": "^3.3 || ^4.0.0" } }, - "node_modules/@nx/react/node_modules/@nx/devkit": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.2.0.tgz", - "integrity": "sha512-fK3zRUE2SLp9BUomFiyCuAX2E1yfWYE/hKimniscsvM34/u/xLZYVmmZ0/jfpGPbyaonXKZr2KTb7RimX/hyqg==", - "dev": true, + "node_modules/@nestjs/bull-shared": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/@nestjs/bull-shared/-/bull-shared-10.2.0.tgz", + "integrity": "sha512-cSi6CyPECHDFumnHWWfwLCnbc6hm5jXt7FqzJ0Id6EhGqdz5ja0FmgRwXoS4xoMA2RRjlxn2vGXr4YOaHBAeig==", "dependencies": { - "@nrwl/devkit": "19.2.0", - "ejs": "^3.1.7", - "enquirer": "~2.3.6", - "ignore": "^5.0.4", - "minimatch": "9.0.3", - "semver": "^7.5.3", - "tmp": "~0.2.1", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" + "tslib": "2.6.3" }, "peerDependencies": { - "nx": ">= 17 <= 20" + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", + "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0" } }, - "node_modules/@nx/react/node_modules/@nx/eslint": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/eslint/-/eslint-19.2.0.tgz", - "integrity": "sha512-9OIMntrLDPrQNZjYxOncIX+65r4RhV2dJ3PrjJ9lwCVqJKZGxfCn6f8JK8ubeLoWFPVjKEtfLTHK529vvfXifQ==", - "dev": true, + "node_modules/@nestjs/cache-manager": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@nestjs/cache-manager/-/cache-manager-3.0.0.tgz", + "integrity": "sha512-csKvxHSQWfC0OiDo0bNEhLqrmYDopHEvRyC81MxV9xFj1AO+rOKocpHa4M1ZGH//6uKFIPGN9oiR0mvZY77APA==", + "license": "MIT", + "peerDependencies": { + "@nestjs/common": "^9.0.0 || ^10.0.0 || ^11.0.0", + "@nestjs/core": "^9.0.0 || ^10.0.0 || ^11.0.0", + "cache-manager": ">=6", + "rxjs": "^7.8.1" + } + }, + "node_modules/@nestjs/common": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.3.10.tgz", + "integrity": "sha512-H8k0jZtxk1IdtErGDmxFRy0PfcOAUg41Prrqpx76DQusGGJjsaovs1zjXVD1rZWaVYchfT1uczJ6L4Kio10VNg==", "dependencies": { - "@nx/devkit": "19.2.0", - "@nx/js": "19.2.0", - "@nx/linter": "19.2.0", - "semver": "^7.5.3", - "tslib": "^2.3.0", - "typescript": "~5.4.2" + "iterare": "1.2.1", + "tslib": "2.6.3", + "uid": "2.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" }, "peerDependencies": { - "@zkochan/js-yaml": "0.0.7", - "eslint": "^8.0.0 || ^9.0.0" + "class-transformer": "*", + "class-validator": "*", + "reflect-metadata": "^0.1.12 || ^0.2.0", + "rxjs": "^7.1.0" }, "peerDependenciesMeta": { - "@zkochan/js-yaml": { + "class-transformer": { + "optional": true + }, + "class-validator": { "optional": true } } }, - "node_modules/@nx/react/node_modules/@nx/linter": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/linter/-/linter-19.2.0.tgz", - "integrity": "sha512-Rahjy3+OLc4aXT8VNXpwyMozeU4RB6HIQOh5NAdcA6PoOH8cG1VtbyjryIZE8l5HT1hrpI5EkONZt1UXiIGw3w==", - "dev": true, + "node_modules/@nestjs/config": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-3.1.1.tgz", + "integrity": "sha512-qu5QlNiJdqQtOsnB6lx4JCXPQ96jkKUsOGd+JXfXwqJqZcOSAq6heNFg0opW4pq4J/VZoNwoo87TNnx9wthnqQ==", "dependencies": { - "@nx/eslint": "19.2.0" - } - }, - "node_modules/@nx/react/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, - "bin": { - "semver": "bin/semver.js" + "dotenv": "16.3.1", + "dotenv-expand": "10.0.0", + "lodash": "4.17.21", + "uuid": "9.0.0" }, - "engines": { - "node": ">=10" + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", + "reflect-metadata": "^0.1.13" } }, - "node_modules/@nx/web": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/web/-/web-19.2.0.tgz", - "integrity": "sha512-iMRwDjkU7GfJql4wT6pGCimFoHYV/2bQuI/N9b9T3NEL9sk5tlMqlik6bbSGtje8XoUAbxaQrTpr9pJeaUPYwg==", - "dev": true, - "dependencies": { - "@nrwl/web": "19.2.0", - "@nx/devkit": "19.2.0", - "@nx/js": "19.2.0", - "chalk": "^4.1.0", - "detect-port": "^1.5.1", - "http-server": "^14.1.0", - "tslib": "^2.3.0" + "node_modules/@nestjs/config/node_modules/dotenv": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" } }, - "node_modules/@nx/web/node_modules/@nrwl/devkit": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.2.0.tgz", - "integrity": "sha512-Ew5AJZkLXJwt15HjaIbHve8FOXmZ3HK8KPqTXqwKHX8jQW+fDUCaSXKe/lCZMNg0RvY+jMNecuC86uGdiIbLMg==", - "dev": true, - "dependencies": { - "@nx/devkit": "19.2.0" + "node_modules/@nestjs/config/node_modules/uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "bin": { + "uuid": "dist/bin/uuid" } }, - "node_modules/@nx/web/node_modules/@nx/devkit": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.2.0.tgz", - "integrity": "sha512-fK3zRUE2SLp9BUomFiyCuAX2E1yfWYE/hKimniscsvM34/u/xLZYVmmZ0/jfpGPbyaonXKZr2KTb7RimX/hyqg==", - "dev": true, + "node_modules/@nestjs/core": { + "version": "10.4.7", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.4.7.tgz", + "integrity": "sha512-AIpQzW/vGGqSLkKvll1R7uaSNv99AxZI2EFyVJPNGDgFsfXaohfV1Ukl6f+s75Km+6Fj/7aNl80EqzNWQCS8Ig==", + "hasInstallScript": true, "dependencies": { - "@nrwl/devkit": "19.2.0", - "ejs": "^3.1.7", - "enquirer": "~2.3.6", - "ignore": "^5.0.4", - "minimatch": "9.0.3", - "semver": "^7.5.3", - "tmp": "~0.2.1", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" + "@nuxtjs/opencollective": "0.3.2", + "fast-safe-stringify": "2.1.1", + "iterare": "1.2.1", + "path-to-regexp": "3.3.0", + "tslib": "2.7.0", + "uid": "2.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" }, "peerDependencies": { - "nx": ">= 17 <= 20" - } - }, - "node_modules/@nx/web/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, - "bin": { - "semver": "bin/semver.js" + "@nestjs/common": "^10.0.0", + "@nestjs/microservices": "^10.0.0", + "@nestjs/platform-express": "^10.0.0", + "@nestjs/websockets": "^10.0.0", + "reflect-metadata": "^0.1.12 || ^0.2.0", + "rxjs": "^7.1.0" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "@nestjs/microservices": { + "optional": true + }, + "@nestjs/platform-express": { + "optional": true + }, + "@nestjs/websockets": { + "optional": true + } } }, - "node_modules/@nx/webpack": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nx/webpack/-/webpack-19.6.3.tgz", - "integrity": "sha512-AUz4SPdD6LtIh+hB8AJX7GdzLHmlj5aU/yXp4UTKF5DZlha4NphN8YIP+NN56nCgEZMxM8txp7U0zytqhcFP1Q==", - "dev": true, - "dependencies": { - "@babel/core": "^7.23.2", - "@module-federation/enhanced": "^0.2.3", - "@module-federation/sdk": "^0.2.3", - "@nrwl/webpack": "19.6.3", - "@nx/devkit": "19.6.3", - "@nx/js": "19.6.3", - "@phenomnomnominal/tsquery": "~5.0.1", - "ajv": "^8.12.0", - "autoprefixer": "^10.4.9", - "babel-loader": "^9.1.2", - "browserslist": "^4.21.4", - "chalk": "^4.1.0", - "copy-webpack-plugin": "^10.2.4", - "css-loader": "^6.4.0", - "css-minimizer-webpack-plugin": "^5.0.0", - "express": "^4.19.2", - "fork-ts-checker-webpack-plugin": "7.2.13", - "http-proxy-middleware": "^3.0.0", - "less": "4.1.3", - "less-loader": "11.1.0", - "license-webpack-plugin": "^4.0.2", - "loader-utils": "^2.0.3", - "mini-css-extract-plugin": "~2.4.7", - "parse5": "4.0.0", - "postcss": "^8.4.38", - "postcss-import": "~14.1.0", - "postcss-loader": "^6.1.1", - "rxjs": "^7.8.0", - "sass": "^1.42.1", - "sass-loader": "^12.2.0", - "source-map-loader": "^5.0.0", - "style-loader": "^3.3.0", - "stylus": "^0.59.0", - "stylus-loader": "^7.1.0", - "terser-webpack-plugin": "^5.3.3", - "ts-loader": "^9.3.1", - "tsconfig-paths-webpack-plugin": "4.0.0", - "tslib": "^2.3.0", - "webpack": "^5.80.0", - "webpack-dev-server": "^5.0.4", - "webpack-node-externals": "^3.0.0", - "webpack-subresource-integrity": "^5.1.0" - } + "node_modules/@nestjs/core/node_modules/path-to-regexp": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.3.0.tgz", + "integrity": "sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==" }, - "node_modules/@nx/webpack/node_modules/@nrwl/devkit": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.6.3.tgz", - "integrity": "sha512-zrAboArNfrEMjimBl/0YeM08HfjqOEG/VHdCHKO+5QMDg65w7vDJ2flwyNhlmnMl8BMJSy9fNo6PNGhboOf3+w==", - "dev": true, + "node_modules/@nestjs/core/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + }, + "node_modules/@nestjs/event-emitter": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@nestjs/event-emitter/-/event-emitter-2.1.1.tgz", + "integrity": "sha512-6L6fBOZTyfFlL7Ih/JDdqlCzZeCW0RjCX28wnzGyg/ncv5F/EOeT1dfopQr1loBRQ3LTgu8OWM7n4zLN4xigsg==", + "license": "MIT", "dependencies": { - "@nx/devkit": "19.6.3" + "eventemitter2": "6.4.9" + }, + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", + "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0" } }, - "node_modules/@nx/webpack/node_modules/@nrwl/js": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nrwl/js/-/js-19.6.3.tgz", - "integrity": "sha512-Z5tYcUQNfgmNFMJpGmZd6fB0D1pCKNiS3aci2gxHAUIP0Z5cznTyCuzcJSIRx3uMHENhxXwzLwv2l/cqOqnD8A==", - "dev": true, - "dependencies": { - "@nx/js": "19.6.3" + "node_modules/@nestjs/mapped-types": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-2.0.5.tgz", + "integrity": "sha512-bSJv4pd6EY99NX9CjBIyn4TVDoSit82DUZlL4I3bqNfy5Gt+gXTa86i3I/i0iIV9P4hntcGM5GyO+FhZAhxtyg==", + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", + "class-transformer": "^0.4.0 || ^0.5.0", + "class-validator": "^0.13.0 || ^0.14.0", + "reflect-metadata": "^0.1.12 || ^0.2.0" + }, + "peerDependenciesMeta": { + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } } }, - "node_modules/@nx/webpack/node_modules/@nrwl/tao": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.6.3.tgz", - "integrity": "sha512-j4vPU87yBhTrdyPFSNhlUkN29w4BQ+M14khT8PFGe+Y26gHMxNRNXNFUCwtVARYAc6IwxS8Uvlwy7AwXG2ETPA==", - "dev": true, + "node_modules/@nestjs/platform-express": { + "version": "10.3.9", + "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.3.9.tgz", + "integrity": "sha512-si/UzobP6YUtYtCT1cSyQYHHzU3yseqYT6l7OHSMVvfG1+TqxaAqI6nmrix02LO+l1YntHRXEs3p+v9a7EfrSQ==", + "license": "MIT", "dependencies": { - "nx": "19.6.3", - "tslib": "^2.3.0" + "body-parser": "1.20.2", + "cors": "2.8.5", + "express": "4.19.2", + "multer": "1.4.4-lts.1", + "tslib": "2.6.2" }, - "bin": { - "tao": "index.js" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^10.0.0", + "@nestjs/core": "^10.0.0" } }, - "node_modules/@nx/webpack/node_modules/@nrwl/workspace": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-19.6.3.tgz", - "integrity": "sha512-NGJ6Mxpw8U6tZRT4ijGzqthr1NMgT/22uteu4otetLEdlqkh1VvLqJC9tjzLkYXmXF9QuoUrkwQib/HafsZmkg==", + "node_modules/@nestjs/platform-express/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "license": "0BSD" + }, + "node_modules/@nestjs/schematics": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-9.2.0.tgz", + "integrity": "sha512-wHpNJDPzM6XtZUOB3gW0J6mkFCSJilzCM3XrHI1o0C8vZmFE1snbmkIXNyoi1eV0Nxh1BMymcgz5vIMJgQtTqw==", "dev": true, "dependencies": { - "@nx/workspace": "19.6.3" + "@angular-devkit/core": "16.0.1", + "@angular-devkit/schematics": "16.0.1", + "jsonc-parser": "3.2.0", + "pluralize": "8.0.0" + }, + "peerDependencies": { + "typescript": ">=4.3.5" } }, - "node_modules/@nx/webpack/node_modules/@nx/devkit": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.6.3.tgz", - "integrity": "sha512-/d8Z5/Cy/H/1rIHxW3VjeK5dlvHwRxRj8rCm8/sj5Pz3GmGX03uuEK+J/p+VlP3gP8dAYMgZu3ImeqTAu6rBtw==", - "dev": true, + "node_modules/@nestjs/swagger": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-7.4.0.tgz", + "integrity": "sha512-dCiwKkRxcR7dZs5jtrGspBAe/nqJd1AYzOBTzw9iCdbq3BGrLpwokelk6lFZPe4twpTsPQqzNKBwKzVbI6AR/g==", "dependencies": { - "@nrwl/devkit": "19.6.3", - "ejs": "^3.1.7", - "enquirer": "~2.3.6", - "ignore": "^5.0.4", - "minimatch": "9.0.3", - "semver": "^7.5.3", - "tmp": "~0.2.1", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" + "@microsoft/tsdoc": "^0.15.0", + "@nestjs/mapped-types": "2.0.5", + "js-yaml": "4.1.0", + "lodash": "4.17.21", + "path-to-regexp": "3.2.0", + "swagger-ui-dist": "5.17.14" }, "peerDependencies": { - "nx": ">= 17 <= 20" + "@fastify/static": "^6.0.0 || ^7.0.0", + "@nestjs/common": "^9.0.0 || ^10.0.0", + "@nestjs/core": "^9.0.0 || ^10.0.0", + "class-transformer": "*", + "class-validator": "*", + "reflect-metadata": "^0.1.12 || ^0.2.0" + }, + "peerDependenciesMeta": { + "@fastify/static": { + "optional": true + }, + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } } }, - "node_modules/@nx/webpack/node_modules/@nx/js": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nx/js/-/js-19.6.3.tgz", - "integrity": "sha512-Ip7DseodvJSRM2sKhUjNMlNLegBtsB1u6TuQUiYOJa2FnIGzXETT2HuDMxBcL+u23xDTNyNvifNZ92mFywa00Q==", + "node_modules/@nestjs/testing": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.4.1.tgz", + "integrity": "sha512-pR+su5+YGqCLH0RhhVkPowQK7FCORU0/PWAywPK7LScAOtD67ZoviZ7hAU4vnGdwkg4HCB0D7W8Bkg19CGU8Xw==", "dev": true, "dependencies": { - "@babel/core": "^7.23.2", - "@babel/plugin-proposal-decorators": "^7.22.7", - "@babel/plugin-transform-class-properties": "^7.22.5", - "@babel/plugin-transform-runtime": "^7.23.2", - "@babel/preset-env": "^7.23.2", - "@babel/preset-typescript": "^7.22.5", - "@babel/runtime": "^7.22.6", - "@nrwl/js": "19.6.3", - "@nx/devkit": "19.6.3", - "@nx/workspace": "19.6.3", - "babel-plugin-const-enum": "^1.0.1", - "babel-plugin-macros": "^2.8.0", - "babel-plugin-transform-typescript-metadata": "^0.3.1", - "chalk": "^4.1.0", - "columnify": "^1.6.0", - "detect-port": "^1.5.1", - "fast-glob": "3.2.7", - "fs-extra": "^11.1.0", - "ignore": "^5.0.4", - "js-tokens": "^4.0.0", - "jsonc-parser": "3.2.0", - "minimatch": "9.0.3", - "npm-package-arg": "11.0.1", - "npm-run-path": "^4.0.1", - "ora": "5.3.0", - "semver": "^7.5.3", - "source-map-support": "0.5.19", - "ts-node": "10.9.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0" + "tslib": "2.6.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" }, "peerDependencies": { - "verdaccio": "^5.0.4" + "@nestjs/common": "^10.0.0", + "@nestjs/core": "^10.0.0", + "@nestjs/microservices": "^10.0.0", + "@nestjs/platform-express": "^10.0.0" }, "peerDependenciesMeta": { - "verdaccio": { + "@nestjs/microservices": { + "optional": true + }, + "@nestjs/platform-express": { "optional": true } } }, - "node_modules/@nx/webpack/node_modules/@nx/nx-darwin-arm64": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.6.3.tgz", - "integrity": "sha512-P7WlX5YDZOABAlyfpR6eObigQTNuUuy3iJVUuGwp1Nuo3VPMPkpK1GMWKWLwOR9+2jGnF5MzuqWHk7CdF33uqQ==", - "cpu": [ - "arm64" - ], + "node_modules/@next/env": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.4.tgz", + "integrity": "sha512-3EtkY5VDkuV2+lNmKlbkibIJxcO4oIHEhBWne6PaAp+76J9KoSsGvNikp6ivzAT8dhhBMYrm6op2pS1ApG0Hzg==" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "14.2.6", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.6.tgz", + "integrity": "sha512-d3+p4AjIYmhqzYHhhmkRYYN6ZU35TwZAKX08xKRfnHkz72KhWL2kxMFsDptpZs5e8bBGdepn7vn1+9DaF8iX+A==", "dev": true, - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "glob": "10.3.10" + } + }, + "node_modules/@next/eslint-plugin-next/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, "engines": { - "node": ">= 10" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@nx/webpack/node_modules/@nx/nx-darwin-x64": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.6.3.tgz", - "integrity": "sha512-HF28dPc7h0EmEGYJWJUPA3cBvjXyHbSbGQP5oP885gos9zcyVBjQ2kdJEUZDNMHB9KlZraeXbmV1umFkikjn6A==", + "node_modules/@next/swc-darwin-arm64": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.4.tgz", + "integrity": "sha512-AH3mO4JlFUqsYcwFUHb1wAKlebHU/Hv2u2kb1pAuRanDZ7pD/A/KPD98RHZmwsJpdHQwfEc/06mgpSzwrJYnNg==", "cpu": [ - "x64" + "arm64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -19270,30 +7226,28 @@ "node": ">= 10" } }, - "node_modules/@nx/webpack/node_modules/@nx/nx-freebsd-x64": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.6.3.tgz", - "integrity": "sha512-y52dWxQ/x2ccyPqA4Vou4CnTqZX4gr/wV9myJX56G1CyEpWasmcqmPFeOKQd6dj7llGM/KJ/4Gz29RYxcWffcA==", + "node_modules/@next/swc-darwin-x64": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.4.tgz", + "integrity": "sha512-QVadW73sWIO6E2VroyUjuAxhWLZWEpiFqHdZdoQ/AMpN9YWGuHV8t2rChr0ahy+irKX5mlDU7OY68k3n4tAZTg==", "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ - "freebsd" + "darwin" ], "engines": { "node": ">= 10" } }, - "node_modules/@nx/webpack/node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.6.3.tgz", - "integrity": "sha512-RneCg1tglLbP4cmGnGUs4FgZVT0aOA9wA53tO4IbyxLnlRXNY9OE452YLgqv3H7sLtNjsey2Lkq1seBHtr3p/Q==", + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.4.tgz", + "integrity": "sha512-KT6GUrb3oyCfcfJ+WliXuJnD6pCpZiosx2X3k66HLR+DMoilRb76LpWPGb4tZprawTtcnyrv75ElD6VncVamUQ==", "cpu": [ - "arm" + "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -19302,14 +7256,13 @@ "node": ">= 10" } }, - "node_modules/@nx/webpack/node_modules/@nx/nx-linux-arm64-gnu": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.6.3.tgz", - "integrity": "sha512-Y+vgqaxrPQUEtCzxK25QY4ahO90l0eWgVrvCALexGmq0lW41JrVpfTTsbH/BAPLsx+u8A/GPAQAgrmg7d5lSxw==", + "node_modules/@next/swc-linux-arm64-musl": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.4.tgz", + "integrity": "sha512-Alv8/XGSs/ytwQcbCHwze1HmiIkIVhDHYLjczSVrf0Wi2MvKn/blt7+S6FJitj3yTlMwMxII1gIJ9WepI4aZ/A==", "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -19318,14 +7271,13 @@ "node": ">= 10" } }, - "node_modules/@nx/webpack/node_modules/@nx/nx-linux-arm64-musl": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.6.3.tgz", - "integrity": "sha512-o/99DBgafbjiJ4e9KFxaldvtlZta/FdzEiQQW+SQQ0JGSYlLCZZ8tIT6t3edV7cmG+gQLNMwolJzgpY53O9wjA==", + "node_modules/@next/swc-linux-x64-gnu": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.4.tgz", + "integrity": "sha512-ze0ShQDBPCqxLImzw4sCdfnB3lRmN3qGMB2GWDRlq5Wqy4G36pxtNOo2usu/Nm9+V2Rh/QQnrRc2l94kYFXO6Q==", "cpu": [ - "arm64" + "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -19334,14 +7286,13 @@ "node": ">= 10" } }, - "node_modules/@nx/webpack/node_modules/@nx/nx-linux-x64-gnu": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.6.3.tgz", - "integrity": "sha512-ppp0NBOhwJ39U1vR7h8jhFSfiur6CZPSUYjXsV44BlaNGc1wHZ+7FDXhzOTokgTNWHavYgYOJuVan5LtTLKJkA==", + "node_modules/@next/swc-linux-x64-musl": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.4.tgz", + "integrity": "sha512-8dwC0UJoc6fC7PX70csdaznVMNr16hQrTDAMPvLPloazlcaWfdPogq+UpZX6Drqb1OBlwowz8iG7WR0Tzk/diQ==", "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -19350,30 +7301,28 @@ "node": ">= 10" } }, - "node_modules/@nx/webpack/node_modules/@nx/nx-linux-x64-musl": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.6.3.tgz", - "integrity": "sha512-H7xgsT5OTtVYCXjXBLZu28v+rIInhbUggrgVJ2iQJFGBT2A2qmvGmDJdcDz8+K90ku1f4VuWmm8i+TEyDEcBuQ==", + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.4.tgz", + "integrity": "sha512-jxyg67NbEWkDyvM+O8UDbPAyYRZqGLQDTPwvrBBeOSyVWW/jFQkQKQ70JDqDSYg1ZDdl+E3nkbFbq8xM8E9x8A==", "cpu": [ - "x64" + "arm64" ], - "dev": true, "optional": true, "os": [ - "linux" + "win32" ], "engines": { "node": ">= 10" } }, - "node_modules/@nx/webpack/node_modules/@nx/nx-win32-arm64-msvc": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.6.3.tgz", - "integrity": "sha512-o9O6lSmx67zUnqOtlDC4YpC++fiUkixgIsQEG8J/2jdNgAATqOtERcqCNra/uke/Q94Vht2tVXjXF3uj92APhw==", + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.4.tgz", + "integrity": "sha512-twrmN753hjXRdcrZmZttb/m5xaCBFa48Dt3FbeEItpJArxriYDunWxJn+QFXdJ3hPkm4u7CKxncVvnmgQMY1ag==", "cpu": [ - "arm64" + "ia32" ], - "dev": true, "optional": true, "os": [ "win32" @@ -19382,14 +7331,13 @@ "node": ">= 10" } }, - "node_modules/@nx/webpack/node_modules/@nx/nx-win32-x64-msvc": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.6.3.tgz", - "integrity": "sha512-6NQhc7jYQ/sqPt5fDy8C+br73kTd5jhb8ZkPtEy2Amr1aA1K9SAxZAYfyvxLHS2z1nBEelNFgXe6HBmDX92FkA==", + "node_modules/@next/swc-win32-x64-msvc": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.4.tgz", + "integrity": "sha512-tkLrjBzqFTP8DVrAAQmZelEahfR9OxWpFR++vAI9FBhCiIxtwHwBHC23SBHCTURBtwB4kc/x44imVOnkKGNVGg==", "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -19398,709 +7346,418 @@ "node": ">= 10" } }, - "node_modules/@nx/webpack/node_modules/@nx/workspace": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-19.6.3.tgz", - "integrity": "sha512-DTvVJZuXHQd+F4M9JkTHGjLQADQZfUTs/h+v9/NC+YQHml8eixaNXSSvoHQcvBqO8HntbJz5LAJfQuiJ4IGBKw==", - "dev": true, - "dependencies": { - "@nrwl/workspace": "19.6.3", - "@nx/devkit": "19.6.3", - "chalk": "^4.1.0", - "enquirer": "~2.3.6", - "nx": "19.6.3", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" - } - }, - "node_modules/@nx/webpack/node_modules/@types/retry": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", - "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", - "dev": true - }, - "node_modules/@nx/webpack/node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "node_modules/@nx/webpack/node_modules/array-union": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz", - "integrity": "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@nx/webpack/node_modules/copy-webpack-plugin": { - "version": "10.2.4", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz", - "integrity": "sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg==", - "dev": true, - "dependencies": { - "fast-glob": "^3.2.7", - "glob-parent": "^6.0.1", - "globby": "^12.0.2", - "normalize-path": "^3.0.0", - "schema-utils": "^4.0.0", - "serialize-javascript": "^6.0.0" - }, + "node_modules/@noble/ciphers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.0.0.tgz", + "integrity": "sha512-wH5EHOmLi0rEazphPbecAzmjd12I6/Yv/SiHdkA9LSycsQk7RuuTp7am5/o62qYr0RScE7Pc9icXGBbsr6cesA==", "engines": { - "node": ">= 12.20.0" + "node": "^14.21.3 || >=16" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@nx/webpack/node_modules/cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", - "dev": true, + "node_modules/@noble/curves": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.6.0.tgz", + "integrity": "sha512-TlaHRXDehJuRNR9TfZDNQ45mMEd5dwUwmicsafcIX4SsNiqnCHKjE/1alYPd/lDRVhxdhUAlv8uEhMCI5zjIJQ==", "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" + "@noble/hashes": "1.5.0" }, "engines": { - "node": ">=10" - } - }, - "node_modules/@nx/webpack/node_modules/define-lazy-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "dev": true, - "engines": { - "node": ">=12" + "node": "^14.21.3 || >=16" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@nx/webpack/node_modules/dotenv-expand": { - "version": "11.0.6", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.6.tgz", - "integrity": "sha512-8NHi73otpWsZGBSZwwknTXS5pqMOrk9+Ssrna8xCaxkzEpU9OTf9R5ArQGVw03//Zmk9MOwLPng9WwndvpAJ5g==", - "dev": true, - "dependencies": { - "dotenv": "^16.4.4" - }, + "node_modules/@noble/curves/node_modules/@noble/hashes": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.5.0.tgz", + "integrity": "sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==", "engines": { - "node": ">=12" + "node": "^14.21.3 || >=16" }, "funding": { - "url": "https://dotenvx.com" + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@nx/webpack/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "node_modules/@noble/ed25519": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/ed25519/-/ed25519-1.7.1.tgz", + "integrity": "sha512-Rk4SkJFaXZiznFyC/t77Q0NKS4FL7TLJJsVG2V2oiEq3kJVeTdxysEe/yRWSpnWMe808XRDJ+VFh5pt/FN5plw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ] }, - "node_modules/@nx/webpack/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" + "node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "engines": { + "node": ">= 16" }, "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@nx/webpack/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@nx/webpack/node_modules/glob/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dependencies": { - "brace-expansion": "^2.0.1" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">= 8" } }, - "node_modules/@nx/webpack/node_modules/globby": { - "version": "12.2.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-12.2.0.tgz", - "integrity": "sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA==", - "dev": true, - "dependencies": { - "array-union": "^3.0.1", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.7", - "ignore": "^5.1.9", - "merge2": "^1.4.1", - "slash": "^4.0.0" - }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 8" } }, - "node_modules/@nx/webpack/node_modules/http-proxy-middleware": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-3.0.0.tgz", - "integrity": "sha512-36AV1fIaI2cWRzHo+rbcxhe3M3jUDCNzc4D5zRl57sEWRAxdXYtw7FSQKYY6PDKssiAKjLYypbssHk+xs/kMXw==", - "dev": true, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dependencies": { - "@types/http-proxy": "^1.17.10", - "debug": "^4.3.4", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.5" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@nx/webpack/node_modules/ipaddr.js": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", - "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/webpack/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@nx/webpack/node_modules/is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 8" } }, - "node_modules/@nx/webpack/node_modules/is-wsl": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", - "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "node_modules/@nrwl/devkit": { + "version": "19.5.1", + "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.5.1.tgz", + "integrity": "sha512-ZsckDZszLTv3oshNsY5fZ86g8a/VcGvgDpdiP/z/A/krtOHL8iUjdT/72Eo5DIult5WcSFjnifyWcyWIGe1PeA==", "dev": true, "dependencies": { - "is-inside-container": "^1.0.0" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "@nx/devkit": "19.5.1" } }, - "node_modules/@nx/webpack/node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "node_modules/@nrwl/eslint-plugin-nx": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nrwl/eslint-plugin-nx/-/eslint-plugin-nx-19.3.2.tgz", + "integrity": "sha512-OD9WYOpTCgMQWTwUKRUuXlVfegkbkqNqkVQ3hsftjTn1dkB8QbvMa9ajqDGU+pbQDLeMMwtjc4itVpUimvmudQ==", "dev": true, "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" + "@nx/eslint-plugin": "19.3.2" } }, - "node_modules/@nx/webpack/node_modules/memfs": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.11.1.tgz", - "integrity": "sha512-LZcMTBAgqUUKNXZagcZxvXXfgF1bHX7Y7nQ0QyEiNbRJgE29GhgPd8Yna1VQcLlPiHt/5RFJMWYN9Uv/VPNvjQ==", + "node_modules/@nrwl/jest": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/jest/-/jest-19.2.0.tgz", + "integrity": "sha512-s3qb0AblY+wqPUJFraWP9MYVyv3EA8bbEsMRCuvDDbhoe2nnyd/7PmluyPsWgJVdgbY9Ajgs3ZjuBEfFQ3VV9A==", "dev": true, "dependencies": { - "@jsonjoy.com/json-pack": "^1.0.3", - "@jsonjoy.com/util": "^1.3.0", - "tree-dump": "^1.0.1", - "tslib": "^2.0.0" - }, - "engines": { - "node": ">= 4.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" + "@nx/jest": "19.2.0" } }, - "node_modules/@nx/webpack/node_modules/mini-css-extract-plugin": { - "version": "2.4.7", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.4.7.tgz", - "integrity": "sha512-euWmddf0sk9Nv1O0gfeeUAvAkoSlWncNLF77C0TP2+WoPvy8mAHKOzMajcCz2dzvyt3CNgxb1obIEVFIRxaipg==", + "node_modules/@nrwl/jest/node_modules/@nrwl/devkit": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.2.0.tgz", + "integrity": "sha512-Ew5AJZkLXJwt15HjaIbHve8FOXmZ3HK8KPqTXqwKHX8jQW+fDUCaSXKe/lCZMNg0RvY+jMNecuC86uGdiIbLMg==", "dev": true, "dependencies": { - "schema-utils": "^4.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" + "@nx/devkit": "19.2.0" } }, - "node_modules/@nx/webpack/node_modules/nx": { - "version": "19.6.3", - "resolved": "https://registry.npmjs.org/nx/-/nx-19.6.3.tgz", - "integrity": "sha512-JbgrEKaIBvTfhw3mG3GeyyzJHBAMfuQkMNrxxIto1fn94gxdjXdMfqUnAzrW6xRAt5OEEU+rf7v2OA3vEXYc3A==", + "node_modules/@nrwl/jest/node_modules/@nx/devkit": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.2.0.tgz", + "integrity": "sha512-fK3zRUE2SLp9BUomFiyCuAX2E1yfWYE/hKimniscsvM34/u/xLZYVmmZ0/jfpGPbyaonXKZr2KTb7RimX/hyqg==", "dev": true, - "hasInstallScript": true, "dependencies": { - "@napi-rs/wasm-runtime": "0.2.4", - "@nrwl/tao": "19.6.3", - "@yarnpkg/lockfile": "^1.1.0", - "@yarnpkg/parsers": "3.0.0-rc.46", - "@zkochan/js-yaml": "0.0.7", - "axios": "^1.7.4", - "chalk": "^4.1.0", - "cli-cursor": "3.1.0", - "cli-spinners": "2.6.1", - "cliui": "^8.0.1", - "dotenv": "~16.4.5", - "dotenv-expand": "~11.0.6", + "@nrwl/devkit": "19.2.0", + "ejs": "^3.1.7", "enquirer": "~2.3.6", - "figures": "3.2.0", - "flat": "^5.0.2", - "front-matter": "^4.0.2", - "fs-extra": "^11.1.0", "ignore": "^5.0.4", - "jest-diff": "^29.4.1", - "jsonc-parser": "3.2.0", - "lines-and-columns": "~2.0.3", "minimatch": "9.0.3", - "node-machine-id": "1.1.12", - "npm-run-path": "^4.0.1", - "open": "^8.4.0", - "ora": "5.3.0", "semver": "^7.5.3", - "string-width": "^4.2.3", - "strong-log-transformer": "^2.1.0", - "tar-stream": "~2.2.0", "tmp": "~0.2.1", - "tsconfig-paths": "^4.1.2", "tslib": "^2.3.0", - "yargs": "^17.6.2", "yargs-parser": "21.1.1" }, - "bin": { - "nx": "bin/nx.js", - "nx-cloud": "bin/nx-cloud.js" - }, - "optionalDependencies": { - "@nx/nx-darwin-arm64": "19.6.3", - "@nx/nx-darwin-x64": "19.6.3", - "@nx/nx-freebsd-x64": "19.6.3", - "@nx/nx-linux-arm-gnueabihf": "19.6.3", - "@nx/nx-linux-arm64-gnu": "19.6.3", - "@nx/nx-linux-arm64-musl": "19.6.3", - "@nx/nx-linux-x64-gnu": "19.6.3", - "@nx/nx-linux-x64-musl": "19.6.3", - "@nx/nx-win32-arm64-msvc": "19.6.3", - "@nx/nx-win32-x64-msvc": "19.6.3" - }, "peerDependencies": { - "@swc-node/register": "^1.8.0", - "@swc/core": "^1.3.85" - }, - "peerDependenciesMeta": { - "@swc-node/register": { - "optional": true - }, - "@swc/core": { - "optional": true - } + "nx": ">= 17 <= 20" } }, - "node_modules/@nx/webpack/node_modules/p-retry": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.0.tgz", - "integrity": "sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==", + "node_modules/@nrwl/jest/node_modules/@nx/jest": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/jest/-/jest-19.2.0.tgz", + "integrity": "sha512-iJMqfwkIB4T7NRYAQe3nZWFEAQGGblMGcxWczMKEixCIZWcAz4up74eb0H6Yv+tUVOQHrFTm6J1OnrW3BqvOZA==", "dev": true, "dependencies": { - "@types/retry": "0.12.2", - "is-network-error": "^1.0.0", - "retry": "^0.13.1" + "@jest/reporters": "^29.4.1", + "@jest/test-result": "^29.4.1", + "@nrwl/jest": "19.2.0", + "@nx/devkit": "19.2.0", + "@nx/js": "19.2.0", + "@phenomnomnominal/tsquery": "~5.0.1", + "chalk": "^4.1.0", + "identity-obj-proxy": "3.0.0", + "jest-config": "^29.4.1", + "jest-resolve": "^29.4.1", + "jest-util": "^29.4.1", + "minimatch": "9.0.3", + "resolve.exports": "1.1.0", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" + } + }, + "node_modules/@nrwl/jest/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=10" } }, - "node_modules/@nx/webpack/node_modules/postcss-loader": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", - "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", + "node_modules/@nrwl/js": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/js/-/js-19.2.0.tgz", + "integrity": "sha512-i6CyQvTP1etmTxjFhUIw/HAtoZCENbhkc7UmAsyCgTX5IJeo0U3YoHsmDI0TE45yu+4x4gcKLqOHs2zqWj7WCw==", "dev": true, "dependencies": { - "cosmiconfig": "^7.0.0", - "klona": "^2.0.5", - "semver": "^7.3.5" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "postcss": "^7.0.0 || ^8.0.1", - "webpack": "^5.0.0" + "@nx/js": "19.2.0" } }, - "node_modules/@nx/webpack/node_modules/rimraf": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", - "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "node_modules/@nrwl/nest": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/nest/-/nest-19.2.0.tgz", + "integrity": "sha512-JjhGurz1neZHyrRtmstBHpIAfh/TE3h/untSMqiixrRg8k+qPZBi2dpcV6HZxWVoDkgKrL6ro7olmiXvWMQdqw==", "dev": true, "dependencies": { - "glob": "^10.3.7" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "@nx/nest": "19.2.0" } }, - "node_modules/@nx/webpack/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "node_modules/@nrwl/next": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/next/-/next-19.2.0.tgz", + "integrity": "sha512-+DFtnuB33w/x5A5c1EuSjnKE0i2YKJT5tltZ1bX7fyDcqukwESmTL+CNpYNlp5VuejDzV/3wp1pNdeqt+85/YA==", "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "dependencies": { + "@nx/next": "19.2.0" } }, - "node_modules/@nx/webpack/node_modules/slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "node_modules/@nrwl/node": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/node/-/node-19.2.0.tgz", + "integrity": "sha512-fy4GPMGRT7/t3sUljOot2h9CVq0QWOv/nPxyK7YVk2jkwkjo9gTovVoZrjacv8DOOL4DE1tRr7yHfEQY6fnDig==", "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "@nx/node": "19.2.0" } }, - "node_modules/@nx/webpack/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/@nrwl/react": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/react/-/react-19.2.0.tgz", + "integrity": "sha512-Zz4lJK1S511s8F1OmbH0HiMz9xX/OCL8UQ5FJ9uViMNnkaLPx0NUGzrAbliDUq2XGYDBZ8ZtGFgC1DTlL9iK+w==", "dev": true, "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" + "@nx/react": "19.2.0" } }, - "node_modules/@nx/webpack/node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "node_modules/@nrwl/tao": { + "version": "19.4.4", + "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.4.4.tgz", + "integrity": "sha512-iwswcp7fW5GiIeAFvA/Ssr9fe2ZZHcuOS20bQx+mLEnEgBaARkgWqNdYMZ594NRqXQ1CrOEy5jncahS6K+pRbw==", "dev": true, "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" + "nx": "19.4.4", + "tslib": "^2.3.0" }, "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } + "tao": "index.js" } }, - "node_modules/@nx/webpack/node_modules/webpack-dev-middleware": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.4.2.tgz", - "integrity": "sha512-xOO8n6eggxnwYpy1NlzUKpvrjfJTvae5/D6WOK0S2LSo7vjmo5gCM1DbLUmFqrMTJP+W/0YZNctm7jasWvLuBA==", + "node_modules/@nrwl/web": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/web/-/web-19.2.0.tgz", + "integrity": "sha512-s6fEyic1cCwZAoKxZ64RMdCfG2jQGZC/FTyO4J7a8iB8oRD8mRLw0lWamXIcW10O0KPrE0zO63+kpjfKJ/ZK+w==", "dev": true, "dependencies": { - "colorette": "^2.0.10", - "memfs": "^4.6.0", - "mime-types": "^2.1.31", - "on-finished": "^2.4.1", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - }, - "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - } + "@nx/web": "19.2.0" } }, - "node_modules/@nx/webpack/node_modules/webpack-dev-server": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.0.4.tgz", - "integrity": "sha512-dljXhUgx3HqKP2d8J/fUMvhxGhzjeNVarDLcbO/EWMSgRizDkxHQDZQaLFL5VJY9tRBj2Gz+rvCEYYvhbqPHNA==", + "node_modules/@nrwl/webpack": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nrwl/webpack/-/webpack-19.6.3.tgz", + "integrity": "sha512-e1Y493FBdNPO3TrXNAJSzbeGWAZiLUsDUfQDXjlAboQRL5n3bn1W/zc98DGMxobJWAzw2vWW7UEm2ZyYyeU/lA==", "dev": true, "dependencies": { - "@types/bonjour": "^3.5.13", - "@types/connect-history-api-fallback": "^1.5.4", - "@types/express": "^4.17.21", - "@types/serve-index": "^1.9.4", - "@types/serve-static": "^1.15.5", - "@types/sockjs": "^0.3.36", - "@types/ws": "^8.5.10", - "ansi-html-community": "^0.0.8", - "bonjour-service": "^1.2.1", - "chokidar": "^3.6.0", - "colorette": "^2.0.10", - "compression": "^1.7.4", - "connect-history-api-fallback": "^2.0.0", - "default-gateway": "^6.0.3", - "express": "^4.17.3", - "graceful-fs": "^4.2.6", - "html-entities": "^2.4.0", - "http-proxy-middleware": "^2.0.3", - "ipaddr.js": "^2.1.0", - "launch-editor": "^2.6.1", - "open": "^10.0.3", - "p-retry": "^6.2.0", - "rimraf": "^5.0.5", - "schema-utils": "^4.2.0", - "selfsigned": "^2.4.1", - "serve-index": "^1.9.1", - "sockjs": "^0.3.24", - "spdy": "^4.0.2", - "webpack-dev-middleware": "^7.1.0", - "ws": "^8.16.0" + "@nx/webpack": "19.6.3" + } + }, + "node_modules/@nrwl/workspace": { + "version": "19.7.3", + "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-19.7.3.tgz", + "integrity": "sha512-2ffUbLzBYGQte6zQ6dDLefgU9X812Uh7v61yTV7z4zfYbUtjwInkWqlkTvRuK08DRhD5vWo9xyUDp7acAdZaxw==", + "dev": true, + "dependencies": { + "@nx/workspace": "19.7.3" + } + }, + "node_modules/@nuxtjs/opencollective": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz", + "integrity": "sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==", + "dependencies": { + "chalk": "^4.1.0", + "consola": "^2.15.0", + "node-fetch": "^2.6.1" }, "bin": { - "webpack-dev-server": "bin/webpack-dev-server.js" + "opencollective": "bin/opencollective.js" }, "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - }, - "webpack-cli": { - "optional": true - } + "node": ">=8.0.0", + "npm": ">=5.0.0" } }, - "node_modules/@nx/webpack/node_modules/webpack-dev-server/node_modules/http-proxy-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", - "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "node_modules/@nx/devkit": { + "version": "19.5.1", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.5.1.tgz", + "integrity": "sha512-Vj8wwzNIR5VIWmuLHhOi4aUVq7eVV5YTbctnEewKT+V/O4LZj+hClGyVNyT8s6b8JIjNWoIO4HXStLnH8rDOlw==", "dev": true, "dependencies": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" - }, - "engines": { - "node": ">=12.0.0" + "@nrwl/devkit": "19.5.1", + "ejs": "^3.1.7", + "enquirer": "~2.3.6", + "ignore": "^5.0.4", + "minimatch": "9.0.3", + "semver": "^7.5.3", + "tmp": "~0.2.1", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" }, "peerDependencies": { - "@types/express": "^4.17.13" - }, - "peerDependenciesMeta": { - "@types/express": { - "optional": true - } + "nx": ">= 17 <= 20" } }, - "node_modules/@nx/webpack/node_modules/webpack-dev-server/node_modules/open": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz", - "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==", + "node_modules/@nx/devkit/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", "dev": true, - "dependencies": { - "default-browser": "^5.2.1", - "define-lazy-prop": "^3.0.0", - "is-inside-container": "^1.0.0", - "is-wsl": "^3.1.0" + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=10" } }, - "node_modules/@nx/webpack/node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "node_modules/@nx/eslint": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/eslint/-/eslint-19.3.2.tgz", + "integrity": "sha512-ICUX8ADAIj9xA7Yc6hY9pfeC55ZxRjiAaqslsK3h4pCrFADVFDluShhrxSpUkp4doBzGUR7s1K7GIbeRrwD4qA==", "dev": true, - "license": "ISC", - "engines": { - "node": ">= 6" + "dependencies": { + "@nx/devkit": "19.3.2", + "@nx/js": "19.3.2", + "@nx/linter": "19.3.2", + "semver": "^7.5.3", + "tslib": "^2.3.0", + "typescript": "~5.4.2" + }, + "peerDependencies": { + "@zkochan/js-yaml": "0.0.7", + "eslint": "^8.0.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "@zkochan/js-yaml": { + "optional": true + } } }, - "node_modules/@nx/webpack/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "node_modules/@nx/eslint-plugin": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/eslint-plugin/-/eslint-plugin-19.3.2.tgz", + "integrity": "sha512-ZhnFrnAKILA29EwiHQhUQnLfXleUH/YrDS3FUYBpwKnICAPXARsgb7Qi+3Uick0q4HlkL6xGRkkQSfA5cZ9Qtw==", "dev": true, "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" + "@nrwl/eslint-plugin-nx": "19.3.2", + "@nx/devkit": "19.3.2", + "@nx/js": "19.3.2", + "@typescript-eslint/type-utils": "^7.3.0", + "@typescript-eslint/utils": "^7.3.0", + "chalk": "^4.1.0", + "confusing-browser-globals": "^1.0.9", + "jsonc-eslint-parser": "^2.1.0", + "semver": "^7.5.3", + "tslib": "^2.3.0" }, - "engines": { - "node": ">=12" + "peerDependencies": { + "@typescript-eslint/parser": "^6.13.2 || ^7.0.0", + "eslint-config-prettier": "^9.0.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } } }, - "node_modules/@nx/workspace": { - "version": "19.7.3", - "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-19.7.3.tgz", - "integrity": "sha512-FUHeOLCXdHEB1b6FiNU9swCZIKXbsGWRDfgHpHGeiZHp7uhH41W/EKTVukRxnQ+HXhE7zfxhn8KkllfaXIifPg==", + "node_modules/@nx/eslint-plugin/node_modules/@nrwl/devkit": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.3.2.tgz", + "integrity": "sha512-n3tFalVPUk1HAJ2VYNnF34yzB9j2+6swFUi4Y92PxD1vN7vrIXnNeaTx2qcee7JDjBpiJ7Zn0KLg2jwiH6hNwA==", "dev": true, "dependencies": { - "@nrwl/workspace": "19.7.3", - "@nx/devkit": "19.7.3", - "chalk": "^4.1.0", - "enquirer": "~2.3.6", - "nx": "19.7.3", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" + "@nx/devkit": "19.3.2" } }, - "node_modules/@nx/workspace/node_modules/@nrwl/devkit": { - "version": "19.7.3", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.7.3.tgz", - "integrity": "sha512-g9vANTuxgHan6uAkI6M6tkfLjHECLmbZ4A80UqpxJNQJsCJFEHkzIC9oxhf8bWV3PjgCH6Xm4VyQ2GHwb3sgWw==", + "node_modules/@nx/eslint-plugin/node_modules/@nrwl/js": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nrwl/js/-/js-19.3.2.tgz", + "integrity": "sha512-ZgCoLsASIlp1xtYpWW/1ZxvKSb6BY3ZNXBmjoUW4LyN7Pk6su55gPAVt6JWIxSMm+HC+v+Cb4XFKZLdtuvE7bg==", "dev": true, "dependencies": { - "@nx/devkit": "19.7.3" + "@nx/js": "19.3.2" } }, - "node_modules/@nx/workspace/node_modules/@nrwl/tao": { - "version": "19.7.3", - "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.7.3.tgz", - "integrity": "sha512-cIGhnSFPZdVTp4bI0fqwFoE9i7ToPg5jXz+hNMl/MTwcOQfKQ1JJY/ZPLM3aBUPORFIZ/GECQEycUb6+xCB56g==", + "node_modules/@nx/eslint-plugin/node_modules/@nrwl/tao": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.3.2.tgz", + "integrity": "sha512-I1gW7woqwU6rdlgwj6XXAKcreJ5ptRKI2WpLdZErkrPmaRG/jMZx/yjZrG4PWdIEuZ4ZmYnRsoXbKN6ilCknQw==", "dev": true, "dependencies": { - "nx": "19.7.3", + "nx": "19.3.2", "tslib": "^2.3.0" }, "bin": { "tao": "index.js" } }, - "node_modules/@nx/workspace/node_modules/@nx/devkit": { - "version": "19.7.3", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.7.3.tgz", - "integrity": "sha512-dIavuzfcMLCTa5uhd4R7HsxcFO0w9fHwG4wDg76wyBAbPGJlrR+9zg359hZ/SkXdguO6bMVmmQg/EXIvo6g69A==", + "node_modules/@nx/eslint-plugin/node_modules/@nrwl/workspace": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-19.3.2.tgz", + "integrity": "sha512-6gV4qa38t3GyRKmO2PLcamDcFRD7I3wl6/R0/E1eC8Wm6K2oBzjOIV5ALpz4iC4LOln88IL+AjuQdG6kdtfXlA==", "dev": true, "dependencies": { - "@nrwl/devkit": "19.7.3", + "@nx/workspace": "19.3.2" + } + }, + "node_modules/@nx/eslint-plugin/node_modules/@nx/devkit": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.3.2.tgz", + "integrity": "sha512-uD3jaJ1Jvf7B6jqH2t2GH0L6REwcCGBLXq1qs1HRQF5SZrEtuUeusn8wvCKP7dftPK3byLHAG0xHRW4+IUAz/g==", + "dev": true, + "dependencies": { + "@nrwl/devkit": "19.3.2", "ejs": "^3.1.7", "enquirer": "~2.3.6", "ignore": "^5.0.4", @@ -20114,10 +7771,55 @@ "nx": ">= 17 <= 20" } }, - "node_modules/@nx/workspace/node_modules/@nx/nx-darwin-arm64": { - "version": "19.7.3", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.7.3.tgz", - "integrity": "sha512-0dDK0UkMR0vBv4AP/48Q9A+OC2dvpivdt8su/4W/CPADy69M9B5O3jPiK+jTRsLshQG/soC9JG0Rll1BNWymPg==", + "node_modules/@nx/eslint-plugin/node_modules/@nx/js": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/js/-/js-19.3.2.tgz", + "integrity": "sha512-WXULhOHYDIAvs+SyDiRaNrpn1DmBAl3u7F5Jpu2VIyrcXgllrYGqUAykUqSu6Oyc2J+asfEtiG67I7UucTHLhA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.23.2", + "@babel/plugin-proposal-decorators": "^7.22.7", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-runtime": "^7.23.2", + "@babel/preset-env": "^7.23.2", + "@babel/preset-typescript": "^7.22.5", + "@babel/runtime": "^7.22.6", + "@nrwl/js": "19.3.2", + "@nx/devkit": "19.3.2", + "@nx/workspace": "19.3.2", + "babel-plugin-const-enum": "^1.0.1", + "babel-plugin-macros": "^2.8.0", + "babel-plugin-transform-typescript-metadata": "^0.3.1", + "chalk": "^4.1.0", + "columnify": "^1.6.0", + "detect-port": "^1.5.1", + "fast-glob": "3.2.7", + "fs-extra": "^11.1.0", + "ignore": "^5.0.4", + "js-tokens": "^4.0.0", + "minimatch": "9.0.3", + "npm-package-arg": "11.0.1", + "npm-run-path": "^4.0.1", + "ora": "5.3.0", + "semver": "^7.5.3", + "source-map-support": "0.5.19", + "ts-node": "10.9.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "verdaccio": "^5.0.4" + }, + "peerDependenciesMeta": { + "verdaccio": { + "optional": true + } + } + }, + "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-darwin-arm64": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.3.2.tgz", + "integrity": "sha512-MTqPTR1FwfVfIkHKUw95dFlPBN6mbqfJ+KzLHvUSPcqLKelhi82tsisjMoB5sNK0YWcNNVqYW72ojCnHVB0TUg==", "cpu": [ "arm64" ], @@ -20130,10 +7832,10 @@ "node": ">= 10" } }, - "node_modules/@nx/workspace/node_modules/@nx/nx-darwin-x64": { - "version": "19.7.3", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.7.3.tgz", - "integrity": "sha512-hTdv5YY2GQTdT7GwVO7ST27ZzvCmAQvmkEapfnCdy74QsL4gapaXJFvtWLHVfG6qHNRHWXbpdegvR3VswRHZVQ==", + "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-darwin-x64": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.3.2.tgz", + "integrity": "sha512-C8s9X5AlVgl3V5PycLdX+75lpAWq0qQs6QUEAnyxrLM9l+/HRecgoW6uZ7tX6Fnd8WGfMIwyahBw4LyZgk6zTw==", "cpu": [ "x64" ], @@ -20146,10 +7848,10 @@ "node": ">= 10" } }, - "node_modules/@nx/workspace/node_modules/@nx/nx-freebsd-x64": { - "version": "19.7.3", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.7.3.tgz", - "integrity": "sha512-dwuB/3eoV2RbD0b0LHnagQOXa9PKAjLi7g5vNxzw6LuNT1tdaLaUZZGv2tfG0hHjsV0cOaAX41rEyOIwJyE7zg==", + "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-freebsd-x64": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.3.2.tgz", + "integrity": "sha512-XeEpEU0iqJ/5cAPMmjqJ0Sdz89ZtDRj4NdksioyhAHri94X5/3lm3lDs4tB3nObT7p3QL7r/HP1itq5DHYmMSQ==", "cpu": [ "x64" ], @@ -20162,10 +7864,10 @@ "node": ">= 10" } }, - "node_modules/@nx/workspace/node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "19.7.3", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.7.3.tgz", - "integrity": "sha512-X/eG3IqvIxlCfIOiCQKv7RKwra54I+SN9zj2TeSOtd/uK0paa3mYSlGUJqoP3wpzasW1+EPIGkTQqV283IA15w==", + "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-linux-arm-gnueabihf": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.3.2.tgz", + "integrity": "sha512-r4Wl0P94QRBUyiexUcfwKxqFXp48avMG3L0no/ZuNWGODbw1w8ppA4vhnkXtXbIaMdaTGx9eIYO7kFJ2SwMCng==", "cpu": [ "arm" ], @@ -20178,10 +7880,10 @@ "node": ">= 10" } }, - "node_modules/@nx/workspace/node_modules/@nx/nx-linux-arm64-gnu": { - "version": "19.7.3", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.7.3.tgz", - "integrity": "sha512-LNaX8DVcPlFVJhMf1AAAR6j1DZF9BlVhWlilRM44tIfnmvPfKIahKJIJbuikHE7q+lkvMrQUUDXKiQJlmm/qDw==", + "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-linux-arm64-gnu": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.3.2.tgz", + "integrity": "sha512-oaTC4iS1fXnc61ZgSxwCQ2GGIqY64G22udRqNsX9TOtgrT7UA/mjE3Si01r+0xODimOiB525ueyxdIh1MAu6Vg==", "cpu": [ "arm64" ], @@ -20194,10 +7896,10 @@ "node": ">= 10" } }, - "node_modules/@nx/workspace/node_modules/@nx/nx-linux-arm64-musl": { - "version": "19.7.3", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.7.3.tgz", - "integrity": "sha512-TJ9PqSebhrn8NfrW+wqMXB9N65U0L0Kjt8FfahWffNKtSAEUvhurbNhqna2Rt5WJe2qaVf6zN2pOHKhF/5pL0w==", + "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-linux-arm64-musl": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.3.2.tgz", + "integrity": "sha512-yyO9bTM7FW7HTYsSQlL4lgbAexUBpzfhdK+RkgsCiW+U/5bi+jFRxo/SbqGUL+IVliFavWyRXahMqOOM6nBq/w==", "cpu": [ "arm64" ], @@ -20210,10 +7912,10 @@ "node": ">= 10" } }, - "node_modules/@nx/workspace/node_modules/@nx/nx-linux-x64-gnu": { - "version": "19.7.3", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.7.3.tgz", - "integrity": "sha512-YMb4WGGovwgxsP6VvAEnyWvLoUwsDrdE5CxFQ2yoThD2BixmSHUKLtx6dtPDHz25nOE3v1ZzM0xTwYXBhPaeRQ==", + "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-linux-x64-gnu": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.3.2.tgz", + "integrity": "sha512-DC+llVdL4toLjQkDGBgzoCe26FWIOT+SzRdVcKePoNliZ4jDhkOh3+p75NEIOEcDUgoE9M2iCWEBUjkV978ogw==", "cpu": [ "x64" ], @@ -20226,10 +7928,10 @@ "node": ">= 10" } }, - "node_modules/@nx/workspace/node_modules/@nx/nx-linux-x64-musl": { - "version": "19.7.3", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.7.3.tgz", - "integrity": "sha512-zkjgDSvw2eDN+KuJBPPAPhU/lOdiMvJU0UMthJFw85dhQIYfAO8+UgiFg/qBsKo0kQ0MkhntnIPBPF8bH40qWg==", + "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-linux-x64-musl": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.3.2.tgz", + "integrity": "sha512-Wun4v+kuuqv20tJiCENkHGisDqfx029bFufqxx2IOe9TvD6vK4rMMkFVPUoK3FP8EBdaMW4nrR0ZucTFnStl6w==", "cpu": [ "x64" ], @@ -20242,10 +7944,10 @@ "node": ">= 10" } }, - "node_modules/@nx/workspace/node_modules/@nx/nx-win32-arm64-msvc": { - "version": "19.7.3", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.7.3.tgz", - "integrity": "sha512-qCTFG6VxNvEe5JfoAELGZsjWDL4G+2NVSoSS3tByJYwVX256qgALcVoUHMjpxBn9FeOvUW9w5PL4Am4PKDdXLw==", + "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-win32-arm64-msvc": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.3.2.tgz", + "integrity": "sha512-bNVf6eu5rWFjHvn0rKHeZYlHUcs3naXvvbduW1g0DPkHG6mt8FYffQmyboN+CSeBd/uWDPNyTUekVWwU7PjtLA==", "cpu": [ "arm64" ], @@ -20258,10 +7960,10 @@ "node": ">= 10" } }, - "node_modules/@nx/workspace/node_modules/@nx/nx-win32-x64-msvc": { - "version": "19.7.3", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.7.3.tgz", - "integrity": "sha512-ULNf73gLgB5cU/O4dlQe6tetbRIROTmaUNYTUUCCAC0BqVwZwPDxn4u9C5LgiErVyfPwwAhlserCGei5taLASQ==", + "node_modules/@nx/eslint-plugin/node_modules/@nx/nx-win32-x64-msvc": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.3.2.tgz", + "integrity": "sha512-8DD5BPa5YrxTOKL3HTAgEd+IXNqRtJfwvbrn2MbOMNMyoMG9Zi5yhFvTH/HTT9Tz6VUHvXP16QWYA3R7eFi7Gg==", "cpu": [ "x64" ], @@ -20274,7 +7976,28 @@ "node": ">= 10" } }, - "node_modules/@nx/workspace/node_modules/dotenv-expand": { + "node_modules/@nx/eslint-plugin/node_modules/@nx/workspace": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-19.3.2.tgz", + "integrity": "sha512-gam41l0hFftYIYTt8eTvZjh+ZWo62HO2p/efqZuFIa/1ZsXF1XG8MDRkCSh5Wfjh1f0jS2ma8HwPV3e8TJm2lw==", + "dev": true, + "dependencies": { + "@nrwl/workspace": "19.3.2", + "@nx/devkit": "19.3.2", + "chalk": "^4.1.0", + "enquirer": "~2.3.6", + "nx": "19.3.2", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" + } + }, + "node_modules/@nx/eslint-plugin/node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/@nx/eslint-plugin/node_modules/dotenv-expand": { "version": "11.0.6", "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.6.tgz", "integrity": "sha512-8NHi73otpWsZGBSZwwknTXS5pqMOrk9+Ssrna8xCaxkzEpU9OTf9R5ArQGVw03//Zmk9MOwLPng9WwndvpAJ5g==", @@ -20289,13 +8012,13 @@ "url": "https://dotenvx.com" } }, - "node_modules/@nx/workspace/node_modules/emoji-regex": { + "node_modules/@nx/eslint-plugin/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "node_modules/@nx/workspace/node_modules/is-fullwidth-code-point": { + "node_modules/@nx/eslint-plugin/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", @@ -20304,28 +8027,18 @@ "node": ">=8" } }, - "node_modules/@nx/workspace/node_modules/lines-and-columns": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.3.tgz", - "integrity": "sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/@nx/workspace/node_modules/nx": { - "version": "19.7.3", - "resolved": "https://registry.npmjs.org/nx/-/nx-19.7.3.tgz", - "integrity": "sha512-8F4CzKavSuOFv+uKVwXHc00Px0q40CWAYCW6NC5IgU3AMaJVumyHzgB8Sn+yfkaVgfVnZVqznOsyrbZUWuj/VA==", + "node_modules/@nx/eslint-plugin/node_modules/nx": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/nx/-/nx-19.3.2.tgz", + "integrity": "sha512-eKWs+ahkTKnq9EeWJCE4u8JLeq1cOHnq5DKoiisy2nwUg4KGy1odReegxUMLeEgNBcMI40EUtEJFiTMJSXZQeg==", "dev": true, "hasInstallScript": true, "dependencies": { - "@napi-rs/wasm-runtime": "0.2.4", - "@nrwl/tao": "19.7.3", + "@nrwl/tao": "19.3.2", "@yarnpkg/lockfile": "^1.1.0", "@yarnpkg/parsers": "3.0.0-rc.46", "@zkochan/js-yaml": "0.0.7", - "axios": "^1.7.4", + "axios": "^1.6.0", "chalk": "^4.1.0", "cli-cursor": "3.1.0", "cli-spinners": "2.6.1", @@ -20340,7 +8053,7 @@ "ignore": "^5.0.4", "jest-diff": "^29.4.1", "jsonc-parser": "3.2.0", - "lines-and-columns": "2.0.3", + "lines-and-columns": "~2.0.3", "minimatch": "9.0.3", "node-machine-id": "1.1.12", "npm-run-path": "^4.0.1", @@ -20361,16 +8074,16 @@ "nx-cloud": "bin/nx-cloud.js" }, "optionalDependencies": { - "@nx/nx-darwin-arm64": "19.7.3", - "@nx/nx-darwin-x64": "19.7.3", - "@nx/nx-freebsd-x64": "19.7.3", - "@nx/nx-linux-arm-gnueabihf": "19.7.3", - "@nx/nx-linux-arm64-gnu": "19.7.3", - "@nx/nx-linux-arm64-musl": "19.7.3", - "@nx/nx-linux-x64-gnu": "19.7.3", - "@nx/nx-linux-x64-musl": "19.7.3", - "@nx/nx-win32-arm64-msvc": "19.7.3", - "@nx/nx-win32-x64-msvc": "19.7.3" + "@nx/nx-darwin-arm64": "19.3.2", + "@nx/nx-darwin-x64": "19.3.2", + "@nx/nx-freebsd-x64": "19.3.2", + "@nx/nx-linux-arm-gnueabihf": "19.3.2", + "@nx/nx-linux-arm64-gnu": "19.3.2", + "@nx/nx-linux-arm64-musl": "19.3.2", + "@nx/nx-linux-x64-gnu": "19.3.2", + "@nx/nx-linux-x64-musl": "19.3.2", + "@nx/nx-win32-arm64-msvc": "19.3.2", + "@nx/nx-win32-x64-msvc": "19.3.2" }, "peerDependencies": { "@swc-node/register": "^1.8.0", @@ -20385,10 +8098,10 @@ } } }, - "node_modules/@nx/workspace/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "node_modules/@nx/eslint-plugin/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -20397,7 +8110,7 @@ "node": ">=10" } }, - "node_modules/@nx/workspace/node_modules/string-width": { + "node_modules/@nx/eslint-plugin/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", @@ -20411,7 +8124,50 @@ "node": ">=8" } }, - "node_modules/@nx/workspace/node_modules/yargs": { + "node_modules/@nx/eslint-plugin/node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/@nx/eslint-plugin/node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", @@ -20429,877 +8185,943 @@ "node": ">=12" } }, - "node_modules/@open-draft/deferred-promise": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", - "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@open-draft/logger": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz", - "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", + "node_modules/@nx/eslint/node_modules/@nrwl/devkit": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.3.2.tgz", + "integrity": "sha512-n3tFalVPUk1HAJ2VYNnF34yzB9j2+6swFUi4Y92PxD1vN7vrIXnNeaTx2qcee7JDjBpiJ7Zn0KLg2jwiH6hNwA==", "dev": true, - "license": "MIT", "dependencies": { - "is-node-process": "^1.2.0", - "outvariant": "^1.4.0" + "@nx/devkit": "19.3.2" } }, - "node_modules/@open-draft/until": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz", - "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", + "node_modules/@nx/eslint/node_modules/@nrwl/js": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nrwl/js/-/js-19.3.2.tgz", + "integrity": "sha512-ZgCoLsASIlp1xtYpWW/1ZxvKSb6BY3ZNXBmjoUW4LyN7Pk6su55gPAVt6JWIxSMm+HC+v+Cb4XFKZLdtuvE7bg==", "dev": true, - "license": "MIT" - }, - "node_modules/@open-policy-agent/opa-wasm": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@open-policy-agent/opa-wasm/-/opa-wasm-1.9.0.tgz", - "integrity": "sha512-wuxQYoqU80ulYdFtZ1BKaFs29IRZZV3hl48L4wMRxXFlEoLBDfl5rL8iBNIyp+DDymvDxGS4ZMRVaBBWXnPYLQ==", "dependencies": { - "sprintf-js": "^1.1.2", - "yaml": "^1.10.2" - } - }, - "node_modules/@open-policy-agent/opa-wasm/node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "license": "ISC", - "engines": { - "node": ">= 6" + "@nx/js": "19.3.2" } }, - "node_modules/@open-rpc/client-js": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@open-rpc/client-js/-/client-js-1.8.1.tgz", - "integrity": "sha512-vV+Hetl688nY/oWI9IFY0iKDrWuLdYhf7OIKI6U1DcnJV7r4gAgwRJjEr1QVYszUc0gjkHoQJzqevmXMGLyA0g==", - "license": "Apache-2.0", + "node_modules/@nx/eslint/node_modules/@nrwl/tao": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.3.2.tgz", + "integrity": "sha512-I1gW7woqwU6rdlgwj6XXAKcreJ5ptRKI2WpLdZErkrPmaRG/jMZx/yjZrG4PWdIEuZ4ZmYnRsoXbKN6ilCknQw==", + "dev": true, "dependencies": { - "isomorphic-fetch": "^3.0.0", - "isomorphic-ws": "^5.0.0", - "strict-event-emitter-types": "^2.0.0", - "ws": "^7.0.0" + "nx": "19.3.2", + "tslib": "^2.3.0" + }, + "bin": { + "tao": "index.js" } }, - "node_modules/@open-rpc/client-js/node_modules/ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "license": "MIT", - "engines": { - "node": ">=8.3.0" + "node_modules/@nx/eslint/node_modules/@nrwl/tao/node_modules/nx": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/nx/-/nx-19.3.2.tgz", + "integrity": "sha512-eKWs+ahkTKnq9EeWJCE4u8JLeq1cOHnq5DKoiisy2nwUg4KGy1odReegxUMLeEgNBcMI40EUtEJFiTMJSXZQeg==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@nrwl/tao": "19.3.2", + "@yarnpkg/lockfile": "^1.1.0", + "@yarnpkg/parsers": "3.0.0-rc.46", + "@zkochan/js-yaml": "0.0.7", + "axios": "^1.6.0", + "chalk": "^4.1.0", + "cli-cursor": "3.1.0", + "cli-spinners": "2.6.1", + "cliui": "^8.0.1", + "dotenv": "~16.4.5", + "dotenv-expand": "~11.0.6", + "enquirer": "~2.3.6", + "figures": "3.2.0", + "flat": "^5.0.2", + "front-matter": "^4.0.2", + "fs-extra": "^11.1.0", + "ignore": "^5.0.4", + "jest-diff": "^29.4.1", + "jsonc-parser": "3.2.0", + "lines-and-columns": "~2.0.3", + "minimatch": "9.0.3", + "node-machine-id": "1.1.12", + "npm-run-path": "^4.0.1", + "open": "^8.4.0", + "ora": "5.3.0", + "semver": "^7.5.3", + "string-width": "^4.2.3", + "strong-log-transformer": "^2.1.0", + "tar-stream": "~2.2.0", + "tmp": "~0.2.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0", + "yargs": "^17.6.2", + "yargs-parser": "21.1.1" + }, + "bin": { + "nx": "bin/nx.js", + "nx-cloud": "bin/nx-cloud.js" + }, + "optionalDependencies": { + "@nx/nx-darwin-arm64": "19.3.2", + "@nx/nx-darwin-x64": "19.3.2", + "@nx/nx-freebsd-x64": "19.3.2", + "@nx/nx-linux-arm-gnueabihf": "19.3.2", + "@nx/nx-linux-arm64-gnu": "19.3.2", + "@nx/nx-linux-arm64-musl": "19.3.2", + "@nx/nx-linux-x64-gnu": "19.3.2", + "@nx/nx-linux-x64-musl": "19.3.2", + "@nx/nx-win32-arm64-msvc": "19.3.2", + "@nx/nx-win32-x64-msvc": "19.3.2" }, "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "@swc-node/register": "^1.8.0", + "@swc/core": "^1.3.85" }, "peerDependenciesMeta": { - "bufferutil": { + "@swc-node/register": { "optional": true }, - "utf-8-validate": { + "@swc/core": { "optional": true } } }, - "node_modules/@openapitools/openapi-generator-cli": { - "version": "2.15.3", - "resolved": "https://registry.npmjs.org/@openapitools/openapi-generator-cli/-/openapi-generator-cli-2.15.3.tgz", - "integrity": "sha512-2UBnsDlMt36thhdXxisbA1qReVtbCaw+NCvXoslRXlaJBL4qkAmZUhNeDLNu3LCbwA2PASMWhJSqeLwgwMCitw==", + "node_modules/@nx/eslint/node_modules/@nrwl/workspace": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-19.3.2.tgz", + "integrity": "sha512-6gV4qa38t3GyRKmO2PLcamDcFRD7I3wl6/R0/E1eC8Wm6K2oBzjOIV5ALpz4iC4LOln88IL+AjuQdG6kdtfXlA==", "dev": true, - "hasInstallScript": true, "dependencies": { - "@nestjs/axios": "3.1.1", - "@nestjs/common": "10.4.6", - "@nestjs/core": "10.4.6", - "@nuxtjs/opencollective": "0.3.2", - "axios": "1.7.7", - "chalk": "4.1.2", - "commander": "8.3.0", - "compare-versions": "4.1.4", - "concurrently": "6.5.1", - "console.table": "0.10.0", - "fs-extra": "10.1.0", - "glob": "9.3.5", - "inquirer": "8.2.6", - "lodash": "4.17.21", - "proxy-agent": "6.4.0", - "reflect-metadata": "0.1.13", - "rxjs": "7.8.1", - "tslib": "2.8.1" - }, - "bin": { - "openapi-generator-cli": "main.js" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/openapi_generator" + "@nx/workspace": "19.3.2" } }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/axios": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-3.1.1.tgz", - "integrity": "sha512-ySoxrzqX80P1q6LKLKGcgyBd2utg4gbC+4FsJNpXYvILorMlxss/ECNogD9EXLCE4JS5exVFD5ez0nK5hXcNTQ==", + "node_modules/@nx/eslint/node_modules/@nx/devkit": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.3.2.tgz", + "integrity": "sha512-uD3jaJ1Jvf7B6jqH2t2GH0L6REwcCGBLXq1qs1HRQF5SZrEtuUeusn8wvCKP7dftPK3byLHAG0xHRW4+IUAz/g==", "dev": true, + "dependencies": { + "@nrwl/devkit": "19.3.2", + "ejs": "^3.1.7", + "enquirer": "~2.3.6", + "ignore": "^5.0.4", + "minimatch": "9.0.3", + "semver": "^7.5.3", + "tmp": "~0.2.1", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" + }, "peerDependencies": { - "@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0", - "axios": "^1.3.1", - "rxjs": "^6.0.0 || ^7.0.0" + "nx": ">= 17 <= 20" } }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/common": { - "version": "10.4.6", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.4.6.tgz", - "integrity": "sha512-KkezkZvU9poWaNq4L+lNvx+386hpOxPJkfXBBeSMrcqBOx8kVr36TGN2uYkF4Ta4zNu1KbCjmZbc0rhHSg296g==", + "node_modules/@nx/eslint/node_modules/@nx/js": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/js/-/js-19.3.2.tgz", + "integrity": "sha512-WXULhOHYDIAvs+SyDiRaNrpn1DmBAl3u7F5Jpu2VIyrcXgllrYGqUAykUqSu6Oyc2J+asfEtiG67I7UucTHLhA==", "dev": true, "dependencies": { - "iterare": "1.2.1", - "tslib": "2.7.0", - "uid": "2.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nest" + "@babel/core": "^7.23.2", + "@babel/plugin-proposal-decorators": "^7.22.7", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-runtime": "^7.23.2", + "@babel/preset-env": "^7.23.2", + "@babel/preset-typescript": "^7.22.5", + "@babel/runtime": "^7.22.6", + "@nrwl/js": "19.3.2", + "@nx/devkit": "19.3.2", + "@nx/workspace": "19.3.2", + "babel-plugin-const-enum": "^1.0.1", + "babel-plugin-macros": "^2.8.0", + "babel-plugin-transform-typescript-metadata": "^0.3.1", + "chalk": "^4.1.0", + "columnify": "^1.6.0", + "detect-port": "^1.5.1", + "fast-glob": "3.2.7", + "fs-extra": "^11.1.0", + "ignore": "^5.0.4", + "js-tokens": "^4.0.0", + "minimatch": "9.0.3", + "npm-package-arg": "11.0.1", + "npm-run-path": "^4.0.1", + "ora": "5.3.0", + "semver": "^7.5.3", + "source-map-support": "0.5.19", + "ts-node": "10.9.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0" }, "peerDependencies": { - "class-transformer": "*", - "class-validator": "*", - "reflect-metadata": "^0.1.12 || ^0.2.0", - "rxjs": "^7.1.0" + "verdaccio": "^5.0.4" }, "peerDependenciesMeta": { - "class-transformer": { - "optional": true - }, - "class-validator": { + "verdaccio": { "optional": true } } }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/common/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", - "dev": true - }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/core": { - "version": "10.4.6", - "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.4.6.tgz", - "integrity": "sha512-zXVPxCNRfO6gAy0yvEDjUxE/8gfZICJFpsl2lZAUH31bPb6m+tXuhUq2mVCTEltyMYQ+DYtRe+fEYM2v152N1g==", + "node_modules/@nx/eslint/node_modules/@nx/js/node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", "dev": true, - "hasInstallScript": true, "dependencies": { - "@nuxtjs/opencollective": "0.3.2", - "fast-safe-stringify": "2.1.1", - "iterare": "1.2.1", - "path-to-regexp": "3.3.0", - "tslib": "2.7.0", - "uid": "2.0.2" + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nest" + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" }, "peerDependencies": { - "@nestjs/common": "^10.0.0", - "@nestjs/microservices": "^10.0.0", - "@nestjs/platform-express": "^10.0.0", - "@nestjs/websockets": "^10.0.0", - "reflect-metadata": "^0.1.12 || ^0.2.0", - "rxjs": "^7.1.0" + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" }, "peerDependenciesMeta": { - "@nestjs/microservices": { - "optional": true - }, - "@nestjs/platform-express": { + "@swc/core": { "optional": true }, - "@nestjs/websockets": { + "@swc/wasm": { "optional": true } } }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/core/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", - "dev": true - }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "node_modules/@nx/eslint/node_modules/@nx/nx-darwin-arm64": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.3.2.tgz", + "integrity": "sha512-MTqPTR1FwfVfIkHKUw95dFlPBN6mbqfJ+KzLHvUSPcqLKelhi82tsisjMoB5sNK0YWcNNVqYW72ojCnHVB0TUg==", + "cpu": [ + "arm64" + ], "dev": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">= 12" + "node": ">= 10" } }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/fs-extra": { - "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==", + "node_modules/@nx/eslint/node_modules/@nx/nx-darwin-x64": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.3.2.tgz", + "integrity": "sha512-C8s9X5AlVgl3V5PycLdX+75lpAWq0qQs6QUEAnyxrLM9l+/HRecgoW6uZ7tX6Fnd8WGfMIwyahBw4LyZgk6zTw==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=12" + "node": ">= 10" } }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/glob": { - "version": "9.3.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", - "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", + "node_modules/@nx/eslint/node_modules/@nx/nx-freebsd-x64": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.3.2.tgz", + "integrity": "sha512-XeEpEU0iqJ/5cAPMmjqJ0Sdz89ZtDRj4NdksioyhAHri94X5/3lm3lDs4tB3nObT7p3QL7r/HP1itq5DHYmMSQ==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "minimatch": "^8.0.2", - "minipass": "^4.2.4", - "path-scurry": "^1.6.1" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">= 10" } }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/minimatch": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", - "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", + "node_modules/@nx/eslint/node_modules/@nx/nx-linux-arm-gnueabihf": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.3.2.tgz", + "integrity": "sha512-r4Wl0P94QRBUyiexUcfwKxqFXp48avMG3L0no/ZuNWGODbw1w8ppA4vhnkXtXbIaMdaTGx9eIYO7kFJ2SwMCng==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">= 10" } }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/minipass": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", - "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "node_modules/@nx/eslint/node_modules/@nx/nx-linux-arm64-gnu": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.3.2.tgz", + "integrity": "sha512-oaTC4iS1fXnc61ZgSxwCQ2GGIqY64G22udRqNsX9TOtgrT7UA/mjE3Si01r+0xODimOiB525ueyxdIh1MAu6Vg==", + "cpu": [ + "arm64" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": ">= 10" } }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/path-to-regexp": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.3.0.tgz", - "integrity": "sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==", - "dev": true - }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/reflect-metadata": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", - "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", - "dev": true - }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true - }, - "node_modules/@opentelemetry/api": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", - "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", + "node_modules/@nx/eslint/node_modules/@nx/nx-linux-arm64-musl": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.3.2.tgz", + "integrity": "sha512-yyO9bTM7FW7HTYsSQlL4lgbAexUBpzfhdK+RkgsCiW+U/5bi+jFRxo/SbqGUL+IVliFavWyRXahMqOOM6nBq/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8.0.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/api-logs": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.53.0.tgz", - "integrity": "sha512-8HArjKx+RaAI8uEIgcORbZIPklyh1YLjPSBus8hjRmvLi6DeFzgOcdZ7KwPabKj8mXF8dX0hyfAyGfycz0DbFw==", - "dependencies": { - "@opentelemetry/api": "^1.0.0" - }, + "node_modules/@nx/eslint/node_modules/@nx/nx-linux-x64-gnu": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.3.2.tgz", + "integrity": "sha512-DC+llVdL4toLjQkDGBgzoCe26FWIOT+SzRdVcKePoNliZ4jDhkOh3+p75NEIOEcDUgoE9M2iCWEBUjkV978ogw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" + "node": ">= 10" } }, - "node_modules/@opentelemetry/auto-instrumentations-node": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/auto-instrumentations-node/-/auto-instrumentations-node-0.51.0.tgz", - "integrity": "sha512-xsgydgtJiToxvFsDcmLDrHiFfHOmdomqk4KCnr40YZdsfw7KO4RJEU0om2f7pFh6WUI5q8nSQ53QgZ+DAz6TzA==", - "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/instrumentation-amqplib": "^0.42.0", - "@opentelemetry/instrumentation-aws-lambda": "^0.45.0", - "@opentelemetry/instrumentation-aws-sdk": "^0.44.0", - "@opentelemetry/instrumentation-bunyan": "^0.41.0", - "@opentelemetry/instrumentation-cassandra-driver": "^0.41.0", - "@opentelemetry/instrumentation-connect": "^0.39.0", - "@opentelemetry/instrumentation-cucumber": "^0.9.0", - "@opentelemetry/instrumentation-dataloader": "^0.12.0", - "@opentelemetry/instrumentation-dns": "^0.39.0", - "@opentelemetry/instrumentation-express": "^0.43.0", - "@opentelemetry/instrumentation-fastify": "^0.40.0", - "@opentelemetry/instrumentation-fs": "^0.15.0", - "@opentelemetry/instrumentation-generic-pool": "^0.39.0", - "@opentelemetry/instrumentation-graphql": "^0.43.0", - "@opentelemetry/instrumentation-grpc": "^0.53.0", - "@opentelemetry/instrumentation-hapi": "^0.41.0", - "@opentelemetry/instrumentation-http": "^0.53.0", - "@opentelemetry/instrumentation-ioredis": "^0.43.0", - "@opentelemetry/instrumentation-kafkajs": "^0.3.0", - "@opentelemetry/instrumentation-knex": "^0.40.0", - "@opentelemetry/instrumentation-koa": "^0.43.0", - "@opentelemetry/instrumentation-lru-memoizer": "^0.40.0", - "@opentelemetry/instrumentation-memcached": "^0.39.0", - "@opentelemetry/instrumentation-mongodb": "^0.47.0", - "@opentelemetry/instrumentation-mongoose": "^0.42.0", - "@opentelemetry/instrumentation-mysql": "^0.41.0", - "@opentelemetry/instrumentation-mysql2": "^0.41.0", - "@opentelemetry/instrumentation-nestjs-core": "^0.40.0", - "@opentelemetry/instrumentation-net": "^0.39.0", - "@opentelemetry/instrumentation-pg": "^0.46.0", - "@opentelemetry/instrumentation-pino": "^0.42.0", - "@opentelemetry/instrumentation-redis": "^0.42.0", - "@opentelemetry/instrumentation-redis-4": "^0.42.1", - "@opentelemetry/instrumentation-restify": "^0.41.0", - "@opentelemetry/instrumentation-router": "^0.40.0", - "@opentelemetry/instrumentation-socket.io": "^0.42.0", - "@opentelemetry/instrumentation-tedious": "^0.14.0", - "@opentelemetry/instrumentation-undici": "^0.6.0", - "@opentelemetry/instrumentation-winston": "^0.40.0", - "@opentelemetry/resource-detector-alibaba-cloud": "^0.29.3", - "@opentelemetry/resource-detector-aws": "^1.6.2", - "@opentelemetry/resource-detector-azure": "^0.2.11", - "@opentelemetry/resource-detector-container": "^0.4.4", - "@opentelemetry/resource-detector-gcp": "^0.29.12", - "@opentelemetry/resources": "^1.24.0", - "@opentelemetry/sdk-node": "^0.53.0" - }, + "node_modules/@nx/eslint/node_modules/@nx/nx-linux-x64-musl": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.3.2.tgz", + "integrity": "sha512-Wun4v+kuuqv20tJiCENkHGisDqfx029bFufqxx2IOe9TvD6vK4rMMkFVPUoK3FP8EBdaMW4nrR0ZucTFnStl6w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.4.1" + "node": ">= 10" } }, - "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, + "node_modules/@nx/eslint/node_modules/@nx/nx-win32-arm64-msvc": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.3.2.tgz", + "integrity": "sha512-bNVf6eu5rWFjHvn0rKHeZYlHUcs3naXvvbduW1g0DPkHG6mt8FYffQmyboN+CSeBd/uWDPNyTUekVWwU7PjtLA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/instrumentation-express": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-express/-/instrumentation-express-0.43.0.tgz", - "integrity": "sha512-bxTIlzn9qPXJgrhz8/Do5Q3jIlqfpoJrSUtVGqH+90eM1v2PkPHc+SdE+zSqe4q9Y1UQJosmZ4N4bm7Zj/++MA==", - "dependencies": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, + "node_modules/@nx/eslint/node_modules/@nx/nx-win32-x64-msvc": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.3.2.tgz", + "integrity": "sha512-8DD5BPa5YrxTOKL3HTAgEd+IXNqRtJfwvbrn2MbOMNMyoMG9Zi5yhFvTH/HTT9Tz6VUHvXP16QWYA3R7eFi7Gg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/instrumentation-http": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.53.0.tgz", - "integrity": "sha512-H74ErMeDuZfj7KgYCTOFGWF5W9AfaPnqLQQxeFq85+D29wwV2yqHbz2IKLYpkOh7EI6QwDEl7rZCIxjJLyc/CQ==", + "node_modules/@nx/eslint/node_modules/@nx/workspace": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-19.3.2.tgz", + "integrity": "sha512-gam41l0hFftYIYTt8eTvZjh+ZWo62HO2p/efqZuFIa/1ZsXF1XG8MDRkCSh5Wfjh1f0jS2ma8HwPV3e8TJm2lw==", + "dev": true, "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/instrumentation": "0.53.0", - "@opentelemetry/semantic-conventions": "1.27.0", - "semver": "^7.5.2" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@nrwl/workspace": "19.3.2", + "@nx/devkit": "19.3.2", + "chalk": "^4.1.0", + "enquirer": "~2.3.6", + "nx": "19.3.2", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" } }, - "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/instrumentation-nestjs-core": { - "version": "0.40.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-nestjs-core/-/instrumentation-nestjs-core-0.40.0.tgz", - "integrity": "sha512-WF1hCUed07vKmf5BzEkL0wSPinqJgH7kGzOjjMAiTGacofNXjb/y4KQ8loj2sNsh5C/NN7s1zxQuCgbWbVTGKg==", + "node_modules/@nx/eslint/node_modules/@nx/workspace/node_modules/nx": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/nx/-/nx-19.3.2.tgz", + "integrity": "sha512-eKWs+ahkTKnq9EeWJCE4u8JLeq1cOHnq5DKoiisy2nwUg4KGy1odReegxUMLeEgNBcMI40EUtEJFiTMJSXZQeg==", + "dev": true, + "hasInstallScript": true, "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@nrwl/tao": "19.3.2", + "@yarnpkg/lockfile": "^1.1.0", + "@yarnpkg/parsers": "3.0.0-rc.46", + "@zkochan/js-yaml": "0.0.7", + "axios": "^1.6.0", + "chalk": "^4.1.0", + "cli-cursor": "3.1.0", + "cli-spinners": "2.6.1", + "cliui": "^8.0.1", + "dotenv": "~16.4.5", + "dotenv-expand": "~11.0.6", + "enquirer": "~2.3.6", + "figures": "3.2.0", + "flat": "^5.0.2", + "front-matter": "^4.0.2", + "fs-extra": "^11.1.0", + "ignore": "^5.0.4", + "jest-diff": "^29.4.1", + "jsonc-parser": "3.2.0", + "lines-and-columns": "~2.0.3", + "minimatch": "9.0.3", + "node-machine-id": "1.1.12", + "npm-run-path": "^4.0.1", + "open": "^8.4.0", + "ora": "5.3.0", + "semver": "^7.5.3", + "string-width": "^4.2.3", + "strong-log-transformer": "^2.1.0", + "tar-stream": "~2.2.0", + "tmp": "~0.2.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0", + "yargs": "^17.6.2", + "yargs-parser": "21.1.1" }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "bin": { - "semver": "bin/semver.js" + "nx": "bin/nx.js", + "nx-cloud": "bin/nx-cloud.js" }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@opentelemetry/context-async-hooks": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-1.26.0.tgz", - "integrity": "sha512-HedpXXYzzbaoutw6DFLWLDket2FwLkLpil4hGCZ1xYEIMTcivdfwEOISgdbLEWyG3HW52gTq2V9mOVJrONgiwg==", - "engines": { - "node": ">=14" + "optionalDependencies": { + "@nx/nx-darwin-arm64": "19.3.2", + "@nx/nx-darwin-x64": "19.3.2", + "@nx/nx-freebsd-x64": "19.3.2", + "@nx/nx-linux-arm-gnueabihf": "19.3.2", + "@nx/nx-linux-arm64-gnu": "19.3.2", + "@nx/nx-linux-arm64-musl": "19.3.2", + "@nx/nx-linux-x64-gnu": "19.3.2", + "@nx/nx-linux-x64-musl": "19.3.2", + "@nx/nx-win32-arm64-msvc": "19.3.2", + "@nx/nx-win32-x64-msvc": "19.3.2" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "@swc-node/register": "^1.8.0", + "@swc/core": "^1.3.85" + }, + "peerDependenciesMeta": { + "@swc-node/register": { + "optional": true + }, + "@swc/core": { + "optional": true + } } }, - "node_modules/@opentelemetry/core": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.26.0.tgz", - "integrity": "sha512-1iKxXXE8415Cdv0yjG3G6hQnB5eVEsJce3QaawX8SjDn0mAS0ZM8fAbZZJD4ajvhC15cePvosSCut404KrIIvQ==", + "node_modules/@nx/eslint/node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/@nx/eslint/node_modules/dotenv-expand": { + "version": "11.0.6", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.6.tgz", + "integrity": "sha512-8NHi73otpWsZGBSZwwknTXS5pqMOrk9+Ssrna8xCaxkzEpU9OTf9R5ArQGVw03//Zmk9MOwLPng9WwndvpAJ5g==", + "dev": true, "dependencies": { - "@opentelemetry/semantic-conventions": "1.27.0" + "dotenv": "^16.4.4" }, "engines": { - "node": ">=14" + "node": ">=12" }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "funding": { + "url": "https://dotenvx.com" } }, - "node_modules/@opentelemetry/exporter-logs-otlp-grpc": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-grpc/-/exporter-logs-otlp-grpc-0.53.0.tgz", - "integrity": "sha512-x5ygAQgWAQOI+UOhyV3z9eW7QU2dCfnfOuIBiyYmC2AWr74f6x/3JBnP27IAcEx6aihpqBYWKnpoUTztkVPAZw==", - "dependencies": { - "@grpc/grpc-js": "^1.7.1", - "@opentelemetry/core": "1.26.0", - "@opentelemetry/otlp-grpc-exporter-base": "0.53.0", - "@opentelemetry/otlp-transformer": "0.53.0", - "@opentelemetry/sdk-logs": "0.53.0" - }, + "node_modules/@nx/eslint/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/@nx/eslint/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "node": ">=8" } }, - "node_modules/@opentelemetry/exporter-logs-otlp-http": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.53.0.tgz", - "integrity": "sha512-cSRKgD/n8rb+Yd+Cif6EnHEL/VZg1o8lEcEwFji1lwene6BdH51Zh3feAD9p2TyVoBKrl6Q9Zm2WltSp2k9gWQ==", - "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@opentelemetry/core": "1.26.0", - "@opentelemetry/otlp-exporter-base": "0.53.0", - "@opentelemetry/otlp-transformer": "0.53.0", - "@opentelemetry/sdk-logs": "0.53.0" + "node_modules/@nx/eslint/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "node": ">=10" } }, - "node_modules/@opentelemetry/exporter-logs-otlp-proto": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.53.0.tgz", - "integrity": "sha512-jhEcVL1deeWNmTUP05UZMriZPSWUBcfg94ng7JuBb1q2NExgnADQFl1VQQ+xo62/JepK+MxQe4xAwlsDQFbISA==", + "node_modules/@nx/eslint/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@opentelemetry/core": "1.26.0", - "@opentelemetry/otlp-exporter-base": "0.53.0", - "@opentelemetry/otlp-transformer": "0.53.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/sdk-logs": "0.53.0", - "@opentelemetry/sdk-trace-base": "1.26.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "node": ">=8" } }, - "node_modules/@opentelemetry/exporter-logs-otlp-proto/node_modules/@opentelemetry/resources": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", - "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", - "license": "Apache-2.0", + "node_modules/@nx/eslint/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "node": ">=12" } }, - "node_modules/@opentelemetry/exporter-logs-otlp-proto/node_modules/@opentelemetry/sdk-trace-base": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.26.0.tgz", - "integrity": "sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw==", - "license": "Apache-2.0", + "node_modules/@nx/jest": { + "version": "20.0.8", + "resolved": "https://registry.npmjs.org/@nx/jest/-/jest-20.0.8.tgz", + "integrity": "sha512-LEs1EKl0RezDycGKxCaJivvKKXXHL5HUGp9dxE2FuS2nzimYhYldxlOH+zr73J5SWEZtxnMHHjRPkbDffnoxug==", + "dev": true, "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "@jest/reporters": "^29.4.1", + "@jest/test-result": "^29.4.1", + "@nx/devkit": "20.0.8", + "@nx/js": "20.0.8", + "@phenomnomnominal/tsquery": "~5.0.1", + "chalk": "^4.1.0", + "identity-obj-proxy": "3.0.0", + "jest-config": "^29.4.1", + "jest-resolve": "^29.4.1", + "jest-util": "^29.4.1", + "minimatch": "9.0.3", + "resolve.exports": "1.1.0", + "semver": "^7.5.3", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" } }, - "node_modules/@opentelemetry/exporter-metrics-otlp-http": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-http/-/exporter-metrics-otlp-http-0.53.0.tgz", - "integrity": "sha512-nvZtOk23pZOrTW10Za2WPd9pk4tWDvL6ALlHRFfInpcTjtOgCrv+fQDxpzosa5PeXvYeFFUO5aYCTnwiCX4Dzg==", + "node_modules/@nx/jest/node_modules/@nx/devkit": { + "version": "20.0.8", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-20.0.8.tgz", + "integrity": "sha512-MRUGgWSMzYtdwtolvWL5EZlX+7xYgu7JIXf1+3rmZU5adMmlqWKrIbyvDf53XocQlT8oxx/xXTEFHhIymGTQCg==", + "dev": true, "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/otlp-exporter-base": "0.53.0", - "@opentelemetry/otlp-transformer": "0.53.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/sdk-metrics": "1.26.0" - }, - "engines": { - "node": ">=14" + "ejs": "^3.1.7", + "enquirer": "~2.3.6", + "ignore": "^5.0.4", + "minimatch": "9.0.3", + "semver": "^7.5.3", + "tmp": "~0.2.1", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "nx": ">= 19 <= 21" } }, - "node_modules/@opentelemetry/exporter-metrics-otlp-http/node_modules/@opentelemetry/resources": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", - "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", - "license": "Apache-2.0", + "node_modules/@nx/jest/node_modules/@nx/js": { + "version": "20.0.8", + "resolved": "https://registry.npmjs.org/@nx/js/-/js-20.0.8.tgz", + "integrity": "sha512-PDkjhen4Gl1bMw65XfgebSceNH7HOeTr1f5C+WY/II+7pcAx2lqWj4n6t0XkzBMWlOyfHt/H+O/F4GuZ/hjIyg==", + "dev": true, "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" + "@babel/core": "^7.23.2", + "@babel/plugin-proposal-decorators": "^7.22.7", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-runtime": "^7.23.2", + "@babel/preset-env": "^7.23.2", + "@babel/preset-typescript": "^7.22.5", + "@babel/runtime": "^7.22.6", + "@nx/devkit": "20.0.8", + "@nx/workspace": "20.0.8", + "@zkochan/js-yaml": "0.0.7", + "babel-plugin-const-enum": "^1.0.1", + "babel-plugin-macros": "^2.8.0", + "babel-plugin-transform-typescript-metadata": "^0.3.1", + "chalk": "^4.1.0", + "columnify": "^1.6.0", + "detect-port": "^1.5.1", + "enquirer": "~2.3.6", + "fast-glob": "3.2.7", + "ignore": "^5.0.4", + "js-tokens": "^4.0.0", + "jsonc-parser": "3.2.0", + "minimatch": "9.0.3", + "npm-package-arg": "11.0.1", + "npm-run-path": "^4.0.1", + "ora": "5.3.0", + "semver": "^7.5.3", + "source-map-support": "0.5.19", + "ts-node": "10.9.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "verdaccio": "^5.0.4" + }, + "peerDependenciesMeta": { + "verdaccio": { + "optional": true + } } }, - "node_modules/@opentelemetry/exporter-metrics-otlp-proto": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-proto/-/exporter-metrics-otlp-proto-0.53.0.tgz", - "integrity": "sha512-cO99cY04Oy+i8nfYoY0DOVRWVSb0unlerblvf4Fyt2Ls8CkUECLfgjfUXqdjOhBYOX/OZGOBSGetqqYFtKGdGA==", - "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/exporter-metrics-otlp-http": "0.53.0", - "@opentelemetry/otlp-exporter-base": "0.53.0", - "@opentelemetry/otlp-transformer": "0.53.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/sdk-metrics": "1.26.0" - }, + "node_modules/@nx/jest/node_modules/@nx/nx-darwin-arm64": { + "version": "20.0.8", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-20.0.8.tgz", + "integrity": "sha512-tDoafq5YUyOwxR1Y796WXA6j49OLJRO7TA/Fym52SSuD3AULbgo3/X5XeY6oL2PWM044CuUVrp3V4cIDUtyJpA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/exporter-metrics-otlp-proto/node_modules/@opentelemetry/resources": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", - "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, + "node_modules/@nx/jest/node_modules/@nx/nx-darwin-x64": { + "version": "20.0.8", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-20.0.8.tgz", + "integrity": "sha512-bvfZ6VhSvOpPV00veaJDO1a4X+f0dn8S1A73/2ThbGZrZLAQIFrA8v+ysax+bfCGRHNdtlAL+f7TG2buh/4BRg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/exporter-trace-otlp-grpc": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-grpc/-/exporter-trace-otlp-grpc-0.53.0.tgz", - "integrity": "sha512-m6KSh6OBDwfDjpzPVbuJbMgMbkoZfpxYH2r262KckgX9cMYvooWXEKzlJYsNDC6ADr28A1rtRoUVRwNfIN4tUg==", - "dependencies": { - "@grpc/grpc-js": "^1.7.1", - "@opentelemetry/core": "1.26.0", - "@opentelemetry/otlp-grpc-exporter-base": "0.53.0", - "@opentelemetry/otlp-transformer": "0.53.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/sdk-trace-base": "1.26.0" - }, + "node_modules/@nx/jest/node_modules/@nx/nx-freebsd-x64": { + "version": "20.0.8", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-20.0.8.tgz", + "integrity": "sha512-AdOme0o/pTFy+TutIOAamuGTqbh6nOLrkNEX8f4ogfDRH+k/WvjRQ4z4ne58wf/2EVXua4jKTIEipIZAP/Ad1w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/exporter-trace-otlp-grpc/node_modules/@opentelemetry/resources": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", - "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, + "node_modules/@nx/jest/node_modules/@nx/nx-linux-arm-gnueabihf": { + "version": "20.0.8", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-20.0.8.tgz", + "integrity": "sha512-PYf7Z30A1TCZq9HVUP6JjT3ghTLYkaBpR6vDwiGWUV/exuNmhUgfYW6TiTpiSArXwnAgSIbaoGe537iEvYzA7A==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/exporter-trace-otlp-grpc/node_modules/@opentelemetry/sdk-trace-base": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.26.0.tgz", - "integrity": "sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, + "node_modules/@nx/jest/node_modules/@nx/nx-linux-arm64-gnu": { + "version": "20.0.8", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-20.0.8.tgz", + "integrity": "sha512-3VpvhjmNR78HVxGzpWiwqZsG5sNvLUv2Qfohtxyc3561o8VU41R9Onf/LJmbbZvmdDaPvvXQp3rs0OXT4i7T1g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/exporter-trace-otlp-proto": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-proto/-/exporter-trace-otlp-proto-0.53.0.tgz", - "integrity": "sha512-T/bdXslwRKj23S96qbvGtaYOdfyew3TjPEKOk5mHjkCmkVl1O9C/YMdejwSsdLdOq2YW30KjR9kVi0YMxZushQ==", - "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/otlp-exporter-base": "0.53.0", - "@opentelemetry/otlp-transformer": "0.53.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/sdk-trace-base": "1.26.0" - }, + "node_modules/@nx/jest/node_modules/@nx/nx-linux-arm64-musl": { + "version": "20.0.8", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-20.0.8.tgz", + "integrity": "sha512-3Z7fTJGG8h4VCHhD8Ix0zr6eFMfa1y3YDlzm8Clxu4Enzz0pEsUrT+ph6qrsArnIyUgiCowSi8+xgHFg7V/F1Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/resources": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", - "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, + "node_modules/@nx/jest/node_modules/@nx/nx-linux-x64-gnu": { + "version": "20.0.8", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-20.0.8.tgz", + "integrity": "sha512-Uttl1RHzWpjZgdzowCUNjC6/b3YhZR31wyXWgVF4PDWpDVgy4EigGc19tdrvv8pUVKQFuj0uaSTPUklguN7c3A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/sdk-trace-base": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.26.0.tgz", - "integrity": "sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, + "node_modules/@nx/jest/node_modules/@nx/nx-linux-x64-musl": { + "version": "20.0.8", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-20.0.8.tgz", + "integrity": "sha512-llc6ywSPaOWQzEzD73USyAXd/y3Slu+GHS02IsQqZeA23EIOEzhvEeeeKgs4F8LKuFW/TpV6T5IhvSHw9/mvBg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/exporter-zipkin": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-zipkin/-/exporter-zipkin-1.26.0.tgz", - "integrity": "sha512-PW5R34n3SJHO4t0UetyHKiXL6LixIqWN6lWncg3eRXhKuT30x+b7m5sDJS0kEWRfHeS+kG7uCw2vBzmB2lk3Dw==", - "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/sdk-trace-base": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, + "node_modules/@nx/jest/node_modules/@nx/nx-win32-arm64-msvc": { + "version": "20.0.8", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-20.0.8.tgz", + "integrity": "sha512-GhPVVNrL0QcQ3B6r0P0Dta3TIesJz7uso7iI5rCZ/oOGa02UsT4NkQBpIhxYQZ4TnHYNy84g4rHtYHrSlpDlEw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/exporter-zipkin/node_modules/@opentelemetry/resources": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", - "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, + "node_modules/@nx/jest/node_modules/@nx/nx-win32-x64-msvc": { + "version": "20.0.8", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-20.0.8.tgz", + "integrity": "sha512-yLlcgM0zFdmsExdLv8O2g5FWQ6d2vyN5OynKV+F5BrWHC4LvrqyYJ99y++5bLFoEi19RYIK6sLnzGIRSF6dHGg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/exporter-zipkin/node_modules/@opentelemetry/sdk-trace-base": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.26.0.tgz", - "integrity": "sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw==", - "license": "Apache-2.0", + "node_modules/@nx/jest/node_modules/@nx/workspace": { + "version": "20.0.8", + "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-20.0.8.tgz", + "integrity": "sha512-G7nON6s3KDWNAH9P8IBvvAmTGgTsFZPuWH7We9px0ZwsRcURDDP1OqZsYmfr0zTHTS58wu4Uax/uQLwnTVC1xQ==", + "dev": true, "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "@nx/devkit": "20.0.8", + "chalk": "^4.1.0", + "enquirer": "~2.3.6", + "nx": "20.0.8", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" } }, - "node_modules/@opentelemetry/instrumentation-amqplib": { - "version": "0.42.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-amqplib/-/instrumentation-amqplib-0.42.0.tgz", - "integrity": "sha512-fiuU6OKsqHJiydHWgTRQ7MnIrJ2lEqsdgFtNIH4LbAUJl/5XmrIeoDzDnox+hfkgWK65jsleFuQDtYb5hW1koQ==", + "node_modules/@nx/jest/node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/@nx/jest/node_modules/axios": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "dev": true, "dependencies": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" } }, - "node_modules/@opentelemetry/instrumentation-amqplib/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@nx/jest/node_modules/dotenv-expand": { + "version": "11.0.6", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.6.tgz", + "integrity": "sha512-8NHi73otpWsZGBSZwwknTXS5pqMOrk9+Ssrna8xCaxkzEpU9OTf9R5ArQGVw03//Zmk9MOwLPng9WwndvpAJ5g==", + "dev": true, "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" + "dotenv": "^16.4.4" }, "engines": { - "node": ">=14" + "node": ">=12" }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "funding": { + "url": "https://dotenvx.com" } }, - "node_modules/@opentelemetry/instrumentation-amqplib/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, + "node_modules/@nx/jest/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/@nx/jest/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/@opentelemetry/instrumentation-aws-lambda": { - "version": "0.45.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-aws-lambda/-/instrumentation-aws-lambda-0.45.0.tgz", - "integrity": "sha512-22ZnmYftKjFoiqC1k3tu2AVKiXSZv+ohuHWk4V4MdJpPuNkadY624aDkv5BmwDeavDxVFgqE9nGgDM9s3Q94mg==", - "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/propagator-aws-xray": "^1.3.1", - "@opentelemetry/resources": "^1.8.0", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@types/aws-lambda": "8.10.143" - }, + "node_modules/@nx/jest/node_modules/lines-and-columns": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.3.tgz", + "integrity": "sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w==", + "dev": true, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, - "node_modules/@opentelemetry/instrumentation-aws-lambda/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@nx/jest/node_modules/nx": { + "version": "20.0.8", + "resolved": "https://registry.npmjs.org/nx/-/nx-20.0.8.tgz", + "integrity": "sha512-cMtb+u5Eji7Xm9xMHZkRXMcO8GH6FFqS2+nMgtLUZ/+ZmquEgoV8mbsKVw1u1sJ6osOpWAu9OwXcilwtvSOoBw==", + "dev": true, + "hasInstallScript": true, "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" + "@napi-rs/wasm-runtime": "0.2.4", + "@yarnpkg/lockfile": "^1.1.0", + "@yarnpkg/parsers": "3.0.0-rc.46", + "@zkochan/js-yaml": "0.0.7", + "axios": "^1.7.4", + "chalk": "^4.1.0", + "cli-cursor": "3.1.0", + "cli-spinners": "2.6.1", + "cliui": "^8.0.1", + "dotenv": "~16.4.5", + "dotenv-expand": "~11.0.6", + "enquirer": "~2.3.6", + "figures": "3.2.0", + "flat": "^5.0.2", + "front-matter": "^4.0.2", + "ignore": "^5.0.4", + "jest-diff": "^29.4.1", + "jsonc-parser": "3.2.0", + "lines-and-columns": "2.0.3", + "minimatch": "9.0.3", + "node-machine-id": "1.1.12", + "npm-run-path": "^4.0.1", + "open": "^8.4.0", + "ora": "5.3.0", + "semver": "^7.5.3", + "string-width": "^4.2.3", + "tar-stream": "~2.2.0", + "tmp": "~0.2.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0", + "yargs": "^17.6.2", + "yargs-parser": "21.1.1" }, - "engines": { - "node": ">=14" + "bin": { + "nx": "bin/nx.js", + "nx-cloud": "bin/nx-cloud.js" + }, + "optionalDependencies": { + "@nx/nx-darwin-arm64": "20.0.8", + "@nx/nx-darwin-x64": "20.0.8", + "@nx/nx-freebsd-x64": "20.0.8", + "@nx/nx-linux-arm-gnueabihf": "20.0.8", + "@nx/nx-linux-arm64-gnu": "20.0.8", + "@nx/nx-linux-arm64-musl": "20.0.8", + "@nx/nx-linux-x64-gnu": "20.0.8", + "@nx/nx-linux-x64-musl": "20.0.8", + "@nx/nx-win32-arm64-msvc": "20.0.8", + "@nx/nx-win32-x64-msvc": "20.0.8" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@swc-node/register": "^1.8.0", + "@swc/core": "^1.3.85" + }, + "peerDependenciesMeta": { + "@swc-node/register": { + "optional": true + }, + "@swc/core": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-aws-lambda/node_modules/semver": { + "node_modules/@nx/jest/node_modules/semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", + "dev": true, "bin": { "semver": "bin/semver.js" }, @@ -21307,387 +9129,461 @@ "node": ">=10" } }, - "node_modules/@opentelemetry/instrumentation-aws-sdk": { - "version": "0.44.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-aws-sdk/-/instrumentation-aws-sdk-0.44.0.tgz", - "integrity": "sha512-HIWFg4TDQsayceiikOnruMmyQ0SZYW6WiR+wknWwWVLHC3lHTCpAnqzp5V42ckArOdlwHZu2Jvq2GMSM4Myx3w==", + "node_modules/@nx/jest/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "dependencies": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/propagation-utils": "^0.30.11", - "@opentelemetry/semantic-conventions": "^1.27.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">=8" } }, - "node_modules/@opentelemetry/instrumentation-aws-sdk/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@nx/jest/node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" }, - "engines": { - "node": ">=14" + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-aws-sdk/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-bunyan": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-bunyan/-/instrumentation-bunyan-0.41.0.tgz", - "integrity": "sha512-NoQS+gcwQ7pzb2PZFyra6bAxDAVXBMmpKxBblEuXJWirGrAksQllg9XTdmqhrwT/KxUYrbVca/lMams7e51ysg==", + "node_modules/@nx/jest/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, "dependencies": { - "@opentelemetry/api-logs": "^0.53.0", - "@opentelemetry/instrumentation": "^0.53.0", - "@types/bunyan": "1.8.9" + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">=12" } }, - "node_modules/@opentelemetry/instrumentation-bunyan/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@nx/js": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/js/-/js-19.2.0.tgz", + "integrity": "sha512-cLz1OSfWpm/y0bZtdv5INlCo9/ED9tC45e6OKBc2ClW5Gz2+IoZz/dK/bCXg7dpEBtF1Y9mHihKisPOmUhaLwQ==", + "dev": true, "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" + "@babel/core": "^7.23.2", + "@babel/plugin-proposal-decorators": "^7.22.7", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-runtime": "^7.23.2", + "@babel/preset-env": "^7.23.2", + "@babel/preset-typescript": "^7.22.5", + "@babel/runtime": "^7.22.6", + "@nrwl/js": "19.2.0", + "@nx/devkit": "19.2.0", + "@nx/workspace": "19.2.0", + "babel-plugin-const-enum": "^1.0.1", + "babel-plugin-macros": "^2.8.0", + "babel-plugin-transform-typescript-metadata": "^0.3.1", + "chalk": "^4.1.0", + "columnify": "^1.6.0", + "detect-port": "^1.5.1", + "fast-glob": "3.2.7", + "fs-extra": "^11.1.0", + "ignore": "^5.0.4", + "js-tokens": "^4.0.0", + "minimatch": "9.0.3", + "npm-package-arg": "11.0.1", + "npm-run-path": "^4.0.1", + "ora": "5.3.0", + "semver": "^7.5.3", + "source-map-support": "0.5.19", + "ts-node": "10.9.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-bunyan/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "verdaccio": "^5.0.4" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "verdaccio": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-cassandra-driver": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-cassandra-driver/-/instrumentation-cassandra-driver-0.41.0.tgz", - "integrity": "sha512-hvTNcC8qjCQEHZTLAlTmDptjsEGqCKpN+90hHH8Nn/GwilGr5TMSwGrlfstdJuZWyw8HAnRUed6bcjvmHHk2Xw==", + "node_modules/@nx/js/node_modules/@nrwl/devkit": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.2.0.tgz", + "integrity": "sha512-Ew5AJZkLXJwt15HjaIbHve8FOXmZ3HK8KPqTXqwKHX8jQW+fDUCaSXKe/lCZMNg0RvY+jMNecuC86uGdiIbLMg==", + "dev": true, "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@nx/devkit": "19.2.0" } }, - "node_modules/@opentelemetry/instrumentation-cassandra-driver/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@nx/js/node_modules/@nrwl/tao": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.2.0.tgz", + "integrity": "sha512-9AOwbY/E7OlLCFu+6jhJGUIs+qurE2/3Pldooe7cJPqQmSQeJuVZuL6A2xHtbSG7VsXTq5Yj8dVvK1KmT45SIA==", + "dev": true, "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" + "nx": "19.2.0", + "tslib": "^2.3.0" }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "bin": { + "tao": "index.js" } }, - "node_modules/@opentelemetry/instrumentation-cassandra-driver/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "node_modules/@nx/js/node_modules/@nrwl/workspace": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-19.2.0.tgz", + "integrity": "sha512-/3p9KNpGHgEVjM5aMFhzdp0Vh+Bt16OnlSA+eSKPd5r0eQyLY+T4zTQ1kjyHGYa/xcN8vsWKEnbZW2fD/HWSng==", + "dev": true, + "dependencies": { + "@nx/workspace": "19.2.0" } }, - "node_modules/@opentelemetry/instrumentation-connect": { - "version": "0.39.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.39.0.tgz", - "integrity": "sha512-pGBiKevLq7NNglMgqzmeKczF4XQMTOUOTkK8afRHMZMnrK3fcETyTH7lVaSozwiOM3Ws+SuEmXZT7DYrrhxGlg==", + "node_modules/@nx/js/node_modules/@nx/devkit": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.2.0.tgz", + "integrity": "sha512-fK3zRUE2SLp9BUomFiyCuAX2E1yfWYE/hKimniscsvM34/u/xLZYVmmZ0/jfpGPbyaonXKZr2KTb7RimX/hyqg==", + "dev": true, "dependencies": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@types/connect": "3.4.36" - }, - "engines": { - "node": ">=14" + "@nrwl/devkit": "19.2.0", + "ejs": "^3.1.7", + "enquirer": "~2.3.6", + "ignore": "^5.0.4", + "minimatch": "9.0.3", + "semver": "^7.5.3", + "tmp": "~0.2.1", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "nx": ">= 17 <= 20" } }, - "node_modules/@opentelemetry/instrumentation-connect/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, + "node_modules/@nx/js/node_modules/@nx/nx-darwin-arm64": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.2.0.tgz", + "integrity": "sha512-W+OpGyzr10oaycf4atPc5uH2wN1G6LJGHkWDN3LGSQhoDWuj13idFpjSy6rJ8WxtL8kIvPXq78GEi1yAADsakA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-connect/node_modules/@types/connect": { - "version": "3.4.36", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.36.tgz", - "integrity": "sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==", - "dependencies": { - "@types/node": "*" + "node_modules/@nx/js/node_modules/@nx/nx-darwin-x64": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.2.0.tgz", + "integrity": "sha512-4l1BDn29R0ugf7ATcGcZGEwK0frZSCtiyXnX3JFq55dNS4Bv3FiZLew7JULjdumXEXr773bH326FQlocLVlcXg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-connect/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, + "node_modules/@nx/js/node_modules/@nx/nx-freebsd-x64": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.2.0.tgz", + "integrity": "sha512-9zdwLRSkEg/H7bbIVWATn0H8QNgnHaTe23tciZPaBr95J6CXVJWWpC4wn9duURhvbscnqUSSSfKK1f+MSEDTbw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=10" + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-cucumber": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-cucumber/-/instrumentation-cucumber-0.9.0.tgz", - "integrity": "sha512-4PQNFnIqnA2WM3ZHpr0xhZpHSqJ5xJ6ppTIzZC7wPqe+ZBpj41vG8B6ieqiPfq+im4QdqbYnzLb3rj48GDEN9g==", - "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, + "node_modules/@nx/js/node_modules/@nx/nx-linux-arm-gnueabihf": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.2.0.tgz", + "integrity": "sha512-KNVnqRPegJza3kU4q3pY8m0pT8OSQZnLGsDZti6morhXh2sE79f/zeevOrbhf8JnaJfQtyrXfGvjYAiL3+I8bw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-cucumber/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, + "node_modules/@nx/js/node_modules/@nx/nx-linux-arm64-gnu": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.2.0.tgz", + "integrity": "sha512-UXIl90l+cDecU17OOLlI+uzbjzQucnNu4Mee67EqE3TyfpSvuU1l3FWZ9sbE0effp8IwKpbL7Gt5KirJKtWzIA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-cucumber/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, + "node_modules/@nx/js/node_modules/@nx/nx-linux-arm64-musl": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.2.0.tgz", + "integrity": "sha512-4Z8XO3WljS2GWOL2SQ1p8SRNn2Kn6FU1FWClh7KBzMtpzjsHdmOXenMP9UOGZ6gBnfBIknCEDjE3uJUHmuShGg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10" + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-dataloader": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dataloader/-/instrumentation-dataloader-0.12.0.tgz", - "integrity": "sha512-pnPxatoFE0OXIZDQhL2okF//dmbiWFzcSc8pUg9TqofCLYZySSxDCgQc69CJBo5JnI3Gz1KP+mOjS4WAeRIH4g==", - "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0" - }, + "node_modules/@nx/js/node_modules/@nx/nx-linux-x64-gnu": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.2.0.tgz", + "integrity": "sha512-EwAkZEp0KB99VEPTskW2feCpSKqWScKdRd6UaIM9Vmqqtb5hSk6yR6p0mprjytbDtFVoKQJMOFa35qe+2R8mKQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-dataloader/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, + "node_modules/@nx/js/node_modules/@nx/nx-linux-x64-musl": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.2.0.tgz", + "integrity": "sha512-LbFcHe83YZUS/my/8nBxQ2i3JWakcXd7zbzZ0cSAQk6DuJVCUk8PLdgZzhrVcmT82Pv7H0fM/4jgEl+oHGoc/g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-dataloader/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, + "node_modules/@nx/js/node_modules/@nx/nx-win32-arm64-msvc": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.2.0.tgz", + "integrity": "sha512-BxOveRfRCdhuCs2GWbsdzGsjtLC3N+MuUlVaXSWADksF6/QKuCHM/2Kq3RYkLVVtlls6NCBp410RSx/XsbSEug==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=10" + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-dns": { - "version": "0.39.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dns/-/instrumentation-dns-0.39.0.tgz", - "integrity": "sha512-+iPzvXqVdJa67QBuz2tuP0UI3LS1/cMMo6dS7360DDtOQX+sQzkiN+mo3Omn4T6ZRhkTDw6c7uwsHBcmL31+1g==", - "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "semver": "^7.5.4" - }, + "node_modules/@nx/js/node_modules/@nx/nx-win32-x64-msvc": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.2.0.tgz", + "integrity": "sha512-QiDxtOHIiRka9Bz7tSpBvQgQPrX5grLhoz6miD6LX1WjO56bZIkEAVefGnMc3WZ1PacS1ZECtymHwUy+WpEqAQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-dns/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@nx/js/node_modules/@nx/workspace": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-19.2.0.tgz", + "integrity": "sha512-0wdv8jrGIGcf/ZF4r2/xWz/jrQjwftgLPmh7BawYPFbDZlRXkzb7a4MTJOxXH8QcR3ZJNhRjkFfHRPbB0luf1A==", + "dev": true, "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@nrwl/workspace": "19.2.0", + "@nx/devkit": "19.2.0", + "chalk": "^4.1.0", + "enquirer": "~2.3.6", + "nx": "19.2.0", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" } }, - "node_modules/@opentelemetry/instrumentation-dns/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "bin": { - "semver": "bin/semver.js" - }, + "node_modules/@nx/js/node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/@nx/js/node_modules/dotenv": { + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.2.tgz", + "integrity": "sha512-HTlk5nmhkm8F6JcdXvHIzaorzCoziNQT9mGxLPVXW8wJF1TiGSL60ZGB4gHWabHOaMmWmhvk2/lPHfnBiT78AQ==", + "dev": true, "engines": { - "node": ">=10" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" } }, - "node_modules/@opentelemetry/instrumentation-fastify": { - "version": "0.40.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fastify/-/instrumentation-fastify-0.40.0.tgz", - "integrity": "sha512-74qj4nG3zPtU7g2x4sm2T4R3/pBMyrYstTsqSZwdlhQk1SD4l8OSY9sPRX1qkhfxOuW3U4KZQAV/Cymb3fB6hg==", - "dependencies": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, + "node_modules/@nx/js/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/@nx/js/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">=8" } }, - "node_modules/@opentelemetry/instrumentation-fastify/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@nx/js/node_modules/nx": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/nx/-/nx-19.2.0.tgz", + "integrity": "sha512-IewqV0eGOpp569TSjfQVIQODxkRYKSDTP0e0j20GKkMTvCAmdbJRYZxyTr6Aw6gSM7lEVgK/4yESRO5YidfV2Q==", + "dev": true, + "hasInstallScript": true, "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" + "@nrwl/tao": "19.2.0", + "@yarnpkg/lockfile": "^1.1.0", + "@yarnpkg/parsers": "3.0.0-rc.46", + "@zkochan/js-yaml": "0.0.7", + "axios": "^1.6.0", + "chalk": "^4.1.0", + "cli-cursor": "3.1.0", + "cli-spinners": "2.6.1", + "cliui": "^8.0.1", + "dotenv": "~16.3.1", + "dotenv-expand": "~10.0.0", + "enquirer": "~2.3.6", + "figures": "3.2.0", + "flat": "^5.0.2", + "front-matter": "^4.0.2", + "fs-extra": "^11.1.0", + "ignore": "^5.0.4", + "jest-diff": "^29.4.1", + "jsonc-parser": "3.2.0", + "lines-and-columns": "~2.0.3", + "minimatch": "9.0.3", + "node-machine-id": "1.1.12", + "npm-run-path": "^4.0.1", + "open": "^8.4.0", + "ora": "5.3.0", + "semver": "^7.5.3", + "string-width": "^4.2.3", + "strong-log-transformer": "^2.1.0", + "tar-stream": "~2.2.0", + "tmp": "~0.2.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0", + "yargs": "^17.6.2", + "yargs-parser": "21.1.1" }, - "engines": { - "node": ">=14" + "bin": { + "nx": "bin/nx.js", + "nx-cloud": "bin/nx-cloud.js" + }, + "optionalDependencies": { + "@nx/nx-darwin-arm64": "19.2.0", + "@nx/nx-darwin-x64": "19.2.0", + "@nx/nx-freebsd-x64": "19.2.0", + "@nx/nx-linux-arm-gnueabihf": "19.2.0", + "@nx/nx-linux-arm64-gnu": "19.2.0", + "@nx/nx-linux-arm64-musl": "19.2.0", + "@nx/nx-linux-x64-gnu": "19.2.0", + "@nx/nx-linux-x64-musl": "19.2.0", + "@nx/nx-win32-arm64-msvc": "19.2.0", + "@nx/nx-win32-x64-msvc": "19.2.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@swc-node/register": "^1.8.0", + "@swc/core": "^1.3.85" + }, + "peerDependenciesMeta": { + "@swc-node/register": { + "optional": true + }, + "@swc/core": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-fastify/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", + "node_modules/@nx/js/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, "bin": { "semver": "bin/semver.js" }, @@ -21695,138 +9591,172 @@ "node": ">=10" } }, - "node_modules/@opentelemetry/instrumentation-fs": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fs/-/instrumentation-fs-0.15.0.tgz", - "integrity": "sha512-JWVKdNLpu1skqZQA//jKOcKdJC66TWKqa2FUFq70rKohvaSq47pmXlnabNO+B/BvLfmidfiaN35XakT5RyMl2Q==", + "node_modules/@nx/js/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "dependencies": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.53.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">=8" } }, - "node_modules/@opentelemetry/instrumentation-fs/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@nx/js/node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" }, - "engines": { - "node": ">=14" + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-fs/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/@nx/js/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" }, "engines": { - "node": ">=10" + "node": ">=12" } }, - "node_modules/@opentelemetry/instrumentation-generic-pool": { - "version": "0.39.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.39.0.tgz", - "integrity": "sha512-y4v8Y+tSfRB3NNBvHjbjrn7rX/7sdARG7FuK6zR8PGb28CTa0kHpEGCJqvL9L8xkTNvTXo+lM36ajFGUaK1aNw==", + "node_modules/@nx/linter": { + "version": "19.3.2", + "resolved": "https://registry.npmjs.org/@nx/linter/-/linter-19.3.2.tgz", + "integrity": "sha512-ODGoo0Xcl+zjRrAfcNrMoOk8m/RnDSF7kr1nXLwfNv7VnMm4gcqmwLePfvA/nQZdaNQjaweQ22OOVEAfyrmqFw==", + "dev": true, "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@nx/eslint": "19.3.2" } }, - "node_modules/@opentelemetry/instrumentation-generic-pool/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@nx/nest": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nest/-/nest-19.2.0.tgz", + "integrity": "sha512-soFP2FpznJuGQ5+MoCdBft2I4ldU0kvkoluGn9bt89D1K3NJGbnp6YS8Hu19nlsgovN27SZXCK0AtVFmxLFfHQ==", + "dev": true, "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@nestjs/schematics": "^9.1.0", + "@nrwl/nest": "19.2.0", + "@nx/devkit": "19.2.0", + "@nx/eslint": "19.2.0", + "@nx/js": "19.2.0", + "@nx/node": "19.2.0", + "@phenomnomnominal/tsquery": "~5.0.1", + "tslib": "^2.3.0" + } + }, + "node_modules/@nx/nest/node_modules/@nrwl/devkit": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.2.0.tgz", + "integrity": "sha512-Ew5AJZkLXJwt15HjaIbHve8FOXmZ3HK8KPqTXqwKHX8jQW+fDUCaSXKe/lCZMNg0RvY+jMNecuC86uGdiIbLMg==", + "dev": true, + "dependencies": { + "@nx/devkit": "19.2.0" } }, - "node_modules/@opentelemetry/instrumentation-generic-pool/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/@nx/nest/node_modules/@nx/devkit": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.2.0.tgz", + "integrity": "sha512-fK3zRUE2SLp9BUomFiyCuAX2E1yfWYE/hKimniscsvM34/u/xLZYVmmZ0/jfpGPbyaonXKZr2KTb7RimX/hyqg==", + "dev": true, + "dependencies": { + "@nrwl/devkit": "19.2.0", + "ejs": "^3.1.7", + "enquirer": "~2.3.6", + "ignore": "^5.0.4", + "minimatch": "9.0.3", + "semver": "^7.5.3", + "tmp": "~0.2.1", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" }, - "engines": { - "node": ">=10" + "peerDependencies": { + "nx": ">= 17 <= 20" } }, - "node_modules/@opentelemetry/instrumentation-graphql": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.43.0.tgz", - "integrity": "sha512-aI3YMmC2McGd8KW5du1a2gBA0iOMOGLqg4s9YjzwbjFwjlmMNFSK1P3AIg374GWg823RPUGfVTIgZ/juk9CVOA==", + "node_modules/@nx/nest/node_modules/@nx/eslint": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/eslint/-/eslint-19.2.0.tgz", + "integrity": "sha512-9OIMntrLDPrQNZjYxOncIX+65r4RhV2dJ3PrjJ9lwCVqJKZGxfCn6f8JK8ubeLoWFPVjKEtfLTHK529vvfXifQ==", + "dev": true, "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0" - }, - "engines": { - "node": ">=14" + "@nx/devkit": "19.2.0", + "@nx/js": "19.2.0", + "@nx/linter": "19.2.0", + "semver": "^7.5.3", + "tslib": "^2.3.0", + "typescript": "~5.4.2" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@zkochan/js-yaml": "0.0.7", + "eslint": "^8.0.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "@zkochan/js-yaml": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-graphql/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@nx/nest/node_modules/@nx/linter": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/linter/-/linter-19.2.0.tgz", + "integrity": "sha512-Rahjy3+OLc4aXT8VNXpwyMozeU4RB6HIQOh5NAdcA6PoOH8cG1VtbyjryIZE8l5HT1hrpI5EkONZt1UXiIGw3w==", + "dev": true, "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@nx/eslint": "19.2.0" } }, - "node_modules/@opentelemetry/instrumentation-graphql/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", + "node_modules/@nx/nest/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, "bin": { "semver": "bin/semver.js" }, @@ -21834,570 +9764,658 @@ "node": ">=10" } }, - "node_modules/@opentelemetry/instrumentation-grpc": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-grpc/-/instrumentation-grpc-0.53.0.tgz", - "integrity": "sha512-Ss338T92yE1UCgr9zXSY3cPuaAy27uQw+wAC5IwsQKCXL5wwkiOgkd+2Ngksa9EGsgUEMwGeHi76bDdHFJ5Rrw==", + "node_modules/@nx/next": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/next/-/next-19.2.0.tgz", + "integrity": "sha512-GL/5J80rKL5ZWmsyUxiB8aEeKy4XC8Gb+9xhV6RunCF/hOQI+B/ScHQW0N7mgYoD86QL40HhvFIa7qYbKjQwnw==", + "dev": true, "dependencies": { - "@opentelemetry/instrumentation": "0.53.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" + "@babel/plugin-proposal-decorators": "^7.22.7", + "@nrwl/next": "19.2.0", + "@nx/devkit": "19.2.0", + "@nx/eslint": "19.2.0", + "@nx/js": "19.2.0", + "@nx/react": "19.2.0", + "@nx/web": "19.2.0", + "@nx/webpack": "19.2.0", + "@nx/workspace": "19.2.0", + "@svgr/webpack": "^8.0.1", + "chalk": "^4.1.0", + "copy-webpack-plugin": "^10.2.4", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.0", + "ignore": "^5.0.4", + "semver": "^7.5.3", + "tslib": "^2.3.0", + "webpack-merge": "^5.8.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "next": ">=14.0.0" } }, - "node_modules/@opentelemetry/instrumentation-grpc/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@nx/next/node_modules/@nrwl/devkit": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.2.0.tgz", + "integrity": "sha512-Ew5AJZkLXJwt15HjaIbHve8FOXmZ3HK8KPqTXqwKHX8jQW+fDUCaSXKe/lCZMNg0RvY+jMNecuC86uGdiIbLMg==", + "dev": true, "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@nx/devkit": "19.2.0" } }, - "node_modules/@opentelemetry/instrumentation-grpc/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/@nx/next/node_modules/@nrwl/tao": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.2.0.tgz", + "integrity": "sha512-9AOwbY/E7OlLCFu+6jhJGUIs+qurE2/3Pldooe7cJPqQmSQeJuVZuL6A2xHtbSG7VsXTq5Yj8dVvK1KmT45SIA==", + "dev": true, + "dependencies": { + "nx": "19.2.0", + "tslib": "^2.3.0" }, - "engines": { - "node": ">=10" + "bin": { + "tao": "index.js" } }, - "node_modules/@opentelemetry/instrumentation-hapi": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.41.0.tgz", - "integrity": "sha512-jKDrxPNXDByPlYcMdZjNPYCvw0SQJjN+B1A+QH+sx+sAHsKSAf9hwFiJSrI6C4XdOls43V/f/fkp9ITkHhKFbQ==", + "node_modules/@nx/next/node_modules/@nrwl/tao/node_modules/nx": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/nx/-/nx-19.2.0.tgz", + "integrity": "sha512-IewqV0eGOpp569TSjfQVIQODxkRYKSDTP0e0j20GKkMTvCAmdbJRYZxyTr6Aw6gSM7lEVgK/4yESRO5YidfV2Q==", + "dev": true, + "hasInstallScript": true, "dependencies": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0" + "@nrwl/tao": "19.2.0", + "@yarnpkg/lockfile": "^1.1.0", + "@yarnpkg/parsers": "3.0.0-rc.46", + "@zkochan/js-yaml": "0.0.7", + "axios": "^1.6.0", + "chalk": "^4.1.0", + "cli-cursor": "3.1.0", + "cli-spinners": "2.6.1", + "cliui": "^8.0.1", + "dotenv": "~16.3.1", + "dotenv-expand": "~10.0.0", + "enquirer": "~2.3.6", + "figures": "3.2.0", + "flat": "^5.0.2", + "front-matter": "^4.0.2", + "fs-extra": "^11.1.0", + "ignore": "^5.0.4", + "jest-diff": "^29.4.1", + "jsonc-parser": "3.2.0", + "lines-and-columns": "~2.0.3", + "minimatch": "9.0.3", + "node-machine-id": "1.1.12", + "npm-run-path": "^4.0.1", + "open": "^8.4.0", + "ora": "5.3.0", + "semver": "^7.5.3", + "string-width": "^4.2.3", + "strong-log-transformer": "^2.1.0", + "tar-stream": "~2.2.0", + "tmp": "~0.2.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0", + "yargs": "^17.6.2", + "yargs-parser": "21.1.1" }, - "engines": { - "node": ">=14" + "bin": { + "nx": "bin/nx.js", + "nx-cloud": "bin/nx-cloud.js" + }, + "optionalDependencies": { + "@nx/nx-darwin-arm64": "19.2.0", + "@nx/nx-darwin-x64": "19.2.0", + "@nx/nx-freebsd-x64": "19.2.0", + "@nx/nx-linux-arm-gnueabihf": "19.2.0", + "@nx/nx-linux-arm64-gnu": "19.2.0", + "@nx/nx-linux-arm64-musl": "19.2.0", + "@nx/nx-linux-x64-gnu": "19.2.0", + "@nx/nx-linux-x64-musl": "19.2.0", + "@nx/nx-win32-arm64-msvc": "19.2.0", + "@nx/nx-win32-x64-msvc": "19.2.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@swc-node/register": "^1.8.0", + "@swc/core": "^1.3.85" + }, + "peerDependenciesMeta": { + "@swc-node/register": { + "optional": true + }, + "@swc/core": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-hapi/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@nx/next/node_modules/@nrwl/webpack": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/webpack/-/webpack-19.2.0.tgz", + "integrity": "sha512-lYj7T967iCgo6fWzZ727oYnmtdKHhM/6A8Li945iWLg+wY/IJdTevaU+0uEvmeSsGFyr0a0DZJ1todk0gHs0Kw==", + "dev": true, "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@nx/webpack": "19.2.0" } }, - "node_modules/@opentelemetry/instrumentation-hapi/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "node_modules/@nx/next/node_modules/@nrwl/workspace": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-19.2.0.tgz", + "integrity": "sha512-/3p9KNpGHgEVjM5aMFhzdp0Vh+Bt16OnlSA+eSKPd5r0eQyLY+T4zTQ1kjyHGYa/xcN8vsWKEnbZW2fD/HWSng==", + "dev": true, + "dependencies": { + "@nx/workspace": "19.2.0" } }, - "node_modules/@opentelemetry/instrumentation-ioredis": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.43.0.tgz", - "integrity": "sha512-i3Dke/LdhZbiUAEImmRG3i7Dimm/BD7t8pDDzwepSvIQ6s2X6FPia7561gw+64w+nx0+G9X14D7rEfaMEmmjig==", + "node_modules/@nx/next/node_modules/@nx/devkit": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.2.0.tgz", + "integrity": "sha512-fK3zRUE2SLp9BUomFiyCuAX2E1yfWYE/hKimniscsvM34/u/xLZYVmmZ0/jfpGPbyaonXKZr2KTb7RimX/hyqg==", + "dev": true, "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/redis-common": "^0.36.2", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@nrwl/devkit": "19.2.0", + "ejs": "^3.1.7", + "enquirer": "~2.3.6", + "ignore": "^5.0.4", + "minimatch": "9.0.3", + "semver": "^7.5.3", + "tmp": "~0.2.1", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "nx": ">= 17 <= 20" } }, - "node_modules/@opentelemetry/instrumentation-ioredis/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@nx/next/node_modules/@nx/eslint": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/eslint/-/eslint-19.2.0.tgz", + "integrity": "sha512-9OIMntrLDPrQNZjYxOncIX+65r4RhV2dJ3PrjJ9lwCVqJKZGxfCn6f8JK8ubeLoWFPVjKEtfLTHK529vvfXifQ==", + "dev": true, "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" + "@nx/devkit": "19.2.0", + "@nx/js": "19.2.0", + "@nx/linter": "19.2.0", + "semver": "^7.5.3", + "tslib": "^2.3.0", + "typescript": "~5.4.2" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-ioredis/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "@zkochan/js-yaml": "0.0.7", + "eslint": "^8.0.0 || ^9.0.0" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "@zkochan/js-yaml": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-kafkajs": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-kafkajs/-/instrumentation-kafkajs-0.3.0.tgz", - "integrity": "sha512-UnkZueYK1ise8FXQeKlpBd7YYUtC7mM8J0wzUSccEfc/G8UqHQqAzIyYCUOUPUKp8GsjLnWOOK/3hJc4owb7Jg==", + "node_modules/@nx/next/node_modules/@nx/linter": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/linter/-/linter-19.2.0.tgz", + "integrity": "sha512-Rahjy3+OLc4aXT8VNXpwyMozeU4RB6HIQOh5NAdcA6PoOH8cG1VtbyjryIZE8l5HT1hrpI5EkONZt1UXiIGw3w==", + "dev": true, "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@nx/eslint": "19.2.0" } }, - "node_modules/@opentelemetry/instrumentation-kafkajs/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, + "node_modules/@nx/next/node_modules/@nx/nx-darwin-arm64": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.2.0.tgz", + "integrity": "sha512-W+OpGyzr10oaycf4atPc5uH2wN1G6LJGHkWDN3LGSQhoDWuj13idFpjSy6rJ8WxtL8kIvPXq78GEi1yAADsakA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-kafkajs/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, + "node_modules/@nx/next/node_modules/@nx/nx-darwin-x64": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.2.0.tgz", + "integrity": "sha512-4l1BDn29R0ugf7ATcGcZGEwK0frZSCtiyXnX3JFq55dNS4Bv3FiZLew7JULjdumXEXr773bH326FQlocLVlcXg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=10" + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-knex": { - "version": "0.40.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-knex/-/instrumentation-knex-0.40.0.tgz", - "integrity": "sha512-6jka2jfX8+fqjEbCn6hKWHVWe++mHrIkLQtaJqUkBt3ZBs2xn1+y0khxiDS0v/mNb0bIKDJWwtpKFfsQDM1Geg==", - "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, + "node_modules/@nx/next/node_modules/@nx/nx-freebsd-x64": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.2.0.tgz", + "integrity": "sha512-9zdwLRSkEg/H7bbIVWATn0H8QNgnHaTe23tciZPaBr95J6CXVJWWpC4wn9duURhvbscnqUSSSfKK1f+MSEDTbw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-knex/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, + "node_modules/@nx/next/node_modules/@nx/nx-linux-arm-gnueabihf": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.2.0.tgz", + "integrity": "sha512-KNVnqRPegJza3kU4q3pY8m0pT8OSQZnLGsDZti6morhXh2sE79f/zeevOrbhf8JnaJfQtyrXfGvjYAiL3+I8bw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-knex/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, + "node_modules/@nx/next/node_modules/@nx/nx-linux-arm64-gnu": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.2.0.tgz", + "integrity": "sha512-UXIl90l+cDecU17OOLlI+uzbjzQucnNu4Mee67EqE3TyfpSvuU1l3FWZ9sbE0effp8IwKpbL7Gt5KirJKtWzIA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10" + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-koa": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.43.0.tgz", - "integrity": "sha512-lDAhSnmoTIN6ELKmLJBplXzT/Jqs5jGZehuG22EdSMaTwgjMpxMDI1YtlKEhiWPWkrz5LUsd0aOO0ZRc9vn3AQ==", - "dependencies": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, + "node_modules/@nx/next/node_modules/@nx/nx-linux-arm64-musl": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.2.0.tgz", + "integrity": "sha512-4Z8XO3WljS2GWOL2SQ1p8SRNn2Kn6FU1FWClh7KBzMtpzjsHdmOXenMP9UOGZ6gBnfBIknCEDjE3uJUHmuShGg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-koa/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, + "node_modules/@nx/next/node_modules/@nx/nx-linux-x64-gnu": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.2.0.tgz", + "integrity": "sha512-EwAkZEp0KB99VEPTskW2feCpSKqWScKdRd6UaIM9Vmqqtb5hSk6yR6p0mprjytbDtFVoKQJMOFa35qe+2R8mKQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-koa/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, + "node_modules/@nx/next/node_modules/@nx/nx-linux-x64-musl": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.2.0.tgz", + "integrity": "sha512-LbFcHe83YZUS/my/8nBxQ2i3JWakcXd7zbzZ0cSAQk6DuJVCUk8PLdgZzhrVcmT82Pv7H0fM/4jgEl+oHGoc/g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10" + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-lru-memoizer": { - "version": "0.40.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-lru-memoizer/-/instrumentation-lru-memoizer-0.40.0.tgz", - "integrity": "sha512-21xRwZsEdMPnROu/QsaOIODmzw59IYpGFmuC4aFWvMj6stA8+Ei1tX67nkarJttlNjoM94um0N4X26AD7ff54A==", - "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0" - }, + "node_modules/@nx/next/node_modules/@nx/nx-win32-arm64-msvc": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.2.0.tgz", + "integrity": "sha512-BxOveRfRCdhuCs2GWbsdzGsjtLC3N+MuUlVaXSWADksF6/QKuCHM/2Kq3RYkLVVtlls6NCBp410RSx/XsbSEug==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-lru-memoizer/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, + "node_modules/@nx/next/node_modules/@nx/nx-win32-x64-msvc": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.2.0.tgz", + "integrity": "sha512-QiDxtOHIiRka9Bz7tSpBvQgQPrX5grLhoz6miD6LX1WjO56bZIkEAVefGnMc3WZ1PacS1ZECtymHwUy+WpEqAQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-lru-memoizer/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "node_modules/@nx/next/node_modules/@nx/webpack": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/webpack/-/webpack-19.2.0.tgz", + "integrity": "sha512-/YGLknUIOmYd2r1DOUcyDnHJ4tZeVU6iHnuqUx2zv6pVZYnBs2cW6JjejH6s+n6y8hMQ7H/mXa7RR2eQI2KgaQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.23.2", + "@nrwl/webpack": "19.2.0", + "@nx/devkit": "19.2.0", + "@nx/js": "19.2.0", + "ajv": "^8.12.0", + "autoprefixer": "^10.4.9", + "babel-loader": "^9.1.2", + "browserslist": "^4.21.4", + "chalk": "^4.1.0", + "copy-webpack-plugin": "^10.2.4", + "css-loader": "^6.4.0", + "css-minimizer-webpack-plugin": "^5.0.0", + "fork-ts-checker-webpack-plugin": "7.2.13", + "less": "4.1.3", + "less-loader": "11.1.0", + "license-webpack-plugin": "^4.0.2", + "loader-utils": "^2.0.3", + "mini-css-extract-plugin": "~2.4.7", + "parse5": "4.0.0", + "postcss": "^8.4.38", + "postcss-import": "~14.1.0", + "postcss-loader": "^6.1.1", + "rxjs": "^7.8.0", + "sass": "^1.42.1", + "sass-loader": "^12.2.0", + "source-map-loader": "^3.0.0", + "style-loader": "^3.3.0", + "stylus": "^0.59.0", + "stylus-loader": "^7.1.0", + "terser-webpack-plugin": "^5.3.3", + "ts-loader": "^9.3.1", + "tsconfig-paths-webpack-plugin": "4.0.0", + "tslib": "^2.3.0", + "webpack": "^5.80.0", + "webpack-dev-server": "^4.9.3", + "webpack-node-externals": "^3.0.0", + "webpack-subresource-integrity": "^5.1.0" } }, - "node_modules/@opentelemetry/instrumentation-memcached": { - "version": "0.39.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-memcached/-/instrumentation-memcached-0.39.0.tgz", - "integrity": "sha512-WfwvKAZ9I1qILRP5EUd88HQjwAAL+trXpCpozjBi4U6a0A07gB3fZ5PFAxbXemSjF5tHk9KVoROnqHvQ+zzFSQ==", + "node_modules/@nx/next/node_modules/@nx/workspace": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-19.2.0.tgz", + "integrity": "sha512-0wdv8jrGIGcf/ZF4r2/xWz/jrQjwftgLPmh7BawYPFbDZlRXkzb7a4MTJOxXH8QcR3ZJNhRjkFfHRPbB0luf1A==", + "dev": true, "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@types/memcached": "^2.2.6" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@nrwl/workspace": "19.2.0", + "@nx/devkit": "19.2.0", + "chalk": "^4.1.0", + "enquirer": "~2.3.6", + "nx": "19.2.0", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" } }, - "node_modules/@opentelemetry/instrumentation-memcached/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@nx/next/node_modules/@nx/workspace/node_modules/nx": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/nx/-/nx-19.2.0.tgz", + "integrity": "sha512-IewqV0eGOpp569TSjfQVIQODxkRYKSDTP0e0j20GKkMTvCAmdbJRYZxyTr6Aw6gSM7lEVgK/4yESRO5YidfV2Q==", + "dev": true, + "hasInstallScript": true, "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" + "@nrwl/tao": "19.2.0", + "@yarnpkg/lockfile": "^1.1.0", + "@yarnpkg/parsers": "3.0.0-rc.46", + "@zkochan/js-yaml": "0.0.7", + "axios": "^1.6.0", + "chalk": "^4.1.0", + "cli-cursor": "3.1.0", + "cli-spinners": "2.6.1", + "cliui": "^8.0.1", + "dotenv": "~16.3.1", + "dotenv-expand": "~10.0.0", + "enquirer": "~2.3.6", + "figures": "3.2.0", + "flat": "^5.0.2", + "front-matter": "^4.0.2", + "fs-extra": "^11.1.0", + "ignore": "^5.0.4", + "jest-diff": "^29.4.1", + "jsonc-parser": "3.2.0", + "lines-and-columns": "~2.0.3", + "minimatch": "9.0.3", + "node-machine-id": "1.1.12", + "npm-run-path": "^4.0.1", + "open": "^8.4.0", + "ora": "5.3.0", + "semver": "^7.5.3", + "string-width": "^4.2.3", + "strong-log-transformer": "^2.1.0", + "tar-stream": "~2.2.0", + "tmp": "~0.2.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0", + "yargs": "^17.6.2", + "yargs-parser": "21.1.1" }, - "engines": { - "node": ">=14" + "bin": { + "nx": "bin/nx.js", + "nx-cloud": "bin/nx-cloud.js" + }, + "optionalDependencies": { + "@nx/nx-darwin-arm64": "19.2.0", + "@nx/nx-darwin-x64": "19.2.0", + "@nx/nx-freebsd-x64": "19.2.0", + "@nx/nx-linux-arm-gnueabihf": "19.2.0", + "@nx/nx-linux-arm64-gnu": "19.2.0", + "@nx/nx-linux-arm64-musl": "19.2.0", + "@nx/nx-linux-x64-gnu": "19.2.0", + "@nx/nx-linux-x64-musl": "19.2.0", + "@nx/nx-win32-arm64-msvc": "19.2.0", + "@nx/nx-win32-x64-msvc": "19.2.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-memcached/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "@swc-node/register": "^1.8.0", + "@swc/core": "^1.3.85" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "@swc-node/register": { + "optional": true + }, + "@swc/core": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-mongodb": { - "version": "0.47.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.47.0.tgz", - "integrity": "sha512-yqyXRx2SulEURjgOQyJzhCECSh5i1uM49NUaq9TqLd6fA7g26OahyJfsr9NE38HFqGRHpi4loyrnfYGdrsoVjQ==", - "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/sdk-metrics": "^1.9.1", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, + "node_modules/@nx/next/node_modules/array-union": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz", + "integrity": "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==", + "dev": true, "engines": { - "node": ">=14" + "node": ">=12" }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@opentelemetry/instrumentation-mongodb/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@nx/next/node_modules/copy-webpack-plugin": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz", + "integrity": "sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg==", + "dev": true, "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" + "fast-glob": "^3.2.7", + "glob-parent": "^6.0.1", + "globby": "^12.0.2", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0" }, "engines": { - "node": ">=14" + "node": ">= 12.20.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "webpack": "^5.1.0" } }, - "node_modules/@opentelemetry/instrumentation-mongodb/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/@nx/next/node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dev": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" }, "engines": { "node": ">=10" } }, - "node_modules/@opentelemetry/instrumentation-mongoose": { - "version": "0.42.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.42.0.tgz", - "integrity": "sha512-AnWv+RaR86uG3qNEMwt3plKX1ueRM7AspfszJYVkvkehiicC3bHQA6vWdb6Zvy5HAE14RyFbu9+2hUUjR2NSyg==", - "dependencies": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, + "node_modules/@nx/next/node_modules/dotenv": { + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.2.tgz", + "integrity": "sha512-HTlk5nmhkm8F6JcdXvHIzaorzCoziNQT9mGxLPVXW8wJF1TiGSL60ZGB4gHWabHOaMmWmhvk2/lPHfnBiT78AQ==", + "dev": true, "engines": { - "node": ">=14" + "node": ">=12" }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" } }, - "node_modules/@opentelemetry/instrumentation-mongoose/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } + "node_modules/@nx/next/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, - "node_modules/@opentelemetry/instrumentation-mongoose/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/@nx/next/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" }, "engines": { - "node": ">=10" + "node": ">=10.13.0" } }, - "node_modules/@opentelemetry/instrumentation-mysql": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.41.0.tgz", - "integrity": "sha512-jnvrV6BsQWyHS2qb2fkfbfSb1R/lmYwqEZITwufuRl37apTopswu9izc0b1CYRp/34tUG/4k/V39PND6eyiNvw==", + "node_modules/@nx/next/node_modules/globby": { + "version": "12.2.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-12.2.0.tgz", + "integrity": "sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA==", + "dev": true, "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@types/mysql": "2.15.26" + "array-union": "^3.0.1", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.7", + "ignore": "^5.1.9", + "merge2": "^1.4.1", + "slash": "^4.0.0" }, "engines": { - "node": ">=14" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@opentelemetry/instrumentation-mysql/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@nx/next/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">=0.10.0" } }, - "node_modules/@opentelemetry/instrumentation-mysql/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, + "node_modules/@nx/next/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/@opentelemetry/instrumentation-mysql2": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.41.0.tgz", - "integrity": "sha512-REQB0x+IzVTpoNgVmy5b+UnH1/mDByrneimP6sbDHkp1j8QOl1HyWOrBH/6YWR0nrbU3l825Em5PlybjT3232g==", + "node_modules/@nx/next/node_modules/mini-css-extract-plugin": { + "version": "2.4.7", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.4.7.tgz", + "integrity": "sha512-euWmddf0sk9Nv1O0gfeeUAvAkoSlWncNLF77C0TP2+WoPvy8mAHKOzMajcCz2dzvyt3CNgxb1obIEVFIRxaipg==", + "dev": true, "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@opentelemetry/sql-common": "^0.40.1" + "schema-utils": "^4.0.0" }, "engines": { - "node": ">=14" + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "webpack": "^5.0.0" } }, - "node_modules/@opentelemetry/instrumentation-mysql2/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@nx/next/node_modules/postcss-loader": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", + "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", + "dev": true, "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" + "cosmiconfig": "^7.0.0", + "klona": "^2.0.5", + "semver": "^7.3.5" }, "engines": { - "node": ">=14" + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" } }, - "node_modules/@opentelemetry/instrumentation-mysql2/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", + "node_modules/@nx/next/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, "bin": { "semver": "bin/semver.js" }, @@ -22405,97 +10423,184 @@ "node": ">=10" } }, - "node_modules/@opentelemetry/instrumentation-net": { - "version": "0.39.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-net/-/instrumentation-net-0.39.0.tgz", - "integrity": "sha512-rixHoODfI/Cx1B0mH1BpxCT0bRSxktuBDrt9IvpT2KSEutK5hR0RsRdgdz/GKk+BQ4u+IG6godgMSGwNQCueEA==", + "node_modules/@nx/next/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@nx/next/node_modules/source-map-loader": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-3.0.2.tgz", + "integrity": "sha512-BokxPoLjyl3iOrgkWaakaxqnelAJSS+0V+De0kKIq6lyWrXuiPgYTGp6z3iHmqljKAaLXwZa+ctD8GccRJeVvg==", + "dev": true, "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0" + "abab": "^2.0.5", + "iconv-lite": "^0.6.3", + "source-map-js": "^1.0.1" }, "engines": { - "node": ">=14" + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "webpack": "^5.0.0" } }, - "node_modules/@opentelemetry/instrumentation-net/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@nx/next/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">=8" } }, - "node_modules/@opentelemetry/instrumentation-net/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "node_modules/@nx/next/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, "engines": { - "node": ">=10" + "node": ">= 6" } }, - "node_modules/@opentelemetry/instrumentation-pg": { - "version": "0.46.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.46.0.tgz", - "integrity": "sha512-PLbYYC7EIoigh9uzhBrDjyL4yhH9akjV2Mln3ci9+lD7p9HE5nUUgYCgcUasyr4bz99c8xy9ErzKLt38Y7Kodg==", + "node_modules/@nx/next/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, "dependencies": { - "@opentelemetry/core": "^1.26.0", - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "1.27.0", - "@opentelemetry/sql-common": "^0.40.1", - "@types/pg": "8.6.1", - "@types/pg-pool": "2.0.6" + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" }, "engines": { - "node": ">=14" + "node": ">=12" + } + }, + "node_modules/@nx/node": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/node/-/node-19.2.0.tgz", + "integrity": "sha512-d4VnUY5i4nWw2dIkc3OJx4tiBNPsym9Xvq0XyyHjCn3DXTFOH9UiYpVR3kOL/22DeQs8hGOkb3jaSNdi2W8Dlg==", + "dev": true, + "dependencies": { + "@nrwl/node": "19.2.0", + "@nx/devkit": "19.2.0", + "@nx/eslint": "19.2.0", + "@nx/jest": "19.2.0", + "@nx/js": "19.2.0", + "tslib": "^2.3.0" + } + }, + "node_modules/@nx/node/node_modules/@nrwl/devkit": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.2.0.tgz", + "integrity": "sha512-Ew5AJZkLXJwt15HjaIbHve8FOXmZ3HK8KPqTXqwKHX8jQW+fDUCaSXKe/lCZMNg0RvY+jMNecuC86uGdiIbLMg==", + "dev": true, + "dependencies": { + "@nx/devkit": "19.2.0" + } + }, + "node_modules/@nx/node/node_modules/@nx/devkit": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.2.0.tgz", + "integrity": "sha512-fK3zRUE2SLp9BUomFiyCuAX2E1yfWYE/hKimniscsvM34/u/xLZYVmmZ0/jfpGPbyaonXKZr2KTb7RimX/hyqg==", + "dev": true, + "dependencies": { + "@nrwl/devkit": "19.2.0", + "ejs": "^3.1.7", + "enquirer": "~2.3.6", + "ignore": "^5.0.4", + "minimatch": "9.0.3", + "semver": "^7.5.3", + "tmp": "~0.2.1", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "nx": ">= 17 <= 20" } }, - "node_modules/@opentelemetry/instrumentation-pg/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@nx/node/node_modules/@nx/eslint": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/eslint/-/eslint-19.2.0.tgz", + "integrity": "sha512-9OIMntrLDPrQNZjYxOncIX+65r4RhV2dJ3PrjJ9lwCVqJKZGxfCn6f8JK8ubeLoWFPVjKEtfLTHK529vvfXifQ==", + "dev": true, "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" + "@nx/devkit": "19.2.0", + "@nx/js": "19.2.0", + "@nx/linter": "19.2.0", + "semver": "^7.5.3", + "tslib": "^2.3.0", + "typescript": "~5.4.2" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@zkochan/js-yaml": "0.0.7", + "eslint": "^8.0.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "@zkochan/js-yaml": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-pg/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", + "node_modules/@nx/node/node_modules/@nx/jest": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/jest/-/jest-19.2.0.tgz", + "integrity": "sha512-iJMqfwkIB4T7NRYAQe3nZWFEAQGGblMGcxWczMKEixCIZWcAz4up74eb0H6Yv+tUVOQHrFTm6J1OnrW3BqvOZA==", + "dev": true, + "dependencies": { + "@jest/reporters": "^29.4.1", + "@jest/test-result": "^29.4.1", + "@nrwl/jest": "19.2.0", + "@nx/devkit": "19.2.0", + "@nx/js": "19.2.0", + "@phenomnomnominal/tsquery": "~5.0.1", + "chalk": "^4.1.0", + "identity-obj-proxy": "3.0.0", + "jest-config": "^29.4.1", + "jest-resolve": "^29.4.1", + "jest-util": "^29.4.1", + "minimatch": "9.0.3", + "resolve.exports": "1.1.0", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" + } + }, + "node_modules/@nx/node/node_modules/@nx/linter": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/linter/-/linter-19.2.0.tgz", + "integrity": "sha512-Rahjy3+OLc4aXT8VNXpwyMozeU4RB6HIQOh5NAdcA6PoOH8cG1VtbyjryIZE8l5HT1hrpI5EkONZt1UXiIGw3w==", + "dev": true, + "dependencies": { + "@nx/eslint": "19.2.0" + } + }, + "node_modules/@nx/node/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, "bin": { "semver": "bin/semver.js" }, @@ -22503,111 +10608,251 @@ "node": ">=10" } }, - "node_modules/@opentelemetry/instrumentation-pino": { - "version": "0.42.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pino/-/instrumentation-pino-0.42.0.tgz", - "integrity": "sha512-SoX6FzucBfTuFNMZjdurJhcYWq2ve8/LkhmyVLUW31HpIB45RF1JNum0u4MkGisosDmXlK4njomcgUovShI+WA==", - "dependencies": { - "@opentelemetry/api-logs": "^0.53.0", - "@opentelemetry/core": "^1.25.0", - "@opentelemetry/instrumentation": "^0.53.0" - }, + "node_modules/@nx/nx-darwin-arm64": { + "version": "19.4.4", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.4.4.tgz", + "integrity": "sha512-qmPz1PYsV1zlpSWBHLmy3J7Hw5H5pPWAps6ObcxwUuQwli6uySi4OKFKCLnmWgi1ICvB2NviChK45OIDtxJ2Iw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-pino/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, + "node_modules/@nx/nx-darwin-x64": { + "version": "19.4.4", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.4.4.tgz", + "integrity": "sha512-/M+KQrjaIovhTP81BGMQ3AezSy9ZYhubXg7G3ltcMfox07yw5Pj10Ip9ZwkE5zF6CuJXNAoLesmNhbqMXodsag==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-pino/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, + "node_modules/@nx/nx-freebsd-x64": { + "version": "19.4.4", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.4.4.tgz", + "integrity": "sha512-PegR8GgHn24/eXqVRme3iRPHVYmH94rSBNoKOrWHJ8RTA/Dw+ZoOmhdLssOSs6z7JQ0S63MKo8x/HILI3+WyXw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=10" + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-redis": { - "version": "0.42.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis/-/instrumentation-redis-0.42.0.tgz", - "integrity": "sha512-jZBoqve0rEC51q0HuhjtZVq1DtUvJHzEJ3YKGvzGar2MU1J4Yt5+pQAQYh1W4jSoDyKeaI4hyeUdWM5N0c2lqA==", - "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/redis-common": "^0.36.2", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, + "node_modules/@nx/nx-linux-arm-gnueabihf": { + "version": "19.4.4", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.4.4.tgz", + "integrity": "sha512-6Yz0aTR8XE/MXpjbQ5HRlGcngYXUv156tJeynO8lyiZ0HK1RkUq+MsbSLw0zvqBUljWQwQwK20rsAx9AUqM9kQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-redis-4": { - "version": "0.42.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis-4/-/instrumentation-redis-4-0.42.1.tgz", - "integrity": "sha512-xm17LJhDfQzQo4wkM/zFwh6wk3SNN/FBFGkscI9Kj4efrb/o5p8Z3yE6ldBPNdIZ6RAwg2p3DL7fvE3DuUDJWA==", - "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/redis-common": "^0.36.2", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, + "node_modules/@nx/nx-linux-arm64-gnu": { + "version": "19.4.4", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.4.4.tgz", + "integrity": "sha512-33zZ+ytnRgXnx7Ls8hoEtXSRDJF8PuZaJBbGocrpfXku58fHj7+AJtQZWjQe3STGJuVUbmIZNfGJ/st+3Zeccg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" + "node": ">= 10" + } + }, + "node_modules/@nx/nx-linux-arm64-musl": { + "version": "19.4.4", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.4.4.tgz", + "integrity": "sha512-00qPmFs0LGmeudYSwhcuMLNRb4/Eaaf6SMkqdbJU2iKEbq6rY7clORAJlOn3FQPmxi/j2uEfbkONMfO8pqsu3A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-linux-x64-gnu": { + "version": "19.4.4", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.4.4.tgz", + "integrity": "sha512-R7wIdVzSVvKTsLPRBIo9eouEik4ZiYhR4eG2XybhdWNhv8vC+VzOdbWWUyxQzzxj2Lo5o7d4UlFxvblTftQJJw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-linux-x64-musl": { + "version": "19.4.4", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.4.4.tgz", + "integrity": "sha512-2Xu71Jwa0Ti2fwvvGXb21kpMaga4eZeS5+2MKMJnE2hzW6NWSx68xnw6TPJIdEKbkJUHWk32vF4vob79puunHQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-win32-arm64-msvc": { + "version": "19.4.4", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.4.4.tgz", + "integrity": "sha512-ztF1MhxB+IdLIqwx1DbAdqJvTHrFstUavinFTxTaGBTu9AtFwziRP567XB8TiyzyCSmY9H8JJHGByQ0Mr6cUbQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-win32-x64-msvc": { + "version": "19.4.4", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.4.4.tgz", + "integrity": "sha512-AdcjRiQ3MXlhpwCt5QprxtwAvG+VcYymF6ZI37aHZ9EkSEkD77iFgpkAhfhhHEgbTmnGBcMZMwJ5MENXjwdW8A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/react": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/react/-/react-19.2.0.tgz", + "integrity": "sha512-G9PSRnX8X4lCaJ7808xwL+kfZ/LWLi/Rph6mGJFnSS+0Y89WyHNcQTIWdvzabQy2RwXgi/eDy1FToDx/5rTZbA==", + "dev": true, + "dependencies": { + "@nrwl/react": "19.2.0", + "@nx/devkit": "19.2.0", + "@nx/eslint": "19.2.0", + "@nx/js": "19.2.0", + "@nx/web": "19.2.0", + "@phenomnomnominal/tsquery": "~5.0.1", + "@svgr/webpack": "^8.0.1", + "chalk": "^4.1.0", + "file-loader": "^6.2.0", + "minimatch": "9.0.3", + "tslib": "^2.3.0" + } + }, + "node_modules/@nx/react/node_modules/@nrwl/devkit": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.2.0.tgz", + "integrity": "sha512-Ew5AJZkLXJwt15HjaIbHve8FOXmZ3HK8KPqTXqwKHX8jQW+fDUCaSXKe/lCZMNg0RvY+jMNecuC86uGdiIbLMg==", + "dev": true, + "dependencies": { + "@nx/devkit": "19.2.0" + } + }, + "node_modules/@nx/react/node_modules/@nx/devkit": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.2.0.tgz", + "integrity": "sha512-fK3zRUE2SLp9BUomFiyCuAX2E1yfWYE/hKimniscsvM34/u/xLZYVmmZ0/jfpGPbyaonXKZr2KTb7RimX/hyqg==", + "dev": true, + "dependencies": { + "@nrwl/devkit": "19.2.0", + "ejs": "^3.1.7", + "enquirer": "~2.3.6", + "ignore": "^5.0.4", + "minimatch": "9.0.3", + "semver": "^7.5.3", + "tmp": "~0.2.1", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "nx": ">= 17 <= 20" } }, - "node_modules/@opentelemetry/instrumentation-redis-4/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@nx/react/node_modules/@nx/eslint": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/eslint/-/eslint-19.2.0.tgz", + "integrity": "sha512-9OIMntrLDPrQNZjYxOncIX+65r4RhV2dJ3PrjJ9lwCVqJKZGxfCn6f8JK8ubeLoWFPVjKEtfLTHK529vvfXifQ==", + "dev": true, "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" + "@nx/devkit": "19.2.0", + "@nx/js": "19.2.0", + "@nx/linter": "19.2.0", + "semver": "^7.5.3", + "tslib": "^2.3.0", + "typescript": "~5.4.2" }, - "engines": { - "node": ">=14" + "peerDependencies": { + "@zkochan/js-yaml": "0.0.7", + "eslint": "^8.0.0 || ^9.0.0" }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "peerDependenciesMeta": { + "@zkochan/js-yaml": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-redis-4/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", + "node_modules/@nx/react/node_modules/@nx/linter": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/linter/-/linter-19.2.0.tgz", + "integrity": "sha512-Rahjy3+OLc4aXT8VNXpwyMozeU4RB6HIQOh5NAdcA6PoOH8cG1VtbyjryIZE8l5HT1hrpI5EkONZt1UXiIGw3w==", + "dev": true, + "dependencies": { + "@nx/eslint": "19.2.0" + } + }, + "node_modules/@nx/react/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, "bin": { "semver": "bin/semver.js" }, @@ -22615,31 +10860,55 @@ "node": ">=10" } }, - "node_modules/@opentelemetry/instrumentation-redis/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@nx/web": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/web/-/web-19.2.0.tgz", + "integrity": "sha512-iMRwDjkU7GfJql4wT6pGCimFoHYV/2bQuI/N9b9T3NEL9sk5tlMqlik6bbSGtje8XoUAbxaQrTpr9pJeaUPYwg==", + "dev": true, "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" + "@nrwl/web": "19.2.0", + "@nx/devkit": "19.2.0", + "@nx/js": "19.2.0", + "chalk": "^4.1.0", + "detect-port": "^1.5.1", + "http-server": "^14.1.0", + "tslib": "^2.3.0" + } + }, + "node_modules/@nx/web/node_modules/@nrwl/devkit": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.2.0.tgz", + "integrity": "sha512-Ew5AJZkLXJwt15HjaIbHve8FOXmZ3HK8KPqTXqwKHX8jQW+fDUCaSXKe/lCZMNg0RvY+jMNecuC86uGdiIbLMg==", + "dev": true, + "dependencies": { + "@nx/devkit": "19.2.0" + } + }, + "node_modules/@nx/web/node_modules/@nx/devkit": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.2.0.tgz", + "integrity": "sha512-fK3zRUE2SLp9BUomFiyCuAX2E1yfWYE/hKimniscsvM34/u/xLZYVmmZ0/jfpGPbyaonXKZr2KTb7RimX/hyqg==", + "dev": true, + "dependencies": { + "@nrwl/devkit": "19.2.0", + "ejs": "^3.1.7", + "enquirer": "~2.3.6", + "ignore": "^5.0.4", + "minimatch": "9.0.3", + "semver": "^7.5.3", + "tmp": "~0.2.1", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "nx": ">= 17 <= 20" } }, - "node_modules/@opentelemetry/instrumentation-redis/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", + "node_modules/@nx/web/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, "bin": { "semver": "bin/semver.js" }, @@ -22647,868 +10916,1042 @@ "node": ">=10" } }, - "node_modules/@opentelemetry/instrumentation-restify": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-restify/-/instrumentation-restify-0.41.0.tgz", - "integrity": "sha512-gKEo+X/wVKUBuD2WDDlF7SlDNBHMWjSQoLxFCsGqeKgHR0MGtwMel8uaDGg9LJ83nKqYy+7Vl/cDFxjba6H+/w==", + "node_modules/@nx/webpack": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nx/webpack/-/webpack-19.6.3.tgz", + "integrity": "sha512-AUz4SPdD6LtIh+hB8AJX7GdzLHmlj5aU/yXp4UTKF5DZlha4NphN8YIP+NN56nCgEZMxM8txp7U0zytqhcFP1Q==", + "dev": true, "dependencies": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@babel/core": "^7.23.2", + "@module-federation/enhanced": "^0.2.3", + "@module-federation/sdk": "^0.2.3", + "@nrwl/webpack": "19.6.3", + "@nx/devkit": "19.6.3", + "@nx/js": "19.6.3", + "@phenomnomnominal/tsquery": "~5.0.1", + "ajv": "^8.12.0", + "autoprefixer": "^10.4.9", + "babel-loader": "^9.1.2", + "browserslist": "^4.21.4", + "chalk": "^4.1.0", + "copy-webpack-plugin": "^10.2.4", + "css-loader": "^6.4.0", + "css-minimizer-webpack-plugin": "^5.0.0", + "express": "^4.19.2", + "fork-ts-checker-webpack-plugin": "7.2.13", + "http-proxy-middleware": "^3.0.0", + "less": "4.1.3", + "less-loader": "11.1.0", + "license-webpack-plugin": "^4.0.2", + "loader-utils": "^2.0.3", + "mini-css-extract-plugin": "~2.4.7", + "parse5": "4.0.0", + "postcss": "^8.4.38", + "postcss-import": "~14.1.0", + "postcss-loader": "^6.1.1", + "rxjs": "^7.8.0", + "sass": "^1.42.1", + "sass-loader": "^12.2.0", + "source-map-loader": "^5.0.0", + "style-loader": "^3.3.0", + "stylus": "^0.59.0", + "stylus-loader": "^7.1.0", + "terser-webpack-plugin": "^5.3.3", + "ts-loader": "^9.3.1", + "tsconfig-paths-webpack-plugin": "4.0.0", + "tslib": "^2.3.0", + "webpack": "^5.80.0", + "webpack-dev-server": "^5.0.4", + "webpack-node-externals": "^3.0.0", + "webpack-subresource-integrity": "^5.1.0" } }, - "node_modules/@opentelemetry/instrumentation-restify/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@nx/webpack/node_modules/@nrwl/devkit": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.6.3.tgz", + "integrity": "sha512-zrAboArNfrEMjimBl/0YeM08HfjqOEG/VHdCHKO+5QMDg65w7vDJ2flwyNhlmnMl8BMJSy9fNo6PNGhboOf3+w==", + "dev": true, "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@nx/devkit": "19.6.3" } }, - "node_modules/@opentelemetry/instrumentation-restify/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "node_modules/@nx/webpack/node_modules/@nrwl/js": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nrwl/js/-/js-19.6.3.tgz", + "integrity": "sha512-Z5tYcUQNfgmNFMJpGmZd6fB0D1pCKNiS3aci2gxHAUIP0Z5cznTyCuzcJSIRx3uMHENhxXwzLwv2l/cqOqnD8A==", + "dev": true, + "dependencies": { + "@nx/js": "19.6.3" } }, - "node_modules/@opentelemetry/instrumentation-router": { - "version": "0.40.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-router/-/instrumentation-router-0.40.0.tgz", - "integrity": "sha512-bRo4RaclGFiKtmv/N1D0MuzO7DuxbeqMkMCbPPng6mDwzpHAMpHz/K/IxJmF+H1Hi/NYXVjCKvHGClageLe9eA==", + "node_modules/@nx/webpack/node_modules/@nrwl/tao": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.6.3.tgz", + "integrity": "sha512-j4vPU87yBhTrdyPFSNhlUkN29w4BQ+M14khT8PFGe+Y26gHMxNRNXNFUCwtVARYAc6IwxS8Uvlwy7AwXG2ETPA==", + "dev": true, "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "nx": "19.6.3", + "tslib": "^2.3.0" }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "bin": { + "tao": "index.js" } }, - "node_modules/@opentelemetry/instrumentation-router/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", + "node_modules/@nx/webpack/node_modules/@nrwl/workspace": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-19.6.3.tgz", + "integrity": "sha512-NGJ6Mxpw8U6tZRT4ijGzqthr1NMgT/22uteu4otetLEdlqkh1VvLqJC9tjzLkYXmXF9QuoUrkwQib/HafsZmkg==", + "dev": true, "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@nx/workspace": "19.6.3" } }, - "node_modules/@opentelemetry/instrumentation-router/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/@nx/webpack/node_modules/@nx/devkit": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.6.3.tgz", + "integrity": "sha512-/d8Z5/Cy/H/1rIHxW3VjeK5dlvHwRxRj8rCm8/sj5Pz3GmGX03uuEK+J/p+VlP3gP8dAYMgZu3ImeqTAu6rBtw==", + "dev": true, + "dependencies": { + "@nrwl/devkit": "19.6.3", + "ejs": "^3.1.7", + "enquirer": "~2.3.6", + "ignore": "^5.0.4", + "minimatch": "9.0.3", + "semver": "^7.5.3", + "tmp": "~0.2.1", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" }, - "engines": { - "node": ">=10" + "peerDependencies": { + "nx": ">= 17 <= 20" } }, - "node_modules/@opentelemetry/instrumentation-socket.io": { - "version": "0.42.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-socket.io/-/instrumentation-socket.io-0.42.0.tgz", - "integrity": "sha512-xB5tdsBzuZyicQTO3hDzJIpHQ7V1BYJ6vWPWgl19gWZDBdjEGc3HOupjkd3BUJyDoDhbMEHGk2nNlkUU99EfkA==", + "node_modules/@nx/webpack/node_modules/@nx/js": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nx/js/-/js-19.6.3.tgz", + "integrity": "sha512-Ip7DseodvJSRM2sKhUjNMlNLegBtsB1u6TuQUiYOJa2FnIGzXETT2HuDMxBcL+u23xDTNyNvifNZ92mFywa00Q==", + "dev": true, "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@babel/core": "^7.23.2", + "@babel/plugin-proposal-decorators": "^7.22.7", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-runtime": "^7.23.2", + "@babel/preset-env": "^7.23.2", + "@babel/preset-typescript": "^7.22.5", + "@babel/runtime": "^7.22.6", + "@nrwl/js": "19.6.3", + "@nx/devkit": "19.6.3", + "@nx/workspace": "19.6.3", + "babel-plugin-const-enum": "^1.0.1", + "babel-plugin-macros": "^2.8.0", + "babel-plugin-transform-typescript-metadata": "^0.3.1", + "chalk": "^4.1.0", + "columnify": "^1.6.0", + "detect-port": "^1.5.1", + "fast-glob": "3.2.7", + "fs-extra": "^11.1.0", + "ignore": "^5.0.4", + "js-tokens": "^4.0.0", + "jsonc-parser": "3.2.0", + "minimatch": "9.0.3", + "npm-package-arg": "11.0.1", + "npm-run-path": "^4.0.1", + "ora": "5.3.0", + "semver": "^7.5.3", + "source-map-support": "0.5.19", + "ts-node": "10.9.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "verdaccio": "^5.0.4" + }, + "peerDependenciesMeta": { + "verdaccio": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-socket.io/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, + "node_modules/@nx/webpack/node_modules/@nx/nx-darwin-arm64": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.6.3.tgz", + "integrity": "sha512-P7WlX5YDZOABAlyfpR6eObigQTNuUuy3iJVUuGwp1Nuo3VPMPkpK1GMWKWLwOR9+2jGnF5MzuqWHk7CdF33uqQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-socket.io/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, + "node_modules/@nx/webpack/node_modules/@nx/nx-darwin-x64": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.6.3.tgz", + "integrity": "sha512-HF28dPc7h0EmEGYJWJUPA3cBvjXyHbSbGQP5oP885gos9zcyVBjQ2kdJEUZDNMHB9KlZraeXbmV1umFkikjn6A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=10" + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-tedious": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.14.0.tgz", - "integrity": "sha512-ofq7pPhSqvRDvD2FVx3RIWPj76wj4QubfrbqJtEx0A+fWoaYxJOCIQ92tYJh28elAmjMmgF/XaYuJuBhBv5J3A==", - "dependencies": { - "@opentelemetry/instrumentation": "^0.53.0", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@types/tedious": "^4.0.14" - }, + "node_modules/@nx/webpack/node_modules/@nx/nx-freebsd-x64": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.6.3.tgz", + "integrity": "sha512-y52dWxQ/x2ccyPqA4Vou4CnTqZX4gr/wV9myJX56G1CyEpWasmcqmPFeOKQd6dj7llGM/KJ/4Gz29RYxcWffcA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-tedious/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, + "node_modules/@nx/webpack/node_modules/@nx/nx-linux-arm-gnueabihf": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.6.3.tgz", + "integrity": "sha512-RneCg1tglLbP4cmGnGUs4FgZVT0aOA9wA53tO4IbyxLnlRXNY9OE452YLgqv3H7sLtNjsey2Lkq1seBHtr3p/Q==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-tedious/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, + "node_modules/@nx/webpack/node_modules/@nx/nx-linux-arm64-gnu": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.6.3.tgz", + "integrity": "sha512-Y+vgqaxrPQUEtCzxK25QY4ahO90l0eWgVrvCALexGmq0lW41JrVpfTTsbH/BAPLsx+u8A/GPAQAgrmg7d5lSxw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10" + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-undici": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.6.0.tgz", - "integrity": "sha512-ABJBhm5OdhGmbh0S/fOTE4N69IZ00CsHC5ijMYfzbw3E5NwLgpQk5xsljaECrJ8wz1SfXbO03FiSuu5AyRAkvQ==", - "dependencies": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.53.0" - }, + "node_modules/@nx/webpack/node_modules/@nx/nx-linux-arm64-musl": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.6.3.tgz", + "integrity": "sha512-o/99DBgafbjiJ4e9KFxaldvtlZta/FdzEiQQW+SQQ0JGSYlLCZZ8tIT6t3edV7cmG+gQLNMwolJzgpY53O9wjA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.7.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-undici/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, + "node_modules/@nx/webpack/node_modules/@nx/nx-linux-x64-gnu": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.6.3.tgz", + "integrity": "sha512-ppp0NBOhwJ39U1vR7h8jhFSfiur6CZPSUYjXsV44BlaNGc1wHZ+7FDXhzOTokgTNWHavYgYOJuVan5LtTLKJkA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-undici/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, + "node_modules/@nx/webpack/node_modules/@nx/nx-linux-x64-musl": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.6.3.tgz", + "integrity": "sha512-H7xgsT5OTtVYCXjXBLZu28v+rIInhbUggrgVJ2iQJFGBT2A2qmvGmDJdcDz8+K90ku1f4VuWmm8i+TEyDEcBuQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10" + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-winston": { - "version": "0.40.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-winston/-/instrumentation-winston-0.40.0.tgz", - "integrity": "sha512-eMk2tKl86YJ8/yHvtDbyhrE35/R0InhO9zuHTflPx8T0+IvKVUhPV71MsJr32sImftqeOww92QHt4Jd+a5db4g==", - "dependencies": { - "@opentelemetry/api-logs": "^0.53.0", - "@opentelemetry/instrumentation": "^0.53.0" - }, + "node_modules/@nx/webpack/node_modules/@nx/nx-win32-arm64-msvc": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.6.3.tgz", + "integrity": "sha512-o9O6lSmx67zUnqOtlDC4YpC++fiUkixgIsQEG8J/2jdNgAATqOtERcqCNra/uke/Q94Vht2tVXjXF3uj92APhw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-winston/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, + "node_modules/@nx/webpack/node_modules/@nx/nx-win32-x64-msvc": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.6.3.tgz", + "integrity": "sha512-6NQhc7jYQ/sqPt5fDy8C+br73kTd5jhb8ZkPtEy2Amr1aA1K9SAxZAYfyvxLHS2z1nBEelNFgXe6HBmDX92FkA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/instrumentation-winston/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "node_modules/@nx/webpack/node_modules/@nx/workspace": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-19.6.3.tgz", + "integrity": "sha512-DTvVJZuXHQd+F4M9JkTHGjLQADQZfUTs/h+v9/NC+YQHml8eixaNXSSvoHQcvBqO8HntbJz5LAJfQuiJ4IGBKw==", + "dev": true, + "dependencies": { + "@nrwl/workspace": "19.6.3", + "@nx/devkit": "19.6.3", + "chalk": "^4.1.0", + "enquirer": "~2.3.6", + "nx": "19.6.3", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" } }, - "node_modules/@opentelemetry/otlp-exporter-base": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.53.0.tgz", - "integrity": "sha512-UCWPreGQEhD6FjBaeDuXhiMf6kkBODF0ZQzrk/tuQcaVDJ+dDQ/xhJp192H9yWnKxVpEjFrSSLnpqmX4VwX+eA==", - "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/otlp-transformer": "0.53.0" - }, + "node_modules/@nx/webpack/node_modules/@types/retry": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", + "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", + "dev": true + }, + "node_modules/@nx/webpack/node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/@nx/webpack/node_modules/array-union": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz", + "integrity": "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==", + "dev": true, "engines": { - "node": ">=14" + "node": ">=12" }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@opentelemetry/otlp-grpc-exporter-base": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.53.0.tgz", - "integrity": "sha512-F7RCN8VN+lzSa4fGjewit8Z5fEUpY/lmMVy5EWn2ZpbAabg3EE3sCLuTNfOiooNGnmvzimUPruoeqeko/5/TzQ==", + "node_modules/@nx/webpack/node_modules/copy-webpack-plugin": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz", + "integrity": "sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg==", + "dev": true, "dependencies": { - "@grpc/grpc-js": "^1.7.1", - "@opentelemetry/core": "1.26.0", - "@opentelemetry/otlp-exporter-base": "0.53.0", - "@opentelemetry/otlp-transformer": "0.53.0" + "fast-glob": "^3.2.7", + "glob-parent": "^6.0.1", + "globby": "^12.0.2", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0" }, "engines": { - "node": ">=14" + "node": ">= 12.20.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "webpack": "^5.1.0" } }, - "node_modules/@opentelemetry/otlp-transformer": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.53.0.tgz", - "integrity": "sha512-rM0sDA9HD8dluwuBxLetUmoqGJKSAbWenwD65KY9iZhUxdBHRLrIdrABfNDP7aiTjcgK8XFyTn5fhDz7N+W6DA==", + "node_modules/@nx/webpack/node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dev": true, "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@opentelemetry/core": "1.26.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/sdk-logs": "0.53.0", - "@opentelemetry/sdk-metrics": "1.26.0", - "@opentelemetry/sdk-trace-base": "1.26.0", - "protobufjs": "^7.3.0" + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "node": ">=10" } }, - "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/resources": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", - "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, + "node_modules/@nx/webpack/node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, "engines": { - "node": ">=14" + "node": ">=12" }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/sdk-trace-base": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.26.0.tgz", - "integrity": "sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw==", - "license": "Apache-2.0", + "node_modules/@nx/webpack/node_modules/dotenv-expand": { + "version": "11.0.6", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.6.tgz", + "integrity": "sha512-8NHi73otpWsZGBSZwwknTXS5pqMOrk9+Ssrna8xCaxkzEpU9OTf9R5ArQGVw03//Zmk9MOwLPng9WwndvpAJ5g==", + "dev": true, "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" + "dotenv": "^16.4.4" }, "engines": { - "node": ">=14" + "node": ">=12" }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "funding": { + "url": "https://dotenvx.com" } }, - "node_modules/@opentelemetry/propagation-utils": { - "version": "0.30.11", - "resolved": "https://registry.npmjs.org/@opentelemetry/propagation-utils/-/propagation-utils-0.30.11.tgz", - "integrity": "sha512-rY4L/2LWNk5p/22zdunpqVmgz6uN419DsRTw5KFMa6u21tWhXS8devlMy4h8m8nnS20wM7r6yYweCNNKjgLYJw==", - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" - } + "node_modules/@nx/webpack/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, - "node_modules/@opentelemetry/propagator-aws-xray": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-aws-xray/-/propagator-aws-xray-1.26.0.tgz", - "integrity": "sha512-Sex+JyEZ/xX328TArBqQjh1NZSfNyw5NdASUIi9hnPsnMBMSBaDe7B9JRnXv0swz7niNyAnXa6MY7yOCV76EvA==", + "node_modules/@nx/webpack/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, "dependencies": { - "@opentelemetry/core": "1.26.0" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, - "engines": { - "node": ">=14" + "bin": { + "glob": "dist/esm/bin.mjs" }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@opentelemetry/propagator-b3": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-b3/-/propagator-b3-1.26.0.tgz", - "integrity": "sha512-vvVkQLQ/lGGyEy9GT8uFnI047pajSOVnZI2poJqVGD3nJ+B9sFGdlHNnQKophE3lHfnIH0pw2ubrCTjZCgIj+Q==", + "node_modules/@nx/webpack/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, "dependencies": { - "@opentelemetry/core": "1.26.0" + "is-glob": "^4.0.3" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "node": ">=10.13.0" } }, - "node_modules/@opentelemetry/propagator-jaeger": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-jaeger/-/propagator-jaeger-1.26.0.tgz", - "integrity": "sha512-DelFGkCdaxA1C/QA0Xilszfr0t4YbGd3DjxiCDPh34lfnFr+VkkrjV9S8ZTJvAzfdKERXhfOxIKBoGPJwoSz7Q==", + "node_modules/@nx/webpack/node_modules/glob/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, "dependencies": { - "@opentelemetry/core": "1.26.0" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=14" + "node": ">=16 || 14 >=14.17" }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/redis-common": { - "version": "0.36.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/redis-common/-/redis-common-0.36.2.tgz", - "integrity": "sha512-faYX1N0gpLhej/6nyp6bgRjzAKXn5GOEMYY7YhciSfCoITAktLUtQ36d24QEWNA1/WA1y6qQunCe0OhHRkVl9g==", - "engines": { - "node": ">=14" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@opentelemetry/resource-detector-alibaba-cloud": { - "version": "0.29.3", - "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-alibaba-cloud/-/resource-detector-alibaba-cloud-0.29.3.tgz", - "integrity": "sha512-jdnG/cYItxwKGRj2n3YsJn1+j3QsMRUfaH/mQSj2b6yULo7bKO4turvASwxy3GuSDH55VwrK+F8oIbanJk69ng==", + "node_modules/@nx/webpack/node_modules/globby": { + "version": "12.2.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-12.2.0.tgz", + "integrity": "sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA==", + "dev": true, "dependencies": { - "@opentelemetry/core": "^1.26.0", - "@opentelemetry/resources": "^1.10.0", - "@opentelemetry/semantic-conventions": "^1.27.0" + "array-union": "^3.0.1", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.7", + "ignore": "^5.1.9", + "merge2": "^1.4.1", + "slash": "^4.0.0" }, "engines": { - "node": ">=14" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@opentelemetry/resource-detector-aws": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-aws/-/resource-detector-aws-1.6.2.tgz", - "integrity": "sha512-xxT6PVmcBTtCo0rf4Bv/mnDMpVRITVt13bDX8mOqKVb0kr5EwIMabZS5EGJhXjP4nljrOIA7ZlOJgSX0Kehfkw==", + "node_modules/@nx/webpack/node_modules/http-proxy-middleware": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-3.0.0.tgz", + "integrity": "sha512-36AV1fIaI2cWRzHo+rbcxhe3M3jUDCNzc4D5zRl57sEWRAxdXYtw7FSQKYY6PDKssiAKjLYypbssHk+xs/kMXw==", + "dev": true, "dependencies": { - "@opentelemetry/core": "^1.0.0", - "@opentelemetry/resources": "^1.10.0", - "@opentelemetry/semantic-conventions": "^1.27.0" + "@types/http-proxy": "^1.17.10", + "debug": "^4.3.4", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.5" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@opentelemetry/resource-detector-azure": { - "version": "0.2.11", - "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-azure/-/resource-detector-azure-0.2.11.tgz", - "integrity": "sha512-XepvQfTXWyHAoAziCfXGwYbSZL0LHtFk5iuKKN2VE2vzcoiw5Tepi0Qafuwb7CCtpQRReao4H7E29MFbCmh47g==", - "dependencies": { - "@opentelemetry/core": "^1.25.1", - "@opentelemetry/resources": "^1.10.1", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, + "node_modules/@nx/webpack/node_modules/ipaddr.js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "dev": true, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "node": ">= 10" } }, - "node_modules/@opentelemetry/resource-detector-container": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-container/-/resource-detector-container-0.4.4.tgz", - "integrity": "sha512-ZEN2mq7lIjQWJ8NTt1umtr6oT/Kb89856BOmESLSvgSHbIwOFYs7cSfSRH5bfiVw6dXTQAVbZA/wLgCHKrebJA==", - "dependencies": { - "@opentelemetry/core": "^1.26.0", - "@opentelemetry/resources": "^1.10.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, + "node_modules/@nx/webpack/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { - "node": ">=14" + "node": ">=8" + } + }, + "node_modules/@nx/webpack/node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "dev": true, + "engines": { + "node": ">=10" }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@opentelemetry/resource-detector-gcp": { - "version": "0.29.12", - "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-gcp/-/resource-detector-gcp-0.29.12.tgz", - "integrity": "sha512-liFG9XTaFVyY9YdFy4r2qVNa4a+Mg3k+XoWzzq2F+/xR0hFLfL0H4k7CsMW+T4Vl+1Cvc9W9WEVt5VCF4u/SYw==", + "node_modules/@nx/webpack/node_modules/is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "dev": true, "dependencies": { - "@opentelemetry/core": "^1.0.0", - "@opentelemetry/resources": "^1.10.0", - "@opentelemetry/semantic-conventions": "^1.27.0", - "gcp-metadata": "^6.0.0" + "is-inside-container": "^1.0.0" }, "engines": { - "node": ">=14" + "node": ">=16" }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@opentelemetry/resources": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.27.0.tgz", - "integrity": "sha512-jOwt2VJ/lUD5BLc+PMNymDrUCpm5PKi1E9oSVYAvz01U/VdndGmrtV3DU1pG4AwlYhJRHbHfOUIlpBeXCPw6QQ==", - "license": "Apache-2.0", + "node_modules/@nx/webpack/node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, "dependencies": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/semantic-conventions": "1.27.0" + "@isaacs/cliui": "^8.0.2" }, - "engines": { - "node": ">=14" + "funding": { + "url": "https://github.com/sponsors/isaacs" }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/@opentelemetry/resources/node_modules/@opentelemetry/core": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.27.0.tgz", - "integrity": "sha512-yQPKnK5e+76XuiqUH/gKyS8wv/7qITd5ln56QkBTf3uggr0VkXOXfcaAuG330UfdYu83wsyoBwqwxigpIG+Jkg==", - "license": "Apache-2.0", + "node_modules/@nx/webpack/node_modules/memfs": { + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.11.1.tgz", + "integrity": "sha512-LZcMTBAgqUUKNXZagcZxvXXfgF1bHX7Y7nQ0QyEiNbRJgE29GhgPd8Yna1VQcLlPiHt/5RFJMWYN9Uv/VPNvjQ==", + "dev": true, "dependencies": { - "@opentelemetry/semantic-conventions": "1.27.0" + "@jsonjoy.com/json-pack": "^1.0.3", + "@jsonjoy.com/util": "^1.3.0", + "tree-dump": "^1.0.1", + "tslib": "^2.0.0" }, "engines": { - "node": ">=14" + "node": ">= 4.0.0" }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" } }, - "node_modules/@opentelemetry/sdk-logs": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.53.0.tgz", - "integrity": "sha512-dhSisnEgIj/vJZXZV6f6KcTnyLDx/VuQ6l3ejuZpMpPlh9S1qMHiZU9NMmOkVkwwHkMy3G6mEBwdP23vUZVr4g==", + "node_modules/@nx/webpack/node_modules/mini-css-extract-plugin": { + "version": "2.4.7", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.4.7.tgz", + "integrity": "sha512-euWmddf0sk9Nv1O0gfeeUAvAkoSlWncNLF77C0TP2+WoPvy8mAHKOzMajcCz2dzvyt3CNgxb1obIEVFIRxaipg==", + "dev": true, "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@opentelemetry/core": "1.26.0", - "@opentelemetry/resources": "1.26.0" + "schema-utils": "^4.0.0" }, "engines": { - "node": ">=14" + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "@opentelemetry/api": ">=1.4.0 <1.10.0" + "webpack": "^5.0.0" } }, - "node_modules/@opentelemetry/sdk-logs/node_modules/@opentelemetry/resources": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", - "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", - "license": "Apache-2.0", + "node_modules/@nx/webpack/node_modules/nx": { + "version": "19.6.3", + "resolved": "https://registry.npmjs.org/nx/-/nx-19.6.3.tgz", + "integrity": "sha512-JbgrEKaIBvTfhw3mG3GeyyzJHBAMfuQkMNrxxIto1fn94gxdjXdMfqUnAzrW6xRAt5OEEU+rf7v2OA3vEXYc3A==", + "dev": true, + "hasInstallScript": true, "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" + "@napi-rs/wasm-runtime": "0.2.4", + "@nrwl/tao": "19.6.3", + "@yarnpkg/lockfile": "^1.1.0", + "@yarnpkg/parsers": "3.0.0-rc.46", + "@zkochan/js-yaml": "0.0.7", + "axios": "^1.7.4", + "chalk": "^4.1.0", + "cli-cursor": "3.1.0", + "cli-spinners": "2.6.1", + "cliui": "^8.0.1", + "dotenv": "~16.4.5", + "dotenv-expand": "~11.0.6", + "enquirer": "~2.3.6", + "figures": "3.2.0", + "flat": "^5.0.2", + "front-matter": "^4.0.2", + "fs-extra": "^11.1.0", + "ignore": "^5.0.4", + "jest-diff": "^29.4.1", + "jsonc-parser": "3.2.0", + "lines-and-columns": "~2.0.3", + "minimatch": "9.0.3", + "node-machine-id": "1.1.12", + "npm-run-path": "^4.0.1", + "open": "^8.4.0", + "ora": "5.3.0", + "semver": "^7.5.3", + "string-width": "^4.2.3", + "strong-log-transformer": "^2.1.0", + "tar-stream": "~2.2.0", + "tmp": "~0.2.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0", + "yargs": "^17.6.2", + "yargs-parser": "21.1.1" }, - "engines": { - "node": ">=14" + "bin": { + "nx": "bin/nx.js", + "nx-cloud": "bin/nx-cloud.js" + }, + "optionalDependencies": { + "@nx/nx-darwin-arm64": "19.6.3", + "@nx/nx-darwin-x64": "19.6.3", + "@nx/nx-freebsd-x64": "19.6.3", + "@nx/nx-linux-arm-gnueabihf": "19.6.3", + "@nx/nx-linux-arm64-gnu": "19.6.3", + "@nx/nx-linux-arm64-musl": "19.6.3", + "@nx/nx-linux-x64-gnu": "19.6.3", + "@nx/nx-linux-x64-musl": "19.6.3", + "@nx/nx-win32-arm64-msvc": "19.6.3", + "@nx/nx-win32-x64-msvc": "19.6.3" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "@swc-node/register": "^1.8.0", + "@swc/core": "^1.3.85" + }, + "peerDependenciesMeta": { + "@swc-node/register": { + "optional": true + }, + "@swc/core": { + "optional": true + } } }, - "node_modules/@opentelemetry/sdk-metrics": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.26.0.tgz", - "integrity": "sha512-0SvDXmou/JjzSDOjUmetAAvcKQW6ZrvosU0rkbDGpXvvZN+pQF6JbK/Kd4hNdK4q/22yeruqvukXEJyySTzyTQ==", + "node_modules/@nx/webpack/node_modules/p-retry": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.0.tgz", + "integrity": "sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==", + "dev": true, "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/resources": "1.26.0" + "@types/retry": "0.12.2", + "is-network-error": "^1.0.0", + "retry": "^0.13.1" }, "engines": { - "node": ">=14" + "node": ">=16.17" }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@opentelemetry/sdk-metrics/node_modules/@opentelemetry/resources": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", - "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", - "license": "Apache-2.0", + "node_modules/@nx/webpack/node_modules/postcss-loader": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", + "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", + "dev": true, "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" + "cosmiconfig": "^7.0.0", + "klona": "^2.0.5", + "semver": "^7.3.5" }, "engines": { - "node": ">=14" + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" } }, - "node_modules/@opentelemetry/sdk-node": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-node/-/sdk-node-0.53.0.tgz", - "integrity": "sha512-0hsxfq3BKy05xGktwG8YdGdxV978++x40EAKyKr1CaHZRh8uqVlXnclnl7OMi9xLMJEcXUw7lGhiRlArFcovyg==", + "node_modules/@nx/webpack/node_modules/rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "dev": true, "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@opentelemetry/core": "1.26.0", - "@opentelemetry/exporter-logs-otlp-grpc": "0.53.0", - "@opentelemetry/exporter-logs-otlp-http": "0.53.0", - "@opentelemetry/exporter-logs-otlp-proto": "0.53.0", - "@opentelemetry/exporter-trace-otlp-grpc": "0.53.0", - "@opentelemetry/exporter-trace-otlp-http": "0.53.0", - "@opentelemetry/exporter-trace-otlp-proto": "0.53.0", - "@opentelemetry/exporter-zipkin": "1.26.0", - "@opentelemetry/instrumentation": "0.53.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/sdk-logs": "0.53.0", - "@opentelemetry/sdk-metrics": "1.26.0", - "@opentelemetry/sdk-trace-base": "1.26.0", - "@opentelemetry/sdk-trace-node": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" + "glob": "^10.3.7" }, - "engines": { - "node": ">=14" + "bin": { + "rimraf": "dist/esm/bin.mjs" }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/exporter-trace-otlp-http": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.53.0.tgz", - "integrity": "sha512-m7F5ZTq+V9mKGWYpX8EnZ7NjoqAU7VemQ1E2HAG+W/u0wpY1x0OmbxAXfGKFHCspdJk8UKlwPGrpcB8nay3P8A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/otlp-exporter-base": "0.53.0", - "@opentelemetry/otlp-transformer": "0.53.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/sdk-trace-base": "1.26.0" + "node_modules/@nx/webpack/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "node": ">=10" } }, - "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/instrumentation": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", - "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.53.0", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, + "node_modules/@nx/webpack/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "dev": true, "engines": { - "node": ">=14" + "node": ">=12" }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/resources": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", - "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", - "license": "Apache-2.0", + "node_modules/@nx/webpack/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "node": ">=8" } }, - "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/sdk-trace-base": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.26.0.tgz", - "integrity": "sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw==", - "license": "Apache-2.0", + "node_modules/@nx/webpack/node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" }, - "engines": { - "node": ">=14" + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-node/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } } }, - "node_modules/@opentelemetry/sdk-trace-base": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.27.0.tgz", - "integrity": "sha512-btz6XTQzwsyJjombpeqCX6LhiMQYpzt2pIYNPnw0IPO/3AhT6yjnf8Mnv3ZC2A4eRYOjqrg+bfaXg9XHDRJDWQ==", + "node_modules/@nx/webpack/node_modules/webpack-dev-middleware": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.4.2.tgz", + "integrity": "sha512-xOO8n6eggxnwYpy1NlzUKpvrjfJTvae5/D6WOK0S2LSo7vjmo5gCM1DbLUmFqrMTJP+W/0YZNctm7jasWvLuBA==", + "dev": true, "dependencies": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/resources": "1.27.0", - "@opentelemetry/semantic-conventions": "1.27.0" + "colorette": "^2.0.10", + "memfs": "^4.6.0", + "mime-types": "^2.1.31", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" }, "engines": { - "node": ">=14" + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } } }, - "node_modules/@opentelemetry/sdk-trace-base/node_modules/@opentelemetry/core": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.27.0.tgz", - "integrity": "sha512-yQPKnK5e+76XuiqUH/gKyS8wv/7qITd5ln56QkBTf3uggr0VkXOXfcaAuG330UfdYu83wsyoBwqwxigpIG+Jkg==", + "node_modules/@nx/webpack/node_modules/webpack-dev-server": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.0.4.tgz", + "integrity": "sha512-dljXhUgx3HqKP2d8J/fUMvhxGhzjeNVarDLcbO/EWMSgRizDkxHQDZQaLFL5VJY9tRBj2Gz+rvCEYYvhbqPHNA==", + "dev": true, "dependencies": { - "@opentelemetry/semantic-conventions": "1.27.0" + "@types/bonjour": "^3.5.13", + "@types/connect-history-api-fallback": "^1.5.4", + "@types/express": "^4.17.21", + "@types/serve-index": "^1.9.4", + "@types/serve-static": "^1.15.5", + "@types/sockjs": "^0.3.36", + "@types/ws": "^8.5.10", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.2.1", + "chokidar": "^3.6.0", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.4.0", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.1.0", + "launch-editor": "^2.6.1", + "open": "^10.0.3", + "p-retry": "^6.2.0", + "rimraf": "^5.0.5", + "schema-utils": "^4.2.0", + "selfsigned": "^2.4.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^7.1.0", + "ws": "^8.16.0" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" }, "engines": { - "node": ">=14" + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-cli": { + "optional": true + } } }, - "node_modules/@opentelemetry/sdk-trace-node": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-1.26.0.tgz", - "integrity": "sha512-Fj5IVKrj0yeUwlewCRwzOVcr5avTuNnMHWf7GPc1t6WaT78J6CJyF3saZ/0RkZfdeNO8IcBl/bNcWMVZBMRW8Q==", - "license": "Apache-2.0", + "node_modules/@nx/webpack/node_modules/webpack-dev-server/node_modules/http-proxy-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "dev": true, "dependencies": { - "@opentelemetry/context-async-hooks": "1.26.0", - "@opentelemetry/core": "1.26.0", - "@opentelemetry/propagator-b3": "1.26.0", - "@opentelemetry/propagator-jaeger": "1.26.0", - "@opentelemetry/sdk-trace-base": "1.26.0", - "semver": "^7.5.2" + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" }, "engines": { - "node": ">=14" + "node": ">=12.0.0" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } } }, - "node_modules/@opentelemetry/sdk-trace-node/node_modules/@opentelemetry/resources": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", - "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", - "license": "Apache-2.0", + "node_modules/@nx/webpack/node_modules/webpack-dev-server/node_modules/open": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz", + "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==", + "dev": true, "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^3.1.0" }, "engines": { - "node": ">=14" + "node": ">=18" }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@opentelemetry/sdk-trace-node/node_modules/@opentelemetry/sdk-trace-base": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.26.0.tgz", - "integrity": "sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.26.0", - "@opentelemetry/resources": "1.26.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, + "node_modules/@nx/webpack/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "license": "ISC", "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "node": ">= 6" } }, - "node_modules/@opentelemetry/sdk-trace-node/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "bin": { - "semver": "bin/semver.js" + "node_modules/@nx/webpack/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" }, "engines": { - "node": ">=10" + "node": ">=12" } }, - "node_modules/@opentelemetry/semantic-conventions": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.27.0.tgz", - "integrity": "sha512-sAay1RrB+ONOem0OZanAR1ZI/k7yDpnOQSQmTMuGImUQb2y8EbSaCJ94FQluM74xoU03vlb2d2U90hZluL6nQg==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" + "node_modules/@nx/workspace": { + "version": "19.7.3", + "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-19.7.3.tgz", + "integrity": "sha512-FUHeOLCXdHEB1b6FiNU9swCZIKXbsGWRDfgHpHGeiZHp7uhH41W/EKTVukRxnQ+HXhE7zfxhn8KkllfaXIifPg==", + "dev": true, + "dependencies": { + "@nrwl/workspace": "19.7.3", + "@nx/devkit": "19.7.3", + "chalk": "^4.1.0", + "enquirer": "~2.3.6", + "nx": "19.7.3", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" } }, - "node_modules/@opentelemetry/sql-common": { - "version": "0.40.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/sql-common/-/sql-common-0.40.1.tgz", - "integrity": "sha512-nSDlnHSqzC3pXn/wZEZVLuAuJ1MYMXPBwtv2qAbCa3847SaHItdE7SzUq/Jtb0KZmh1zfAbNi3AAMjztTT4Ugg==", + "node_modules/@nx/workspace/node_modules/@nrwl/devkit": { + "version": "19.7.3", + "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.7.3.tgz", + "integrity": "sha512-g9vANTuxgHan6uAkI6M6tkfLjHECLmbZ4A80UqpxJNQJsCJFEHkzIC9oxhf8bWV3PjgCH6Xm4VyQ2GHwb3sgWw==", + "dev": true, "dependencies": { - "@opentelemetry/core": "^1.1.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.1.0" + "@nx/devkit": "19.7.3" } }, - "node_modules/@opentelemetry/winston-transport": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/winston-transport/-/winston-transport-0.7.0.tgz", - "integrity": "sha512-Q35p/glAOE6sl0ZgbddYsdjy23mzt89lFGhht4pJwrrJyInFIgdONFmMJb47kmXbFM3JHOcI0j+PL1BPPTPXBQ==", + "node_modules/@nx/workspace/node_modules/@nrwl/tao": { + "version": "19.7.3", + "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.7.3.tgz", + "integrity": "sha512-cIGhnSFPZdVTp4bI0fqwFoE9i7ToPg5jXz+hNMl/MTwcOQfKQ1JJY/ZPLM3aBUPORFIZ/GECQEycUb6+xCB56g==", + "dev": true, "dependencies": { - "@opentelemetry/api-logs": "^0.54.0", - "winston-transport": "4.*" + "nx": "19.7.3", + "tslib": "^2.3.0" }, - "engines": { - "node": ">=14" + "bin": { + "tao": "index.js" } }, - "node_modules/@opentelemetry/winston-transport/node_modules/@opentelemetry/api-logs": { - "version": "0.54.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.54.0.tgz", - "integrity": "sha512-9HhEh5GqFrassUndqJsyW7a0PzfyWr2eV2xwzHLIS+wX3125+9HE9FMRAKmJRwxZhgZGwH3HNQQjoMGZqmOeVA==", + "node_modules/@nx/workspace/node_modules/@nx/devkit": { + "version": "19.7.3", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.7.3.tgz", + "integrity": "sha512-dIavuzfcMLCTa5uhd4R7HsxcFO0w9fHwG4wDg76wyBAbPGJlrR+9zg359hZ/SkXdguO6bMVmmQg/EXIvo6g69A==", + "dev": true, "dependencies": { - "@opentelemetry/api": "^1.3.0" + "@nrwl/devkit": "19.7.3", + "ejs": "^3.1.7", + "enquirer": "~2.3.6", + "ignore": "^5.0.4", + "minimatch": "9.0.3", + "semver": "^7.5.3", + "tmp": "~0.2.1", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" }, - "engines": { - "node": ">=14" + "peerDependencies": { + "nx": ">= 17 <= 20" } }, - "node_modules/@oxc-resolver/binding-darwin-arm64": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-darwin-arm64/-/binding-darwin-arm64-1.10.2.tgz", - "integrity": "sha512-aOCZYXqmFL+2sXlaVkYbAOtICGGeTFtmdul8OimQfOXHJods6YHJ2nR6+rEeBcJzaXyXPP18ne1IsEc4AYL1IA==", + "node_modules/@nx/workspace/node_modules/@nx/nx-darwin-arm64": { + "version": "19.7.3", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.7.3.tgz", + "integrity": "sha512-0dDK0UkMR0vBv4AP/48Q9A+OC2dvpivdt8su/4W/CPADy69M9B5O3jPiK+jTRsLshQG/soC9JG0Rll1BNWymPg==", "cpu": [ "arm64" ], @@ -23516,12 +11959,15 @@ "optional": true, "os": [ "darwin" - ] + ], + "engines": { + "node": ">= 10" + } }, - "node_modules/@oxc-resolver/binding-darwin-x64": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-darwin-x64/-/binding-darwin-x64-1.10.2.tgz", - "integrity": "sha512-6WD7lHGkoduFZfUgnC2suKOlqttQRKxWsiVXiiGPu3mfXvQAhMd/gekuH1t8vOhFlPJduaww15n5UB0bSjCK+w==", + "node_modules/@nx/workspace/node_modules/@nx/nx-darwin-x64": { + "version": "19.7.3", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.7.3.tgz", + "integrity": "sha512-hTdv5YY2GQTdT7GwVO7ST27ZzvCmAQvmkEapfnCdy74QsL4gapaXJFvtWLHVfG6qHNRHWXbpdegvR3VswRHZVQ==", "cpu": [ "x64" ], @@ -23529,12 +11975,15 @@ "optional": true, "os": [ "darwin" - ] + ], + "engines": { + "node": ">= 10" + } }, - "node_modules/@oxc-resolver/binding-freebsd-x64": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-freebsd-x64/-/binding-freebsd-x64-1.10.2.tgz", - "integrity": "sha512-nEqHWx/Ot5p7Mafj8qH6vFlLSvHjECxAcZwhnAMqRuQu1NgXC/QM3emkdhVGy7QJgsxZbHpPaF6TERNf5/NL9Q==", + "node_modules/@nx/workspace/node_modules/@nx/nx-freebsd-x64": { + "version": "19.7.3", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.7.3.tgz", + "integrity": "sha512-dwuB/3eoV2RbD0b0LHnagQOXa9PKAjLi7g5vNxzw6LuNT1tdaLaUZZGv2tfG0hHjsV0cOaAX41rEyOIwJyE7zg==", "cpu": [ "x64" ], @@ -23542,12 +11991,15 @@ "optional": true, "os": [ "freebsd" - ] + ], + "engines": { + "node": ">= 10" + } }, - "node_modules/@oxc-resolver/binding-linux-arm-gnueabihf": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.10.2.tgz", - "integrity": "sha512-+AlZI0fPnpfArh8aC5k2295lmQrxa2p8gBLxC3buvCkz0ZpbVLxyyAXz3J2jGwJnmc5MUPLEqPYw6ZlAGH4XHA==", + "node_modules/@nx/workspace/node_modules/@nx/nx-linux-arm-gnueabihf": { + "version": "19.7.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.7.3.tgz", + "integrity": "sha512-X/eG3IqvIxlCfIOiCQKv7RKwra54I+SN9zj2TeSOtd/uK0paa3mYSlGUJqoP3wpzasW1+EPIGkTQqV283IA15w==", "cpu": [ "arm" ], @@ -23555,12 +12007,15 @@ "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": ">= 10" + } }, - "node_modules/@oxc-resolver/binding-linux-arm64-gnu": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.10.2.tgz", - "integrity": "sha512-8fZ8NszFaUZaoA8eUwkF2lHjgUs76aFiewWgG/cjcZmwKp+ErZQLW8eOvIWZ4SohHQ+ScvhVsSaU2PU38c88gw==", + "node_modules/@nx/workspace/node_modules/@nx/nx-linux-arm64-gnu": { + "version": "19.7.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.7.3.tgz", + "integrity": "sha512-LNaX8DVcPlFVJhMf1AAAR6j1DZF9BlVhWlilRM44tIfnmvPfKIahKJIJbuikHE7q+lkvMrQUUDXKiQJlmm/qDw==", "cpu": [ "arm64" ], @@ -23568,12 +12023,15 @@ "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": ">= 10" + } }, - "node_modules/@oxc-resolver/binding-linux-arm64-musl": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.10.2.tgz", - "integrity": "sha512-oPrLICrw96Ym9n04FWXWGkbkpF6qJtZ57JSnqI3oQ24xHTt4iWyjHKHQO46NbJAK9sFb3Qce4BzV8faDI5Rifg==", + "node_modules/@nx/workspace/node_modules/@nx/nx-linux-arm64-musl": { + "version": "19.7.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.7.3.tgz", + "integrity": "sha512-TJ9PqSebhrn8NfrW+wqMXB9N65U0L0Kjt8FfahWffNKtSAEUvhurbNhqna2Rt5WJe2qaVf6zN2pOHKhF/5pL0w==", "cpu": [ "arm64" ], @@ -23581,12 +12039,15 @@ "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": ">= 10" + } }, - "node_modules/@oxc-resolver/binding-linux-x64-gnu": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.10.2.tgz", - "integrity": "sha512-eli74jTAUiIfqi8IPFqiPxQS69Alcr6w/IFRyf3XxrkxeFGgcgxJkRIxWNTKJ6T3EXxjuma+49LdZn6l9rEj7A==", + "node_modules/@nx/workspace/node_modules/@nx/nx-linux-x64-gnu": { + "version": "19.7.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.7.3.tgz", + "integrity": "sha512-YMb4WGGovwgxsP6VvAEnyWvLoUwsDrdE5CxFQ2yoThD2BixmSHUKLtx6dtPDHz25nOE3v1ZzM0xTwYXBhPaeRQ==", "cpu": [ "x64" ], @@ -23594,12 +12055,15 @@ "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": ">= 10" + } }, - "node_modules/@oxc-resolver/binding-linux-x64-musl": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-musl/-/binding-linux-x64-musl-1.10.2.tgz", - "integrity": "sha512-HH9zmjNSQo3rkbqJH5nIjGrtjC+QPrUy0KGGMR/oRCSLuD0cNFJ/Uly1XAugwSm4oEw0+rv6PmeclXmVTKsxhw==", + "node_modules/@nx/workspace/node_modules/@nx/nx-linux-x64-musl": { + "version": "19.7.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.7.3.tgz", + "integrity": "sha512-zkjgDSvw2eDN+KuJBPPAPhU/lOdiMvJU0UMthJFw85dhQIYfAO8+UgiFg/qBsKo0kQ0MkhntnIPBPF8bH40qWg==", "cpu": [ "x64" ], @@ -23607,28 +12071,15 @@ "optional": true, "os": [ "linux" - ] - }, - "node_modules/@oxc-resolver/binding-wasm32-wasi": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-wasm32-wasi/-/binding-wasm32-wasi-1.10.2.tgz", - "integrity": "sha512-3ItX23q33sfVBtMMdMhVDSe0NX5zBHxHfmFiXhSJuwNaVIwGpLFU7WU2nmq9oNdnmTOvjL8vlhOqiGvumBLlRA==", - "cpu": [ - "wasm32" ], - "dev": true, - "optional": true, - "dependencies": { - "@napi-rs/wasm-runtime": "^0.2.4" - }, "engines": { - "node": ">=14.0.0" + "node": ">= 10" } }, - "node_modules/@oxc-resolver/binding-win32-arm64-msvc": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.10.2.tgz", - "integrity": "sha512-aVoj2V+jmQ1N+lVy9AhaLmzssJM0lcKt8D0UL83aNLZJ5lSN7hgBuUXTVmL+VF268f167khjo38z+fbELDVm8Q==", + "node_modules/@nx/workspace/node_modules/@nx/nx-win32-arm64-msvc": { + "version": "19.7.3", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.7.3.tgz", + "integrity": "sha512-qCTFG6VxNvEe5JfoAELGZsjWDL4G+2NVSoSS3tByJYwVX256qgALcVoUHMjpxBn9FeOvUW9w5PL4Am4PKDdXLw==", "cpu": [ "arm64" ], @@ -23636,12 +12087,15 @@ "optional": true, "os": [ "win32" - ] + ], + "engines": { + "node": ">= 10" + } }, - "node_modules/@oxc-resolver/binding-win32-x64-msvc": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.10.2.tgz", - "integrity": "sha512-l8BDQWyP0Piw8hlmYPUqTRKLsq+ceG9h+9p6ZrjNzwW9AmJX7T7T2hgoVVHqS6f4WNA/CFkb3RyZP9QTzNkyyA==", + "node_modules/@nx/workspace/node_modules/@nx/nx-win32-x64-msvc": { + "version": "19.7.3", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.7.3.tgz", + "integrity": "sha512-ULNf73gLgB5cU/O4dlQe6tetbRIROTmaUNYTUUCCAC0BqVwZwPDxn4u9C5LgiErVyfPwwAhlserCGei5taLASQ==", "cpu": [ "x64" ], @@ -23649,3452 +12103,3156 @@ "optional": true, "os": [ "win32" - ] + ], + "engines": { + "node": ">= 10" + } }, - "node_modules/@parcel/watcher": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.0.tgz", - "integrity": "sha512-i0GV1yJnm2n3Yq1qw6QrUrd/LI9bE8WEBOTtOkpCXHHdyN3TAGgqAK/DAT05z4fq2x04cARXt2pDmjWjL92iTQ==", - "hasInstallScript": true, + "node_modules/@nx/workspace/node_modules/dotenv-expand": { + "version": "11.0.6", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.6.tgz", + "integrity": "sha512-8NHi73otpWsZGBSZwwknTXS5pqMOrk9+Ssrna8xCaxkzEpU9OTf9R5ArQGVw03//Zmk9MOwLPng9WwndvpAJ5g==", + "dev": true, "dependencies": { - "detect-libc": "^1.0.3", - "is-glob": "^4.0.3", - "micromatch": "^4.0.5", - "node-addon-api": "^7.0.0" + "dotenv": "^16.4.4" }, "engines": { - "node": ">= 10.0.0" + "node": ">=12" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "@parcel/watcher-android-arm64": "2.5.0", - "@parcel/watcher-darwin-arm64": "2.5.0", - "@parcel/watcher-darwin-x64": "2.5.0", - "@parcel/watcher-freebsd-x64": "2.5.0", - "@parcel/watcher-linux-arm-glibc": "2.5.0", - "@parcel/watcher-linux-arm-musl": "2.5.0", - "@parcel/watcher-linux-arm64-glibc": "2.5.0", - "@parcel/watcher-linux-arm64-musl": "2.5.0", - "@parcel/watcher-linux-x64-glibc": "2.5.0", - "@parcel/watcher-linux-x64-musl": "2.5.0", - "@parcel/watcher-win32-arm64": "2.5.0", - "@parcel/watcher-win32-ia32": "2.5.0", - "@parcel/watcher-win32-x64": "2.5.0" + "url": "https://dotenvx.com" } }, - "node_modules/@parcel/watcher-android-arm64": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.0.tgz", - "integrity": "sha512-qlX4eS28bUcQCdribHkg/herLe+0A9RyYC+mm2PXpncit8z5b3nSqGVzMNR3CmtAOgRutiZ02eIJJgP/b1iEFQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "android" - ], + "node_modules/@nx/workspace/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/@nx/workspace/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">=8" } }, - "node_modules/@parcel/watcher-darwin-arm64": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.0.tgz", - "integrity": "sha512-hyZ3TANnzGfLpRA2s/4U1kbw2ZI4qGxaRJbBH2DCSREFfubMswheh8TeiC1sGZ3z2jUf3s37P0BBlrD3sjVTUw==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], + "node_modules/@nx/workspace/node_modules/lines-and-columns": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.3.tgz", + "integrity": "sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w==", + "dev": true, "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, - "node_modules/@parcel/watcher-darwin-x64": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.0.tgz", - "integrity": "sha512-9rhlwd78saKf18fT869/poydQK8YqlU26TMiNg7AIu7eBp9adqbJZqmdFOsbZ5cnLp5XvRo9wcFmNHgHdWaGYA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10.0.0" + "node_modules/@nx/workspace/node_modules/nx": { + "version": "19.7.3", + "resolved": "https://registry.npmjs.org/nx/-/nx-19.7.3.tgz", + "integrity": "sha512-8F4CzKavSuOFv+uKVwXHc00Px0q40CWAYCW6NC5IgU3AMaJVumyHzgB8Sn+yfkaVgfVnZVqznOsyrbZUWuj/VA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@napi-rs/wasm-runtime": "0.2.4", + "@nrwl/tao": "19.7.3", + "@yarnpkg/lockfile": "^1.1.0", + "@yarnpkg/parsers": "3.0.0-rc.46", + "@zkochan/js-yaml": "0.0.7", + "axios": "^1.7.4", + "chalk": "^4.1.0", + "cli-cursor": "3.1.0", + "cli-spinners": "2.6.1", + "cliui": "^8.0.1", + "dotenv": "~16.4.5", + "dotenv-expand": "~11.0.6", + "enquirer": "~2.3.6", + "figures": "3.2.0", + "flat": "^5.0.2", + "front-matter": "^4.0.2", + "fs-extra": "^11.1.0", + "ignore": "^5.0.4", + "jest-diff": "^29.4.1", + "jsonc-parser": "3.2.0", + "lines-and-columns": "2.0.3", + "minimatch": "9.0.3", + "node-machine-id": "1.1.12", + "npm-run-path": "^4.0.1", + "open": "^8.4.0", + "ora": "5.3.0", + "semver": "^7.5.3", + "string-width": "^4.2.3", + "strong-log-transformer": "^2.1.0", + "tar-stream": "~2.2.0", + "tmp": "~0.2.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0", + "yargs": "^17.6.2", + "yargs-parser": "21.1.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "bin": { + "nx": "bin/nx.js", + "nx-cloud": "bin/nx-cloud.js" + }, + "optionalDependencies": { + "@nx/nx-darwin-arm64": "19.7.3", + "@nx/nx-darwin-x64": "19.7.3", + "@nx/nx-freebsd-x64": "19.7.3", + "@nx/nx-linux-arm-gnueabihf": "19.7.3", + "@nx/nx-linux-arm64-gnu": "19.7.3", + "@nx/nx-linux-arm64-musl": "19.7.3", + "@nx/nx-linux-x64-gnu": "19.7.3", + "@nx/nx-linux-x64-musl": "19.7.3", + "@nx/nx-win32-arm64-msvc": "19.7.3", + "@nx/nx-win32-x64-msvc": "19.7.3" + }, + "peerDependencies": { + "@swc-node/register": "^1.8.0", + "@swc/core": "^1.3.85" + }, + "peerDependenciesMeta": { + "@swc-node/register": { + "optional": true + }, + "@swc/core": { + "optional": true + } } }, - "node_modules/@parcel/watcher-freebsd-x64": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.0.tgz", - "integrity": "sha512-syvfhZzyM8kErg3VF0xpV8dixJ+RzbUaaGaeb7uDuz0D3FK97/mZ5AJQ3XNnDsXX7KkFNtyQyFrXZzQIcN49Tw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10.0.0" + "node_modules/@nx/workspace/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "engines": { + "node": ">=10" } }, - "node_modules/@parcel/watcher-linux-arm-glibc": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.0.tgz", - "integrity": "sha512-0VQY1K35DQET3dVYWpOaPFecqOT9dbuCfzjxoQyif1Wc574t3kOSkKevULddcR9znz1TcklCE7Ht6NIxjvTqLA==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" + "node_modules/@nx/workspace/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "engines": { + "node": ">=8" } }, - "node_modules/@parcel/watcher-linux-arm-musl": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.0.tgz", - "integrity": "sha512-6uHywSIzz8+vi2lAzFeltnYbdHsDm3iIB57d4g5oaB9vKwjb6N6dRIgZMujw4nm5r6v9/BQH0noq6DzHrqr2pA==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" + "node_modules/@nx/workspace/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "engines": { + "node": ">=12" } }, - "node_modules/@parcel/watcher-linux-arm64-glibc": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.0.tgz", - "integrity": "sha512-BfNjXwZKxBy4WibDb/LDCriWSKLz+jJRL3cM/DllnHH5QUyoiUNEp3GmL80ZqxeumoADfCCP19+qiYiC8gUBjA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node_modules/@open-draft/deferred-promise": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", + "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@open-draft/logger": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz", + "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-node-process": "^1.2.0", + "outvariant": "^1.4.0" } }, - "node_modules/@parcel/watcher-linux-arm64-musl": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.0.tgz", - "integrity": "sha512-S1qARKOphxfiBEkwLUbHjCY9BWPdWnW9j7f7Hb2jPplu8UZ3nes7zpPOW9bkLbHRvWM0WDTsjdOTUgW0xLBN1Q==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/@open-draft/until": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz", + "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@open-policy-agent/opa-wasm": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@open-policy-agent/opa-wasm/-/opa-wasm-1.9.0.tgz", + "integrity": "sha512-wuxQYoqU80ulYdFtZ1BKaFs29IRZZV3hl48L4wMRxXFlEoLBDfl5rL8iBNIyp+DDymvDxGS4ZMRVaBBWXnPYLQ==", + "dependencies": { + "sprintf-js": "^1.1.2", + "yaml": "^1.10.2" + } + }, + "node_modules/@open-policy-agent/opa-wasm/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "license": "ISC", "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">= 6" } }, - "node_modules/@parcel/watcher-linux-x64-glibc": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.0.tgz", - "integrity": "sha512-d9AOkusyXARkFD66S6zlGXyzx5RvY+chTP9Jp0ypSTC9d4lzyRs9ovGf/80VCxjKddcUvnsGwCHWuF2EoPgWjw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/@openapitools/openapi-generator-cli": { + "version": "2.15.3", + "resolved": "https://registry.npmjs.org/@openapitools/openapi-generator-cli/-/openapi-generator-cli-2.15.3.tgz", + "integrity": "sha512-2UBnsDlMt36thhdXxisbA1qReVtbCaw+NCvXoslRXlaJBL4qkAmZUhNeDLNu3LCbwA2PASMWhJSqeLwgwMCitw==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@nestjs/axios": "3.1.1", + "@nestjs/common": "10.4.6", + "@nestjs/core": "10.4.6", + "@nuxtjs/opencollective": "0.3.2", + "axios": "1.7.7", + "chalk": "4.1.2", + "commander": "8.3.0", + "compare-versions": "4.1.4", + "concurrently": "6.5.1", + "console.table": "0.10.0", + "fs-extra": "10.1.0", + "glob": "9.3.5", + "inquirer": "8.2.6", + "lodash": "4.17.21", + "proxy-agent": "6.4.0", + "reflect-metadata": "0.1.13", + "rxjs": "7.8.1", + "tslib": "2.8.1" + }, + "bin": { + "openapi-generator-cli": "main.js" + }, "engines": { - "node": ">= 10.0.0" + "node": ">=16" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://opencollective.com/openapi_generator" } }, - "node_modules/@parcel/watcher-linux-x64-musl": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.0.tgz", - "integrity": "sha512-iqOC+GoTDoFyk/VYSFHwjHhYrk8bljW6zOhPuhi5t9ulqiYq1togGJB5e3PwYVFFfeVgc6pbz3JdQyDoBszVaA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" + "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/axios": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-3.1.1.tgz", + "integrity": "sha512-ySoxrzqX80P1q6LKLKGcgyBd2utg4gbC+4FsJNpXYvILorMlxss/ECNogD9EXLCE4JS5exVFD5ez0nK5hXcNTQ==", + "dev": true, + "peerDependencies": { + "@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0", + "axios": "^1.3.1", + "rxjs": "^6.0.0 || ^7.0.0" + } + }, + "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/common": { + "version": "10.4.6", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.4.6.tgz", + "integrity": "sha512-KkezkZvU9poWaNq4L+lNvx+386hpOxPJkfXBBeSMrcqBOx8kVr36TGN2uYkF4Ta4zNu1KbCjmZbc0rhHSg296g==", + "dev": true, + "dependencies": { + "iterare": "1.2.1", + "tslib": "2.7.0", + "uid": "2.0.2" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "class-transformer": "*", + "class-validator": "*", + "reflect-metadata": "^0.1.12 || ^0.2.0", + "rxjs": "^7.1.0" + }, + "peerDependenciesMeta": { + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } } }, - "node_modules/@parcel/watcher-wasm": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-wasm/-/watcher-wasm-2.5.0.tgz", - "integrity": "sha512-Z4ouuR8Pfggk1EYYbTaIoxc+Yv4o7cGQnH0Xy8+pQ+HbiW+ZnwhcD2LPf/prfq1nIWpAxjOkQ8uSMFWMtBLiVQ==", - "bundleDependencies": [ - "napi-wasm" - ], + "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/common/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + }, + "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/core": { + "version": "10.4.6", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.4.6.tgz", + "integrity": "sha512-zXVPxCNRfO6gAy0yvEDjUxE/8gfZICJFpsl2lZAUH31bPb6m+tXuhUq2mVCTEltyMYQ+DYtRe+fEYM2v152N1g==", + "dev": true, + "hasInstallScript": true, "dependencies": { - "is-glob": "^4.0.3", - "micromatch": "^4.0.5", - "napi-wasm": "^1.1.0" - }, - "engines": { - "node": ">= 10.0.0" + "@nuxtjs/opencollective": "0.3.2", + "fast-safe-stringify": "2.1.1", + "iterare": "1.2.1", + "path-to-regexp": "3.3.0", + "tslib": "2.7.0", + "uid": "2.0.2" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^10.0.0", + "@nestjs/microservices": "^10.0.0", + "@nestjs/platform-express": "^10.0.0", + "@nestjs/websockets": "^10.0.0", + "reflect-metadata": "^0.1.12 || ^0.2.0", + "rxjs": "^7.1.0" + }, + "peerDependenciesMeta": { + "@nestjs/microservices": { + "optional": true + }, + "@nestjs/platform-express": { + "optional": true + }, + "@nestjs/websockets": { + "optional": true + } } }, - "node_modules/@parcel/watcher-wasm/node_modules/napi-wasm": { - "version": "1.1.0", - "inBundle": true, - "license": "MIT" + "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/core/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true }, - "node_modules/@parcel/watcher-win32-arm64": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.0.tgz", - "integrity": "sha512-twtft1d+JRNkM5YbmexfcH/N4znDtjgysFaV9zvZmmJezQsKpkfLYJ+JFV3uygugK6AtIM2oADPkB2AdhBrNig==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], + "node_modules/@openapitools/openapi-generator-cli/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, "engines": { - "node": ">= 10.0.0" + "node": ">= 12" + } + }, + "node_modules/@openapitools/openapi-generator-cli/node_modules/fs-extra": { + "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==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "engines": { + "node": ">=12" } }, - "node_modules/@parcel/watcher-win32-ia32": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.0.tgz", - "integrity": "sha512-+rgpsNRKwo8A53elqbbHXdOMtY/tAtTzManTWShB5Kk54N8Q9mzNWV7tV+IbGueCbcj826MfWGU3mprWtuf1TA==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], + "node_modules/@openapitools/openapi-generator-cli/node_modules/glob": { + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", + "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "minimatch": "^8.0.2", + "minipass": "^4.2.4", + "path-scurry": "^1.6.1" + }, "engines": { - "node": ">= 10.0.0" + "node": ">=16 || 14 >=14.17" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@parcel/watcher-win32-x64": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.0.tgz", - "integrity": "sha512-lPrxve92zEHdgeff3aiu4gDOIt4u7sJYha6wbdEZDCDUhtjTsOMiaJzG5lMY4GkWH8p0fMmO2Ppq5G5XXG+DQw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], + "node_modules/@openapitools/openapi-generator-cli/node_modules/minimatch": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", + "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, "engines": { - "node": ">= 10.0.0" + "node": ">=16 || 14 >=14.17" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@parcel/watcher/node_modules/detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", - "bin": { - "detect-libc": "bin/detect-libc.js" - }, + "node_modules/@openapitools/openapi-generator-cli/node_modules/minipass": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", + "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "dev": true, "engines": { - "node": ">=0.10" + "node": ">=8" } }, - "node_modules/@parcel/watcher/node_modules/node-addon-api": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", - "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==" + "node_modules/@openapitools/openapi-generator-cli/node_modules/path-to-regexp": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.3.0.tgz", + "integrity": "sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==", + "dev": true }, - "node_modules/@peculiar/asn1-schema": { - "version": "2.3.15", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.3.15.tgz", - "integrity": "sha512-QPeD8UA8axQREpgR5UTAfu2mqQmm97oUqahDtNdBcfj3qAnoXzFdQW+aNf/tD2WVXF8Fhmftxoj0eMIT++gX2w==", - "license": "MIT", - "dependencies": { - "asn1js": "^3.0.5", - "pvtsutils": "^1.3.6", - "tslib": "^2.8.1" - } + "node_modules/@openapitools/openapi-generator-cli/node_modules/reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", + "dev": true }, - "node_modules/@peculiar/asn1-schema/node_modules/tslib": { + "node_modules/@openapitools/openapi-generator-cli/node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" + "dev": true }, - "node_modules/@peculiar/json-schema": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/@peculiar/json-schema/-/json-schema-1.1.12.tgz", - "integrity": "sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==", - "license": "MIT", + "node_modules/@opentelemetry/api": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", + "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@opentelemetry/api-logs": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.53.0.tgz", + "integrity": "sha512-8HArjKx+RaAI8uEIgcORbZIPklyh1YLjPSBus8hjRmvLi6DeFzgOcdZ7KwPabKj8mXF8dX0hyfAyGfycz0DbFw==", "dependencies": { - "tslib": "^2.0.0" + "@opentelemetry/api": "^1.0.0" }, "engines": { - "node": ">=8.0.0" + "node": ">=14" } }, - "node_modules/@peculiar/webcrypto": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.5.0.tgz", - "integrity": "sha512-BRs5XUAwiyCDQMsVA9IDvDa7UBR9gAvPHgugOeGng3YN6vJ9JYonyDc0lNczErgtCWtucjR5N7VtaonboD/ezg==", - "license": "MIT", + "node_modules/@opentelemetry/auto-instrumentations-node": { + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/auto-instrumentations-node/-/auto-instrumentations-node-0.51.0.tgz", + "integrity": "sha512-xsgydgtJiToxvFsDcmLDrHiFfHOmdomqk4KCnr40YZdsfw7KO4RJEU0om2f7pFh6WUI5q8nSQ53QgZ+DAz6TzA==", "dependencies": { - "@peculiar/asn1-schema": "^2.3.8", - "@peculiar/json-schema": "^1.1.12", - "pvtsutils": "^1.3.5", - "tslib": "^2.6.2", - "webcrypto-core": "^1.8.0" + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/instrumentation-amqplib": "^0.42.0", + "@opentelemetry/instrumentation-aws-lambda": "^0.45.0", + "@opentelemetry/instrumentation-aws-sdk": "^0.44.0", + "@opentelemetry/instrumentation-bunyan": "^0.41.0", + "@opentelemetry/instrumentation-cassandra-driver": "^0.41.0", + "@opentelemetry/instrumentation-connect": "^0.39.0", + "@opentelemetry/instrumentation-cucumber": "^0.9.0", + "@opentelemetry/instrumentation-dataloader": "^0.12.0", + "@opentelemetry/instrumentation-dns": "^0.39.0", + "@opentelemetry/instrumentation-express": "^0.43.0", + "@opentelemetry/instrumentation-fastify": "^0.40.0", + "@opentelemetry/instrumentation-fs": "^0.15.0", + "@opentelemetry/instrumentation-generic-pool": "^0.39.0", + "@opentelemetry/instrumentation-graphql": "^0.43.0", + "@opentelemetry/instrumentation-grpc": "^0.53.0", + "@opentelemetry/instrumentation-hapi": "^0.41.0", + "@opentelemetry/instrumentation-http": "^0.53.0", + "@opentelemetry/instrumentation-ioredis": "^0.43.0", + "@opentelemetry/instrumentation-kafkajs": "^0.3.0", + "@opentelemetry/instrumentation-knex": "^0.40.0", + "@opentelemetry/instrumentation-koa": "^0.43.0", + "@opentelemetry/instrumentation-lru-memoizer": "^0.40.0", + "@opentelemetry/instrumentation-memcached": "^0.39.0", + "@opentelemetry/instrumentation-mongodb": "^0.47.0", + "@opentelemetry/instrumentation-mongoose": "^0.42.0", + "@opentelemetry/instrumentation-mysql": "^0.41.0", + "@opentelemetry/instrumentation-mysql2": "^0.41.0", + "@opentelemetry/instrumentation-nestjs-core": "^0.40.0", + "@opentelemetry/instrumentation-net": "^0.39.0", + "@opentelemetry/instrumentation-pg": "^0.46.0", + "@opentelemetry/instrumentation-pino": "^0.42.0", + "@opentelemetry/instrumentation-redis": "^0.42.0", + "@opentelemetry/instrumentation-redis-4": "^0.42.1", + "@opentelemetry/instrumentation-restify": "^0.41.0", + "@opentelemetry/instrumentation-router": "^0.40.0", + "@opentelemetry/instrumentation-socket.io": "^0.42.0", + "@opentelemetry/instrumentation-tedious": "^0.14.0", + "@opentelemetry/instrumentation-undici": "^0.6.0", + "@opentelemetry/instrumentation-winston": "^0.40.0", + "@opentelemetry/resource-detector-alibaba-cloud": "^0.29.3", + "@opentelemetry/resource-detector-aws": "^1.6.2", + "@opentelemetry/resource-detector-azure": "^0.2.11", + "@opentelemetry/resource-detector-container": "^0.4.4", + "@opentelemetry/resource-detector-gcp": "^0.29.12", + "@opentelemetry/resources": "^1.24.0", + "@opentelemetry/sdk-node": "^0.53.0" }, "engines": { - "node": ">=10.12.0" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.4.1" } }, - "node_modules/@phenomnomnominal/tsquery": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@phenomnomnominal/tsquery/-/tsquery-5.0.1.tgz", - "integrity": "sha512-3nVv+e2FQwsW8Aw6qTU6f+1rfcJ3hrcnvH/mu9i8YhxO+9sqbOfpL8m6PbET5+xKOlz/VSbp0RoYWYCtIsnmuA==", - "dev": true, + "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "esquery": "^1.4.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { - "typescript": "^3 || ^4 || ^5" + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "optional": true, + "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/instrumentation-express": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-express/-/instrumentation-express-0.43.0.tgz", + "integrity": "sha512-bxTIlzn9qPXJgrhz8/Do5Q3jIlqfpoJrSUtVGqH+90eM1v2PkPHc+SdE+zSqe4q9Y1UQJosmZ4N4bm7Zj/++MA==", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, "engines": { "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@pnpm/config.env-replace": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", - "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", + "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/instrumentation-http": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.53.0.tgz", + "integrity": "sha512-H74ErMeDuZfj7KgYCTOFGWF5W9AfaPnqLQQxeFq85+D29wwV2yqHbz2IKLYpkOh7EI6QwDEl7rZCIxjJLyc/CQ==", + "dependencies": { + "@opentelemetry/core": "1.26.0", + "@opentelemetry/instrumentation": "0.53.0", + "@opentelemetry/semantic-conventions": "1.27.0", + "semver": "^7.5.2" + }, "engines": { - "node": ">=12.22.0" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@pnpm/network.ca-file": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", - "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", + "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/instrumentation-nestjs-core": { + "version": "0.40.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-nestjs-core/-/instrumentation-nestjs-core-0.40.0.tgz", + "integrity": "sha512-WF1hCUed07vKmf5BzEkL0wSPinqJgH7kGzOjjMAiTGacofNXjb/y4KQ8loj2sNsh5C/NN7s1zxQuCgbWbVTGKg==", "dependencies": { - "graceful-fs": "4.2.10" + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { - "node": ">=12.22.0" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } }, - "node_modules/@pnpm/npm-conf": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.2.2.tgz", - "integrity": "sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==", + "node_modules/@opentelemetry/context-async-hooks": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-1.26.0.tgz", + "integrity": "sha512-HedpXXYzzbaoutw6DFLWLDket2FwLkLpil4hGCZ1xYEIMTcivdfwEOISgdbLEWyG3HW52gTq2V9mOVJrONgiwg==", + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/core": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.26.0.tgz", + "integrity": "sha512-1iKxXXE8415Cdv0yjG3G6hQnB5eVEsJce3QaawX8SjDn0mAS0ZM8fAbZZJD4ajvhC15cePvosSCut404KrIIvQ==", "dependencies": { - "@pnpm/config.env-replace": "^1.1.0", - "@pnpm/network.ca-file": "^1.0.1", - "config-chain": "^1.1.11" + "@opentelemetry/semantic-conventions": "1.27.0" }, "engines": { - "node": ">=12" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@polka/url": { - "version": "1.0.0-next.25", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.25.tgz", - "integrity": "sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==" - }, - "node_modules/@polkadot-api/json-rpc-provider": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/@polkadot-api/json-rpc-provider/-/json-rpc-provider-0.0.1.tgz", - "integrity": "sha512-/SMC/l7foRjpykLTUTacIH05H3mr9ip8b5xxfwXlVezXrNVLp3Cv0GX6uItkKd+ZjzVPf3PFrDF2B2/HLSNESA==", - "license": "MIT", - "optional": true + "node_modules/@opentelemetry/exporter-logs-otlp-grpc": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-grpc/-/exporter-logs-otlp-grpc-0.53.0.tgz", + "integrity": "sha512-x5ygAQgWAQOI+UOhyV3z9eW7QU2dCfnfOuIBiyYmC2AWr74f6x/3JBnP27IAcEx6aihpqBYWKnpoUTztkVPAZw==", + "dependencies": { + "@grpc/grpc-js": "^1.7.1", + "@opentelemetry/core": "1.26.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.53.0", + "@opentelemetry/otlp-transformer": "0.53.0", + "@opentelemetry/sdk-logs": "0.53.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } }, - "node_modules/@polkadot-api/json-rpc-provider-proxy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@polkadot-api/json-rpc-provider-proxy/-/json-rpc-provider-proxy-0.1.0.tgz", - "integrity": "sha512-8GSFE5+EF73MCuLQm8tjrbCqlgclcHBSRaswvXziJ0ZW7iw3UEMsKkkKvELayWyBuOPa2T5i1nj6gFOeIsqvrg==", - "license": "MIT", - "optional": true + "node_modules/@opentelemetry/exporter-logs-otlp-http": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.53.0.tgz", + "integrity": "sha512-cSRKgD/n8rb+Yd+Cif6EnHEL/VZg1o8lEcEwFji1lwene6BdH51Zh3feAD9p2TyVoBKrl6Q9Zm2WltSp2k9gWQ==", + "dependencies": { + "@opentelemetry/api-logs": "0.53.0", + "@opentelemetry/core": "1.26.0", + "@opentelemetry/otlp-exporter-base": "0.53.0", + "@opentelemetry/otlp-transformer": "0.53.0", + "@opentelemetry/sdk-logs": "0.53.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } }, - "node_modules/@polkadot-api/metadata-builders": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@polkadot-api/metadata-builders/-/metadata-builders-0.3.2.tgz", - "integrity": "sha512-TKpfoT6vTb+513KDzMBTfCb/ORdgRnsS3TDFpOhAhZ08ikvK+hjHMt5plPiAX/OWkm1Wc9I3+K6W0hX5Ab7MVg==", - "license": "MIT", - "optional": true, + "node_modules/@opentelemetry/exporter-logs-otlp-proto": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.53.0.tgz", + "integrity": "sha512-jhEcVL1deeWNmTUP05UZMriZPSWUBcfg94ng7JuBb1q2NExgnADQFl1VQQ+xo62/JepK+MxQe4xAwlsDQFbISA==", "dependencies": { - "@polkadot-api/substrate-bindings": "0.6.0", - "@polkadot-api/utils": "0.1.0" + "@opentelemetry/api-logs": "0.53.0", + "@opentelemetry/core": "1.26.0", + "@opentelemetry/otlp-exporter-base": "0.53.0", + "@opentelemetry/otlp-transformer": "0.53.0", + "@opentelemetry/resources": "1.26.0", + "@opentelemetry/sdk-logs": "0.53.0", + "@opentelemetry/sdk-trace-base": "1.26.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@polkadot-api/observable-client": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@polkadot-api/observable-client/-/observable-client-0.3.2.tgz", - "integrity": "sha512-HGgqWgEutVyOBXoGOPp4+IAq6CNdK/3MfQJmhCJb8YaJiaK4W6aRGrdQuQSTPHfERHCARt9BrOmEvTXAT257Ug==", - "license": "MIT", - "optional": true, + "node_modules/@opentelemetry/exporter-logs-otlp-proto/node_modules/@opentelemetry/resources": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", + "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", + "license": "Apache-2.0", "dependencies": { - "@polkadot-api/metadata-builders": "0.3.2", - "@polkadot-api/substrate-bindings": "0.6.0", - "@polkadot-api/utils": "0.1.0" + "@opentelemetry/core": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { - "@polkadot-api/substrate-client": "0.1.4", - "rxjs": ">=7.8.0" + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@polkadot-api/substrate-bindings": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@polkadot-api/substrate-bindings/-/substrate-bindings-0.6.0.tgz", - "integrity": "sha512-lGuhE74NA1/PqdN7fKFdE5C1gNYX357j1tWzdlPXI0kQ7h3kN0zfxNOpPUN7dIrPcOFZ6C0tRRVrBylXkI6xPw==", - "license": "MIT", - "optional": true, + "node_modules/@opentelemetry/exporter-logs-otlp-proto/node_modules/@opentelemetry/sdk-trace-base": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.26.0.tgz", + "integrity": "sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw==", + "license": "Apache-2.0", "dependencies": { - "@noble/hashes": "^1.3.1", - "@polkadot-api/utils": "0.1.0", - "@scure/base": "^1.1.1", - "scale-ts": "^1.6.0" + "@opentelemetry/core": "1.26.0", + "@opentelemetry/resources": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@polkadot-api/substrate-client": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@polkadot-api/substrate-client/-/substrate-client-0.1.4.tgz", - "integrity": "sha512-MljrPobN0ZWTpn++da9vOvt+Ex+NlqTlr/XT7zi9sqPtDJiQcYl+d29hFAgpaeTqbeQKZwz3WDE9xcEfLE8c5A==", - "license": "MIT", - "optional": true, + "node_modules/@opentelemetry/exporter-metrics-otlp-http": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-http/-/exporter-metrics-otlp-http-0.53.0.tgz", + "integrity": "sha512-nvZtOk23pZOrTW10Za2WPd9pk4tWDvL6ALlHRFfInpcTjtOgCrv+fQDxpzosa5PeXvYeFFUO5aYCTnwiCX4Dzg==", "dependencies": { - "@polkadot-api/json-rpc-provider": "0.0.1", - "@polkadot-api/utils": "0.1.0" + "@opentelemetry/core": "1.26.0", + "@opentelemetry/otlp-exporter-base": "0.53.0", + "@opentelemetry/otlp-transformer": "0.53.0", + "@opentelemetry/resources": "1.26.0", + "@opentelemetry/sdk-metrics": "1.26.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@polkadot-api/utils": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@polkadot-api/utils/-/utils-0.1.0.tgz", - "integrity": "sha512-MXzWZeuGxKizPx2Xf/47wx9sr/uxKw39bVJUptTJdsaQn/TGq+z310mHzf1RCGvC1diHM8f593KrnDgc9oNbJA==", - "license": "MIT", - "optional": true - }, - "node_modules/@polkadot/api": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@polkadot/api/-/api-14.1.1.tgz", - "integrity": "sha512-3uSJUdaohKtAvj9fjqyOkYs0PthWBdWtkko2TcYGRxj9BikbZMmx+agdkty8VrOxvn3pPoTRKe/jMt2Txn2MaA==", + "node_modules/@opentelemetry/exporter-metrics-otlp-http/node_modules/@opentelemetry/resources": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", + "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", "license": "Apache-2.0", "dependencies": { - "@polkadot/api-augment": "14.1.1", - "@polkadot/api-base": "14.1.1", - "@polkadot/api-derive": "14.1.1", - "@polkadot/keyring": "^13.2.1", - "@polkadot/rpc-augment": "14.1.1", - "@polkadot/rpc-core": "14.1.1", - "@polkadot/rpc-provider": "14.1.1", - "@polkadot/types": "14.1.1", - "@polkadot/types-augment": "14.1.1", - "@polkadot/types-codec": "14.1.1", - "@polkadot/types-create": "14.1.1", - "@polkadot/types-known": "14.1.1", - "@polkadot/util": "^13.2.1", - "@polkadot/util-crypto": "^13.2.1", - "eventemitter3": "^5.0.1", - "rxjs": "^7.8.1", - "tslib": "^2.8.0" + "@opentelemetry/core": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" }, "engines": { - "node": ">=18" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@polkadot/api-augment": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@polkadot/api-augment/-/api-augment-14.1.1.tgz", - "integrity": "sha512-n6aexVgdlHfh3d12qFYpooxzS9yjKq/oxLNXKvhpV3CMg36Hlq4ULDdtI6L3sB8I3nwdBEWaXyBvbpKvPZGUxQ==", - "license": "Apache-2.0", + "node_modules/@opentelemetry/exporter-metrics-otlp-proto": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-proto/-/exporter-metrics-otlp-proto-0.53.0.tgz", + "integrity": "sha512-cO99cY04Oy+i8nfYoY0DOVRWVSb0unlerblvf4Fyt2Ls8CkUECLfgjfUXqdjOhBYOX/OZGOBSGetqqYFtKGdGA==", "dependencies": { - "@polkadot/api-base": "14.1.1", - "@polkadot/rpc-augment": "14.1.1", - "@polkadot/types": "14.1.1", - "@polkadot/types-augment": "14.1.1", - "@polkadot/types-codec": "14.1.1", - "@polkadot/util": "^13.2.1", - "tslib": "^2.8.0" + "@opentelemetry/core": "1.26.0", + "@opentelemetry/exporter-metrics-otlp-http": "0.53.0", + "@opentelemetry/otlp-exporter-base": "0.53.0", + "@opentelemetry/otlp-transformer": "0.53.0", + "@opentelemetry/resources": "1.26.0", + "@opentelemetry/sdk-metrics": "1.26.0" }, "engines": { - "node": ">=18" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@polkadot/api-augment/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@polkadot/api-base": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@polkadot/api-base/-/api-base-14.1.1.tgz", - "integrity": "sha512-gMj0uIlAv6RkRMzmhl61KU1/Pcadrarxn0lBdDTcVua3KEWLuncI+VbiN3cEd/aW6QUTgcDFpppm8nfwD9eVzQ==", + "node_modules/@opentelemetry/exporter-metrics-otlp-proto/node_modules/@opentelemetry/resources": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", + "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", "license": "Apache-2.0", "dependencies": { - "@polkadot/rpc-core": "14.1.1", - "@polkadot/types": "14.1.1", - "@polkadot/util": "^13.2.1", - "rxjs": "^7.8.1", - "tslib": "^2.8.0" + "@opentelemetry/core": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" }, "engines": { - "node": ">=18" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@polkadot/api-base/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@polkadot/api-derive": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@polkadot/api-derive/-/api-derive-14.1.1.tgz", - "integrity": "sha512-ZElYAr/euw2fR7RmGkgJgF88IK9iz3rqgesmdLtgQ2a85MEiR4UrVvhNKSjMr9PSn7EUM1mUixZhGp3jvuqrsA==", - "license": "Apache-2.0", + "node_modules/@opentelemetry/exporter-trace-otlp-grpc": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-grpc/-/exporter-trace-otlp-grpc-0.53.0.tgz", + "integrity": "sha512-m6KSh6OBDwfDjpzPVbuJbMgMbkoZfpxYH2r262KckgX9cMYvooWXEKzlJYsNDC6ADr28A1rtRoUVRwNfIN4tUg==", "dependencies": { - "@polkadot/api": "14.1.1", - "@polkadot/api-augment": "14.1.1", - "@polkadot/api-base": "14.1.1", - "@polkadot/rpc-core": "14.1.1", - "@polkadot/types": "14.1.1", - "@polkadot/types-codec": "14.1.1", - "@polkadot/util": "^13.2.1", - "@polkadot/util-crypto": "^13.2.1", - "rxjs": "^7.8.1", - "tslib": "^2.8.0" + "@grpc/grpc-js": "^1.7.1", + "@opentelemetry/core": "1.26.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.53.0", + "@opentelemetry/otlp-transformer": "0.53.0", + "@opentelemetry/resources": "1.26.0", + "@opentelemetry/sdk-trace-base": "1.26.0" }, "engines": { - "node": ">=18" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@polkadot/api-derive/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@polkadot/api/node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "license": "MIT" - }, - "node_modules/@polkadot/api/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@polkadot/keyring": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/keyring/-/keyring-13.2.3.tgz", - "integrity": "sha512-pgTo6DXNXub0wGD+MnVHYhKxf80Jl+QMOCb818ioGdXz++Uw4mTueFAwtB+N7TGo0HafhChUiNJDxFdlDkcAng==", + "node_modules/@opentelemetry/exporter-trace-otlp-grpc/node_modules/@opentelemetry/resources": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", + "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", "license": "Apache-2.0", "dependencies": { - "@polkadot/util": "13.2.3", - "@polkadot/util-crypto": "13.2.3", - "tslib": "^2.8.0" + "@opentelemetry/core": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" }, "engines": { - "node": ">=18" + "node": ">=14" }, "peerDependencies": { - "@polkadot/util": "13.2.3", - "@polkadot/util-crypto": "13.2.3" + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@polkadot/keyring/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@polkadot/networks": { - "version": "13.3.1", - "resolved": "https://registry.npmjs.org/@polkadot/networks/-/networks-13.3.1.tgz", - "integrity": "sha512-g/0OmCMUrbbW4RQ/xajTYd2SMJvFKY4kmMvpxtNN57hWQpY7c5oDXSz57jGH2uwvcBWeDfaNokcS+9hJL1RBcA==", + "node_modules/@opentelemetry/exporter-trace-otlp-grpc/node_modules/@opentelemetry/sdk-trace-base": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.26.0.tgz", + "integrity": "sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw==", "license": "Apache-2.0", "dependencies": { - "@polkadot/util": "13.3.1", - "@substrate/ss58-registry": "^1.51.0", - "tslib": "^2.8.0" + "@opentelemetry/core": "1.26.0", + "@opentelemetry/resources": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" }, "engines": { - "node": ">=18" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@polkadot/networks/node_modules/@polkadot/util": { - "version": "13.3.1", - "resolved": "https://registry.npmjs.org/@polkadot/util/-/util-13.3.1.tgz", - "integrity": "sha512-5crLP/rUZOJzuo/W8t73J8PxpibJ5vrxY57rR6V+mIpCZd1ORiw0wxeHcV5F9Adpn7yJyuGBwxPbueNR5Rr1Zw==", - "license": "Apache-2.0", + "node_modules/@opentelemetry/exporter-trace-otlp-proto": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-proto/-/exporter-trace-otlp-proto-0.53.0.tgz", + "integrity": "sha512-T/bdXslwRKj23S96qbvGtaYOdfyew3TjPEKOk5mHjkCmkVl1O9C/YMdejwSsdLdOq2YW30KjR9kVi0YMxZushQ==", "dependencies": { - "@polkadot/x-bigint": "13.3.1", - "@polkadot/x-global": "13.3.1", - "@polkadot/x-textdecoder": "13.3.1", - "@polkadot/x-textencoder": "13.3.1", - "@types/bn.js": "^5.1.6", - "bn.js": "^5.2.1", - "tslib": "^2.8.0" + "@opentelemetry/core": "1.26.0", + "@opentelemetry/otlp-exporter-base": "0.53.0", + "@opentelemetry/otlp-transformer": "0.53.0", + "@opentelemetry/resources": "1.26.0", + "@opentelemetry/sdk-trace-base": "1.26.0" }, "engines": { - "node": ">=18" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@polkadot/networks/node_modules/@polkadot/x-textdecoder": { - "version": "13.3.1", - "resolved": "https://registry.npmjs.org/@polkadot/x-textdecoder/-/x-textdecoder-13.3.1.tgz", - "integrity": "sha512-g2R9O1p0ZsNDhZ3uEBZh6fQaVLlo3yFr0YNqt15v7e9lBI4APvTJ202EINlo2jB5lz/R438/BdjEA3AL+0zUtQ==", + "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/resources": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", + "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", "license": "Apache-2.0", "dependencies": { - "@polkadot/x-global": "13.3.1", - "tslib": "^2.8.0" + "@opentelemetry/core": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" }, "engines": { - "node": ">=18" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@polkadot/networks/node_modules/@polkadot/x-textencoder": { - "version": "13.3.1", - "resolved": "https://registry.npmjs.org/@polkadot/x-textencoder/-/x-textencoder-13.3.1.tgz", - "integrity": "sha512-DnHLUdoKDYxekfxopuUuPB+j5Mu7Jemejcduu5gz3/89GP/sYPAu0CAVbq9B+hK1yGjBBj31eA4wkAV1oktYmg==", + "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/sdk-trace-base": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.26.0.tgz", + "integrity": "sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw==", "license": "Apache-2.0", "dependencies": { - "@polkadot/x-global": "13.3.1", - "tslib": "^2.8.0" + "@opentelemetry/core": "1.26.0", + "@opentelemetry/resources": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" }, "engines": { - "node": ">=18" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@polkadot/networks/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@polkadot/rpc-augment": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@polkadot/rpc-augment/-/rpc-augment-14.1.1.tgz", - "integrity": "sha512-jeDYDepe6IOzgUFD+vLEuLrWGqw/dJIcxb8uf/YpnsvzA8kbPZx3BcIhboIpI8HpdKdn6f5mflSTVgDUpUPmNg==", - "license": "Apache-2.0", + "node_modules/@opentelemetry/exporter-zipkin": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-zipkin/-/exporter-zipkin-1.26.0.tgz", + "integrity": "sha512-PW5R34n3SJHO4t0UetyHKiXL6LixIqWN6lWncg3eRXhKuT30x+b7m5sDJS0kEWRfHeS+kG7uCw2vBzmB2lk3Dw==", "dependencies": { - "@polkadot/rpc-core": "14.1.1", - "@polkadot/types": "14.1.1", - "@polkadot/types-codec": "14.1.1", - "@polkadot/util": "^13.2.1", - "tslib": "^2.8.0" + "@opentelemetry/core": "1.26.0", + "@opentelemetry/resources": "1.26.0", + "@opentelemetry/sdk-trace-base": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" }, "engines": { - "node": ">=18" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@polkadot/rpc-augment/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@polkadot/rpc-core": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@polkadot/rpc-core/-/rpc-core-14.1.1.tgz", - "integrity": "sha512-rfV1ArJcAZQ3lzAM9P+yIaXN720yJysNGy14FxupLsFsvzowEnEPs4khS2HgnX6j1RqkElw6va/ZVhOsLPhy9w==", + "node_modules/@opentelemetry/exporter-zipkin/node_modules/@opentelemetry/resources": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", + "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", "license": "Apache-2.0", "dependencies": { - "@polkadot/rpc-augment": "14.1.1", - "@polkadot/rpc-provider": "14.1.1", - "@polkadot/types": "14.1.1", - "@polkadot/util": "^13.2.1", - "rxjs": "^7.8.1", - "tslib": "^2.8.0" + "@opentelemetry/core": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" }, "engines": { - "node": ">=18" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@polkadot/rpc-core/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@polkadot/rpc-provider": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@polkadot/rpc-provider/-/rpc-provider-14.1.1.tgz", - "integrity": "sha512-BY0H1CC7M360uHXU2IfFdgFmcdjmIz6NxPmXRhrT3QGFmJSHuFevjTbIFlPG7YBK5ivochLrcISelRr7HKXYOg==", + "node_modules/@opentelemetry/exporter-zipkin/node_modules/@opentelemetry/sdk-trace-base": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.26.0.tgz", + "integrity": "sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw==", "license": "Apache-2.0", "dependencies": { - "@polkadot/keyring": "^13.2.1", - "@polkadot/types": "14.1.1", - "@polkadot/types-support": "14.1.1", - "@polkadot/util": "^13.2.1", - "@polkadot/util-crypto": "^13.2.1", - "@polkadot/x-fetch": "^13.2.1", - "@polkadot/x-global": "^13.2.1", - "@polkadot/x-ws": "^13.2.1", - "eventemitter3": "^5.0.1", - "mock-socket": "^9.3.1", - "nock": "^13.5.5", - "tslib": "^2.8.0" + "@opentelemetry/core": "1.26.0", + "@opentelemetry/resources": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" }, "engines": { - "node": ">=18" + "node": ">=14" }, - "optionalDependencies": { - "@substrate/connect": "0.8.11" + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@polkadot/rpc-provider/node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "license": "MIT" - }, - "node_modules/@polkadot/rpc-provider/node_modules/nock": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/nock/-/nock-13.5.6.tgz", - "integrity": "sha512-o2zOYiCpzRqSzPj0Zt/dQ/DqZeYoaQ7TUonc/xUPjCGl9WeHpNbxgVvOquXYAaJzI0M9BXV3HTzG0p8IUAbBTQ==", - "license": "MIT", + "node_modules/@opentelemetry/instrumentation-amqplib": { + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-amqplib/-/instrumentation-amqplib-0.42.0.tgz", + "integrity": "sha512-fiuU6OKsqHJiydHWgTRQ7MnIrJ2lEqsdgFtNIH4LbAUJl/5XmrIeoDzDnox+hfkgWK65jsleFuQDtYb5hW1koQ==", "dependencies": { - "debug": "^4.1.0", - "json-stringify-safe": "^5.0.1", - "propagate": "^2.0.0" + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { - "node": ">= 10.13" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@polkadot/rpc-provider/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@polkadot/types": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-14.1.1.tgz", - "integrity": "sha512-bT1wxu2wZsKR8Ih1PHu4SqptOF+MQbh21e+NJVZkIsrjQz1DvKkdcW4G/s0i0vX/QIjnXTJFC84vMzr5cxJm8Q==", + "node_modules/@opentelemetry/instrumentation-amqplib/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", "license": "Apache-2.0", "dependencies": { - "@polkadot/keyring": "^13.2.1", - "@polkadot/types-augment": "14.1.1", - "@polkadot/types-codec": "14.1.1", - "@polkadot/types-create": "14.1.1", - "@polkadot/util": "^13.2.1", - "@polkadot/util-crypto": "^13.2.1", - "rxjs": "^7.8.1", - "tslib": "^2.8.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, "engines": { - "node": ">=18" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@polkadot/types-augment": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@polkadot/types-augment/-/types-augment-14.1.1.tgz", - "integrity": "sha512-A73JCwmg5ZuYVHw1k7Lxx4MjjRwQd6Yw/VaRIPqjk3iyG5r9RyFJgsJ7xRafDlKFG0AJ5c6ixvlaHOnBrEAzpQ==", - "license": "Apache-2.0", - "dependencies": { - "@polkadot/types": "14.1.1", - "@polkadot/types-codec": "14.1.1", - "@polkadot/util": "^13.2.1", - "tslib": "^2.8.0" + "node_modules/@opentelemetry/instrumentation-amqplib/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=18" + "node": ">=10" } }, - "node_modules/@polkadot/types-augment/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@polkadot/types-codec": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@polkadot/types-codec/-/types-codec-14.1.1.tgz", - "integrity": "sha512-O6UyTjEAeZMf/uthF3NjCy4tiAeWjj4tfTEWTx2Z65fNTTbXx1Mq5YBBOWsvzBXGBFK35C8buYa4l8cgQS9MoA==", - "license": "Apache-2.0", + "node_modules/@opentelemetry/instrumentation-aws-lambda": { + "version": "0.45.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-aws-lambda/-/instrumentation-aws-lambda-0.45.0.tgz", + "integrity": "sha512-22ZnmYftKjFoiqC1k3tu2AVKiXSZv+ohuHWk4V4MdJpPuNkadY624aDkv5BmwDeavDxVFgqE9nGgDM9s3Q94mg==", "dependencies": { - "@polkadot/util": "^13.2.1", - "@polkadot/x-bigint": "^13.2.1", - "tslib": "^2.8.0" + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/propagator-aws-xray": "^1.3.1", + "@opentelemetry/resources": "^1.8.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/aws-lambda": "8.10.143" }, "engines": { - "node": ">=18" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@polkadot/types-codec/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@polkadot/types-create": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@polkadot/types-create/-/types-create-14.1.1.tgz", - "integrity": "sha512-t4gr5NKU8zZetnDvoRnlioEZlkYybBSql+Ep3mQUiJosF5w/SCN6EKV0GPqs0fB1ovqhDQSnwe2xoRjHsiHObA==", + "node_modules/@opentelemetry/instrumentation-aws-lambda/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", "license": "Apache-2.0", "dependencies": { - "@polkadot/types-codec": "14.1.1", - "@polkadot/util": "^13.2.1", - "tslib": "^2.8.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, "engines": { - "node": ">=18" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@polkadot/types-create/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" + "node_modules/@opentelemetry/instrumentation-aws-lambda/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } }, - "node_modules/@polkadot/types-known": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@polkadot/types-known/-/types-known-14.1.1.tgz", - "integrity": "sha512-TvyqTsm1Wxw+tjN8UsB04+vZv5znZE5ETGunHLHnvv4WF/lkz4WpkRc/9iqduM5O/iOZh8mEb7n/uyz8LL4brA==", - "license": "Apache-2.0", + "node_modules/@opentelemetry/instrumentation-aws-sdk": { + "version": "0.44.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-aws-sdk/-/instrumentation-aws-sdk-0.44.0.tgz", + "integrity": "sha512-HIWFg4TDQsayceiikOnruMmyQ0SZYW6WiR+wknWwWVLHC3lHTCpAnqzp5V42ckArOdlwHZu2Jvq2GMSM4Myx3w==", "dependencies": { - "@polkadot/networks": "^13.2.1", - "@polkadot/types": "14.1.1", - "@polkadot/types-codec": "14.1.1", - "@polkadot/types-create": "14.1.1", - "@polkadot/util": "^13.2.1", - "tslib": "^2.8.0" + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/propagation-utils": "^0.30.11", + "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { - "node": ">=18" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@polkadot/types-known/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@polkadot/types-support": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/@polkadot/types-support/-/types-support-14.1.1.tgz", - "integrity": "sha512-DJgJ/2n3eWFlgH1K/U7G4NSbgdsx4Lb1fK4yVlZ9t81lJWWiAeb/FodHJb8jlQ6Jezx5S71fRripXfg+FdyCDA==", + "node_modules/@opentelemetry/instrumentation-aws-sdk/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", "license": "Apache-2.0", "dependencies": { - "@polkadot/util": "^13.2.1", - "tslib": "^2.8.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, "engines": { - "node": ">=18" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@polkadot/types-support/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@polkadot/types/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" + "node_modules/@opentelemetry/instrumentation-aws-sdk/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } }, - "node_modules/@polkadot/util": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/util/-/util-13.2.3.tgz", - "integrity": "sha512-pioNnsig3qHXrfOKMe4Yqos8B8N3/EZUpS+WfTpWnn1VjYban/0GrTXeavPlAwggnY27b8fS6rBzQBhnVYDw8g==", - "license": "Apache-2.0", + "node_modules/@opentelemetry/instrumentation-bunyan": { + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-bunyan/-/instrumentation-bunyan-0.41.0.tgz", + "integrity": "sha512-NoQS+gcwQ7pzb2PZFyra6bAxDAVXBMmpKxBblEuXJWirGrAksQllg9XTdmqhrwT/KxUYrbVca/lMams7e51ysg==", "dependencies": { - "@polkadot/x-bigint": "13.2.3", - "@polkadot/x-global": "13.2.3", - "@polkadot/x-textdecoder": "13.2.3", - "@polkadot/x-textencoder": "13.2.3", - "@types/bn.js": "^5.1.6", - "bn.js": "^5.2.1", - "tslib": "^2.8.0" + "@opentelemetry/api-logs": "^0.53.0", + "@opentelemetry/instrumentation": "^0.53.0", + "@types/bunyan": "1.8.9" }, "engines": { - "node": ">=18" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@polkadot/util-crypto": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/util-crypto/-/util-crypto-13.2.3.tgz", - "integrity": "sha512-5sbggmLbn5eiuVMyPROPlT5roHRqdKHOfSpioNbGvGIZ1qIWVoC1RfsK0NWJOVGDzy6DpQe0KYT/kgcU5Xsrzw==", + "node_modules/@opentelemetry/instrumentation-bunyan/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", "license": "Apache-2.0", "dependencies": { - "@noble/curves": "^1.3.0", - "@noble/hashes": "^1.3.3", - "@polkadot/networks": "13.2.3", - "@polkadot/util": "13.2.3", - "@polkadot/wasm-crypto": "^7.4.1", - "@polkadot/wasm-util": "^7.4.1", - "@polkadot/x-bigint": "13.2.3", - "@polkadot/x-randomvalues": "13.2.3", - "@scure/base": "^1.1.7", - "tslib": "^2.8.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, "engines": { - "node": ">=18" + "node": ">=14" }, "peerDependencies": { - "@polkadot/util": "13.2.3" + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@polkadot/util-crypto/node_modules/@polkadot/networks": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/networks/-/networks-13.2.3.tgz", - "integrity": "sha512-mG+zkXg/33AyPrkv2xBbAo3LBUwOwBn6qznBU/4jxiZPnVvCwMaxE7xHM22B5riItbNJ169FXv3wy0v6ZmkFbw==", - "license": "Apache-2.0", - "dependencies": { - "@polkadot/util": "13.2.3", - "@substrate/ss58-registry": "^1.51.0", - "tslib": "^2.8.0" + "node_modules/@opentelemetry/instrumentation-bunyan/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=18" + "node": ">=10" } }, - "node_modules/@polkadot/util-crypto/node_modules/@polkadot/x-bigint": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-bigint/-/x-bigint-13.2.3.tgz", - "integrity": "sha512-VKgEAh0LsxTd/Hg517Tt5ZU4CySjBwMpaojbkjgv3fOdg1cN7t4eFEUxpyj7mlO0cp22SzDh7nmy4TO98qhLQA==", - "license": "Apache-2.0", + "node_modules/@opentelemetry/instrumentation-cassandra-driver": { + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-cassandra-driver/-/instrumentation-cassandra-driver-0.41.0.tgz", + "integrity": "sha512-hvTNcC8qjCQEHZTLAlTmDptjsEGqCKpN+90hHH8Nn/GwilGr5TMSwGrlfstdJuZWyw8HAnRUed6bcjvmHHk2Xw==", "dependencies": { - "@polkadot/x-global": "13.2.3", - "tslib": "^2.8.0" + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { - "node": ">=18" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@polkadot/util-crypto/node_modules/@polkadot/x-global": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-global/-/x-global-13.2.3.tgz", - "integrity": "sha512-7MYQIAEwBkRcNrgqac5PbB0kNPlI6ISJEy6/Nb+crj8BFjQ8rf11PF49fq0QsvDeuYM1aNLigrvYZNptQs4lbw==", + "node_modules/@opentelemetry/instrumentation-cassandra-driver/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", "license": "Apache-2.0", "dependencies": { - "tslib": "^2.8.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, "engines": { - "node": ">=18" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@polkadot/util-crypto/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@polkadot/util/node_modules/@polkadot/x-bigint": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-bigint/-/x-bigint-13.2.3.tgz", - "integrity": "sha512-VKgEAh0LsxTd/Hg517Tt5ZU4CySjBwMpaojbkjgv3fOdg1cN7t4eFEUxpyj7mlO0cp22SzDh7nmy4TO98qhLQA==", - "license": "Apache-2.0", - "dependencies": { - "@polkadot/x-global": "13.2.3", - "tslib": "^2.8.0" + "node_modules/@opentelemetry/instrumentation-cassandra-driver/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=18" + "node": ">=10" } }, - "node_modules/@polkadot/util/node_modules/@polkadot/x-global": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-global/-/x-global-13.2.3.tgz", - "integrity": "sha512-7MYQIAEwBkRcNrgqac5PbB0kNPlI6ISJEy6/Nb+crj8BFjQ8rf11PF49fq0QsvDeuYM1aNLigrvYZNptQs4lbw==", - "license": "Apache-2.0", + "node_modules/@opentelemetry/instrumentation-connect": { + "version": "0.39.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.39.0.tgz", + "integrity": "sha512-pGBiKevLq7NNglMgqzmeKczF4XQMTOUOTkK8afRHMZMnrK3fcETyTH7lVaSozwiOM3Ws+SuEmXZT7DYrrhxGlg==", "dependencies": { - "tslib": "^2.8.0" + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/connect": "3.4.36" }, "engines": { - "node": ">=18" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@polkadot/util/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@polkadot/wasm-bridge": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-bridge/-/wasm-bridge-7.4.1.tgz", - "integrity": "sha512-tdkJaV453tezBxhF39r4oeG0A39sPKGDJmN81LYLf+Fihb7astzwju+u75BRmDrHZjZIv00un3razJEWCxze6g==", + "node_modules/@opentelemetry/instrumentation-connect/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", "license": "Apache-2.0", "dependencies": { - "@polkadot/wasm-util": "7.4.1", - "tslib": "^2.7.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, "engines": { - "node": ">=18" + "node": ">=14" }, "peerDependencies": { - "@polkadot/util": "*", - "@polkadot/x-randomvalues": "*" + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@polkadot/wasm-bridge/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@polkadot/wasm-crypto": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto/-/wasm-crypto-7.4.1.tgz", - "integrity": "sha512-kHN/kF7hYxm1y0WeFLWeWir6oTzvcFmR4N8fJJokR+ajYbdmrafPN+6iLgQVbhZnDdxyv9jWDuRRsDnBx8tPMQ==", - "license": "Apache-2.0", + "node_modules/@opentelemetry/instrumentation-connect/node_modules/@types/connect": { + "version": "3.4.36", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.36.tgz", + "integrity": "sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==", "dependencies": { - "@polkadot/wasm-bridge": "7.4.1", - "@polkadot/wasm-crypto-asmjs": "7.4.1", - "@polkadot/wasm-crypto-init": "7.4.1", - "@polkadot/wasm-crypto-wasm": "7.4.1", - "@polkadot/wasm-util": "7.4.1", - "tslib": "^2.7.0" + "@types/node": "*" + } + }, + "node_modules/@opentelemetry/instrumentation-connect/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@polkadot/util": "*", - "@polkadot/x-randomvalues": "*" + "node": ">=10" } }, - "node_modules/@polkadot/wasm-crypto-asmjs": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-asmjs/-/wasm-crypto-asmjs-7.4.1.tgz", - "integrity": "sha512-pwU8QXhUW7IberyHJIQr37IhbB6DPkCG5FhozCiNTq4vFBsFPjm9q8aZh7oX1QHQaiAZa2m2/VjIVE+FHGbvHQ==", - "license": "Apache-2.0", + "node_modules/@opentelemetry/instrumentation-cucumber": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-cucumber/-/instrumentation-cucumber-0.9.0.tgz", + "integrity": "sha512-4PQNFnIqnA2WM3ZHpr0xhZpHSqJ5xJ6ppTIzZC7wPqe+ZBpj41vG8B6ieqiPfq+im4QdqbYnzLb3rj48GDEN9g==", "dependencies": { - "tslib": "^2.7.0" + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { - "node": ">=18" + "node": ">=14" }, "peerDependencies": { - "@polkadot/util": "*" + "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@polkadot/wasm-crypto-asmjs/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@polkadot/wasm-crypto-init": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-init/-/wasm-crypto-init-7.4.1.tgz", - "integrity": "sha512-AVka33+f7MvXEEIGq5U0dhaA2SaXMXnxVCQyhJTaCnJ5bRDj0Xlm3ijwDEQUiaDql7EikbkkRtmlvs95eSUWYQ==", + "node_modules/@opentelemetry/instrumentation-cucumber/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", "license": "Apache-2.0", "dependencies": { - "@polkadot/wasm-bridge": "7.4.1", - "@polkadot/wasm-crypto-asmjs": "7.4.1", - "@polkadot/wasm-crypto-wasm": "7.4.1", - "@polkadot/wasm-util": "7.4.1", - "tslib": "^2.7.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, "engines": { - "node": ">=18" + "node": ">=14" }, "peerDependencies": { - "@polkadot/util": "*", - "@polkadot/x-randomvalues": "*" + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@polkadot/wasm-crypto-init/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" + "node_modules/@opentelemetry/instrumentation-cucumber/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } }, - "node_modules/@polkadot/wasm-crypto-wasm": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-wasm/-/wasm-crypto-wasm-7.4.1.tgz", - "integrity": "sha512-PE1OAoupFR0ZOV2O8tr7D1FEUAwaggzxtfs3Aa5gr+yxlSOaWUKeqsOYe1KdrcjmZVV3iINEAXxgrbzCmiuONg==", - "license": "Apache-2.0", + "node_modules/@opentelemetry/instrumentation-dataloader": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dataloader/-/instrumentation-dataloader-0.12.0.tgz", + "integrity": "sha512-pnPxatoFE0OXIZDQhL2okF//dmbiWFzcSc8pUg9TqofCLYZySSxDCgQc69CJBo5JnI3Gz1KP+mOjS4WAeRIH4g==", "dependencies": { - "@polkadot/wasm-util": "7.4.1", - "tslib": "^2.7.0" + "@opentelemetry/instrumentation": "^0.53.0" }, "engines": { - "node": ">=18" + "node": ">=14" }, "peerDependencies": { - "@polkadot/util": "*" + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@polkadot/wasm-crypto-wasm/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@polkadot/wasm-crypto/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@polkadot/wasm-util": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-util/-/wasm-util-7.4.1.tgz", - "integrity": "sha512-RAcxNFf3zzpkr+LX/ItAsvj+QyM56TomJ0xjUMo4wKkHjwsxkz4dWJtx5knIgQz/OthqSDMR59VNEycQeNuXzA==", + "node_modules/@opentelemetry/instrumentation-dataloader/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", "license": "Apache-2.0", "dependencies": { - "tslib": "^2.7.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, "engines": { - "node": ">=18" + "node": ">=14" }, "peerDependencies": { - "@polkadot/util": "*" + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@polkadot/wasm-util/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@polkadot/x-bigint": { - "version": "13.3.1", - "resolved": "https://registry.npmjs.org/@polkadot/x-bigint/-/x-bigint-13.3.1.tgz", - "integrity": "sha512-ewc708a7LUdrT92v9DsSAIbcJQBn3aR9/LavF/iyMOq5lZJyPXDSjAnskfMs818R3RLCrKVKfs+aKkxt2eqo8g==", - "license": "Apache-2.0", - "dependencies": { - "@polkadot/x-global": "13.3.1", - "tslib": "^2.8.0" + "node_modules/@opentelemetry/instrumentation-dataloader/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=18" + "node": ">=10" } }, - "node_modules/@polkadot/x-bigint/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@polkadot/x-fetch": { - "version": "13.3.1", - "resolved": "https://registry.npmjs.org/@polkadot/x-fetch/-/x-fetch-13.3.1.tgz", - "integrity": "sha512-J+HM42j0KGqdC/eo7vmsdLPz74MR7+0My4km6TG9HGjKqqztwygtenpopPod2SbRnL4nHiEG0wZzpVOW6HN2gw==", - "license": "Apache-2.0", + "node_modules/@opentelemetry/instrumentation-dns": { + "version": "0.39.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dns/-/instrumentation-dns-0.39.0.tgz", + "integrity": "sha512-+iPzvXqVdJa67QBuz2tuP0UI3LS1/cMMo6dS7360DDtOQX+sQzkiN+mo3Omn4T6ZRhkTDw6c7uwsHBcmL31+1g==", "dependencies": { - "@polkadot/x-global": "13.3.1", - "node-fetch": "^3.3.2", - "tslib": "^2.8.0" + "@opentelemetry/instrumentation": "^0.53.0", + "semver": "^7.5.4" }, "engines": { - "node": ">=18" - } - }, - "node_modules/@polkadot/x-fetch/node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "license": "MIT", - "engines": { - "node": ">= 12" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@polkadot/x-fetch/node_modules/node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", - "license": "MIT", + "node_modules/@opentelemetry/instrumentation-dns/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=14" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@polkadot/x-fetch/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@polkadot/x-global": { - "version": "13.3.1", - "resolved": "https://registry.npmjs.org/@polkadot/x-global/-/x-global-13.3.1.tgz", - "integrity": "sha512-861TeIw49a3JvkwlUWrddfG+JaUqtFZDsemYxxZIjjcRJLrKOsoKNqHbiHi2OPrwlX8PwAA/wc5I9Q4XRQ7KEg==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.8.0" + "node_modules/@opentelemetry/instrumentation-dns/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=18" + "node": ">=10" } }, - "node_modules/@polkadot/x-global/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@polkadot/x-randomvalues": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-randomvalues/-/x-randomvalues-13.2.3.tgz", - "integrity": "sha512-Zf0GTfLmVk+VzPUmcQSpXjjmFzMTjPhXoLuIoE7xIu73T+vQ+TX9j7DvorN6bIRsnZ9l1SyTZsSf/NTjNZKIZg==", - "license": "Apache-2.0", + "node_modules/@opentelemetry/instrumentation-fastify": { + "version": "0.40.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fastify/-/instrumentation-fastify-0.40.0.tgz", + "integrity": "sha512-74qj4nG3zPtU7g2x4sm2T4R3/pBMyrYstTsqSZwdlhQk1SD4l8OSY9sPRX1qkhfxOuW3U4KZQAV/Cymb3fB6hg==", "dependencies": { - "@polkadot/x-global": "13.2.3", - "tslib": "^2.8.0" + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { - "node": ">=18" + "node": ">=14" }, "peerDependencies": { - "@polkadot/util": "13.2.3", - "@polkadot/wasm-util": "*" + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@polkadot/x-randomvalues/node_modules/@polkadot/x-global": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-global/-/x-global-13.2.3.tgz", - "integrity": "sha512-7MYQIAEwBkRcNrgqac5PbB0kNPlI6ISJEy6/Nb+crj8BFjQ8rf11PF49fq0QsvDeuYM1aNLigrvYZNptQs4lbw==", + "node_modules/@opentelemetry/instrumentation-fastify/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", "license": "Apache-2.0", "dependencies": { - "tslib": "^2.8.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, "engines": { - "node": ">=18" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@polkadot/x-randomvalues/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@polkadot/x-textdecoder": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-textdecoder/-/x-textdecoder-13.2.3.tgz", - "integrity": "sha512-i8hRXPtGknmdm3FYv6/94I52VXHJZa5sgYNw1+Hqb4Jqmq4awUjea35CKXd/+aw70Qn8Ngg31l2GoiH494fa+Q==", - "license": "Apache-2.0", - "dependencies": { - "@polkadot/x-global": "13.2.3", - "tslib": "^2.8.0" + "node_modules/@opentelemetry/instrumentation-fastify/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=18" + "node": ">=10" } }, - "node_modules/@polkadot/x-textdecoder/node_modules/@polkadot/x-global": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-global/-/x-global-13.2.3.tgz", - "integrity": "sha512-7MYQIAEwBkRcNrgqac5PbB0kNPlI6ISJEy6/Nb+crj8BFjQ8rf11PF49fq0QsvDeuYM1aNLigrvYZNptQs4lbw==", - "license": "Apache-2.0", + "node_modules/@opentelemetry/instrumentation-fs": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fs/-/instrumentation-fs-0.15.0.tgz", + "integrity": "sha512-JWVKdNLpu1skqZQA//jKOcKdJC66TWKqa2FUFq70rKohvaSq47pmXlnabNO+B/BvLfmidfiaN35XakT5RyMl2Q==", "dependencies": { - "tslib": "^2.8.0" + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.53.0" }, "engines": { - "node": ">=18" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@polkadot/x-textdecoder/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@polkadot/x-textencoder": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-textencoder/-/x-textencoder-13.2.3.tgz", - "integrity": "sha512-wJI3Bb/dC4zyBXJFm5+ZhyBXWoI5wvP8k8qX0/ZC0PQsgSAqs7LVhiofk4Wd94n0P41W5re58LrGXLyziSAshw==", + "node_modules/@opentelemetry/instrumentation-fs/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", "license": "Apache-2.0", "dependencies": { - "@polkadot/x-global": "13.2.3", - "tslib": "^2.8.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, "engines": { - "node": ">=18" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@polkadot/x-textencoder/node_modules/@polkadot/x-global": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-global/-/x-global-13.2.3.tgz", - "integrity": "sha512-7MYQIAEwBkRcNrgqac5PbB0kNPlI6ISJEy6/Nb+crj8BFjQ8rf11PF49fq0QsvDeuYM1aNLigrvYZNptQs4lbw==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.8.0" + "node_modules/@opentelemetry/instrumentation-fs/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=18" + "node": ">=10" } }, - "node_modules/@polkadot/x-textencoder/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@polkadot/x-ws": { - "version": "13.3.1", - "resolved": "https://registry.npmjs.org/@polkadot/x-ws/-/x-ws-13.3.1.tgz", - "integrity": "sha512-ytqkC7FwVs4BlzNFAmPMFp+xD1KIdMMP/mvCSOrnxjlsyM5DVGop4x4c2ZgDUBmrFqmIiVkWDfMIZeOxui2OLQ==", - "license": "Apache-2.0", + "node_modules/@opentelemetry/instrumentation-generic-pool": { + "version": "0.39.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.39.0.tgz", + "integrity": "sha512-y4v8Y+tSfRB3NNBvHjbjrn7rX/7sdARG7FuK6zR8PGb28CTa0kHpEGCJqvL9L8xkTNvTXo+lM36ajFGUaK1aNw==", "dependencies": { - "@polkadot/x-global": "13.3.1", - "tslib": "^2.8.0", - "ws": "^8.18.0" + "@opentelemetry/instrumentation": "^0.53.0" }, "engines": { - "node": ">=18" - } - }, - "node_modules/@polkadot/x-ws/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@prisma/client": { - "version": "5.8.1", - "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.8.1.tgz", - "integrity": "sha512-xQtMPfbIwLlbm0VVIVQY2yqQVOxPwRQhvIp7Z3m2900g1bu/zRHKhYZJQWELqmjl6d8YwBy0K2NvMqh47v1ubw==", - "hasInstallScript": true, - "engines": { - "node": ">=16.13" + "node": ">=14" }, "peerDependencies": { - "prisma": "*" - }, - "peerDependenciesMeta": { - "prisma": { - "optional": true - } - } - }, - "node_modules/@prisma/debug": { - "version": "5.16.2", - "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.16.2.tgz", - "integrity": "sha512-ItzB4nR4O8eLzuJiuP3WwUJfoIvewMHqpGCad+64gvThcKEVOtaUza9AEJo2DPqAOa/AWkFyK54oM4WwHeew+A==", - "devOptional": true - }, - "node_modules/@prisma/engines": { - "version": "5.16.2", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.16.2.tgz", - "integrity": "sha512-qUxwMtrwoG3byd4PbX6T7EjHJ8AUhzTuwniOGkh/hIznBfcE2QQnGakyEq4VnwNuttMqvh/GgPFapHQ3lCuRHg==", - "devOptional": true, - "hasInstallScript": true, - "dependencies": { - "@prisma/debug": "5.16.2", - "@prisma/engines-version": "5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303", - "@prisma/fetch-engine": "5.16.2", - "@prisma/get-platform": "5.16.2" - } - }, - "node_modules/@prisma/engines-version": { - "version": "5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303.tgz", - "integrity": "sha512-HkT2WbfmFZ9WUPyuJHhkiADxazHg8Y4gByrTSVeb3OikP6tjQ7txtSUGu9OBOBH0C13dPKN2qqH12xKtHu/Hiw==", - "devOptional": true - }, - "node_modules/@prisma/fetch-engine": { - "version": "5.16.2", - "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.16.2.tgz", - "integrity": "sha512-sq51lfHKfH2jjYSjBtMjP+AznFqOJzXpqmq6B9auWrlTJrMgZ7lPyhWUW7VU7LsQU48/TJ+DZeIz8s9bMYvcHg==", - "devOptional": true, - "dependencies": { - "@prisma/debug": "5.16.2", - "@prisma/engines-version": "5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303", - "@prisma/get-platform": "5.16.2" - } - }, - "node_modules/@prisma/get-platform": { - "version": "5.16.2", - "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.16.2.tgz", - "integrity": "sha512-cXiHPgNLNyj22vLouPVNegklpRL/iX2jxTeap5GRO3DmCoVyIHmJAV1CgUMUJhHlcol9yYy7EHvsnXTDJ/PKEA==", - "devOptional": true, - "dependencies": { - "@prisma/debug": "5.16.2" - } - }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" - }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" - }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" - }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" - }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", - "dependencies": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" - }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" - }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" - }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" - }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" - }, - "node_modules/@radix-ui/primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.1.tgz", - "integrity": "sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==", - "dependencies": { - "@babel/runtime": "^7.13.10" + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-arrow": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz", - "integrity": "sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw==", + "node_modules/@opentelemetry/instrumentation-generic-pool/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@radix-ui/react-primitive": "2.0.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-arrow/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", - "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-arrow/node_modules/@radix-ui/react-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz", - "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==", - "dependencies": { - "@radix-ui/react-slot": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "node_modules/@opentelemetry/instrumentation-generic-pool/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "engines": { + "node": ">=10" } }, - "node_modules/@radix-ui/react-arrow/node_modules/@radix-ui/react-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", - "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", + "node_modules/@opentelemetry/instrumentation-graphql": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.43.0.tgz", + "integrity": "sha512-aI3YMmC2McGd8KW5du1a2gBA0iOMOGLqg4s9YjzwbjFwjlmMNFSK1P3AIg374GWg823RPUGfVTIgZ/juk9CVOA==", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0" + "@opentelemetry/instrumentation": "^0.53.0" }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-checkbox": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.1.1.tgz", - "integrity": "sha512-0i/EKJ222Afa1FE0C6pNJxDq1itzcl3HChE9DwskA4th4KRse8ojx8a1nVcOjwJdbpDLcz7uol77yYnQNMHdKw==", + "node_modules/@opentelemetry/instrumentation-graphql/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-presence": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-controllable-state": "1.1.0", - "@radix-ui/react-use-previous": "1.1.0", - "@radix-ui/react-use-size": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/primitive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz", - "integrity": "sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==" - }, - "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", - "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "node_modules/@opentelemetry/instrumentation-graphql/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=10" } }, - "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-context": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz", - "integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "node_modules/@opentelemetry/instrumentation-grpc": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-grpc/-/instrumentation-grpc-0.53.0.tgz", + "integrity": "sha512-Ss338T92yE1UCgr9zXSY3cPuaAy27uQw+wAC5IwsQKCXL5wwkiOgkd+2Ngksa9EGsgUEMwGeHi76bDdHFJ5Rrw==", + "dependencies": { + "@opentelemetry/instrumentation": "0.53.0", + "@opentelemetry/semantic-conventions": "1.27.0" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-presence": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.0.tgz", - "integrity": "sha512-Gq6wuRN/asf9H/E/VzdKoUtT8GC9PQc9z40/vEr0VCJ4u5XvvhWIrSsCB6vD2/cH7ugTdSfYq9fLJCcM00acrQ==", + "node_modules/@opentelemetry/instrumentation-grpc/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-grpc/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "engines": { + "node": ">=10" } }, - "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz", - "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==", + "node_modules/@opentelemetry/instrumentation-hapi": { + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.41.0.tgz", + "integrity": "sha512-jKDrxPNXDByPlYcMdZjNPYCvw0SQJjN+B1A+QH+sx+sAHsKSAf9hwFiJSrI6C4XdOls43V/f/fkp9ITkHhKFbQ==", "dependencies": { - "@radix-ui/react-slot": "1.1.0" + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", - "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", + "node_modules/@opentelemetry/instrumentation-hapi/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-use-callback-ref": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", - "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "node_modules/@opentelemetry/instrumentation-hapi/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=10" } }, - "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-use-controllable-state": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz", - "integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==", + "node_modules/@opentelemetry/instrumentation-ioredis": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.43.0.tgz", + "integrity": "sha512-i3Dke/LdhZbiUAEImmRG3i7Dimm/BD7t8pDDzwepSvIQ6s2X6FPia7561gw+64w+nx0+G9X14D7rEfaMEmmjig==", "dependencies": { - "@radix-ui/react-use-callback-ref": "1.1.0" + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/redis-common": "^0.36.2", + "@opentelemetry/semantic-conventions": "^1.27.0" }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", - "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", + "node_modules/@opentelemetry/instrumentation-ioredis/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-ioredis/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=10" } }, - "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-use-size": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz", - "integrity": "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==", + "node_modules/@opentelemetry/instrumentation-kafkajs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-kafkajs/-/instrumentation-kafkajs-0.3.0.tgz", + "integrity": "sha512-UnkZueYK1ise8FXQeKlpBd7YYUtC7mM8J0wzUSccEfc/G8UqHQqAzIyYCUOUPUKp8GsjLnWOOK/3hJc4owb7Jg==", "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.0" + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0" }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-collapsible": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.0.3.tgz", - "integrity": "sha512-UBmVDkmR6IvDsloHVN+3rtx4Mi5TFvylYXpluuv0f37dtaz3H99bp8No0LGXRigVpl3UAT4l9j6bIchh42S/Gg==", + "node_modules/@opentelemetry/instrumentation-kafkajs/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-id": "1.0.1", - "@radix-ui/react-presence": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-controllable-state": "1.0.1", - "@radix-ui/react-use-layout-effect": "1.0.1" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-kafkajs/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "engines": { + "node": ">=10" } }, - "node_modules/@radix-ui/react-collection": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.3.tgz", - "integrity": "sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==", + "node_modules/@opentelemetry/instrumentation-knex": { + "version": "0.40.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-knex/-/instrumentation-knex-0.40.0.tgz", + "integrity": "sha512-6jka2jfX8+fqjEbCn6hKWHVWe++mHrIkLQtaJqUkBt3ZBs2xn1+y0khxiDS0v/mNb0bIKDJWwtpKFfsQDM1Geg==", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-slot": "1.0.2" + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-compose-refs": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz", - "integrity": "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==", + "node_modules/@opentelemetry/instrumentation-knex/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@babel/runtime": "^7.13.10" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-knex/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=10" } }, - "node_modules/@radix-ui/react-context": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.0.1.tgz", - "integrity": "sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==", + "node_modules/@opentelemetry/instrumentation-koa": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.43.0.tgz", + "integrity": "sha512-lDAhSnmoTIN6ELKmLJBplXzT/Jqs5jGZehuG22EdSMaTwgjMpxMDI1YtlKEhiWPWkrz5LUsd0aOO0ZRc9vn3AQ==", "dependencies": { - "@babel/runtime": "^7.13.10" + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0" }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-dialog": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.2.tgz", - "integrity": "sha512-Yj4dZtqa2o+kG61fzB0H2qUvmwBA2oyQroGLyNtBj1beo1khoQ3q1a2AO8rrQYjd8256CO9+N8L9tvsS+bnIyA==", + "node_modules/@opentelemetry/instrumentation-koa/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-dismissable-layer": "1.1.1", - "@radix-ui/react-focus-guards": "1.1.1", - "@radix-ui/react-focus-scope": "1.1.0", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-portal": "1.1.2", - "@radix-ui/react-presence": "1.1.1", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-slot": "1.1.0", - "@radix-ui/react-use-controllable-state": "1.1.0", - "aria-hidden": "^1.1.1", - "react-remove-scroll": "2.6.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/primitive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz", - "integrity": "sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==" - }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", - "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "node_modules/@opentelemetry/instrumentation-koa/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=10" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-context": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", - "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "node_modules/@opentelemetry/instrumentation-lru-memoizer": { + "version": "0.40.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-lru-memoizer/-/instrumentation-lru-memoizer-0.40.0.tgz", + "integrity": "sha512-21xRwZsEdMPnROu/QsaOIODmzw59IYpGFmuC4aFWvMj6stA8+Ei1tX67nkarJttlNjoM94um0N4X26AD7ff54A==", + "dependencies": { + "@opentelemetry/instrumentation": "^0.53.0" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-dismissable-layer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.1.tgz", - "integrity": "sha512-QSxg29lfr/xcev6kSz7MAlmDnzbP1eI/Dwn3Tp1ip0KT5CUELsxkekFEMVBEoykI3oV39hKT4TKZzBNMbcTZYQ==", + "node_modules/@opentelemetry/instrumentation-lru-memoizer/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-escape-keydown": "1.1.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-focus-guards": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz", - "integrity": "sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "node_modules/@opentelemetry/instrumentation-lru-memoizer/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=10" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-focus-scope": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.0.tgz", - "integrity": "sha512-200UD8zylvEyL8Bx+z76RJnASR2gRMuxlgFCPAe/Q/679a/r0eK3MBVYMb7vZODZcffZBdob1EGnky78xmVvcA==", + "node_modules/@opentelemetry/instrumentation-memcached": { + "version": "0.39.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-memcached/-/instrumentation-memcached-0.39.0.tgz", + "integrity": "sha512-WfwvKAZ9I1qILRP5EUd88HQjwAAL+trXpCpozjBi4U6a0A07gB3fZ5PFAxbXemSjF5tHk9KVoROnqHvQ+zzFSQ==", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-callback-ref": "1.1.0" + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/memcached": "^2.2.6" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-id": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz", - "integrity": "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==", + "node_modules/@opentelemetry/instrumentation-memcached/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-memcached/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=10" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-portal": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.2.tgz", - "integrity": "sha512-WeDYLGPxJb/5EGBoedyJbT0MpoULmwnIPMJMSldkuiMsBAv7N1cRdsTWZWht9vpPOiN3qyiGAtbK2is47/uMFg==", + "node_modules/@opentelemetry/instrumentation-mongodb": { + "version": "0.47.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.47.0.tgz", + "integrity": "sha512-yqyXRx2SulEURjgOQyJzhCECSh5i1uM49NUaq9TqLd6fA7g26OahyJfsr9NE38HFqGRHpi4loyrnfYGdrsoVjQ==", "dependencies": { - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-layout-effect": "1.1.0" + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/sdk-metrics": "^1.9.1", + "@opentelemetry/semantic-conventions": "^1.27.0" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-presence": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.1.tgz", - "integrity": "sha512-IeFXVi4YS1K0wVZzXNrbaaUvIJ3qdY+/Ih4eHFhWA9SwGR9UDX7Ck8abvL57C4cv3wwMvUE0OG69Qc3NCcTe/A==", + "node_modules/@opentelemetry/instrumentation-mongodb/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mongodb/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "engines": { + "node": ">=10" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz", - "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==", + "node_modules/@opentelemetry/instrumentation-mongoose": { + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.42.0.tgz", + "integrity": "sha512-AnWv+RaR86uG3qNEMwt3plKX1ueRM7AspfszJYVkvkehiicC3bHQA6vWdb6Zvy5HAE14RyFbu9+2hUUjR2NSyg==", "dependencies": { - "@radix-ui/react-slot": "1.1.0" + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", - "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", + "node_modules/@opentelemetry/instrumentation-mongoose/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-use-callback-ref": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", - "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "node_modules/@opentelemetry/instrumentation-mongoose/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=10" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-use-controllable-state": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz", - "integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==", + "node_modules/@opentelemetry/instrumentation-mysql": { + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.41.0.tgz", + "integrity": "sha512-jnvrV6BsQWyHS2qb2fkfbfSb1R/lmYwqEZITwufuRl37apTopswu9izc0b1CYRp/34tUG/4k/V39PND6eyiNvw==", "dependencies": { - "@radix-ui/react-use-callback-ref": "1.1.0" + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/mysql": "2.15.26" }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-use-escape-keydown": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz", - "integrity": "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==", + "node_modules/@opentelemetry/instrumentation-mysql/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@radix-ui/react-use-callback-ref": "1.1.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", - "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "node_modules/@opentelemetry/instrumentation-mysql/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=10" } }, - "node_modules/@radix-ui/react-dialog/node_modules/react-remove-scroll": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.0.tgz", - "integrity": "sha512-I2U4JVEsQenxDAKaVa3VZ/JeJZe0/2DxPWL8Tj8yLKctQJQiZM52pn/GWFpSp8dftjM3pSAHVJZscAnC/y+ySQ==", + "node_modules/@opentelemetry/instrumentation-mysql2": { + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.41.0.tgz", + "integrity": "sha512-REQB0x+IzVTpoNgVmy5b+UnH1/mDByrneimP6sbDHkp1j8QOl1HyWOrBH/6YWR0nrbU3l825Em5PlybjT3232g==", "dependencies": { - "react-remove-scroll-bar": "^2.3.6", - "react-style-singleton": "^2.2.1", - "tslib": "^2.1.0", - "use-callback-ref": "^1.3.0", - "use-sidecar": "^1.1.2" + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@opentelemetry/sql-common": "^0.40.1" }, "engines": { - "node": ">=10" + "node": ">=14" }, "peerDependencies": { - "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-direction": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.0.1.tgz", - "integrity": "sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==", + "node_modules/@opentelemetry/instrumentation-mysql2/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@babel/runtime": "^7.13.10" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mysql2/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=10" } }, - "node_modules/@radix-ui/react-dismissable-layer": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.5.tgz", - "integrity": "sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g==", + "node_modules/@opentelemetry/instrumentation-net": { + "version": "0.39.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-net/-/instrumentation-net-0.39.0.tgz", + "integrity": "sha512-rixHoODfI/Cx1B0mH1BpxCT0bRSxktuBDrt9IvpT2KSEutK5hR0RsRdgdz/GKk+BQ4u+IG6godgMSGwNQCueEA==", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-callback-ref": "1.0.1", - "@radix-ui/react-use-escape-keydown": "1.0.3" + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-dropdown-menu": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.0.6.tgz", - "integrity": "sha512-i6TuFOoWmLWq+M/eCLGd/bQ2HfAX1RJgvrBQ6AQLmzfvsLdefxbWu8G9zczcPFfcSPehz9GcpF6K9QYreFV8hA==", + "node_modules/@opentelemetry/instrumentation-net/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-id": "1.0.1", - "@radix-ui/react-menu": "2.0.6", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-controllable-state": "1.0.1" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-net/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "engines": { + "node": ">=10" } }, - "node_modules/@radix-ui/react-focus-guards": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.1.tgz", - "integrity": "sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==", + "node_modules/@opentelemetry/instrumentation-pg": { + "version": "0.46.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.46.0.tgz", + "integrity": "sha512-PLbYYC7EIoigh9uzhBrDjyL4yhH9akjV2Mln3ci9+lD7p9HE5nUUgYCgcUasyr4bz99c8xy9ErzKLt38Y7Kodg==", "dependencies": { - "@babel/runtime": "^7.13.10" + "@opentelemetry/core": "^1.26.0", + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "1.27.0", + "@opentelemetry/sql-common": "^0.40.1", + "@types/pg": "8.6.1", + "@types/pg-pool": "2.0.6" }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-focus-scope": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.4.tgz", - "integrity": "sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA==", + "node_modules/@opentelemetry/instrumentation-pg/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-callback-ref": "1.0.1" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-pg/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "engines": { + "node": ">=10" } }, - "node_modules/@radix-ui/react-id": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.0.1.tgz", - "integrity": "sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==", + "node_modules/@opentelemetry/instrumentation-pino": { + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pino/-/instrumentation-pino-0.42.0.tgz", + "integrity": "sha512-SoX6FzucBfTuFNMZjdurJhcYWq2ve8/LkhmyVLUW31HpIB45RF1JNum0u4MkGisosDmXlK4njomcgUovShI+WA==", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-use-layout-effect": "1.0.1" + "@opentelemetry/api-logs": "^0.53.0", + "@opentelemetry/core": "^1.25.0", + "@opentelemetry/instrumentation": "^0.53.0" }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-menu": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.0.6.tgz", - "integrity": "sha512-BVkFLS+bUC8HcImkRKPSiVumA1VPOOEC5WBMiT+QAVsPzW1FJzI9KnqgGxVDPBcql5xXrHkD3JOVoXWEXD8SYA==", + "node_modules/@opentelemetry/instrumentation-pino/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-collection": "1.0.3", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-direction": "1.0.1", - "@radix-ui/react-dismissable-layer": "1.0.5", - "@radix-ui/react-focus-guards": "1.0.1", - "@radix-ui/react-focus-scope": "1.0.4", - "@radix-ui/react-id": "1.0.1", - "@radix-ui/react-popper": "1.1.3", - "@radix-ui/react-portal": "1.0.4", - "@radix-ui/react-presence": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-roving-focus": "1.0.4", - "@radix-ui/react-slot": "1.0.2", - "@radix-ui/react-use-callback-ref": "1.0.1", - "aria-hidden": "^1.1.1", - "react-remove-scroll": "2.5.5" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-pino/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "engines": { + "node": ">=10" } }, - "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-arrow": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz", - "integrity": "sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA==", + "node_modules/@opentelemetry/instrumentation-redis": { + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis/-/instrumentation-redis-0.42.0.tgz", + "integrity": "sha512-jZBoqve0rEC51q0HuhjtZVq1DtUvJHzEJ3YKGvzGar2MU1J4Yt5+pQAQYh1W4jSoDyKeaI4hyeUdWM5N0c2lqA==", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-primitive": "1.0.3" + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/redis-common": "^0.36.2", + "@opentelemetry/semantic-conventions": "^1.27.0" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-popper": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.1.3.tgz", - "integrity": "sha512-cKpopj/5RHZWjrbF2846jBNacjQVwkP068DfmgrNJXpvVWrOvlAmE9xSiy5OqeE+Gi8D9fP+oDhUnPqNMY8/5w==", + "node_modules/@opentelemetry/instrumentation-redis-4": { + "version": "0.42.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis-4/-/instrumentation-redis-4-0.42.1.tgz", + "integrity": "sha512-xm17LJhDfQzQo4wkM/zFwh6wk3SNN/FBFGkscI9Kj4efrb/o5p8Z3yE6ldBPNdIZ6RAwg2p3DL7fvE3DuUDJWA==", "dependencies": { - "@babel/runtime": "^7.13.10", - "@floating-ui/react-dom": "^2.0.0", - "@radix-ui/react-arrow": "1.0.3", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-callback-ref": "1.0.1", - "@radix-ui/react-use-layout-effect": "1.0.1", - "@radix-ui/react-use-rect": "1.0.1", - "@radix-ui/react-use-size": "1.0.1", - "@radix-ui/rect": "1.0.1" + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/redis-common": "^0.36.2", + "@opentelemetry/semantic-conventions": "^1.27.0" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-use-rect": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.0.1.tgz", - "integrity": "sha512-Cq5DLuSiuYVKNU8orzJMbl15TXilTnJKUCltMVQg53BQOF1/C5toAaGrowkgksdBQ9H+SRL23g0HDmg9tvmxXw==", + "node_modules/@opentelemetry/instrumentation-redis-4/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/rect": "1.0.1" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/rect": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.0.1.tgz", - "integrity": "sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ==", - "dependencies": { - "@babel/runtime": "^7.13.10" + "node_modules/@opentelemetry/instrumentation-redis-4/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/@radix-ui/react-popper": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.0.tgz", - "integrity": "sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg==", + "node_modules/@opentelemetry/instrumentation-redis/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@floating-ui/react-dom": "^2.0.0", - "@radix-ui/react-arrow": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0", - "@radix-ui/react-use-rect": "1.1.0", - "@radix-ui/react-use-size": "1.1.0", - "@radix-ui/rect": "1.1.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", - "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-context": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz", - "integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "node_modules/@opentelemetry/instrumentation-redis/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=10" } }, - "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz", - "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==", + "node_modules/@opentelemetry/instrumentation-restify": { + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-restify/-/instrumentation-restify-0.41.0.tgz", + "integrity": "sha512-gKEo+X/wVKUBuD2WDDlF7SlDNBHMWjSQoLxFCsGqeKgHR0MGtwMel8uaDGg9LJ83nKqYy+7Vl/cDFxjba6H+/w==", "dependencies": { - "@radix-ui/react-slot": "1.1.0" + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", - "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", + "node_modules/@opentelemetry/instrumentation-restify/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-use-callback-ref": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", - "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", - "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "node_modules/@opentelemetry/instrumentation-restify/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=10" } }, - "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-use-size": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz", - "integrity": "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==", + "node_modules/@opentelemetry/instrumentation-router": { + "version": "0.40.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-router/-/instrumentation-router-0.40.0.tgz", + "integrity": "sha512-bRo4RaclGFiKtmv/N1D0MuzO7DuxbeqMkMCbPPng6mDwzpHAMpHz/K/IxJmF+H1Hi/NYXVjCKvHGClageLe9eA==", "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.0" + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0" }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-portal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.4.tgz", - "integrity": "sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==", + "node_modules/@opentelemetry/instrumentation-router/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-primitive": "1.0.3" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-presence": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.0.1.tgz", - "integrity": "sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==", - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-use-layout-effect": "1.0.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" + "node_modules/@opentelemetry/instrumentation-router/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "engines": { + "node": ">=10" } }, - "node_modules/@radix-ui/react-primitive": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz", - "integrity": "sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==", + "node_modules/@opentelemetry/instrumentation-socket.io": { + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-socket.io/-/instrumentation-socket.io-0.42.0.tgz", + "integrity": "sha512-xB5tdsBzuZyicQTO3hDzJIpHQ7V1BYJ6vWPWgl19gWZDBdjEGc3HOupjkd3BUJyDoDhbMEHGk2nNlkUU99EfkA==", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-slot": "1.0.2" + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-radio-group": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.2.0.tgz", - "integrity": "sha512-yv+oiLaicYMBpqgfpSPw6q+RyXlLdIpQWDHZbUKURxe+nEh53hFXPPlfhfQQtYkS5MMK/5IWIa76SksleQZSzw==", + "node_modules/@opentelemetry/instrumentation-socket.io/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-direction": "1.1.0", - "@radix-ui/react-presence": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-roving-focus": "1.1.0", - "@radix-ui/react-use-controllable-state": "1.1.0", - "@radix-ui/react-use-previous": "1.1.0", - "@radix-ui/react-use-size": "1.1.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/primitive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz", - "integrity": "sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==" + "node_modules/@opentelemetry/instrumentation-socket.io/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-collection": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.0.tgz", - "integrity": "sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw==", + "node_modules/@opentelemetry/instrumentation-tedious": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.14.0.tgz", + "integrity": "sha512-ofq7pPhSqvRDvD2FVx3RIWPj76wj4QubfrbqJtEx0A+fWoaYxJOCIQ92tYJh28elAmjMmgF/XaYuJuBhBv5J3A==", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-slot": "1.1.0" + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/tedious": "^4.0.14" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", - "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-context": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz", - "integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "node_modules/@opentelemetry/instrumentation-tedious/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-direction": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz", - "integrity": "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "node_modules/@opentelemetry/instrumentation-tedious/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=10" } }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-id": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz", - "integrity": "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==", + "node_modules/@opentelemetry/instrumentation-undici": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.6.0.tgz", + "integrity": "sha512-ABJBhm5OdhGmbh0S/fOTE4N69IZ00CsHC5ijMYfzbw3E5NwLgpQk5xsljaECrJ8wz1SfXbO03FiSuu5AyRAkvQ==", "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.0" + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.53.0" }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.7.0" } }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-presence": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.0.tgz", - "integrity": "sha512-Gq6wuRN/asf9H/E/VzdKoUtT8GC9PQc9z40/vEr0VCJ4u5XvvhWIrSsCB6vD2/cH7ugTdSfYq9fLJCcM00acrQ==", + "node_modules/@opentelemetry/instrumentation-undici/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-undici/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "engines": { + "node": ">=10" } }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz", - "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==", + "node_modules/@opentelemetry/instrumentation-winston": { + "version": "0.40.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-winston/-/instrumentation-winston-0.40.0.tgz", + "integrity": "sha512-eMk2tKl86YJ8/yHvtDbyhrE35/R0InhO9zuHTflPx8T0+IvKVUhPV71MsJr32sImftqeOww92QHt4Jd+a5db4g==", "dependencies": { - "@radix-ui/react-slot": "1.1.0" + "@opentelemetry/api-logs": "^0.53.0", + "@opentelemetry/instrumentation": "^0.53.0" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-roving-focus": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.0.tgz", - "integrity": "sha512-EA6AMGeq9AEeQDeSH0aZgG198qkfHSbvWTf1HvoDmOB5bBG/qTxjYMWUKMnYiV6J/iP/J8MEFSuB2zRU2n7ODA==", + "node_modules/@opentelemetry/instrumentation-winston/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-collection": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-direction": "1.1.0", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-controllable-state": "1.1.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-winston/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "engines": { + "node": ">=10" } }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", - "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", + "node_modules/@opentelemetry/otlp-exporter-base": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.53.0.tgz", + "integrity": "sha512-UCWPreGQEhD6FjBaeDuXhiMf6kkBODF0ZQzrk/tuQcaVDJ+dDQ/xhJp192H9yWnKxVpEjFrSSLnpqmX4VwX+eA==", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0" + "@opentelemetry/core": "1.26.0", + "@opentelemetry/otlp-transformer": "0.53.0" }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-use-callback-ref": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", - "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "node_modules/@opentelemetry/otlp-grpc-exporter-base": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.53.0.tgz", + "integrity": "sha512-F7RCN8VN+lzSa4fGjewit8Z5fEUpY/lmMVy5EWn2ZpbAabg3EE3sCLuTNfOiooNGnmvzimUPruoeqeko/5/TzQ==", + "dependencies": { + "@grpc/grpc-js": "^1.7.1", + "@opentelemetry/core": "1.26.0", + "@opentelemetry/otlp-exporter-base": "0.53.0", + "@opentelemetry/otlp-transformer": "0.53.0" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-use-controllable-state": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz", - "integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==", + "node_modules/@opentelemetry/otlp-transformer": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.53.0.tgz", + "integrity": "sha512-rM0sDA9HD8dluwuBxLetUmoqGJKSAbWenwD65KY9iZhUxdBHRLrIdrABfNDP7aiTjcgK8XFyTn5fhDz7N+W6DA==", "dependencies": { - "@radix-ui/react-use-callback-ref": "1.1.0" + "@opentelemetry/api-logs": "0.53.0", + "@opentelemetry/core": "1.26.0", + "@opentelemetry/resources": "1.26.0", + "@opentelemetry/sdk-logs": "0.53.0", + "@opentelemetry/sdk-metrics": "1.26.0", + "@opentelemetry/sdk-trace-base": "1.26.0", + "protobufjs": "^7.3.0" }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", - "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/resources": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", + "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-use-size": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz", - "integrity": "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==", + "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/sdk-trace-base": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.26.0.tgz", + "integrity": "sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw==", + "license": "Apache-2.0", "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.0" + "@opentelemetry/core": "1.26.0", + "@opentelemetry/resources": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/propagation-utils": { + "version": "0.30.11", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagation-utils/-/propagation-utils-0.30.11.tgz", + "integrity": "sha512-rY4L/2LWNk5p/22zdunpqVmgz6uN419DsRTw5KFMa6u21tWhXS8devlMy4h8m8nnS20wM7r6yYweCNNKjgLYJw==", + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@radix-ui/react-roving-focus": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.4.tgz", - "integrity": "sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==", + "node_modules/@opentelemetry/propagator-aws-xray": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-aws-xray/-/propagator-aws-xray-1.26.0.tgz", + "integrity": "sha512-Sex+JyEZ/xX328TArBqQjh1NZSfNyw5NdASUIi9hnPsnMBMSBaDe7B9JRnXv0swz7niNyAnXa6MY7yOCV76EvA==", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-collection": "1.0.3", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-direction": "1.0.1", - "@radix-ui/react-id": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-callback-ref": "1.0.1", - "@radix-ui/react-use-controllable-state": "1.0.1" + "@opentelemetry/core": "1.26.0" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@radix-ui/react-slot": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz", - "integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==", + "node_modules/@opentelemetry/propagator-b3": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-b3/-/propagator-b3-1.26.0.tgz", + "integrity": "sha512-vvVkQLQ/lGGyEy9GT8uFnI047pajSOVnZI2poJqVGD3nJ+B9sFGdlHNnQKophE3lHfnIH0pw2ubrCTjZCgIj+Q==", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-compose-refs": "1.0.1" + "@opentelemetry/core": "1.26.0" }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@radix-ui/react-tooltip": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.0.7.tgz", - "integrity": "sha512-lPh5iKNFVQ/jav/j6ZrWq3blfDJ0OH9R6FlNUHPMqdLuQ9vwDgFsRxvl8b7Asuy5c8xmoojHUxKHQSOAvMHxyw==", + "node_modules/@opentelemetry/propagator-jaeger": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-jaeger/-/propagator-jaeger-1.26.0.tgz", + "integrity": "sha512-DelFGkCdaxA1C/QA0Xilszfr0t4YbGd3DjxiCDPh34lfnFr+VkkrjV9S8ZTJvAzfdKERXhfOxIKBoGPJwoSz7Q==", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-dismissable-layer": "1.0.5", - "@radix-ui/react-id": "1.0.1", - "@radix-ui/react-popper": "1.1.3", - "@radix-ui/react-portal": "1.0.4", - "@radix-ui/react-presence": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-slot": "1.0.2", - "@radix-ui/react-use-controllable-state": "1.0.1", - "@radix-ui/react-visually-hidden": "1.0.3" + "@opentelemetry/core": "1.26.0" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-arrow": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz", - "integrity": "sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA==", + "node_modules/@opentelemetry/redis-common": { + "version": "0.36.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/redis-common/-/redis-common-0.36.2.tgz", + "integrity": "sha512-faYX1N0gpLhej/6nyp6bgRjzAKXn5GOEMYY7YhciSfCoITAktLUtQ36d24QEWNA1/WA1y6qQunCe0OhHRkVl9g==", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/resource-detector-alibaba-cloud": { + "version": "0.29.3", + "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-alibaba-cloud/-/resource-detector-alibaba-cloud-0.29.3.tgz", + "integrity": "sha512-jdnG/cYItxwKGRj2n3YsJn1+j3QsMRUfaH/mQSj2b6yULo7bKO4turvASwxy3GuSDH55VwrK+F8oIbanJk69ng==", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-primitive": "1.0.3" + "@opentelemetry/core": "^1.26.0", + "@opentelemetry/resources": "^1.10.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" }, "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-popper": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.1.3.tgz", - "integrity": "sha512-cKpopj/5RHZWjrbF2846jBNacjQVwkP068DfmgrNJXpvVWrOvlAmE9xSiy5OqeE+Gi8D9fP+oDhUnPqNMY8/5w==", + "node_modules/@opentelemetry/resource-detector-aws": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-aws/-/resource-detector-aws-1.6.2.tgz", + "integrity": "sha512-xxT6PVmcBTtCo0rf4Bv/mnDMpVRITVt13bDX8mOqKVb0kr5EwIMabZS5EGJhXjP4nljrOIA7ZlOJgSX0Kehfkw==", "dependencies": { - "@babel/runtime": "^7.13.10", - "@floating-ui/react-dom": "^2.0.0", - "@radix-ui/react-arrow": "1.0.3", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-callback-ref": "1.0.1", - "@radix-ui/react-use-layout-effect": "1.0.1", - "@radix-ui/react-use-rect": "1.0.1", - "@radix-ui/react-use-size": "1.0.1", - "@radix-ui/rect": "1.0.1" + "@opentelemetry/core": "^1.0.0", + "@opentelemetry/resources": "^1.10.0", + "@opentelemetry/semantic-conventions": "^1.27.0" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-use-rect": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.0.1.tgz", - "integrity": "sha512-Cq5DLuSiuYVKNU8orzJMbl15TXilTnJKUCltMVQg53BQOF1/C5toAaGrowkgksdBQ9H+SRL23g0HDmg9tvmxXw==", + "node_modules/@opentelemetry/resource-detector-azure": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-azure/-/resource-detector-azure-0.2.11.tgz", + "integrity": "sha512-XepvQfTXWyHAoAziCfXGwYbSZL0LHtFk5iuKKN2VE2vzcoiw5Tepi0Qafuwb7CCtpQRReao4H7E29MFbCmh47g==", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/rect": "1.0.1" + "@opentelemetry/core": "^1.25.1", + "@opentelemetry/resources": "^1.10.1", + "@opentelemetry/semantic-conventions": "^1.27.0" }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/rect": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.0.1.tgz", - "integrity": "sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ==", + "node_modules/@opentelemetry/resource-detector-container": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-container/-/resource-detector-container-0.4.4.tgz", + "integrity": "sha512-ZEN2mq7lIjQWJ8NTt1umtr6oT/Kb89856BOmESLSvgSHbIwOFYs7cSfSRH5bfiVw6dXTQAVbZA/wLgCHKrebJA==", "dependencies": { - "@babel/runtime": "^7.13.10" + "@opentelemetry/core": "^1.26.0", + "@opentelemetry/resources": "^1.10.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@radix-ui/react-use-callback-ref": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz", - "integrity": "sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==", + "node_modules/@opentelemetry/resource-detector-gcp": { + "version": "0.29.12", + "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-gcp/-/resource-detector-gcp-0.29.12.tgz", + "integrity": "sha512-liFG9XTaFVyY9YdFy4r2qVNa4a+Mg3k+XoWzzq2F+/xR0hFLfL0H4k7CsMW+T4Vl+1Cvc9W9WEVt5VCF4u/SYw==", "dependencies": { - "@babel/runtime": "^7.13.10" + "@opentelemetry/core": "^1.0.0", + "@opentelemetry/resources": "^1.10.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "gcp-metadata": "^6.0.0" }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@radix-ui/react-use-controllable-state": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.1.tgz", - "integrity": "sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==", + "node_modules/@opentelemetry/resources": { + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.27.0.tgz", + "integrity": "sha512-jOwt2VJ/lUD5BLc+PMNymDrUCpm5PKi1E9oSVYAvz01U/VdndGmrtV3DU1pG4AwlYhJRHbHfOUIlpBeXCPw6QQ==", + "license": "Apache-2.0", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-use-callback-ref": "1.0.1" + "@opentelemetry/core": "1.27.0", + "@opentelemetry/semantic-conventions": "1.27.0" }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@radix-ui/react-use-escape-keydown": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.3.tgz", - "integrity": "sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==", + "node_modules/@opentelemetry/resources/node_modules/@opentelemetry/core": { + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.27.0.tgz", + "integrity": "sha512-yQPKnK5e+76XuiqUH/gKyS8wv/7qITd5ln56QkBTf3uggr0VkXOXfcaAuG330UfdYu83wsyoBwqwxigpIG+Jkg==", + "license": "Apache-2.0", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-use-callback-ref": "1.0.1" + "@opentelemetry/semantic-conventions": "1.27.0" }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.1.tgz", - "integrity": "sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==", + "node_modules/@opentelemetry/sdk-logs": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.53.0.tgz", + "integrity": "sha512-dhSisnEgIj/vJZXZV6f6KcTnyLDx/VuQ6l3ejuZpMpPlh9S1qMHiZU9NMmOkVkwwHkMy3G6mEBwdP23vUZVr4g==", "dependencies": { - "@babel/runtime": "^7.13.10" + "@opentelemetry/api-logs": "0.53.0", + "@opentelemetry/core": "1.26.0", + "@opentelemetry/resources": "1.26.0" }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": ">=1.4.0 <1.10.0" } }, - "node_modules/@radix-ui/react-use-previous": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.0.tgz", - "integrity": "sha512-Z/e78qg2YFnnXcW88A4JmTtm4ADckLno6F7OXotmkQfeuCVaKuYzqAATPhVzl3delXE7CxIV8shofPn3jPc5Og==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "node_modules/@opentelemetry/sdk-logs/node_modules/@opentelemetry/resources": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", + "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@radix-ui/react-use-rect": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz", - "integrity": "sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==", + "node_modules/@opentelemetry/sdk-metrics": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.26.0.tgz", + "integrity": "sha512-0SvDXmou/JjzSDOjUmetAAvcKQW6ZrvosU0rkbDGpXvvZN+pQF6JbK/Kd4hNdK4q/22yeruqvukXEJyySTzyTQ==", "dependencies": { - "@radix-ui/rect": "1.1.0" + "@opentelemetry/core": "1.26.0", + "@opentelemetry/resources": "1.26.0" }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, - "node_modules/@radix-ui/react-use-size": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.0.1.tgz", - "integrity": "sha512-ibay+VqrgcaI6veAojjofPATwledXiSmX+C0KrBk/xgpX9rBzPV3OsfwlhQdUOFbh+LKQorLYT+xTXW9V8yd0g==", + "node_modules/@opentelemetry/sdk-metrics/node_modules/@opentelemetry/resources": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", + "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", + "license": "Apache-2.0", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-use-layout-effect": "1.0.1" + "@opentelemetry/core": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@radix-ui/react-visually-hidden": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.0.3.tgz", - "integrity": "sha512-D4w41yN5YRKtu464TLnByKzMDG/JlMPHtfZgQAu9v6mNakUqGUI9vUrfQKz8NK41VMm/xbZbh76NUTVtIYqOMA==", + "node_modules/@opentelemetry/sdk-node": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-node/-/sdk-node-0.53.0.tgz", + "integrity": "sha512-0hsxfq3BKy05xGktwG8YdGdxV978++x40EAKyKr1CaHZRh8uqVlXnclnl7OMi9xLMJEcXUw7lGhiRlArFcovyg==", "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-primitive": "1.0.3" + "@opentelemetry/api-logs": "0.53.0", + "@opentelemetry/core": "1.26.0", + "@opentelemetry/exporter-logs-otlp-grpc": "0.53.0", + "@opentelemetry/exporter-logs-otlp-http": "0.53.0", + "@opentelemetry/exporter-logs-otlp-proto": "0.53.0", + "@opentelemetry/exporter-trace-otlp-grpc": "0.53.0", + "@opentelemetry/exporter-trace-otlp-http": "0.53.0", + "@opentelemetry/exporter-trace-otlp-proto": "0.53.0", + "@opentelemetry/exporter-zipkin": "1.26.0", + "@opentelemetry/instrumentation": "0.53.0", + "@opentelemetry/resources": "1.26.0", + "@opentelemetry/sdk-logs": "0.53.0", + "@opentelemetry/sdk-metrics": "1.26.0", + "@opentelemetry/sdk-trace-base": "1.26.0", + "@opentelemetry/sdk-trace-node": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, - "node_modules/@radix-ui/rect": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.0.tgz", - "integrity": "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==" - }, - "node_modules/@react-native/assets-registry": { - "version": "0.77.0", - "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.77.0.tgz", - "integrity": "sha512-Ms4tYYAMScgINAXIhE4riCFJPPL/yltughHS950l0VP5sm5glbimn9n7RFn9Tc8cipX74/ddbk19+ydK2iDMmA==", - "license": "MIT", - "peer": true, + "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/exporter-trace-otlp-http": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.53.0.tgz", + "integrity": "sha512-m7F5ZTq+V9mKGWYpX8EnZ7NjoqAU7VemQ1E2HAG+W/u0wpY1x0OmbxAXfGKFHCspdJk8UKlwPGrpcB8nay3P8A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.26.0", + "@opentelemetry/otlp-exporter-base": "0.53.0", + "@opentelemetry/otlp-transformer": "0.53.0", + "@opentelemetry/resources": "1.26.0", + "@opentelemetry/sdk-trace-base": "1.26.0" + }, "engines": { - "node": ">=18" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@react-native/babel-plugin-codegen": { - "version": "0.77.0", - "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.77.0.tgz", - "integrity": "sha512-5TYPn1k+jdDOZJU4EVb1kZ0p9TCVICXK3uplRev5Gul57oWesAaiWGZOzfRS3lonWeuR4ij8v8PFfIHOaq0vmA==", - "license": "MIT", - "peer": true, + "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", "dependencies": { - "@babel/traverse": "^7.25.3", - "@react-native/codegen": "0.77.0" + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, "engines": { - "node": ">=18" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@react-native/babel-preset": { - "version": "0.77.0", - "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.77.0.tgz", - "integrity": "sha512-Z4yxE66OvPyQ/iAlaETI1ptRLcDm7Tk6ZLqtCPuUX3AMg+JNgIA86979T4RSk486/JrBUBH5WZe2xjj7eEHXsA==", - "license": "MIT", - "peer": true, + "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/resources": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", + "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", + "license": "Apache-2.0", "dependencies": { - "@babel/core": "^7.25.2", - "@babel/plugin-proposal-export-default-from": "^7.24.7", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-default-from": "^7.24.7", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-transform-arrow-functions": "^7.24.7", - "@babel/plugin-transform-async-generator-functions": "^7.25.4", - "@babel/plugin-transform-async-to-generator": "^7.24.7", - "@babel/plugin-transform-block-scoping": "^7.25.0", - "@babel/plugin-transform-class-properties": "^7.25.4", - "@babel/plugin-transform-classes": "^7.25.4", - "@babel/plugin-transform-computed-properties": "^7.24.7", - "@babel/plugin-transform-destructuring": "^7.24.8", - "@babel/plugin-transform-flow-strip-types": "^7.25.2", - "@babel/plugin-transform-for-of": "^7.24.7", - "@babel/plugin-transform-function-name": "^7.25.1", - "@babel/plugin-transform-literals": "^7.25.2", - "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", - "@babel/plugin-transform-modules-commonjs": "^7.24.8", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", - "@babel/plugin-transform-numeric-separator": "^7.24.7", - "@babel/plugin-transform-object-rest-spread": "^7.24.7", - "@babel/plugin-transform-optional-catch-binding": "^7.24.7", - "@babel/plugin-transform-optional-chaining": "^7.24.8", - "@babel/plugin-transform-parameters": "^7.24.7", - "@babel/plugin-transform-private-methods": "^7.24.7", - "@babel/plugin-transform-private-property-in-object": "^7.24.7", - "@babel/plugin-transform-react-display-name": "^7.24.7", - "@babel/plugin-transform-react-jsx": "^7.25.2", - "@babel/plugin-transform-react-jsx-self": "^7.24.7", - "@babel/plugin-transform-react-jsx-source": "^7.24.7", - "@babel/plugin-transform-regenerator": "^7.24.7", - "@babel/plugin-transform-runtime": "^7.24.7", - "@babel/plugin-transform-shorthand-properties": "^7.24.7", - "@babel/plugin-transform-spread": "^7.24.7", - "@babel/plugin-transform-sticky-regex": "^7.24.7", - "@babel/plugin-transform-typescript": "^7.25.2", - "@babel/plugin-transform-unicode-regex": "^7.24.7", - "@babel/template": "^7.25.0", - "@react-native/babel-plugin-codegen": "0.77.0", - "babel-plugin-syntax-hermes-parser": "0.25.1", - "babel-plugin-transform-flow-enums": "^0.0.2", - "react-refresh": "^0.14.0" + "@opentelemetry/core": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" }, "engines": { - "node": ">=18" + "node": ">=14" }, "peerDependencies": { - "@babel/core": "*" + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@react-native/codegen": { - "version": "0.77.0", - "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.77.0.tgz", - "integrity": "sha512-rE9lXx41ZjvE8cG7e62y/yGqzUpxnSvJ6me6axiX+aDewmI4ZrddvRGYyxCnawxy5dIBHSnrpZse3P87/4Lm7w==", - "license": "MIT", - "peer": true, + "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/sdk-trace-base": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.26.0.tgz", + "integrity": "sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw==", + "license": "Apache-2.0", "dependencies": { - "@babel/parser": "^7.25.3", - "glob": "^7.1.1", - "hermes-parser": "0.25.1", - "invariant": "^2.2.4", - "jscodeshift": "^17.0.0", - "nullthrows": "^1.1.1", - "yargs": "^17.6.2" + "@opentelemetry/core": "1.26.0", + "@opentelemetry/resources": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" }, "engines": { - "node": ">=18" + "node": ">=14" }, "peerDependencies": { - "@babel/preset-env": "^7.1.6" + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@react-native/codegen/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT", - "peer": true - }, - "node_modules/@react-native/codegen/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "license": "MIT", - "peer": true, + "node_modules/@opentelemetry/sdk-node/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/@react-native/codegen/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "peer": true, + "node_modules/@opentelemetry/sdk-trace-base": { + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.27.0.tgz", + "integrity": "sha512-btz6XTQzwsyJjombpeqCX6LhiMQYpzt2pIYNPnw0IPO/3AhT6yjnf8Mnv3ZC2A4eRYOjqrg+bfaXg9XHDRJDWQ==", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "@opentelemetry/core": "1.27.0", + "@opentelemetry/resources": "1.27.0", + "@opentelemetry/semantic-conventions": "1.27.0" }, "engines": { - "node": ">=8" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@react-native/codegen/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "license": "MIT", - "peer": true, + "node_modules/@opentelemetry/sdk-trace-base/node_modules/@opentelemetry/core": { + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.27.0.tgz", + "integrity": "sha512-yQPKnK5e+76XuiqUH/gKyS8wv/7qITd5ln56QkBTf3uggr0VkXOXfcaAuG330UfdYu83wsyoBwqwxigpIG+Jkg==", "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" + "@opentelemetry/semantic-conventions": "1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-node": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-1.26.0.tgz", + "integrity": "sha512-Fj5IVKrj0yeUwlewCRwzOVcr5avTuNnMHWf7GPc1t6WaT78J6CJyF3saZ/0RkZfdeNO8IcBl/bNcWMVZBMRW8Q==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/context-async-hooks": "1.26.0", + "@opentelemetry/core": "1.26.0", + "@opentelemetry/propagator-b3": "1.26.0", + "@opentelemetry/propagator-jaeger": "1.26.0", + "@opentelemetry/sdk-trace-base": "1.26.0", + "semver": "^7.5.2" }, "engines": { - "node": ">=12" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@react-native/community-cli-plugin": { - "version": "0.77.0", - "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.77.0.tgz", - "integrity": "sha512-GRshwhCHhtupa3yyCbel14SlQligV8ffNYN5L1f8HCo2SeGPsBDNjhj2U+JTrMPnoqpwowPGvkCwyqwqYff4MQ==", - "license": "MIT", - "peer": true, + "node_modules/@opentelemetry/sdk-trace-node/node_modules/@opentelemetry/resources": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.26.0.tgz", + "integrity": "sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==", + "license": "Apache-2.0", "dependencies": { - "@react-native/dev-middleware": "0.77.0", - "@react-native/metro-babel-transformer": "0.77.0", - "chalk": "^4.0.0", - "debug": "^2.2.0", - "invariant": "^2.2.4", - "metro": "^0.81.0", - "metro-config": "^0.81.0", - "metro-core": "^0.81.0", - "readline": "^1.3.0", - "semver": "^7.1.3" + "@opentelemetry/core": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" }, "engines": { - "node": ">=18" + "node": ">=14" }, "peerDependencies": { - "@react-native-community/cli-server-api": "*" - }, - "peerDependenciesMeta": { - "@react-native-community/cli-server-api": { - "optional": true - } + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@react-native/community-cli-plugin/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "peer": true, + "node_modules/@opentelemetry/sdk-trace-node/node_modules/@opentelemetry/sdk-trace-base": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.26.0.tgz", + "integrity": "sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw==", + "license": "Apache-2.0", "dependencies": { - "ms": "2.0.0" + "@opentelemetry/core": "1.26.0", + "@opentelemetry/resources": "1.26.0", + "@opentelemetry/semantic-conventions": "1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@react-native/community-cli-plugin/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT", - "peer": true - }, - "node_modules/@react-native/community-cli-plugin/node_modules/semver": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.0.tgz", - "integrity": "sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ==", - "license": "ISC", - "peer": true, + "node_modules/@opentelemetry/sdk-trace-node/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "bin": { "semver": "bin/semver.js" }, @@ -27102,6035 +15260,6770 @@ "node": ">=10" } }, - "node_modules/@react-native/debugger-frontend": { - "version": "0.77.0", - "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.77.0.tgz", - "integrity": "sha512-glOvSEjCbVXw+KtfiOAmrq21FuLE1VsmBsyT7qud4KWbXP43aUEhzn70mWyFuiIdxnzVPKe2u8iWTQTdJksR1w==", - "license": "BSD-3-Clause", - "peer": true, + "node_modules/@opentelemetry/semantic-conventions": { + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.27.0.tgz", + "integrity": "sha512-sAay1RrB+ONOem0OZanAR1ZI/k7yDpnOQSQmTMuGImUQb2y8EbSaCJ94FQluM74xoU03vlb2d2U90hZluL6nQg==", + "license": "Apache-2.0", "engines": { - "node": ">=18" + "node": ">=14" } }, - "node_modules/@react-native/dev-middleware": { - "version": "0.77.0", - "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.77.0.tgz", - "integrity": "sha512-DAlEYujm43O+Dq98KP2XfLSX5c/TEGtt+JBDEIOQewk374uYY52HzRb1+Gj6tNaEj/b33no4GibtdxbO5zmPhg==", - "license": "MIT", - "peer": true, + "node_modules/@opentelemetry/sql-common": { + "version": "0.40.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sql-common/-/sql-common-0.40.1.tgz", + "integrity": "sha512-nSDlnHSqzC3pXn/wZEZVLuAuJ1MYMXPBwtv2qAbCa3847SaHItdE7SzUq/Jtb0KZmh1zfAbNi3AAMjztTT4Ugg==", "dependencies": { - "@isaacs/ttlcache": "^1.4.1", - "@react-native/debugger-frontend": "0.77.0", - "chrome-launcher": "^0.15.2", - "chromium-edge-launcher": "^0.2.0", - "connect": "^3.6.5", - "debug": "^2.2.0", - "nullthrows": "^1.1.1", - "open": "^7.0.3", - "selfsigned": "^2.4.1", - "serve-static": "^1.16.2", - "ws": "^6.2.3" + "@opentelemetry/core": "^1.1.0" }, "engines": { - "node": ">=18" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0" } }, - "node_modules/@react-native/dev-middleware/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "peer": true, + "node_modules/@opentelemetry/winston-transport": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/winston-transport/-/winston-transport-0.7.0.tgz", + "integrity": "sha512-Q35p/glAOE6sl0ZgbddYsdjy23mzt89lFGhht4pJwrrJyInFIgdONFmMJb47kmXbFM3JHOcI0j+PL1BPPTPXBQ==", "dependencies": { - "ms": "2.0.0" + "@opentelemetry/api-logs": "^0.54.0", + "winston-transport": "4.*" + }, + "engines": { + "node": ">=14" } }, - "node_modules/@react-native/dev-middleware/node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "license": "MIT", - "peer": true, + "node_modules/@opentelemetry/winston-transport/node_modules/@opentelemetry/api-logs": { + "version": "0.54.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.54.0.tgz", + "integrity": "sha512-9HhEh5GqFrassUndqJsyW7a0PzfyWr2eV2xwzHLIS+wX3125+9HE9FMRAKmJRwxZhgZGwH3HNQQjoMGZqmOeVA==", + "dependencies": { + "@opentelemetry/api": "^1.3.0" + }, "engines": { - "node": ">= 0.8" + "node": ">=14" } }, - "node_modules/@react-native/dev-middleware/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT", - "peer": true + "node_modules/@oxc-resolver/binding-darwin-arm64": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-darwin-arm64/-/binding-darwin-arm64-1.10.2.tgz", + "integrity": "sha512-aOCZYXqmFL+2sXlaVkYbAOtICGGeTFtmdul8OimQfOXHJods6YHJ2nR6+rEeBcJzaXyXPP18ne1IsEc4AYL1IA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@react-native/dev-middleware/node_modules/open": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", - "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", - "license": "MIT", - "peer": true, + "node_modules/@oxc-resolver/binding-darwin-x64": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-darwin-x64/-/binding-darwin-x64-1.10.2.tgz", + "integrity": "sha512-6WD7lHGkoduFZfUgnC2suKOlqttQRKxWsiVXiiGPu3mfXvQAhMd/gekuH1t8vOhFlPJduaww15n5UB0bSjCK+w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@oxc-resolver/binding-freebsd-x64": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-freebsd-x64/-/binding-freebsd-x64-1.10.2.tgz", + "integrity": "sha512-nEqHWx/Ot5p7Mafj8qH6vFlLSvHjECxAcZwhnAMqRuQu1NgXC/QM3emkdhVGy7QJgsxZbHpPaF6TERNf5/NL9Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@oxc-resolver/binding-linux-arm-gnueabihf": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.10.2.tgz", + "integrity": "sha512-+AlZI0fPnpfArh8aC5k2295lmQrxa2p8gBLxC3buvCkz0ZpbVLxyyAXz3J2jGwJnmc5MUPLEqPYw6ZlAGH4XHA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-arm64-gnu": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.10.2.tgz", + "integrity": "sha512-8fZ8NszFaUZaoA8eUwkF2lHjgUs76aFiewWgG/cjcZmwKp+ErZQLW8eOvIWZ4SohHQ+ScvhVsSaU2PU38c88gw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-arm64-musl": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.10.2.tgz", + "integrity": "sha512-oPrLICrw96Ym9n04FWXWGkbkpF6qJtZ57JSnqI3oQ24xHTt4iWyjHKHQO46NbJAK9sFb3Qce4BzV8faDI5Rifg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-x64-gnu": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.10.2.tgz", + "integrity": "sha512-eli74jTAUiIfqi8IPFqiPxQS69Alcr6w/IFRyf3XxrkxeFGgcgxJkRIxWNTKJ6T3EXxjuma+49LdZn6l9rEj7A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-x64-musl": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-musl/-/binding-linux-x64-musl-1.10.2.tgz", + "integrity": "sha512-HH9zmjNSQo3rkbqJH5nIjGrtjC+QPrUy0KGGMR/oRCSLuD0cNFJ/Uly1XAugwSm4oEw0+rv6PmeclXmVTKsxhw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-wasm32-wasi": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-wasm32-wasi/-/binding-wasm32-wasi-1.10.2.tgz", + "integrity": "sha512-3ItX23q33sfVBtMMdMhVDSe0NX5zBHxHfmFiXhSJuwNaVIwGpLFU7WU2nmq9oNdnmTOvjL8vlhOqiGvumBLlRA==", + "cpu": [ + "wasm32" + ], + "dev": true, + "optional": true, "dependencies": { - "is-docker": "^2.0.0", - "is-wsl": "^2.1.1" + "@napi-rs/wasm-runtime": "^0.2.4" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=14.0.0" } }, - "node_modules/@react-native/dev-middleware/node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", - "license": "MIT", - "peer": true, + "node_modules/@oxc-resolver/binding-win32-arm64-msvc": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.10.2.tgz", + "integrity": "sha512-aVoj2V+jmQ1N+lVy9AhaLmzssJM0lcKt8D0UL83aNLZJ5lSN7hgBuUXTVmL+VF268f167khjo38z+fbELDVm8Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@oxc-resolver/binding-win32-x64-msvc": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.10.2.tgz", + "integrity": "sha512-l8BDQWyP0Piw8hlmYPUqTRKLsq+ceG9h+9p6ZrjNzwW9AmJX7T7T2hgoVVHqS6f4WNA/CFkb3RyZP9QTzNkyyA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@parcel/watcher": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.0.tgz", + "integrity": "sha512-i0GV1yJnm2n3Yq1qw6QrUrd/LI9bE8WEBOTtOkpCXHHdyN3TAGgqAK/DAT05z4fq2x04cARXt2pDmjWjL92iTQ==", + "hasInstallScript": true, "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" + "detect-libc": "^1.0.3", + "is-glob": "^4.0.3", + "micromatch": "^4.0.5", + "node-addon-api": "^7.0.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.0", + "@parcel/watcher-darwin-arm64": "2.5.0", + "@parcel/watcher-darwin-x64": "2.5.0", + "@parcel/watcher-freebsd-x64": "2.5.0", + "@parcel/watcher-linux-arm-glibc": "2.5.0", + "@parcel/watcher-linux-arm-musl": "2.5.0", + "@parcel/watcher-linux-arm64-glibc": "2.5.0", + "@parcel/watcher-linux-arm64-musl": "2.5.0", + "@parcel/watcher-linux-x64-glibc": "2.5.0", + "@parcel/watcher-linux-x64-musl": "2.5.0", + "@parcel/watcher-win32-arm64": "2.5.0", + "@parcel/watcher-win32-ia32": "2.5.0", + "@parcel/watcher-win32-x64": "2.5.0" } }, - "node_modules/@react-native/dev-middleware/node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "license": "MIT", - "peer": true, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.0.tgz", + "integrity": "sha512-qlX4eS28bUcQCdribHkg/herLe+0A9RyYC+mm2PXpncit8z5b3nSqGVzMNR3CmtAOgRutiZ02eIJJgP/b1iEFQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">= 0.8" + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@react-native/dev-middleware/node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT", - "peer": true - }, - "node_modules/@react-native/dev-middleware/node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", - "license": "MIT", - "peer": true, - "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" - }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.0.tgz", + "integrity": "sha512-hyZ3TANnzGfLpRA2s/4U1kbw2ZI4qGxaRJbBH2DCSREFfubMswheh8TeiC1sGZ3z2jUf3s37P0BBlrD3sjVTUw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">= 0.8.0" + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@react-native/dev-middleware/node_modules/ws": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", - "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", - "license": "MIT", - "peer": true, - "dependencies": { - "async-limiter": "~1.0.0" + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.0.tgz", + "integrity": "sha512-9rhlwd78saKf18fT869/poydQK8YqlU26TMiNg7AIu7eBp9adqbJZqmdFOsbZ5cnLp5XvRo9wcFmNHgHdWaGYA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@react-native/gradle-plugin": { - "version": "0.77.0", - "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.77.0.tgz", - "integrity": "sha512-rmfh93jzbndSq7kihYHUQ/EGHTP8CCd3GDCmg5SbxSOHAaAYx2HZ28ZG7AVcGUsWeXp+e/90zGIyfOzDRx0Zaw==", - "license": "MIT", - "peer": true, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.0.tgz", + "integrity": "sha512-syvfhZzyM8kErg3VF0xpV8dixJ+RzbUaaGaeb7uDuz0D3FK97/mZ5AJQ3XNnDsXX7KkFNtyQyFrXZzQIcN49Tw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=18" + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@react-native/js-polyfills": { - "version": "0.77.0", - "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.77.0.tgz", - "integrity": "sha512-kHFcMJVkGb3ptj3yg1soUsMHATqal4dh0QTGAbYihngJ6zy+TnP65J3GJq4UlwqFE9K1RZkeCmTwlmyPFHOGvA==", - "license": "MIT", - "peer": true, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.0.tgz", + "integrity": "sha512-0VQY1K35DQET3dVYWpOaPFecqOT9dbuCfzjxoQyif1Wc574t3kOSkKevULddcR9znz1TcklCE7Ht6NIxjvTqLA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18" + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@react-native/metro-babel-transformer": { - "version": "0.77.0", - "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.77.0.tgz", - "integrity": "sha512-19GfvhBRKCU3UDWwCnDR4QjIzz3B2ZuwhnxMRwfAgPxz7QY9uKour9RGmBAVUk1Wxi/SP7dLEvWnmnuBO39e2A==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/core": "^7.25.2", - "@react-native/babel-preset": "0.77.0", - "hermes-parser": "0.25.1", - "nullthrows": "^1.1.1" - }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.0.tgz", + "integrity": "sha512-6uHywSIzz8+vi2lAzFeltnYbdHsDm3iIB57d4g5oaB9vKwjb6N6dRIgZMujw4nm5r6v9/BQH0noq6DzHrqr2pA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18" + "node": ">= 10.0.0" }, - "peerDependencies": { - "@babel/core": "*" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@react-native/normalize-color": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@react-native/normalize-color/-/normalize-color-2.1.0.tgz", - "integrity": "sha512-Z1jQI2NpdFJCVgpY+8Dq/Bt3d+YUi1928Q+/CZm/oh66fzM0RUl54vvuXlPJKybH4pdCZey1eDTPaLHkMPNgWA==", - "license": "MIT", - "peer": true - }, - "node_modules/@react-native/normalize-colors": { - "version": "0.77.0", - "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.77.0.tgz", - "integrity": "sha512-qjmxW3xRZe4T0ZBEaXZNHtuUbRgyfybWijf1yUuQwjBt24tSapmIslwhCjpKidA0p93ssPcepquhY0ykH25mew==", - "license": "MIT", - "peer": true - }, - "node_modules/@react-native/virtualized-lists": { - "version": "0.77.0", - "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.77.0.tgz", - "integrity": "sha512-ppPtEu9ISO9iuzpA2HBqrfmDpDAnGGduNDVaegadOzbMCPAB3tC9Blxdu9W68LyYlNQILIsP6/FYtLwf7kfNew==", - "license": "MIT", - "peer": true, - "dependencies": { - "invariant": "^2.2.4", - "nullthrows": "^1.1.1" - }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.0.tgz", + "integrity": "sha512-BfNjXwZKxBy4WibDb/LDCriWSKLz+jJRL3cM/DllnHH5QUyoiUNEp3GmL80ZqxeumoADfCCP19+qiYiC8gUBjA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/react": "^18.2.6", - "react": "*", - "react-native": "*" + "node": ">= 10.0.0" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@rushstack/eslint-patch": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.3.tgz", - "integrity": "sha512-qC/xYId4NMebE6w/V33Fh9gWxLgURiNYgVNObbJl2LZv0GUUItCcCqC5axQSwRaAgaxl2mELq1rMzlswaQ0Zxg==", - "dev": true - }, - "node_modules/@safe-global/safe-apps-provider": { - "version": "0.18.4", - "resolved": "https://registry.npmjs.org/@safe-global/safe-apps-provider/-/safe-apps-provider-0.18.4.tgz", - "integrity": "sha512-SWYeG3gyTO6wGHMSokfHakZ9isByn2mHsM0VohIorYFFEyGGmJ89btnTm+DqDUSoQtvWAatZB7XNy6CaYMvqtg==", - "dependencies": { - "@safe-global/safe-apps-sdk": "^9.1.0", - "events": "^3.3.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@safe-global/safe-apps-sdk": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/@safe-global/safe-apps-sdk/-/safe-apps-sdk-9.1.0.tgz", - "integrity": "sha512-N5p/ulfnnA2Pi2M3YeWjULeWbjo7ei22JwU/IXnhoHzKq3pYCN6ynL9mJBOlvDVv892EgLPCWCOwQk/uBT2v0Q==", - "dependencies": { - "@safe-global/safe-gateway-typescript-sdk": "^3.5.3", - "viem": "^2.1.1" + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.0.tgz", + "integrity": "sha512-S1qARKOphxfiBEkwLUbHjCY9BWPdWnW9j7f7Hb2jPplu8UZ3nes7zpPOW9bkLbHRvWM0WDTsjdOTUgW0xLBN1Q==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@safe-global/safe-gateway-typescript-sdk": { - "version": "3.22.2", - "resolved": "https://registry.npmjs.org/@safe-global/safe-gateway-typescript-sdk/-/safe-gateway-typescript-sdk-3.22.2.tgz", - "integrity": "sha512-Y0yAxRaB98LFp2Dm+ACZqBSdAmI3FlpH/LjxOZ94g/ouuDJecSq0iR26XZ5QDuEL8Rf+L4jBJaoDC08CD0KkJw==", + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.0.tgz", + "integrity": "sha512-d9AOkusyXARkFD66S6zlGXyzx5RvY+chTP9Jp0ypSTC9d4lzyRs9ovGf/80VCxjKddcUvnsGwCHWuF2EoPgWjw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=16" + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@scure/base": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.7.tgz", - "integrity": "sha512-PPNYBslrLNNUQ/Yad37MHYsNQtK67EhWb6WtSvNLLPo7SdVZgkUjD6Dg+5On7zNwmskf8OX7I7Nx5oN+MIWE0g==", + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.0.tgz", + "integrity": "sha512-iqOC+GoTDoFyk/VYSFHwjHhYrk8bljW6zOhPuhi5t9ulqiYq1togGJB5e3PwYVFFfeVgc6pbz3JdQyDoBszVaA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, "funding": { - "url": "https://paulmillr.com/funding/" + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@scure/bip32": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.5.0.tgz", - "integrity": "sha512-8EnFYkqEQdnkuGBVpCzKxyIwDCBLDVj3oiX0EKUFre/tOjL/Hqba1D6n/8RcmaQy4f95qQFrO2A8Sr6ybh4NRw==", + "node_modules/@parcel/watcher-wasm": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-wasm/-/watcher-wasm-2.5.0.tgz", + "integrity": "sha512-Z4ouuR8Pfggk1EYYbTaIoxc+Yv4o7cGQnH0Xy8+pQ+HbiW+ZnwhcD2LPf/prfq1nIWpAxjOkQ8uSMFWMtBLiVQ==", + "bundleDependencies": [ + "napi-wasm" + ], "dependencies": { - "@noble/curves": "~1.6.0", - "@noble/hashes": "~1.5.0", - "@scure/base": "~1.1.7" + "is-glob": "^4.0.3", + "micromatch": "^4.0.5", + "napi-wasm": "^1.1.0" + }, + "engines": { + "node": ">= 10.0.0" }, "funding": { - "url": "https://paulmillr.com/funding/" + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@scure/bip32/node_modules/@noble/hashes": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.5.0.tgz", - "integrity": "sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==", + "node_modules/@parcel/watcher-wasm/node_modules/napi-wasm": { + "version": "1.1.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.0.tgz", + "integrity": "sha512-twtft1d+JRNkM5YbmexfcH/N4znDtjgysFaV9zvZmmJezQsKpkfLYJ+JFV3uygugK6AtIM2oADPkB2AdhBrNig==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": "^14.21.3 || >=16" + "node": ">= 10.0.0" }, "funding": { - "url": "https://paulmillr.com/funding/" + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@scure/bip39": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", - "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", - "dependencies": { - "@noble/hashes": "~1.4.0", - "@scure/base": "~1.1.6" + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.0.tgz", + "integrity": "sha512-+rgpsNRKwo8A53elqbbHXdOMtY/tAtTzManTWShB5Kk54N8Q9mzNWV7tV+IbGueCbcj826MfWGU3mprWtuf1TA==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" }, "funding": { - "url": "https://paulmillr.com/funding/" + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@segment/loosely-validate-event": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@segment/loosely-validate-event/-/loosely-validate-event-2.0.0.tgz", - "integrity": "sha512-ZMCSfztDBqwotkl848ODgVcAmN4OItEWDCkshcKz0/W6gGSQayuuCtWV/MlodFivAZD793d6UgANd6wCXUfrIw==", + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.0.tgz", + "integrity": "sha512-lPrxve92zEHdgeff3aiu4gDOIt4u7sJYha6wbdEZDCDUhtjTsOMiaJzG5lMY4GkWH8p0fMmO2Ppq5G5XXG+DQw==", + "cpu": [ + "x64" + ], "optional": true, - "peer": true, - "dependencies": { - "component-type": "^1.2.1", - "join-component": "^1.1.0" + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@sepior/tsmsdkv2": { - "version": "63.0.0", - "resolved": "https://nexus.sepior.net/repository/sepior-nodejs-tsm-sdk-group/@sepior/tsmsdkv2/-/tsmsdkv2-63.0.0.tgz", - "integrity": "sha512-SERPces5/gCumUzZK8fE0oGWG6+zlRohz1VWLjEzncWEAWeC65RNhIQvCrCUSosirpoSSflxx5Kf7OHU19M8UA==", - "hasInstallScript": true, - "optional": true, - "dependencies": { - "bindings": "^1.5.0", - "elliptic": "^6.5.4", - "node-addon-api": "^7.1.0" + "node_modules/@parcel/watcher/node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" } }, - "node_modules/@sepior/tsmsdkv2/node_modules/node-addon-api": { + "node_modules/@parcel/watcher/node_modules/node-addon-api": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", - "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", - "optional": true + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==" }, - "node_modules/@sideway/address": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", - "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", + "node_modules/@phenomnomnominal/tsquery": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@phenomnomnominal/tsquery/-/tsquery-5.0.1.tgz", + "integrity": "sha512-3nVv+e2FQwsW8Aw6qTU6f+1rfcJ3hrcnvH/mu9i8YhxO+9sqbOfpL8m6PbET5+xKOlz/VSbp0RoYWYCtIsnmuA==", + "dev": true, "dependencies": { - "@hapi/hoek": "^9.0.0" + "esquery": "^1.4.0" + }, + "peerDependencies": { + "typescript": "^3 || ^4 || ^5" } }, - "node_modules/@sideway/formula": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", - "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" - }, - "node_modules/@sideway/pinpoint": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", - "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" - }, - "node_modules/@silencelaboratories/dkls-wasm-ll-node": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@silencelaboratories/dkls-wasm-ll-node/-/dkls-wasm-ll-node-1.1.2.tgz", - "integrity": "sha512-ZGnE0p/GQRIMHJzbPtSy/3deUmD340NbWrBwpU0NyqJW4EKvh9xxv5ZFnJApq1YboHxHTaz2aP03eu+ZPZShpQ==", - "license": "SLL" - }, - "node_modules/@silencelaboratories/dkls-wasm-ll-web": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@silencelaboratories/dkls-wasm-ll-web/-/dkls-wasm-ll-web-1.1.2.tgz", - "integrity": "sha512-GFdQdeTAK5RQ6SP+RVenjm/cSAXYek8+hMOL6Uw6uqsoGhJzveJHMEKEEbitGDpBjoN/admwxIKcv0wpIo022Q==", - "license": "SLL" - }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" - }, - "node_modules/@sindresorhus/is": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" + "node": ">=14" } }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", - "dependencies": { - "type-detect": "4.0.8" + "node_modules/@pnpm/config.env-replace": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", + "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", + "engines": { + "node": ">=12.22.0" } }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "node_modules/@pnpm/network.ca-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", + "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", "dependencies": { - "@sinonjs/commons": "^3.0.0" + "graceful-fs": "4.2.10" + }, + "engines": { + "node": ">=12.22.0" } }, - "node_modules/@slorber/remark-comment": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@slorber/remark-comment/-/remark-comment-1.0.0.tgz", - "integrity": "sha512-RCE24n7jsOj1M0UPvIQCHTe7fI0sFL4S2nwKVWwHyVr/wI/H8GosgsJGyhnsZoGFnD/P2hLf1mSbrrgSLN93NA==", - "dependencies": { - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.1.0", - "micromark-util-symbol": "^1.0.1" - } + "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, - "node_modules/@smithy/abort-controller": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.1.4.tgz", - "integrity": "sha512-VupaALAQlXViW3/enTf/f5l5JZYSAxoJL7f0nanhNNKnww6DGCg1oYIuNP78KDugnkwthBO6iEcym16HhWV8RQ==", + "node_modules/@pnpm/npm-conf": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.2.2.tgz", + "integrity": "sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==", "dependencies": { - "@smithy/types": "^3.4.2", - "tslib": "^2.6.2" + "@pnpm/config.env-replace": "^1.1.0", + "@pnpm/network.ca-file": "^1.0.1", + "config-chain": "^1.1.11" }, "engines": { - "node": ">=16.0.0" + "node": ">=12" } }, - "node_modules/@smithy/config-resolver": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-3.0.8.tgz", - "integrity": "sha512-Tv1obAC18XOd2OnDAjSWmmthzx6Pdeh63FbLin8MlPiuJ2ATpKkq0NcNOJFr0dO+JmZXnwu8FQxKJ3TKJ3Hulw==", - "dependencies": { - "@smithy/node-config-provider": "^3.1.7", - "@smithy/types": "^3.4.2", - "@smithy/util-config-provider": "^3.0.0", - "@smithy/util-middleware": "^3.0.6", - "tslib": "^2.6.2" - }, + "node_modules/@polka/url": { + "version": "1.0.0-next.25", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.25.tgz", + "integrity": "sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==" + }, + "node_modules/@prisma/client": { + "version": "5.8.1", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.8.1.tgz", + "integrity": "sha512-xQtMPfbIwLlbm0VVIVQY2yqQVOxPwRQhvIp7Z3m2900g1bu/zRHKhYZJQWELqmjl6d8YwBy0K2NvMqh47v1ubw==", + "hasInstallScript": true, "engines": { - "node": ">=16.0.0" + "node": ">=16.13" + }, + "peerDependencies": { + "prisma": "*" + }, + "peerDependenciesMeta": { + "prisma": { + "optional": true + } } }, - "node_modules/@smithy/core": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.4.5.tgz", - "integrity": "sha512-Z0qlPXgZ0pouYgnu/cZTEYeRAvniiKZmVl4wIbZHX/nEMHkMDV9ao6KFArsU9KndE0TuhL149xcRx45wfw1YCA==", + "node_modules/@prisma/debug": { + "version": "5.16.2", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.16.2.tgz", + "integrity": "sha512-ItzB4nR4O8eLzuJiuP3WwUJfoIvewMHqpGCad+64gvThcKEVOtaUza9AEJo2DPqAOa/AWkFyK54oM4WwHeew+A==", + "devOptional": true + }, + "node_modules/@prisma/engines": { + "version": "5.16.2", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.16.2.tgz", + "integrity": "sha512-qUxwMtrwoG3byd4PbX6T7EjHJ8AUhzTuwniOGkh/hIznBfcE2QQnGakyEq4VnwNuttMqvh/GgPFapHQ3lCuRHg==", + "devOptional": true, + "hasInstallScript": true, "dependencies": { - "@smithy/middleware-endpoint": "^3.1.3", - "@smithy/middleware-retry": "^3.0.20", - "@smithy/middleware-serde": "^3.0.6", - "@smithy/protocol-http": "^4.1.3", - "@smithy/smithy-client": "^3.3.4", - "@smithy/types": "^3.4.2", - "@smithy/util-body-length-browser": "^3.0.0", - "@smithy/util-middleware": "^3.0.6", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "@prisma/debug": "5.16.2", + "@prisma/engines-version": "5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303", + "@prisma/fetch-engine": "5.16.2", + "@prisma/get-platform": "5.16.2" } }, - "node_modules/@smithy/credential-provider-imds": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.3.tgz", - "integrity": "sha512-VoxMzSzdvkkjMJNE38yQgx4CfnmT+Z+5EUXkg4x7yag93eQkVQgZvN3XBSHC/ylfBbLbAtdu7flTCChX9I+mVg==", + "node_modules/@prisma/engines-version": { + "version": "5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303.tgz", + "integrity": "sha512-HkT2WbfmFZ9WUPyuJHhkiADxazHg8Y4gByrTSVeb3OikP6tjQ7txtSUGu9OBOBH0C13dPKN2qqH12xKtHu/Hiw==", + "devOptional": true + }, + "node_modules/@prisma/fetch-engine": { + "version": "5.16.2", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.16.2.tgz", + "integrity": "sha512-sq51lfHKfH2jjYSjBtMjP+AznFqOJzXpqmq6B9auWrlTJrMgZ7lPyhWUW7VU7LsQU48/TJ+DZeIz8s9bMYvcHg==", + "devOptional": true, "dependencies": { - "@smithy/node-config-provider": "^3.1.7", - "@smithy/property-provider": "^3.1.6", - "@smithy/types": "^3.4.2", - "@smithy/url-parser": "^3.0.6", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "@prisma/debug": "5.16.2", + "@prisma/engines-version": "5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303", + "@prisma/get-platform": "5.16.2" } }, - "node_modules/@smithy/fetch-http-handler": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.8.tgz", - "integrity": "sha512-Lqe0B8F5RM7zkw//6avq1SJ8AfaRd3ubFUS1eVp5WszV7p6Ne5hQ4dSuMHDpNRPhgTvj4va9Kd/pcVigHEHRow==", + "node_modules/@prisma/get-platform": { + "version": "5.16.2", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.16.2.tgz", + "integrity": "sha512-cXiHPgNLNyj22vLouPVNegklpRL/iX2jxTeap5GRO3DmCoVyIHmJAV1CgUMUJhHlcol9yYy7EHvsnXTDJ/PKEA==", + "devOptional": true, "dependencies": { - "@smithy/protocol-http": "^4.1.3", - "@smithy/querystring-builder": "^3.0.6", - "@smithy/types": "^3.4.2", - "@smithy/util-base64": "^3.0.0", - "tslib": "^2.6.2" + "@prisma/debug": "5.16.2" } }, - "node_modules/@smithy/hash-node": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-3.0.6.tgz", - "integrity": "sha512-c/FHEdKK/7DU2z6ZE91L36ahyXWayR3B+FzELjnYq7wH5YqIseM24V+pWCS9kFn1Ln8OFGTf+pyYPiHZuX0s/Q==", + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", "dependencies": { - "@smithy/types": "^3.4.2", - "@smithy/util-buffer-from": "^3.0.0", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" } }, - "node_modules/@smithy/invalid-dependency": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-3.0.6.tgz", - "integrity": "sha512-czM7Ioq3s8pIXht7oD+vmgy4Wfb4XavU/k/irO8NdXFFOx7YAlsCCcKOh/lJD1mJSYQqiR7NmpZ9JviryD/7AQ==", - "dependencies": { - "@smithy/types": "^3.4.2", - "tslib": "^2.6.2" - } + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, - "node_modules/@smithy/is-array-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", - "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "node_modules/@radix-ui/primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.1.tgz", + "integrity": "sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==", "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "@babel/runtime": "^7.13.10" } }, - "node_modules/@smithy/middleware-content-length": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-3.0.8.tgz", - "integrity": "sha512-VuyszlSO49WKh3H9/kIO2kf07VUwGV80QRiaDxUfP8P8UKlokz381ETJvwLhwuypBYhLymCYyNhB3fLAGBX2og==", + "node_modules/@radix-ui/react-arrow": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz", + "integrity": "sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw==", "dependencies": { - "@smithy/protocol-http": "^4.1.3", - "@smithy/types": "^3.4.2", - "tslib": "^2.6.2" + "@radix-ui/react-primitive": "2.0.0" }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/middleware-endpoint": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.1.3.tgz", - "integrity": "sha512-KeM/OrK8MVFUsoJsmCN0MZMVPjKKLudn13xpgwIMpGTYpA8QZB2Xq5tJ+RE6iu3A6NhOI4VajDTwBsm8pwwrhg==", - "dependencies": { - "@smithy/middleware-serde": "^3.0.6", - "@smithy/node-config-provider": "^3.1.7", - "@smithy/shared-ini-file-loader": "^3.1.7", - "@smithy/types": "^3.4.2", - "@smithy/url-parser": "^3.0.6", - "@smithy/util-middleware": "^3.0.6", - "tslib": "^2.6.2" + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "engines": { - "node": ">=16.0.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@smithy/middleware-retry": { - "version": "3.0.20", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.20.tgz", - "integrity": "sha512-HELCOVwYw5hFDBm69d+LmmGjBCjWnwp/t7SJiHmp+c4u9vgfIaCjdSeIdnlOsLrr5ic5jGTJXvJFUQnd987b/g==", - "dependencies": { - "@smithy/node-config-provider": "^3.1.7", - "@smithy/protocol-http": "^4.1.3", - "@smithy/service-error-classification": "^3.0.6", - "@smithy/smithy-client": "^3.3.4", - "@smithy/types": "^3.4.2", - "@smithy/util-middleware": "^3.0.6", - "@smithy/util-retry": "^3.0.6", - "tslib": "^2.6.2", - "uuid": "^9.0.1" + "node_modules/@radix-ui/react-arrow/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", + "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "engines": { - "node": ">=16.0.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@smithy/middleware-serde": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.6.tgz", - "integrity": "sha512-KKTUSl1MzOM0MAjGbudeaVNtIDo+PpekTBkCNwvfZlKndodrnvRo+00USatiyLOc0ujjO9UydMRu3O9dYML7ag==", + "node_modules/@radix-ui/react-arrow/node_modules/@radix-ui/react-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz", + "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==", "dependencies": { - "@smithy/types": "^3.4.2", - "tslib": "^2.6.2" + "@radix-ui/react-slot": "1.1.0" }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/middleware-stack": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.6.tgz", - "integrity": "sha512-2c0eSYhTQ8xQqHMcRxLMpadFbTXg6Zla5l0mwNftFCZMQmuhI7EbAJMx6R5eqfuV3YbJ3QGyS3d5uSmrHV8Khg==", - "dependencies": { - "@smithy/types": "^3.4.2", - "tslib": "^2.6.2" + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "engines": { - "node": ">=16.0.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@smithy/node-config-provider": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.7.tgz", - "integrity": "sha512-g3mfnC3Oo8pOI0dYuPXLtdW1WGVb3bR2tkV21GNkm0ZvQjLTtamXAwCWt/FCb0HGvKt3gHHmF1XerG0ICfalOg==", + "node_modules/@radix-ui/react-arrow/node_modules/@radix-ui/react-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", + "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", "dependencies": { - "@smithy/property-provider": "^3.1.6", - "@smithy/shared-ini-file-loader": "^3.1.7", - "@smithy/types": "^3.4.2", - "tslib": "^2.6.2" + "@radix-ui/react-compose-refs": "1.1.0" }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/node-http-handler": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.2.3.tgz", - "integrity": "sha512-/gcm5DJ3k1b1zEInzBGAZC8ntJ+jwrz1NcSIu+9dSXd1FfG0G6QgkDI40tt8/WYUbHtLyo8fEqtm2v29koWo/w==", - "dependencies": { - "@smithy/abort-controller": "^3.1.4", - "@smithy/protocol-http": "^4.1.3", - "@smithy/querystring-builder": "^3.0.6", - "@smithy/types": "^3.4.2", - "tslib": "^2.6.2" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "engines": { - "node": ">=16.0.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@smithy/property-provider": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.6.tgz", - "integrity": "sha512-NK3y/T7Q/Bw+Z8vsVs9MYIQ5v7gOX7clyrXcwhhIBQhbPgRl6JDrZbusO9qWDhcEus75Tg+VCxtIRfo3H76fpw==", + "node_modules/@radix-ui/react-checkbox": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.1.1.tgz", + "integrity": "sha512-0i/EKJ222Afa1FE0C6pNJxDq1itzcl3HChE9DwskA4th4KRse8ojx8a1nVcOjwJdbpDLcz7uol77yYnQNMHdKw==", "dependencies": { - "@smithy/types": "^3.4.2", - "tslib": "^2.6.2" + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-presence": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-controllable-state": "1.1.0", + "@radix-ui/react-use-previous": "1.1.0", + "@radix-ui/react-use-size": "1.1.0" }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/protocol-http": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.3.tgz", - "integrity": "sha512-GcbMmOYpH9iRqtC05RbRnc/0FssxSTHlmaNhYBTgSgNCYpdR3Kt88u5GAZTBmouzv+Zlj/VRv92J9ruuDeJuEw==", - "dependencies": { - "@smithy/types": "^3.4.2", - "tslib": "^2.6.2" + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "engines": { - "node": ">=16.0.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@smithy/querystring-builder": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.6.tgz", - "integrity": "sha512-sQe08RunoObe+Usujn9+R2zrLuQERi3CWvRO3BvnoWSYUaIrLKuAIeY7cMeDax6xGyfIP3x/yFWbEKSXvOnvVg==", - "dependencies": { - "@smithy/types": "^3.4.2", - "@smithy/util-uri-escape": "^3.0.0", - "tslib": "^2.6.2" + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz", + "integrity": "sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==" + }, + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", + "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "engines": { - "node": ">=16.0.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@smithy/querystring-parser": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.6.tgz", - "integrity": "sha512-UJKw4LlEkytzz2Wq+uIdHf6qOtFfee/o7ruH0jF5I6UAuU+19r9QV7nU3P/uI0l6+oElRHmG/5cBBcGJrD7Ozg==", - "dependencies": { - "@smithy/types": "^3.4.2", - "tslib": "^2.6.2" + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-context": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz", + "integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "engines": { - "node": ">=16.0.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@smithy/service-error-classification": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-3.0.6.tgz", - "integrity": "sha512-53SpchU3+DUZrN7J6sBx9tBiCVGzsib2e4sc512Q7K9fpC5zkJKs6Z9s+qbMxSYrkEkle6hnMtrts7XNkMJJMg==", + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-presence": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.0.tgz", + "integrity": "sha512-Gq6wuRN/asf9H/E/VzdKoUtT8GC9PQc9z40/vEr0VCJ4u5XvvhWIrSsCB6vD2/cH7ugTdSfYq9fLJCcM00acrQ==", "dependencies": { - "@smithy/types": "^3.4.2" + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0" }, - "engines": { - "node": ">=16.0.0" + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@smithy/shared-ini-file-loader": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.7.tgz", - "integrity": "sha512-IA4K2qTJYXkF5OfVN4vsY1hfnUZjaslEE8Fsr/gGFza4TAC2A9NfnZuSY2srQIbt9bwtjHiAayrRVgKse4Q7fA==", + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz", + "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==", "dependencies": { - "@smithy/types": "^3.4.2", - "tslib": "^2.6.2" + "@radix-ui/react-slot": "1.1.0" }, - "engines": { - "node": ">=16.0.0" + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@smithy/signature-v4": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-4.1.4.tgz", - "integrity": "sha512-72MiK7xYukNsnLJI9NqvUHqTu0ziEsfMsYNlWpiJfuGQnCTFKpckThlEatirvcA/LmT1h7rRO+pJD06PYsPu9Q==", + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", + "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", "dependencies": { - "@smithy/is-array-buffer": "^3.0.0", - "@smithy/protocol-http": "^4.1.3", - "@smithy/types": "^3.4.2", - "@smithy/util-hex-encoding": "^3.0.0", - "@smithy/util-middleware": "^3.0.6", - "@smithy/util-uri-escape": "^3.0.0", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" + "@radix-ui/react-compose-refs": "1.1.0" }, - "engines": { - "node": ">=16.0.0" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@smithy/smithy-client": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.3.4.tgz", - "integrity": "sha512-NKw/2XxOW/Rg3rzB90HxsmGok5oS6vRzJgMh/JN4BHaOQQ4q5OuX999GmOGxEp730wbpIXIowfKZmIMXkG4v0Q==", - "dependencies": { - "@smithy/middleware-endpoint": "^3.1.3", - "@smithy/middleware-stack": "^3.0.6", - "@smithy/protocol-http": "^4.1.3", - "@smithy/types": "^3.4.2", - "@smithy/util-stream": "^3.1.8", - "tslib": "^2.6.2" + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", + "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "engines": { - "node": ">=16.0.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@smithy/types": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.4.2.tgz", - "integrity": "sha512-tHiFcfcVedVBHpmHUEUHOCCih8iZbIAYn9NvPsNzaPm/237I3imdDdZoOC8c87H5HBAVEa06tTgb+OcSWV9g5w==", + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz", + "integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==", "dependencies": { - "tslib": "^2.6.2" + "@radix-ui/react-use-callback-ref": "1.1.0" }, - "engines": { - "node": ">=16.0.0" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@smithy/url-parser": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.6.tgz", - "integrity": "sha512-47Op/NU8Opt49KyGpHtVdnmmJMsp2hEwBdyjuFB9M2V5QVOwA7pBhhxKN5z6ztKGrMw76gd8MlbPuzzvaAncuQ==", - "dependencies": { - "@smithy/querystring-parser": "^3.0.6", - "@smithy/types": "^3.4.2", - "tslib": "^2.6.2" + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", + "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@smithy/util-base64": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-3.0.0.tgz", - "integrity": "sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==", + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-use-size": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz", + "integrity": "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==", "dependencies": { - "@smithy/util-buffer-from": "^3.0.0", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" + "@radix-ui/react-use-layout-effect": "1.1.0" }, - "engines": { - "node": ">=16.0.0" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@smithy/util-body-length-browser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz", - "integrity": "sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ==", + "node_modules/@radix-ui/react-collapsible": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.0.3.tgz", + "integrity": "sha512-UBmVDkmR6IvDsloHVN+3rtx4Mi5TFvylYXpluuv0f37dtaz3H99bp8No0LGXRigVpl3UAT4l9j6bIchh42S/Gg==", "dependencies": { - "tslib": "^2.6.2" + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-controllable-state": "1.0.1", + "@radix-ui/react-use-layout-effect": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@smithy/util-body-length-node": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-3.0.0.tgz", - "integrity": "sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA==", + "node_modules/@radix-ui/react-collection": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.3.tgz", + "integrity": "sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==", "dependencies": { - "tslib": "^2.6.2" + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-slot": "1.0.2" }, - "engines": { - "node": ">=16.0.0" + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@smithy/util-buffer-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", - "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz", + "integrity": "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==", "dependencies": { - "@smithy/is-array-buffer": "^3.0.0", - "tslib": "^2.6.2" + "@babel/runtime": "^7.13.10" }, - "engines": { - "node": ">=16.0.0" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@smithy/util-config-provider": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz", - "integrity": "sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==", + "node_modules/@radix-ui/react-context": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.0.1.tgz", + "integrity": "sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==", "dependencies": { - "tslib": "^2.6.2" + "@babel/runtime": "^7.13.10" }, - "engines": { - "node": ">=16.0.0" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@smithy/util-defaults-mode-browser": { - "version": "3.0.20", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.20.tgz", - "integrity": "sha512-HpYmCpEThQJpCKzwzrGrklhdegRfuXI9keHRrHidbyEMliCdgic6t38MikJeZEkdIcEMhO1g95HIYMzjUzB+xg==", + "node_modules/@radix-ui/react-dialog": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.2.tgz", + "integrity": "sha512-Yj4dZtqa2o+kG61fzB0H2qUvmwBA2oyQroGLyNtBj1beo1khoQ3q1a2AO8rrQYjd8256CO9+N8L9tvsS+bnIyA==", "dependencies": { - "@smithy/property-provider": "^3.1.6", - "@smithy/smithy-client": "^3.3.4", - "@smithy/types": "^3.4.2", - "bowser": "^2.11.0", - "tslib": "^2.6.2" + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.1", + "@radix-ui/react-focus-guards": "1.1.1", + "@radix-ui/react-focus-scope": "1.1.0", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-portal": "1.1.2", + "@radix-ui/react-presence": "1.1.1", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-slot": "1.1.0", + "@radix-ui/react-use-controllable-state": "1.1.0", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.6.0" }, - "engines": { - "node": ">= 10.0.0" + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@smithy/util-defaults-mode-node": { - "version": "3.0.20", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.20.tgz", - "integrity": "sha512-atdsHNtAX0rwTvRRGsrONU0C0XzapH6tI8T1y/OReOvWN7uBwXqqWRft6m8egU2DgeReU0xqT3PHdGCe5VRaaQ==", - "dependencies": { - "@smithy/config-resolver": "^3.0.8", - "@smithy/credential-provider-imds": "^3.2.3", - "@smithy/node-config-provider": "^3.1.7", - "@smithy/property-provider": "^3.1.6", - "@smithy/smithy-client": "^3.3.4", - "@smithy/types": "^3.4.2", - "tslib": "^2.6.2" + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz", + "integrity": "sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==" + }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", + "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "engines": { - "node": ">= 10.0.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@smithy/util-endpoints": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-2.1.2.tgz", - "integrity": "sha512-FEISzffb4H8DLzGq1g4MuDpcv6CIG15fXoQzDH9SjpRJv6h7J++1STFWWinilG0tQh9H1v2UKWG19Jjr2B16zQ==", - "dependencies": { - "@smithy/node-config-provider": "^3.1.7", - "@smithy/types": "^3.4.2", - "tslib": "^2.6.2" + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-context": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", + "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "engines": { - "node": ">=16.0.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@smithy/util-hex-encoding": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz", - "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==", + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.1.tgz", + "integrity": "sha512-QSxg29lfr/xcev6kSz7MAlmDnzbP1eI/Dwn3Tp1ip0KT5CUELsxkekFEMVBEoykI3oV39hKT4TKZzBNMbcTZYQ==", "dependencies": { - "tslib": "^2.6.2" + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-escape-keydown": "1.1.0" }, - "engines": { - "node": ">=16.0.0" + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@smithy/util-middleware": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.6.tgz", - "integrity": "sha512-BxbX4aBhI1O9p87/xM+zWy0GzT3CEVcXFPBRDoHAM+pV0eSW156pR+PSYEz0DQHDMYDsYAflC2bQNz2uaDBUZQ==", - "dependencies": { - "@smithy/types": "^3.4.2", - "tslib": "^2.6.2" + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-focus-guards": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz", + "integrity": "sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "engines": { - "node": ">=16.0.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@smithy/util-retry": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.6.tgz", - "integrity": "sha512-BRZiuF7IwDntAbevqMco67an0Sr9oLQJqqRCsSPZZHYRnehS0LHDAkJk/pSmI7Z8c/1Vet294H7fY2fWUgB+Rg==", + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-focus-scope": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.0.tgz", + "integrity": "sha512-200UD8zylvEyL8Bx+z76RJnASR2gRMuxlgFCPAe/Q/679a/r0eK3MBVYMb7vZODZcffZBdob1EGnky78xmVvcA==", "dependencies": { - "@smithy/service-error-classification": "^3.0.6", - "@smithy/types": "^3.4.2", - "tslib": "^2.6.2" + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0" }, - "engines": { - "node": ">=16.0.0" + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@smithy/util-stream": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.1.8.tgz", - "integrity": "sha512-hoKOqSmb8FD3WLObuB5hwbM7bNIWgcnvkThokTvVq7J5PKjlLUK5qQQcB9zWLHIoSaIlf3VIv2OxZY2wtQjcRQ==", + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-id": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz", + "integrity": "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==", "dependencies": { - "@smithy/fetch-http-handler": "^3.2.8", - "@smithy/node-http-handler": "^3.2.3", - "@smithy/types": "^3.4.2", - "@smithy/util-base64": "^3.0.0", - "@smithy/util-buffer-from": "^3.0.0", - "@smithy/util-hex-encoding": "^3.0.0", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" + "@radix-ui/react-use-layout-effect": "1.1.0" }, - "engines": { - "node": ">=16.0.0" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@smithy/util-uri-escape": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", - "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-portal": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.2.tgz", + "integrity": "sha512-WeDYLGPxJb/5EGBoedyJbT0MpoULmwnIPMJMSldkuiMsBAv7N1cRdsTWZWht9vpPOiN3qyiGAtbK2is47/uMFg==", "dependencies": { - "tslib": "^2.6.2" + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-layout-effect": "1.1.0" }, - "engines": { - "node": ">=16.0.0" + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@smithy/util-utf8": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", - "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-presence": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.1.tgz", + "integrity": "sha512-IeFXVi4YS1K0wVZzXNrbaaUvIJ3qdY+/Ih4eHFhWA9SwGR9UDX7Ck8abvL57C4cv3wwMvUE0OG69Qc3NCcTe/A==", "dependencies": { - "@smithy/util-buffer-from": "^3.0.0", - "tslib": "^2.6.2" + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0" }, - "engines": { - "node": ">=16.0.0" + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@socket.io/component-emitter": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", - "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" - }, - "node_modules/@solana/buffer-layout": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz", - "integrity": "sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA==", - "license": "MIT", + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz", + "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==", "dependencies": { - "buffer": "~6.0.3" + "@radix-ui/react-slot": "1.1.0" }, - "engines": { - "node": ">=5.10" + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@solana/buffer-layout-utils": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@solana/buffer-layout-utils/-/buffer-layout-utils-0.2.0.tgz", - "integrity": "sha512-szG4sxgJGktbuZYDg2FfNmkMi0DYQoVjN2h7ta1W1hPrwzarcFLBq9UpX1UjNXsNpT9dn+chgprtWGioUAr4/g==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", + "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", "dependencies": { - "@solana/buffer-layout": "^4.0.0", - "@solana/web3.js": "^1.32.0", - "bigint-buffer": "^1.1.5", - "bignumber.js": "^9.0.1" + "@radix-ui/react-compose-refs": "1.1.0" }, - "engines": { - "node": ">= 10" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@solana/buffer-layout/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", + "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" } }, - "node_modules/@solana/spl-token": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@solana/spl-token/-/spl-token-0.3.1.tgz", - "integrity": "sha512-26/0XlW5Lyeu3CUlBGt+0o3l4H6AJtRtMMtsxhcKj+DwfGg+QMnPl/exTmZLEsymsn03PFhogd97v5fJXhYeow==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz", + "integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==", "dependencies": { - "@solana/buffer-layout": "^4.0.0", - "@solana/buffer-layout-utils": "^0.2.0", - "@solana/web3.js": "^1.41.0" + "@radix-ui/react-use-callback-ref": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@solana/web3.js": { - "version": "1.92.1", - "resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.92.1.tgz", - "integrity": "sha512-72hytgOHfJLbvKT0+HRuFUhxxZpCnlo4zFDt37UHPel1DJbgqGOWo3xUf3VEPRWBvSRv0EH15g8MGatdj1PO9g==", - "license": "MIT", + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-use-escape-keydown": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz", + "integrity": "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==", "dependencies": { - "@babel/runtime": "^7.24.6", - "@noble/curves": "^1.4.0", - "@noble/hashes": "^1.4.0", - "@solana/buffer-layout": "^4.0.1", - "agentkeepalive": "^4.5.0", - "bigint-buffer": "^1.1.5", - "bn.js": "^5.2.1", - "borsh": "^0.7.0", - "bs58": "^4.0.1", - "buffer": "6.0.3", - "fast-stable-stringify": "^1.0.0", - "jayson": "^4.1.0", - "node-fetch": "^2.7.0", - "rpc-websockets": "^7.11.1", - "superstruct": "^1.0.4" + "@radix-ui/react-use-callback-ref": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@solana/web3.js/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", + "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" } }, - "node_modules/@stablelib/aead": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/aead/-/aead-1.0.1.tgz", - "integrity": "sha512-q39ik6sxGHewqtO0nP4BuSe3db5G1fEJE8ukvngS2gLkBXyy6E7pLubhbYgnkDFv6V8cWaxcE4Xn0t6LWcJkyg==" - }, - "node_modules/@stablelib/binary": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/binary/-/binary-1.0.1.tgz", - "integrity": "sha512-ClJWvmL6UBM/wjkvv/7m5VP3GMr9t0osr4yVgLZsLCOz4hGN9gIAFEqnJ0TsSMAN+n840nf2cHZnA5/KFqHC7Q==", + "node_modules/@radix-ui/react-dialog/node_modules/react-remove-scroll": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.0.tgz", + "integrity": "sha512-I2U4JVEsQenxDAKaVa3VZ/JeJZe0/2DxPWL8Tj8yLKctQJQiZM52pn/GWFpSp8dftjM3pSAHVJZscAnC/y+ySQ==", "dependencies": { - "@stablelib/int": "^1.0.1" + "react-remove-scroll-bar": "^2.3.6", + "react-style-singleton": "^2.2.1", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.0", + "use-sidecar": "^1.1.2" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@stablelib/bytes": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/bytes/-/bytes-1.0.1.tgz", - "integrity": "sha512-Kre4Y4kdwuqL8BR2E9hV/R5sOrUj6NanZaZis0V6lX5yzqC3hBuVSDXUIBqQv/sCpmuWRiHLwqiT1pqqjuBXoQ==" - }, - "node_modules/@stablelib/chacha": { + "node_modules/@radix-ui/react-direction": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/chacha/-/chacha-1.0.1.tgz", - "integrity": "sha512-Pmlrswzr0pBzDofdFuVe1q7KdsHKhhU24e8gkEwnTGOmlC7PADzLVxGdn2PoNVBBabdg0l/IfLKg6sHAbTQugg==", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.0.1.tgz", + "integrity": "sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==", "dependencies": { - "@stablelib/binary": "^1.0.1", - "@stablelib/wipe": "^1.0.1" + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@stablelib/chacha20poly1305": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/chacha20poly1305/-/chacha20poly1305-1.0.1.tgz", - "integrity": "sha512-MmViqnqHd1ymwjOQfghRKw2R/jMIGT3wySN7cthjXCBdO+qErNPUBnRzqNpnvIwg7JBCg3LdeCZZO4de/yEhVA==", + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.5.tgz", + "integrity": "sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g==", "dependencies": { - "@stablelib/aead": "^1.0.1", - "@stablelib/binary": "^1.0.1", - "@stablelib/chacha": "^1.0.1", - "@stablelib/constant-time": "^1.0.1", - "@stablelib/poly1305": "^1.0.1", - "@stablelib/wipe": "^1.0.1" + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-escape-keydown": "1.0.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@stablelib/constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/constant-time/-/constant-time-1.0.1.tgz", - "integrity": "sha512-tNOs3uD0vSJcK6z1fvef4Y+buN7DXhzHDPqRLSXUel1UfqMB1PWNsnnAezrKfEwTLpN0cGH2p9NNjs6IqeD0eg==" - }, - "node_modules/@stablelib/ed25519": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@stablelib/ed25519/-/ed25519-1.0.3.tgz", - "integrity": "sha512-puIMWaX9QlRsbhxfDc5i+mNPMY+0TmQEskunY1rZEBPi1acBCVQAhnsk/1Hk50DGPtVsZtAWQg4NHGlVaO9Hqg==", + "node_modules/@radix-ui/react-dropdown-menu": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.0.6.tgz", + "integrity": "sha512-i6TuFOoWmLWq+M/eCLGd/bQ2HfAX1RJgvrBQ6AQLmzfvsLdefxbWu8G9zczcPFfcSPehz9GcpF6K9QYreFV8hA==", "dependencies": { - "@stablelib/random": "^1.0.2", - "@stablelib/sha512": "^1.0.1", - "@stablelib/wipe": "^1.0.1" + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-menu": "2.0.6", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-controllable-state": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@stablelib/hash": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/hash/-/hash-1.0.1.tgz", - "integrity": "sha512-eTPJc/stDkdtOcrNMZ6mcMK1e6yBbqRBaNW55XA1jU8w/7QdnCF0CmMmOD1m7VSkBR44PWrMHU2l6r8YEQHMgg==" - }, - "node_modules/@stablelib/hex": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/hex/-/hex-1.0.1.tgz", - "integrity": "sha512-PQOEChVBjhYGgAD+ehO2ow1gSj1slre3jW4oMD4kV8VrhYhzmtsQDWDZej3BQO8qkVezdczDvISxVSF24PuYNA==", - "license": "MIT" - }, - "node_modules/@stablelib/hkdf": { + "node_modules/@radix-ui/react-focus-guards": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/hkdf/-/hkdf-1.0.1.tgz", - "integrity": "sha512-SBEHYE16ZXlHuaW5RcGk533YlBj4grMeg5TooN80W3NpcHRtLZLLXvKyX0qcRFxf+BGDobJLnwkvgEwHIDBR6g==", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.1.tgz", + "integrity": "sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==", "dependencies": { - "@stablelib/hash": "^1.0.1", - "@stablelib/hmac": "^1.0.1", - "@stablelib/wipe": "^1.0.1" + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@stablelib/hmac": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/hmac/-/hmac-1.0.1.tgz", - "integrity": "sha512-V2APD9NSnhVpV/QMYgCVMIYKiYG6LSqw1S65wxVoirhU/51ACio6D4yDVSwMzuTJXWZoVHbDdINioBwKy5kVmA==", + "node_modules/@radix-ui/react-focus-scope": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.4.tgz", + "integrity": "sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA==", "dependencies": { - "@stablelib/constant-time": "^1.0.1", - "@stablelib/hash": "^1.0.1", - "@stablelib/wipe": "^1.0.1" + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@stablelib/int": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/int/-/int-1.0.1.tgz", - "integrity": "sha512-byr69X/sDtDiIjIV6m4roLVWnNNlRGzsvxw+agj8CIEazqWGOQp2dTYgQhtyVXV9wpO6WyXRQUzLV/JRNumT2w==" - }, - "node_modules/@stablelib/keyagreement": { + "node_modules/@radix-ui/react-id": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/keyagreement/-/keyagreement-1.0.1.tgz", - "integrity": "sha512-VKL6xBwgJnI6l1jKrBAfn265cspaWBPAPEc62VBQrWHLqVgNRE09gQ/AnOEyKUWrrqfD+xSQ3u42gJjLDdMDQg==", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.0.1.tgz", + "integrity": "sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==", "dependencies": { - "@stablelib/bytes": "^1.0.1" + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-layout-effect": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@stablelib/poly1305": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/poly1305/-/poly1305-1.0.1.tgz", - "integrity": "sha512-1HlG3oTSuQDOhSnLwJRKeTRSAdFNVB/1djy2ZbS35rBSJ/PFqx9cf9qatinWghC2UbfOYD8AcrtbUQl8WoxabA==", + "node_modules/@radix-ui/react-menu": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.0.6.tgz", + "integrity": "sha512-BVkFLS+bUC8HcImkRKPSiVumA1VPOOEC5WBMiT+QAVsPzW1FJzI9KnqgGxVDPBcql5xXrHkD3JOVoXWEXD8SYA==", "dependencies": { - "@stablelib/constant-time": "^1.0.1", - "@stablelib/wipe": "^1.0.1" + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-collection": "1.0.3", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-direction": "1.0.1", + "@radix-ui/react-dismissable-layer": "1.0.5", + "@radix-ui/react-focus-guards": "1.0.1", + "@radix-ui/react-focus-scope": "1.0.4", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-popper": "1.1.3", + "@radix-ui/react-portal": "1.0.4", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-roving-focus": "1.0.4", + "@radix-ui/react-slot": "1.0.2", + "@radix-ui/react-use-callback-ref": "1.0.1", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.5.5" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@stablelib/random": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@stablelib/random/-/random-1.0.2.tgz", - "integrity": "sha512-rIsE83Xpb7clHPVRlBj8qNe5L8ISQOzjghYQm/dZ7VaM2KHYwMW5adjQjrzTZCchFnNCNhkwtnOBa9HTMJCI8w==", + "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-arrow": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz", + "integrity": "sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA==", "dependencies": { - "@stablelib/binary": "^1.0.1", - "@stablelib/wipe": "^1.0.1" + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@stablelib/sha256": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/sha256/-/sha256-1.0.1.tgz", - "integrity": "sha512-GIIH3e6KH+91FqGV42Kcj71Uefd/QEe7Dy42sBTeqppXV95ggCcxLTk39bEr+lZfJmp+ghsR07J++ORkRELsBQ==", + "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-popper": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.1.3.tgz", + "integrity": "sha512-cKpopj/5RHZWjrbF2846jBNacjQVwkP068DfmgrNJXpvVWrOvlAmE9xSiy5OqeE+Gi8D9fP+oDhUnPqNMY8/5w==", "dependencies": { - "@stablelib/binary": "^1.0.1", - "@stablelib/hash": "^1.0.1", - "@stablelib/wipe": "^1.0.1" + "@babel/runtime": "^7.13.10", + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.0.3", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-layout-effect": "1.0.1", + "@radix-ui/react-use-rect": "1.0.1", + "@radix-ui/react-use-size": "1.0.1", + "@radix-ui/rect": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@stablelib/sha384": { + "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-use-rect": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/sha384/-/sha384-1.0.1.tgz", - "integrity": "sha512-LkhNw9E/9JJzPFxVVBw70yXp2l90XZOm6yPiqh9id+AFscDk2OZ0UkTddUKpPuvjdVtc+7ENvtkSNFJmMncLQg==", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.0.1.tgz", + "integrity": "sha512-Cq5DLuSiuYVKNU8orzJMbl15TXilTnJKUCltMVQg53BQOF1/C5toAaGrowkgksdBQ9H+SRL23g0HDmg9tvmxXw==", "dependencies": { - "@stablelib/sha512": "^1.0.1" + "@babel/runtime": "^7.13.10", + "@radix-ui/rect": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@stablelib/sha512": { + "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/rect": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/sha512/-/sha512-1.0.1.tgz", - "integrity": "sha512-13gl/iawHV9zvDKciLo1fQ8Bgn2Pvf7OV6amaRVKiq3pjQ3UmEpXxWiAfV8tYjUpeZroBxtyrwtdooQT/i3hzw==", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.0.1.tgz", + "integrity": "sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ==", "dependencies": { - "@stablelib/binary": "^1.0.1", - "@stablelib/hash": "^1.0.1", - "@stablelib/wipe": "^1.0.1" + "@babel/runtime": "^7.13.10" } }, - "node_modules/@stablelib/wipe": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/wipe/-/wipe-1.0.1.tgz", - "integrity": "sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg==" - }, - "node_modules/@stablelib/x25519": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@stablelib/x25519/-/x25519-1.0.3.tgz", - "integrity": "sha512-KnTbKmUhPhHavzobclVJQG5kuivH+qDLpe84iRqX3CLrKp881cF160JvXJ+hjn1aMyCwYOKeIZefIH/P5cJoRw==", + "node_modules/@radix-ui/react-popper": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.0.tgz", + "integrity": "sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg==", "dependencies": { - "@stablelib/keyagreement": "^1.0.1", - "@stablelib/random": "^1.0.2", - "@stablelib/wipe": "^1.0.1" + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0", + "@radix-ui/react-use-rect": "1.1.0", + "@radix-ui/react-use-size": "1.1.0", + "@radix-ui/rect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@stacks/common": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/@stacks/common/-/common-4.3.5.tgz", - "integrity": "sha512-UuViiQ7fn3vdtTe3739aRzbl+wbukekeQuXgqt8d7nB2HC2HodD7GcHhpUga165cO35CD6lQUtj3vXxJb5Ga+A==", - "license": "MIT", - "dependencies": { - "@types/bn.js": "^5.1.0", - "@types/node": "^18.0.4", - "buffer": "^6.0.3" + "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", + "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@stacks/common/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" + "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-context": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz", + "integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" } }, - "node_modules/@stacks/network": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/@stacks/network/-/network-4.3.5.tgz", - "integrity": "sha512-TC4+AkuT6qi3MoEGxTftA+4BNp99QvGnI+qtKQkoA1m0KDr8b9hSBUhugJHRhQbWuo7D6q0+JagYEGxLID29Kw==", - "license": "MIT", + "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz", + "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==", "dependencies": { - "@stacks/common": "^4.3.5", - "cross-fetch": "^3.1.5" + "@radix-ui/react-slot": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@stacks/network/node_modules/cross-fetch": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", - "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", - "license": "MIT", + "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", + "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", "dependencies": { - "node-fetch": "^2.7.0" + "@radix-ui/react-compose-refs": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@stacks/transactions": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-2.0.1.tgz", - "integrity": "sha512-q+8nCbn+0m1T8NbGG2sfMcBcCxdaH/F+vgBEHkhMIFHFLYXVYBGYbTX2llGS9StLp/tQq6p2Bfb1kzKFSw8FRQ==", - "license": "GPL-3.0-or-later", - "dependencies": { - "@stacks/common": "^2.0.1", - "@stacks/network": "^1.2.2", - "@types/bn.js": "^4.11.6", - "@types/elliptic": "^6.4.12", - "@types/node": "^14.14.43", - "@types/randombytes": "^2.0.0", - "@types/sha.js": "^2.4.0", - "bn.js": "^4.12.0", - "c32check": "^1.1.2", - "cross-fetch": "^3.1.4", - "elliptic": "^6.5.4", - "lodash": "^4.17.20", - "randombytes": "^2.1.0", - "ripemd160-min": "^0.0.6", - "sha.js": "^2.4.11", - "smart-buffer": "^4.1.0" + "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", + "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@stacks/transactions/node_modules/@stacks/common": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@stacks/common/-/common-2.0.2.tgz", - "integrity": "sha512-RpuNIqf+XmcHlMjXeVZE4fS3yIUlCvOYmxyBKOarh010Kx3Gs/LhAeejn/329lYcIE6VwNPoeXPSE9deq7Yjcw==", - "license": "GPL-3.0-or-later", - "dependencies": { - "@types/node": "^14.14.43", - "bn.js": "^4.12.0", - "buffer": "^6.0.3", - "cross-fetch": "^3.1.4" + "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", + "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@stacks/transactions/node_modules/@stacks/network": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@stacks/network/-/network-1.2.2.tgz", - "integrity": "sha512-xcWwuRrLJn9qqi3PEBcP2UPZHQztTZd31C0aVlzYHttNMir/sY9SrUqSnw45z2Jo4O9pIYYPIiPRtdV91Ho3fw==", - "license": "GPL-3.0-or-later", + "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-use-size": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz", + "integrity": "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==", "dependencies": { - "@stacks/common": "^1.2.2" + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@stacks/transactions/node_modules/@stacks/network/node_modules/@stacks/common": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@stacks/common/-/common-1.2.2.tgz", - "integrity": "sha512-knCqq88EBRCN8AhS7+Sx2PJuRv0EFNChEpqLqCAchCHCQfp5bWad/47Zw+fLP9ccBwFXh4pl1wDtbQLBfDo0+A==", - "license": "GPL-3.0-or-later", + "node_modules/@radix-ui/react-portal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.4.tgz", + "integrity": "sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==", "dependencies": { - "cross-fetch": "^3.0.6" + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@stacks/transactions/node_modules/@types/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", - "license": "MIT", + "node_modules/@radix-ui/react-presence": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.0.1.tgz", + "integrity": "sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==", "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@stacks/transactions/node_modules/@types/node": { - "version": "14.18.63", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.63.tgz", - "integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==", - "license": "MIT" - }, - "node_modules/@stacks/transactions/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", - "license": "MIT" - }, - "node_modules/@stacks/transactions/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-use-layout-effect": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true }, - { - "type": "consulting", - "url": "https://feross.org/support" + "@types/react-dom": { + "optional": true } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" } }, - "node_modules/@stacks/transactions/node_modules/cross-fetch": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", - "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", - "license": "MIT", + "node_modules/@radix-ui/react-primitive": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz", + "integrity": "sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==", "dependencies": { - "node-fetch": "^2.7.0" + "@babel/runtime": "^7.13.10", + "@radix-ui/react-slot": "1.0.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@substrate/connect": { - "version": "0.8.11", - "resolved": "https://registry.npmjs.org/@substrate/connect/-/connect-0.8.11.tgz", - "integrity": "sha512-ofLs1PAO9AtDdPbdyTYj217Pe+lBfTLltdHDs3ds8no0BseoLeAGxpz1mHfi7zB4IxI3YyAiLjH6U8cw4pj4Nw==", - "deprecated": "versions below 1.x are no longer maintained", - "license": "GPL-3.0-only", - "optional": true, + "node_modules/@radix-ui/react-radio-group": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.2.0.tgz", + "integrity": "sha512-yv+oiLaicYMBpqgfpSPw6q+RyXlLdIpQWDHZbUKURxe+nEh53hFXPPlfhfQQtYkS5MMK/5IWIa76SksleQZSzw==", "dependencies": { - "@substrate/connect-extension-protocol": "^2.0.0", - "@substrate/connect-known-chains": "^1.1.5", - "@substrate/light-client-extension-helpers": "^1.0.0", - "smoldot": "2.0.26" + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-direction": "1.1.0", + "@radix-ui/react-presence": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-roving-focus": "1.1.0", + "@radix-ui/react-use-controllable-state": "1.1.0", + "@radix-ui/react-use-previous": "1.1.0", + "@radix-ui/react-use-size": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@substrate/connect-extension-protocol": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@substrate/connect-extension-protocol/-/connect-extension-protocol-2.2.1.tgz", - "integrity": "sha512-GoafTgm/Jey9E4Xlj4Z5ZBt/H4drH2CNq8VrAro80rtoznrXnFDNVivLQzZN0Xaj2g8YXSn9pC9Oc9IovYZJXw==", - "license": "GPL-3.0-only", - "optional": true - }, - "node_modules/@substrate/connect-known-chains": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@substrate/connect-known-chains/-/connect-known-chains-1.9.0.tgz", - "integrity": "sha512-R7yE0kIRUnvNlMiYramQ+dQwSY0ZpqRJ1mK8hLKlvCbEMqjSFa0n/WYYG6/bst9nNA1O6OZLWpvMso6yhENe3A==", - "license": "GPL-3.0-only", - "optional": true + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz", + "integrity": "sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==" }, - "node_modules/@substrate/light-client-extension-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@substrate/light-client-extension-helpers/-/light-client-extension-helpers-1.0.0.tgz", - "integrity": "sha512-TdKlni1mBBZptOaeVrKnusMg/UBpWUORNDv5fdCaJklP4RJiFOzBCrzC+CyVI5kQzsXBisZ+2pXm+rIjS38kHg==", - "license": "MIT", - "optional": true, + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-collection": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.0.tgz", + "integrity": "sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw==", "dependencies": { - "@polkadot-api/json-rpc-provider": "^0.0.1", - "@polkadot-api/json-rpc-provider-proxy": "^0.1.0", - "@polkadot-api/observable-client": "^0.3.0", - "@polkadot-api/substrate-client": "^0.1.2", - "@substrate/connect-extension-protocol": "^2.0.0", - "@substrate/connect-known-chains": "^1.1.5", - "rxjs": "^7.8.1" + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-slot": "1.1.0" }, "peerDependencies": { - "smoldot": "2.x" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@substrate/ss58-registry": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/@substrate/ss58-registry/-/ss58-registry-1.51.0.tgz", - "integrity": "sha512-TWDurLiPxndFgKjVavCniytBIw+t4ViOi7TYp9h/D0NMmkEc9klFTo+827eyEJ0lELpqO207Ey7uGxUa+BS1jQ==", - "license": "Apache-2.0" - }, - "node_modules/@substrate/txwrapper-core": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/@substrate/txwrapper-core/-/txwrapper-core-7.5.2.tgz", - "integrity": "sha512-QbWNA8teVYS2YfrZ5JWtl6nmX11UIS7k4ZF5ukKe/oqaCSifoNhTYkTDnN/AWImOPQ0N0QeVge1XlF1TUtfFDA==", - "license": "Apache-2.0", - "dependencies": { - "@polkadot/api": "^14.0.1", - "@polkadot/keyring": "^13.1.1", - "memoizee": "0.4.15" + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", + "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@substrate/txwrapper-polkadot": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/@substrate/txwrapper-polkadot/-/txwrapper-polkadot-7.5.2.tgz", - "integrity": "sha512-ekTnEOdyuwjHj2HIjh2NK7Rqu5QadKVMsTadU/bAfAoKJEEFXy/WMnsmCahGg09eFx77MX/rPuqv6IRQxl+8VA==", - "license": "Apache-2.0", - "dependencies": { - "@substrate/txwrapper-core": "^7.5.2", - "@substrate/txwrapper-substrate": "^7.5.2" + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-context": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz", + "integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@substrate/txwrapper-substrate": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/@substrate/txwrapper-substrate/-/txwrapper-substrate-7.5.3.tgz", - "integrity": "sha512-hAZTcZzB7uGLwm62JFCmxM9M0lm+5Id1tROqdKkuukesAAt06UcTTiaopq2w/B9syWamMor63aQEFugEIK2PLQ==", - "license": "Apache-2.0", - "dependencies": { - "@substrate/txwrapper-core": "^7.5.3" + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-direction": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz", + "integrity": "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@substrate/txwrapper-substrate/node_modules/@substrate/txwrapper-core": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/@substrate/txwrapper-core/-/txwrapper-core-7.5.3.tgz", - "integrity": "sha512-vcb9GaAY8ex330yjJoDCa2w32R2u/KUmEKsD/5DRgTbPEUF1OYiKmmuOJWcD0jHu9HZ8HWlniiV8wxxwo3PVCA==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-id": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz", + "integrity": "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==", "dependencies": { - "@polkadot/api": "^14.0.1", - "@polkadot/keyring": "^13.1.1", - "memoizee": "0.4.17" + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@substrate/txwrapper-substrate/node_modules/memoizee": { - "version": "0.4.17", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.17.tgz", - "integrity": "sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA==", - "license": "ISC", + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-presence": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.0.tgz", + "integrity": "sha512-Gq6wuRN/asf9H/E/VzdKoUtT8GC9PQc9z40/vEr0VCJ4u5XvvhWIrSsCB6vD2/cH7ugTdSfYq9fLJCcM00acrQ==", "dependencies": { - "d": "^1.0.2", - "es5-ext": "^0.10.64", - "es6-weak-map": "^2.0.3", - "event-emitter": "^0.3.5", - "is-promise": "^2.2.2", - "lru-queue": "^0.1.0", - "next-tick": "^1.1.0", - "timers-ext": "^0.1.7" + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0" }, - "engines": { - "node": ">=0.12" + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@svgr/babel-plugin-add-jsx-attribute": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", - "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz", + "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==", + "dependencies": { + "@radix-ui/react-slot": "1.1.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", - "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-roving-focus": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.0.tgz", + "integrity": "sha512-EA6AMGeq9AEeQDeSH0aZgG198qkfHSbvWTf1HvoDmOB5bBG/qTxjYMWUKMnYiV6J/iP/J8MEFSuB2zRU2n7ODA==", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-collection": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-direction": "1.1.0", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-controllable-state": "1.1.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", - "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", + "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", - "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", + "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@svgr/babel-plugin-svg-dynamic-title": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", - "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz", + "integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@svgr/babel-plugin-svg-em-dimensions": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", - "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", + "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@svgr/babel-plugin-transform-react-native-svg": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", - "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-use-size": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz", + "integrity": "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@svgr/babel-plugin-transform-svg-component": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", - "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", - "engines": { - "node": ">=12" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" + "node_modules/@radix-ui/react-roving-focus": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.4.tgz", + "integrity": "sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-collection": "1.0.3", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-direction": "1.0.1", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-controllable-state": "1.0.1" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@svgr/babel-preset": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", - "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", + "node_modules/@radix-ui/react-slot": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz", + "integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==", "dependencies": { - "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", - "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", - "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", - "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", - "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", - "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", - "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", - "@svgr/babel-plugin-transform-svg-component": "8.0.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@svgr/core": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", - "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", + "node_modules/@radix-ui/react-tooltip": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.0.7.tgz", + "integrity": "sha512-lPh5iKNFVQ/jav/j6ZrWq3blfDJ0OH9R6FlNUHPMqdLuQ9vwDgFsRxvl8b7Asuy5c8xmoojHUxKHQSOAvMHxyw==", "dependencies": { - "@babel/core": "^7.21.3", - "@svgr/babel-preset": "8.1.0", - "camelcase": "^6.2.0", - "cosmiconfig": "^8.1.3", - "snake-case": "^3.0.4" + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-dismissable-layer": "1.0.5", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-popper": "1.1.3", + "@radix-ui/react-portal": "1.0.4", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-slot": "1.0.2", + "@radix-ui/react-use-controllable-state": "1.0.1", + "@radix-ui/react-visually-hidden": "1.0.3" }, - "engines": { - "node": ">=14" + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@svgr/hast-util-to-babel-ast": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", - "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-arrow": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz", + "integrity": "sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA==", "dependencies": { - "@babel/types": "^7.21.3", - "entities": "^4.4.0" + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" }, - "engines": { - "node": ">=14" + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@svgr/plugin-jsx": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", - "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-popper": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.1.3.tgz", + "integrity": "sha512-cKpopj/5RHZWjrbF2846jBNacjQVwkP068DfmgrNJXpvVWrOvlAmE9xSiy5OqeE+Gi8D9fP+oDhUnPqNMY8/5w==", "dependencies": { - "@babel/core": "^7.21.3", - "@svgr/babel-preset": "8.1.0", - "@svgr/hast-util-to-babel-ast": "8.0.0", - "svg-parser": "^2.0.4" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" + "@babel/runtime": "^7.13.10", + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.0.3", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-layout-effect": "1.0.1", + "@radix-ui/react-use-rect": "1.0.1", + "@radix-ui/react-use-size": "1.0.1", + "@radix-ui/rect": "1.0.1" }, "peerDependencies": { - "@svgr/core": "*" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@svgr/plugin-svgo": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-8.1.0.tgz", - "integrity": "sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA==", + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-use-rect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.0.1.tgz", + "integrity": "sha512-Cq5DLuSiuYVKNU8orzJMbl15TXilTnJKUCltMVQg53BQOF1/C5toAaGrowkgksdBQ9H+SRL23g0HDmg9tvmxXw==", "dependencies": { - "cosmiconfig": "^8.1.3", - "deepmerge": "^4.3.1", - "svgo": "^3.0.2" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" + "@babel/runtime": "^7.13.10", + "@radix-ui/rect": "1.0.1" }, "peerDependencies": { - "@svgr/core": "*" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/rect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.0.1.tgz", + "integrity": "sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ==", + "dependencies": { + "@babel/runtime": "^7.13.10" } }, - "node_modules/@svgr/webpack": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.1.0.tgz", - "integrity": "sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==", + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz", + "integrity": "sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==", "dependencies": { - "@babel/core": "^7.21.3", - "@babel/plugin-transform-react-constant-elements": "^7.21.3", - "@babel/preset-env": "^7.20.2", - "@babel/preset-react": "^7.18.6", - "@babel/preset-typescript": "^7.21.0", - "@svgr/core": "8.1.0", - "@svgr/plugin-jsx": "8.1.0", - "@svgr/plugin-svgo": "8.1.0" + "@babel/runtime": "^7.13.10" }, - "engines": { - "node": ">=14" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@swc-node/core": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/@swc-node/core/-/core-1.13.3.tgz", - "integrity": "sha512-OGsvXIid2Go21kiNqeTIn79jcaX4l0G93X2rAnas4LFoDyA9wAwVK7xZdm+QsKoMn5Mus2yFLCc4OtX2dD/PWA==", - "dev": true, - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.1.tgz", + "integrity": "sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-callback-ref": "1.0.1" }, "peerDependencies": { - "@swc/core": ">= 1.4.13", - "@swc/types": ">= 0.1" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@swc-node/register": { - "version": "1.10.9", - "resolved": "https://registry.npmjs.org/@swc-node/register/-/register-1.10.9.tgz", - "integrity": "sha512-iXy2sjP0phPEpK2yivjRC3PAgoLaT4sjSk0LDWCTdcTBJmR4waEog0E6eJbvoOkLkOtWw37SB8vCkl/bbh4+8A==", - "dev": true, + "node_modules/@radix-ui/react-use-escape-keydown": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.3.tgz", + "integrity": "sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==", "dependencies": { - "@swc-node/core": "^1.13.3", - "@swc-node/sourcemap-support": "^0.5.1", - "colorette": "^2.0.20", - "debug": "^4.3.5", - "oxc-resolver": "^1.10.2", - "pirates": "^4.0.6", - "tslib": "^2.6.3" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-callback-ref": "1.0.1" }, "peerDependencies": { - "@swc/core": ">= 1.4.13", - "typescript": ">= 4.3" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@swc-node/sourcemap-support": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@swc-node/sourcemap-support/-/sourcemap-support-0.5.1.tgz", - "integrity": "sha512-JxIvIo/Hrpv0JCHSyRpetAdQ6lB27oFYhv0PKCNf1g2gUXOjpeR1exrXccRxLMuAV5WAmGFBwRnNOJqN38+qtg==", - "dev": true, + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.1.tgz", + "integrity": "sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==", "dependencies": { - "source-map-support": "^0.5.21", - "tslib": "^2.6.3" + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@swc-node/sourcemap-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" + "node_modules/@radix-ui/react-use-previous": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.0.tgz", + "integrity": "sha512-Z/e78qg2YFnnXcW88A4JmTtm4ADckLno6F7OXotmkQfeuCVaKuYzqAATPhVzl3delXE7CxIV8shofPn3jPc5Og==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@swc-node/sourcemap-support/node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, + "node_modules/@radix-ui/react-use-rect": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz", + "integrity": "sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==", "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "@radix-ui/rect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@swc/core": { - "version": "1.7.26", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.7.26.tgz", - "integrity": "sha512-f5uYFf+TmMQyYIoxkn/evWhNGuUzC730dFwAKGwBVHHVoPyak1/GvJUm6i1SKl+2Hrj9oN0i3WSoWWZ4pgI8lw==", - "dev": true, - "hasInstallScript": true, + "node_modules/@radix-ui/react-use-size": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.0.1.tgz", + "integrity": "sha512-ibay+VqrgcaI6veAojjofPATwledXiSmX+C0KrBk/xgpX9rBzPV3OsfwlhQdUOFbh+LKQorLYT+xTXW9V8yd0g==", "dependencies": { - "@swc/counter": "^0.1.3", - "@swc/types": "^0.1.12" - }, - "engines": { - "node": ">=10" + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-layout-effect": "1.0.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/swc" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" }, - "optionalDependencies": { - "@swc/core-darwin-arm64": "1.7.26", - "@swc/core-darwin-x64": "1.7.26", - "@swc/core-linux-arm-gnueabihf": "1.7.26", - "@swc/core-linux-arm64-gnu": "1.7.26", - "@swc/core-linux-arm64-musl": "1.7.26", - "@swc/core-linux-x64-gnu": "1.7.26", - "@swc/core-linux-x64-musl": "1.7.26", - "@swc/core-win32-arm64-msvc": "1.7.26", - "@swc/core-win32-ia32-msvc": "1.7.26", - "@swc/core-win32-x64-msvc": "1.7.26" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-visually-hidden": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.0.3.tgz", + "integrity": "sha512-D4w41yN5YRKtu464TLnByKzMDG/JlMPHtfZgQAu9v6mNakUqGUI9vUrfQKz8NK41VMm/xbZbh76NUTVtIYqOMA==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" }, "peerDependencies": { - "@swc/helpers": "*" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" }, "peerDependenciesMeta": { - "@swc/helpers": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { "optional": true } } }, - "node_modules/@swc/core-darwin-arm64": { - "version": "1.7.26", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.26.tgz", - "integrity": "sha512-FF3CRYTg6a7ZVW4yT9mesxoVVZTrcSWtmZhxKCYJX9brH4CS/7PRPjAKNk6kzWgWuRoglP7hkjQcd6EpMcZEAw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], + "node_modules/@radix-ui/rect": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.0.tgz", + "integrity": "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==" + }, + "node_modules/@react-native/assets-registry": { + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.77.0.tgz", + "integrity": "sha512-Ms4tYYAMScgINAXIhE4riCFJPPL/yltughHS950l0VP5sm5glbimn9n7RFn9Tc8cipX74/ddbk19+ydK2iDMmA==", + "license": "MIT", + "peer": true, "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/@swc/core-darwin-x64": { - "version": "1.7.26", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.7.26.tgz", - "integrity": "sha512-az3cibZdsay2HNKmc4bjf62QVukuiMRh5sfM5kHR/JMTrLyS6vSw7Ihs3UTkZjUxkLTT8ro54LI6sV6sUQUbLQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], + "node_modules/@react-native/babel-plugin-codegen": { + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.77.0.tgz", + "integrity": "sha512-5TYPn1k+jdDOZJU4EVb1kZ0p9TCVICXK3uplRev5Gul57oWesAaiWGZOzfRS3lonWeuR4ij8v8PFfIHOaq0vmA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/traverse": "^7.25.3", + "@react-native/codegen": "0.77.0" + }, "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.7.26", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.7.26.tgz", - "integrity": "sha512-VYPFVJDO5zT5U3RpCdHE5v1gz4mmR8BfHecUZTmD2v1JeFY6fv9KArJUpjrHEEsjK/ucXkQFmJ0jaiWXmpOV9Q==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@react-native/babel-preset": { + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.77.0.tgz", + "integrity": "sha512-Z4yxE66OvPyQ/iAlaETI1ptRLcDm7Tk6ZLqtCPuUX3AMg+JNgIA86979T4RSk486/JrBUBH5WZe2xjj7eEHXsA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/core": "^7.25.2", + "@babel/plugin-proposal-export-default-from": "^7.24.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-default-from": "^7.24.7", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-transform-arrow-functions": "^7.24.7", + "@babel/plugin-transform-async-generator-functions": "^7.25.4", + "@babel/plugin-transform-async-to-generator": "^7.24.7", + "@babel/plugin-transform-block-scoping": "^7.25.0", + "@babel/plugin-transform-class-properties": "^7.25.4", + "@babel/plugin-transform-classes": "^7.25.4", + "@babel/plugin-transform-computed-properties": "^7.24.7", + "@babel/plugin-transform-destructuring": "^7.24.8", + "@babel/plugin-transform-flow-strip-types": "^7.25.2", + "@babel/plugin-transform-for-of": "^7.24.7", + "@babel/plugin-transform-function-name": "^7.25.1", + "@babel/plugin-transform-literals": "^7.25.2", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.8", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-numeric-separator": "^7.24.7", + "@babel/plugin-transform-object-rest-spread": "^7.24.7", + "@babel/plugin-transform-optional-catch-binding": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.8", + "@babel/plugin-transform-parameters": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.24.7", + "@babel/plugin-transform-private-property-in-object": "^7.24.7", + "@babel/plugin-transform-react-display-name": "^7.24.7", + "@babel/plugin-transform-react-jsx": "^7.25.2", + "@babel/plugin-transform-react-jsx-self": "^7.24.7", + "@babel/plugin-transform-react-jsx-source": "^7.24.7", + "@babel/plugin-transform-regenerator": "^7.24.7", + "@babel/plugin-transform-runtime": "^7.24.7", + "@babel/plugin-transform-shorthand-properties": "^7.24.7", + "@babel/plugin-transform-spread": "^7.24.7", + "@babel/plugin-transform-sticky-regex": "^7.24.7", + "@babel/plugin-transform-typescript": "^7.25.2", + "@babel/plugin-transform-unicode-regex": "^7.24.7", + "@babel/template": "^7.25.0", + "@react-native/babel-plugin-codegen": "0.77.0", + "babel-plugin-syntax-hermes-parser": "0.25.1", + "babel-plugin-transform-flow-enums": "^0.0.2", + "react-refresh": "^0.14.0" + }, "engines": { - "node": ">=10" + "node": ">=18" + }, + "peerDependencies": { + "@babel/core": "*" } }, - "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.7.26", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.7.26.tgz", - "integrity": "sha512-YKevOV7abpjcAzXrhsl+W48Z9mZvgoVs2eP5nY+uoMAdP2b3GxC0Df1Co0I90o2lkzO4jYBpTMcZlmUXLdXn+Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@react-native/codegen": { + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.77.0.tgz", + "integrity": "sha512-rE9lXx41ZjvE8cG7e62y/yGqzUpxnSvJ6me6axiX+aDewmI4ZrddvRGYyxCnawxy5dIBHSnrpZse3P87/4Lm7w==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/parser": "^7.25.3", + "glob": "^7.1.1", + "hermes-parser": "0.25.1", + "invariant": "^2.2.4", + "jscodeshift": "^17.0.0", + "nullthrows": "^1.1.1", + "yargs": "^17.6.2" + }, "engines": { - "node": ">=10" + "node": ">=18" + }, + "peerDependencies": { + "@babel/preset-env": "^7.1.6" } }, - "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.7.26", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.7.26.tgz", - "integrity": "sha512-3w8iZICMkQQON0uIcvz7+Q1MPOW6hJ4O5ETjA0LSP/tuKqx30hIniCGOgPDnv3UTMruLUnQbtBwVCZTBKR3Rkg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@react-native/codegen/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT", + "peer": true + }, + "node_modules/@react-native/codegen/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "peer": true, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.7.26", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.26.tgz", - "integrity": "sha512-c+pp9Zkk2lqb06bNGkR2Looxrs7FtGDMA4/aHjZcCqATgp348hOKH5WPvNLBl+yPrISuWjbKDVn3NgAvfvpH4w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@react-native/codegen/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "peer": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/@swc/core-linux-x64-musl": { - "version": "1.7.26", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.7.26.tgz", - "integrity": "sha512-PgtyfHBF6xG87dUSSdTJHwZ3/8vWZfNIXQV2GlwEpslrOkGqy+WaiiyE7Of7z9AvDILfBBBcJvJ/r8u980wAfQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/@react-native/codegen/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "peer": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, "engines": { - "node": ">=10" + "node": ">=12" } }, - "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.7.26", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.7.26.tgz", - "integrity": "sha512-9TNXPIJqFynlAOrRD6tUQjMq7KApSklK3R/tXgIxc7Qx+lWu8hlDQ/kVPLpU7PWvMMwC/3hKBW+p5f+Tms1hmA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], + "node_modules/@react-native/community-cli-plugin": { + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.77.0.tgz", + "integrity": "sha512-GRshwhCHhtupa3yyCbel14SlQligV8ffNYN5L1f8HCo2SeGPsBDNjhj2U+JTrMPnoqpwowPGvkCwyqwqYff4MQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@react-native/dev-middleware": "0.77.0", + "@react-native/metro-babel-transformer": "0.77.0", + "chalk": "^4.0.0", + "debug": "^2.2.0", + "invariant": "^2.2.4", + "metro": "^0.81.0", + "metro-config": "^0.81.0", + "metro-core": "^0.81.0", + "readline": "^1.3.0", + "semver": "^7.1.3" + }, "engines": { - "node": ">=10" + "node": ">=18" + }, + "peerDependencies": { + "@react-native-community/cli-server-api": "*" + }, + "peerDependenciesMeta": { + "@react-native-community/cli-server-api": { + "optional": true + } } }, - "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.7.26", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.7.26.tgz", - "integrity": "sha512-9YngxNcG3177GYdsTum4V98Re+TlCeJEP4kEwEg9EagT5s3YejYdKwVAkAsJszzkXuyRDdnHUpYbTrPG6FiXrQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], + "node_modules/@react-native/community-cli-plugin/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/@react-native/community-cli-plugin/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT", + "peer": true + }, + "node_modules/@react-native/community-cli-plugin/node_modules/semver": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.0.tgz", + "integrity": "sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ==", + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + }, "engines": { "node": ">=10" } }, - "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.7.26", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.26.tgz", - "integrity": "sha512-VR+hzg9XqucgLjXxA13MtV5O3C0bK0ywtLIBw/+a+O+Oc6mxFWHtdUeXDbIi5AiPbn0fjgVJMqYnyjGyyX8u0w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], + "node_modules/@react-native/debugger-frontend": { + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.77.0.tgz", + "integrity": "sha512-glOvSEjCbVXw+KtfiOAmrq21FuLE1VsmBsyT7qud4KWbXP43aUEhzn70mWyFuiIdxnzVPKe2u8iWTQTdJksR1w==", + "license": "BSD-3-Clause", + "peer": true, "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/@swc/counter": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", - "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" - }, - "node_modules/@swc/helpers": { - "version": "0.5.11", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.11.tgz", - "integrity": "sha512-YNlnKRWF2sVojTpIyzwou9XoTNbzbzONwRhOoniEioF1AtaitTvVZblaQRrAzChWQ1bLYyYSWzM18y4WwgzJ+A==", - "dev": true, + "node_modules/@react-native/dev-middleware": { + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.77.0.tgz", + "integrity": "sha512-DAlEYujm43O+Dq98KP2XfLSX5c/TEGtt+JBDEIOQewk374uYY52HzRb1+Gj6tNaEj/b33no4GibtdxbO5zmPhg==", + "license": "MIT", + "peer": true, "dependencies": { - "tslib": "^2.4.0" + "@isaacs/ttlcache": "^1.4.1", + "@react-native/debugger-frontend": "0.77.0", + "chrome-launcher": "^0.15.2", + "chromium-edge-launcher": "^0.2.0", + "connect": "^3.6.5", + "debug": "^2.2.0", + "nullthrows": "^1.1.1", + "open": "^7.0.3", + "selfsigned": "^2.4.1", + "serve-static": "^1.16.2", + "ws": "^6.2.3" + }, + "engines": { + "node": ">=18" } }, - "node_modules/@swc/types": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.12.tgz", - "integrity": "sha512-wBJA+SdtkbFhHjTMYH+dEH1y4VpfGdAc2Kw/LK09i9bXd/K6j6PkDcFCEzb6iVfZMkPRrl/q0e3toqTAJdkIVA==", - "dev": true, + "node_modules/@react-native/dev-middleware/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "peer": true, "dependencies": { - "@swc/counter": "^0.1.3" + "ms": "2.0.0" } }, - "node_modules/@szmarczak/http-timer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", - "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", - "dependencies": { - "defer-to-connect": "^2.0.1" - }, + "node_modules/@react-native/dev-middleware/node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "peer": true, "engines": { - "node": ">=14.16" + "node": ">= 0.8" } }, - "node_modules/@tanstack/query-core": { - "version": "5.51.9", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.51.9.tgz", - "integrity": "sha512-HsAwaY5J19MD18ykZDS3aVVh+bAt0i7m6uQlFC2b77DLV9djo+xEN7MWQAQQTR8IM+7r/zbozTQ7P0xr0bHuew==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - } + "node_modules/@react-native/dev-middleware/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT", + "peer": true }, - "node_modules/@tanstack/react-query": { - "version": "5.51.11", - "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.51.11.tgz", - "integrity": "sha512-4Kq2x0XpDlpvSnaLG+8pHNH60zEc3mBvb3B2tOMDjcPCi/o+Du3p/9qpPLwJOTliVxxPJAP27fuIhLrsRdCr7A==", + "node_modules/@react-native/dev-middleware/node_modules/open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "license": "MIT", + "peer": true, "dependencies": { - "@tanstack/query-core": "5.51.9" + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" + "engines": { + "node": ">=8" }, - "peerDependencies": { - "react": "^18.0.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@taquito/local-forging": { - "version": "6.3.5-beta.0", - "resolved": "https://registry.npmjs.org/@taquito/local-forging/-/local-forging-6.3.5-beta.0.tgz", - "integrity": "sha512-p0E3Ww3kg+YQYPmp/XK4YKZpWdKqtIg1ZlDtptLn66nbDA3ivzbiFHe3LxceJsYnaCcoWTXl/sRf34VKTkMK3Q==", + "node_modules/@react-native/dev-middleware/node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "license": "MIT", + "peer": true, "dependencies": { - "@taquito/utils": "^6.3.5-beta.0", - "bignumber.js": "^9.0.0" + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" }, "engines": { - "node": ">=6.0.0" + "node": ">= 0.8.0" } }, - "node_modules/@taquito/signer": { - "version": "6.3.5-beta.0", - "resolved": "https://registry.npmjs.org/@taquito/signer/-/signer-6.3.5-beta.0.tgz", - "integrity": "sha512-8f2XPXw8XveGuJGCiqj9vyAiATBepz+s/J6asYil4HGwjgAXZ2unBemuqNk7oQ9xSz9fCCbFxc4ZER1GtJ8Auw==", + "node_modules/@react-native/dev-middleware/node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "license": "MIT", - "dependencies": { - "@taquito/utils": "^6.3.5-beta.0", - "bignumber.js": "^9.0.0", - "bip39": "^3.0.2", - "elliptic": "^6.5.2", - "libsodium-wrappers": "^0.7.6", - "pbkdf2": "^3.0.17", - "typedarray-to-buffer": "^3.1.5" - }, + "peer": true, "engines": { - "node": ">=6.0.0" + "node": ">= 0.8" } }, - "node_modules/@taquito/utils": { - "version": "6.3.5-beta.0", - "resolved": "https://registry.npmjs.org/@taquito/utils/-/utils-6.3.5-beta.0.tgz", - "integrity": "sha512-EFzDnTXMctbIEnt3yfgqPmogwxR2jTYnAZqxGOgfycYlZQWGNAfvgW5KFMlhYPAfYEAU/2euvE5BYMgnexBIOA==", + "node_modules/@react-native/dev-middleware/node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT", + "peer": true + }, + "node_modules/@react-native/dev-middleware/node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "license": "MIT", + "peer": true, "dependencies": { - "blakejs": "^1.1.0", - "bs58check": "^2.1.2", - "buffer": "^5.6.0" + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" }, "engines": { - "node": ">=6.0.0" + "node": ">= 0.8.0" } }, - "node_modules/@testing-library/dom": { - "version": "9.3.4", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.4.tgz", - "integrity": "sha512-FlS4ZWlp97iiNWig0Muq8p+3rVDjRiYE+YKGbAqXOu9nwJFFOdL00kFpz42M+4huzYi86vAK1sOOfyOG45muIQ==", - "dev": true, + "node_modules/@react-native/dev-middleware/node_modules/ws": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", + "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", + "license": "MIT", + "peer": true, "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^5.0.1", - "aria-query": "5.1.3", - "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.5.0", - "pretty-format": "^27.0.2" - }, + "async-limiter": "~1.0.0" + } + }, + "node_modules/@react-native/gradle-plugin": { + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.77.0.tgz", + "integrity": "sha512-rmfh93jzbndSq7kihYHUQ/EGHTP8CCd3GDCmg5SbxSOHAaAYx2HZ28ZG7AVcGUsWeXp+e/90zGIyfOzDRx0Zaw==", + "license": "MIT", + "peer": true, "engines": { - "node": ">=14" + "node": ">=18" } }, - "node_modules/@testing-library/react": { - "version": "14.1.2", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-14.1.2.tgz", - "integrity": "sha512-z4p7DVBTPjKM5qDZ0t5ZjzkpSNb+fZy1u6bzO7kk8oeGagpPCAtgh4cx1syrfp7a+QWkM021jGqjJaxJJnXAZg==", - "dev": true, + "node_modules/@react-native/js-polyfills": { + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.77.0.tgz", + "integrity": "sha512-kHFcMJVkGb3ptj3yg1soUsMHATqal4dh0QTGAbYihngJ6zy+TnP65J3GJq4UlwqFE9K1RZkeCmTwlmyPFHOGvA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/metro-babel-transformer": { + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.77.0.tgz", + "integrity": "sha512-19GfvhBRKCU3UDWwCnDR4QjIzz3B2ZuwhnxMRwfAgPxz7QY9uKour9RGmBAVUk1Wxi/SP7dLEvWnmnuBO39e2A==", + "license": "MIT", + "peer": true, "dependencies": { - "@babel/runtime": "^7.12.5", - "@testing-library/dom": "^9.0.0", - "@types/react-dom": "^18.0.0" + "@babel/core": "^7.25.2", + "@react-native/babel-preset": "0.77.0", + "hermes-parser": "0.25.1", + "nullthrows": "^1.1.1" }, "engines": { - "node": ">=14" + "node": ">=18" }, "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true, - "engines": { - "node": ">= 10" + "@babel/core": "*" } }, - "node_modules/@tootallnate/quickjs-emscripten": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", - "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==" - }, - "node_modules/@tronweb3/google-protobuf": { - "version": "3.21.4", - "resolved": "https://registry.npmjs.org/@tronweb3/google-protobuf/-/google-protobuf-3.21.4.tgz", - "integrity": "sha512-joxgV4esCdyZ921AprMIG1T7HjkypquhbJ5qJti/priCBJhRE1z9GOxIEMvayxSVSRbMGIoJNE0Knrg3vpwM1w==", - "license": "(BSD-3-Clause AND Apache-2.0)" + "node_modules/@react-native/normalize-colors": { + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.77.0.tgz", + "integrity": "sha512-qjmxW3xRZe4T0ZBEaXZNHtuUbRgyfybWijf1yUuQwjBt24tSapmIslwhCjpKidA0p93ssPcepquhY0ykH25mew==", + "license": "MIT", + "peer": true }, - "node_modules/@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "node_modules/@react-native/virtualized-lists": { + "version": "0.77.0", + "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.77.0.tgz", + "integrity": "sha512-ppPtEu9ISO9iuzpA2HBqrfmDpDAnGGduNDVaegadOzbMCPAB3tC9Blxdu9W68LyYlNQILIsP6/FYtLwf7kfNew==", + "license": "MIT", + "peer": true, + "dependencies": { + "invariant": "^2.2.4", + "nullthrows": "^1.1.1" + }, "engines": { - "node": ">=10.13.0" + "node": ">=18" + }, + "peerDependencies": { + "@types/react": "^18.2.6", + "react": "*", + "react-native": "*" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@tsconfig/node10": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", - "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", - "dev": true - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "node_modules/@rushstack/eslint-patch": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.3.tgz", + "integrity": "sha512-qC/xYId4NMebE6w/V33Fh9gWxLgURiNYgVNObbJl2LZv0GUUItCcCqC5axQSwRaAgaxl2mELq1rMzlswaQ0Zxg==", "dev": true }, - "node_modules/@tybys/wasm-util": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", - "integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==", - "dev": true, + "node_modules/@safe-global/safe-apps-provider": { + "version": "0.18.4", + "resolved": "https://registry.npmjs.org/@safe-global/safe-apps-provider/-/safe-apps-provider-0.18.4.tgz", + "integrity": "sha512-SWYeG3gyTO6wGHMSokfHakZ9isByn2mHsM0VohIorYFFEyGGmJ89btnTm+DqDUSoQtvWAatZB7XNy6CaYMvqtg==", "dependencies": { - "tslib": "^2.4.0" + "@safe-global/safe-apps-sdk": "^9.1.0", + "events": "^3.3.0" } }, - "node_modules/@types/acorn": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz", - "integrity": "sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==", + "node_modules/@safe-global/safe-apps-sdk": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@safe-global/safe-apps-sdk/-/safe-apps-sdk-9.1.0.tgz", + "integrity": "sha512-N5p/ulfnnA2Pi2M3YeWjULeWbjo7ei22JwU/IXnhoHzKq3pYCN6ynL9mJBOlvDVv892EgLPCWCOwQk/uBT2v0Q==", "dependencies": { - "@types/estree": "*" + "@safe-global/safe-gateway-typescript-sdk": "^3.5.3", + "viem": "^2.1.1" } }, - "node_modules/@types/aria-query": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", - "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", - "dev": true + "node_modules/@safe-global/safe-gateway-typescript-sdk": { + "version": "3.22.2", + "resolved": "https://registry.npmjs.org/@safe-global/safe-gateway-typescript-sdk/-/safe-gateway-typescript-sdk-3.22.2.tgz", + "integrity": "sha512-Y0yAxRaB98LFp2Dm+ACZqBSdAmI3FlpH/LjxOZ94g/ouuDJecSq0iR26XZ5QDuEL8Rf+L4jBJaoDC08CD0KkJw==", + "engines": { + "node": ">=16" + } }, - "node_modules/@types/aws-lambda": { - "version": "8.10.143", - "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.143.tgz", - "integrity": "sha512-u5vzlcR14ge/4pMTTMDQr3MF0wEe38B2F9o84uC4F43vN5DGTy63npRrB6jQhyt+C0lGv4ZfiRcRkqJoZuPnmg==" + "node_modules/@scure/base": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.7.tgz", + "integrity": "sha512-PPNYBslrLNNUQ/Yad37MHYsNQtK67EhWb6WtSvNLLPo7SdVZgkUjD6Dg+5On7zNwmskf8OX7I7Nx5oN+MIWE0g==", + "funding": { + "url": "https://paulmillr.com/funding/" + } }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "node_modules/@scure/bip32": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.5.0.tgz", + "integrity": "sha512-8EnFYkqEQdnkuGBVpCzKxyIwDCBLDVj3oiX0EKUFre/tOjL/Hqba1D6n/8RcmaQy4f95qQFrO2A8Sr6ybh4NRw==", "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" + "@noble/curves": "~1.6.0", + "@noble/hashes": "~1.5.0", + "@scure/base": "~1.1.7" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@types/babel__generator": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", - "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", - "dependencies": { - "@babel/types": "^7.0.0" + "node_modules/@scure/bip32/node_modules/@noble/hashes": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.5.0.tgz", + "integrity": "sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "node_modules/@scure/bip39": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", + "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@types/babel__traverse": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", - "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "node_modules/@sepior/tsmsdkv2": { + "version": "63.0.0", + "resolved": "https://nexus.sepior.net/repository/sepior-nodejs-tsm-sdk-group/@sepior/tsmsdkv2/-/tsmsdkv2-63.0.0.tgz", + "integrity": "sha512-SERPces5/gCumUzZK8fE0oGWG6+zlRohz1VWLjEzncWEAWeC65RNhIQvCrCUSosirpoSSflxx5Kf7OHU19M8UA==", + "hasInstallScript": true, + "optional": true, "dependencies": { - "@babel/types": "^7.20.7" + "bindings": "^1.5.0", + "elliptic": "^6.5.4", + "node-addon-api": "^7.1.0" } }, - "node_modules/@types/bluebird": { - "version": "3.5.42", - "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.42.tgz", - "integrity": "sha512-Jhy+MWRlro6UjVi578V/4ZGNfeCOcNCp0YaFNIUGFKlImowqwb1O/22wDVk3FDGMLqxdpOV3qQHD5fPEH4hK6A==", - "license": "MIT" + "node_modules/@sepior/tsmsdkv2/node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "optional": true }, - "node_modules/@types/bn.js": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.6.tgz", - "integrity": "sha512-Xh8vSwUeMKeYYrj3cX4lGQgFSF/N03r+tv4AiLl1SucqV+uTQpxRcnM8AkXKHwYP9ZPXOYXRr2KPXpVlIvqh9w==", - "license": "MIT", + "node_modules/@sideway/address": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", + "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", "dependencies": { - "@types/node": "*" + "@hapi/hoek": "^9.0.0" } }, - "node_modules/@types/body-parser": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", - "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } + "node_modules/@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" }, - "node_modules/@types/bonjour": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", - "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", - "dependencies": { - "@types/node": "*" + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" } }, - "node_modules/@types/bunyan": { - "version": "1.8.9", - "resolved": "https://registry.npmjs.org/@types/bunyan/-/bunyan-1.8.9.tgz", - "integrity": "sha512-ZqS9JGpBxVOvsawzmVt30sP++gSQMTejCkIAQ3VdadOcRE8izTyW66hufvwLeH+YEGP6Js2AW7Gz+RMyvrEbmw==", + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", "dependencies": { - "@types/node": "*" + "type-detect": "4.0.8" } }, - "node_modules/@types/cacheable-request": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", - "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", - "license": "MIT", + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", "dependencies": { - "@types/http-cache-semantics": "*", - "@types/keyv": "^3.1.4", - "@types/node": "*", - "@types/responselike": "^1.0.0" + "@sinonjs/commons": "^3.0.0" } }, - "node_modules/@types/compression": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@types/compression/-/compression-1.7.5.tgz", - "integrity": "sha512-AAQvK5pxMpaT+nDvhHrsBhLSYG5yQdtkaJE1WYieSNY2mVFKAgmU4ks65rkZD5oqnGCFLyQpUr1CqI4DmUMyDg==", - "dev": true, + "node_modules/@slorber/remark-comment": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@slorber/remark-comment/-/remark-comment-1.0.0.tgz", + "integrity": "sha512-RCE24n7jsOj1M0UPvIQCHTe7fI0sFL4S2nwKVWwHyVr/wI/H8GosgsJGyhnsZoGFnD/P2hLf1mSbrrgSLN93NA==", "dependencies": { - "@types/express": "*" + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.1.0", + "micromark-util-symbol": "^1.0.1" } }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "node_modules/@smithy/abort-controller": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.1.4.tgz", + "integrity": "sha512-VupaALAQlXViW3/enTf/f5l5JZYSAxoJL7f0nanhNNKnww6DGCg1oYIuNP78KDugnkwthBO6iEcym16HhWV8RQ==", "dependencies": { - "@types/node": "*" + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/connect-history-api-fallback": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", - "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", + "node_modules/@smithy/config-resolver": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-3.0.8.tgz", + "integrity": "sha512-Tv1obAC18XOd2OnDAjSWmmthzx6Pdeh63FbLin8MlPiuJ2ATpKkq0NcNOJFr0dO+JmZXnwu8FQxKJ3TKJ3Hulw==", "dependencies": { - "@types/express-serve-static-core": "*", - "@types/node": "*" + "@smithy/node-config-provider": "^3.1.7", + "@smithy/types": "^3.4.2", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.6", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/cookiejar": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.5.tgz", - "integrity": "sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==" - }, - "node_modules/@types/debug": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", - "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "node_modules/@smithy/core": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.4.5.tgz", + "integrity": "sha512-Z0qlPXgZ0pouYgnu/cZTEYeRAvniiKZmVl4wIbZHX/nEMHkMDV9ao6KFArsU9KndE0TuhL149xcRx45wfw1YCA==", "dependencies": { - "@types/ms": "*" + "@smithy/middleware-endpoint": "^3.1.3", + "@smithy/middleware-retry": "^3.0.20", + "@smithy/middleware-serde": "^3.0.6", + "@smithy/protocol-http": "^4.1.3", + "@smithy/smithy-client": "^3.3.4", + "@smithy/types": "^3.4.2", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-middleware": "^3.0.6", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/duplexify": { - "version": "3.6.4", - "resolved": "https://registry.npmjs.org/@types/duplexify/-/duplexify-3.6.4.tgz", - "integrity": "sha512-2eahVPsd+dy3CL6FugAzJcxoraWhUghZGEQJns1kTKfCXWKJ5iG/VkaB05wRVrDKHfOFKqb0X0kXh91eE99RZg==", + "node_modules/@smithy/credential-provider-imds": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.3.tgz", + "integrity": "sha512-VoxMzSzdvkkjMJNE38yQgx4CfnmT+Z+5EUXkg4x7yag93eQkVQgZvN3XBSHC/ylfBbLbAtdu7flTCChX9I+mVg==", "dependencies": { - "@types/node": "*" + "@smithy/node-config-provider": "^3.1.7", + "@smithy/property-provider": "^3.1.6", + "@smithy/types": "^3.4.2", + "@smithy/url-parser": "^3.0.6", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/eccrypto": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@types/eccrypto/-/eccrypto-1.1.6.tgz", - "integrity": "sha512-rsmcX5LdDZ3xN2W3al6+YR+XNmiQWlXSwVhsU184QOwNQNJ83YpwvAt8a7cT7y3RpVWkKWmXoIFdanI/z38rNQ==", - "license": "MIT", + "node_modules/@smithy/fetch-http-handler": { + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.8.tgz", + "integrity": "sha512-Lqe0B8F5RM7zkw//6avq1SJ8AfaRd3ubFUS1eVp5WszV7p6Ne5hQ4dSuMHDpNRPhgTvj4va9Kd/pcVigHEHRow==", "dependencies": { - "@types/expect": "^1.20.4", - "@types/node": "*" + "@smithy/protocol-http": "^4.1.3", + "@smithy/querystring-builder": "^3.0.6", + "@smithy/types": "^3.4.2", + "@smithy/util-base64": "^3.0.0", + "tslib": "^2.6.2" } }, - "node_modules/@types/elliptic": { - "version": "6.4.18", - "resolved": "https://registry.npmjs.org/@types/elliptic/-/elliptic-6.4.18.tgz", - "integrity": "sha512-UseG6H5vjRiNpQvrhy4VF/JXdA3V/Fp5amvveaL+fs28BZ6xIKJBPnUPRlEaZpysD9MbpfaLi8lbl7PGUAkpWw==", - "license": "MIT", + "node_modules/@smithy/hash-node": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-3.0.6.tgz", + "integrity": "sha512-c/FHEdKK/7DU2z6ZE91L36ahyXWayR3B+FzELjnYq7wH5YqIseM24V+pWCS9kFn1Ln8OFGTf+pyYPiHZuX0s/Q==", "dependencies": { - "@types/bn.js": "*" + "@smithy/types": "^3.4.2", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/eslint": { - "version": "8.56.10", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", - "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==", + "node_modules/@smithy/invalid-dependency": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-3.0.6.tgz", + "integrity": "sha512-czM7Ioq3s8pIXht7oD+vmgy4Wfb4XavU/k/irO8NdXFFOx7YAlsCCcKOh/lJD1mJSYQqiR7NmpZ9JviryD/7AQ==", "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" } }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" - }, - "node_modules/@types/estree-jsx": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", - "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "node_modules/@smithy/middleware-content-length": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-3.0.8.tgz", + "integrity": "sha512-VuyszlSO49WKh3H9/kIO2kf07VUwGV80QRiaDxUfP8P8UKlokz381ETJvwLhwuypBYhLymCYyNhB3fLAGBX2og==", "dependencies": { - "@types/estree": "*" + "@smithy/protocol-http": "^4.1.3", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/ethereumjs-util": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@types/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", - "integrity": "sha512-qwQgQqXXTRv2h2AlJef+tMEszLFkCB9dWnrJYIdAwqjubERXEc/geB+S3apRw0yQyTVnsBf8r6BhlrE8vx+3WQ==", - "license": "MIT", + "node_modules/@smithy/middleware-endpoint": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.1.3.tgz", + "integrity": "sha512-KeM/OrK8MVFUsoJsmCN0MZMVPjKKLudn13xpgwIMpGTYpA8QZB2Xq5tJ+RE6iu3A6NhOI4VajDTwBsm8pwwrhg==", "dependencies": { - "@types/bn.js": "*", - "@types/node": "*" + "@smithy/middleware-serde": "^3.0.6", + "@smithy/node-config-provider": "^3.1.7", + "@smithy/shared-ini-file-loader": "^3.1.7", + "@smithy/types": "^3.4.2", + "@smithy/url-parser": "^3.0.6", + "@smithy/util-middleware": "^3.0.6", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/eventsource": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/@types/eventsource/-/eventsource-1.1.15.tgz", - "integrity": "sha512-XQmGcbnxUNa06HR3VBVkc9+A2Vpi9ZyLJcdS5dwaQQ/4ZMWFO+5c90FnMUpbtMZwB/FChoYHwuVg8TvkECacTA==", - "license": "MIT" - }, - "node_modules/@types/expect": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/@types/expect/-/expect-1.20.4.tgz", - "integrity": "sha512-Q5Vn3yjTDyCMV50TB6VRIbQNxSE4OmZR86VSbGaNpfUolm0iePBB4KdEEHmxoY5sT2+2DIvXW0rvMDP2nHZ4Mg==", - "license": "MIT" - }, - "node_modules/@types/express": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", - "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "node_modules/@smithy/middleware-retry": { + "version": "3.0.20", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.20.tgz", + "integrity": "sha512-HELCOVwYw5hFDBm69d+LmmGjBCjWnwp/t7SJiHmp+c4u9vgfIaCjdSeIdnlOsLrr5ic5jGTJXvJFUQnd987b/g==", "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" + "@smithy/node-config-provider": "^3.1.7", + "@smithy/protocol-http": "^4.1.3", + "@smithy/service-error-classification": "^3.0.6", + "@smithy/smithy-client": "^3.3.4", + "@smithy/types": "^3.4.2", + "@smithy/util-middleware": "^3.0.6", + "@smithy/util-retry": "^3.0.6", + "tslib": "^2.6.2", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/express-serve-static-core": { - "version": "4.19.5", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz", - "integrity": "sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==", + "node_modules/@smithy/middleware-serde": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.6.tgz", + "integrity": "sha512-KKTUSl1MzOM0MAjGbudeaVNtIDo+PpekTBkCNwvfZlKndodrnvRo+00USatiyLOc0ujjO9UydMRu3O9dYML7ag==", "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/graceful-fs": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", - "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "node_modules/@smithy/middleware-stack": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.6.tgz", + "integrity": "sha512-2c0eSYhTQ8xQqHMcRxLMpadFbTXg6Zla5l0mwNftFCZMQmuhI7EbAJMx6R5eqfuV3YbJ3QGyS3d5uSmrHV8Khg==", "dependencies": { - "@types/node": "*" + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/gtag.js": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/@types/gtag.js/-/gtag.js-0.0.12.tgz", - "integrity": "sha512-YQV9bUsemkzG81Ea295/nF/5GijnD2Af7QhEofh7xu+kvCN6RdodgNwwGWXB5GMI3NoyvQo0odNctoH/qLMIpg==" - }, - "node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "node_modules/@smithy/node-config-provider": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.7.tgz", + "integrity": "sha512-g3mfnC3Oo8pOI0dYuPXLtdW1WGVb3bR2tkV21GNkm0ZvQjLTtamXAwCWt/FCb0HGvKt3gHHmF1XerG0ICfalOg==", "dependencies": { - "@types/unist": "*" + "@smithy/property-provider": "^3.1.6", + "@smithy/shared-ini-file-loader": "^3.1.7", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/history": { - "version": "4.7.11", - "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", - "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==" - }, - "node_modules/@types/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==" - }, - "node_modules/@types/http-cache-semantics": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", - "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==" - }, - "node_modules/@types/http-errors": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==" - }, - "node_modules/@types/http-proxy": { - "version": "1.17.14", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", - "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", + "node_modules/@smithy/node-http-handler": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.2.3.tgz", + "integrity": "sha512-/gcm5DJ3k1b1zEInzBGAZC8ntJ+jwrz1NcSIu+9dSXd1FfG0G6QgkDI40tt8/WYUbHtLyo8fEqtm2v29koWo/w==", "dependencies": { - "@types/node": "*" + "@smithy/abort-controller": "^3.1.4", + "@smithy/protocol-http": "^4.1.3", + "@smithy/querystring-builder": "^3.0.6", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==" - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", - "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "node_modules/@smithy/property-provider": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.6.tgz", + "integrity": "sha512-NK3y/T7Q/Bw+Z8vsVs9MYIQ5v7gOX7clyrXcwhhIBQhbPgRl6JDrZbusO9qWDhcEus75Tg+VCxtIRfo3H76fpw==", "dependencies": { - "@types/istanbul-lib-coverage": "*" + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", - "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "node_modules/@smithy/protocol-http": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.3.tgz", + "integrity": "sha512-GcbMmOYpH9iRqtC05RbRnc/0FssxSTHlmaNhYBTgSgNCYpdR3Kt88u5GAZTBmouzv+Zlj/VRv92J9ruuDeJuEw==", "dependencies": { - "@types/istanbul-lib-report": "*" + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/jest": { - "version": "29.5.12", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", - "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", - "dev": true, + "node_modules/@smithy/querystring-builder": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.6.tgz", + "integrity": "sha512-sQe08RunoObe+Usujn9+R2zrLuQERi3CWvRO3BvnoWSYUaIrLKuAIeY7cMeDax6xGyfIP3x/yFWbEKSXvOnvVg==", "dependencies": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" + "@smithy/types": "^3.4.2", + "@smithy/util-uri-escape": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/jest/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" + "node_modules/@smithy/querystring-parser": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.6.tgz", + "integrity": "sha512-UJKw4LlEkytzz2Wq+uIdHf6qOtFfee/o7ruH0jF5I6UAuU+19r9QV7nU3P/uI0l6+oElRHmG/5cBBcGJrD7Ozg==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/jest/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, + "node_modules/@smithy/service-error-classification": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-3.0.6.tgz", + "integrity": "sha512-53SpchU3+DUZrN7J6sBx9tBiCVGzsib2e4sc512Q7K9fpC5zkJKs6Z9s+qbMxSYrkEkle6hnMtrts7XNkMJJMg==", "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" + "@smithy/types": "^3.4.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=16.0.0" } }, - "node_modules/@types/jest/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true - }, - "node_modules/@types/jsdom": { - "version": "20.0.1", - "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz", - "integrity": "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==", - "dev": true, + "node_modules/@smithy/shared-ini-file-loader": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.7.tgz", + "integrity": "sha512-IA4K2qTJYXkF5OfVN4vsY1hfnUZjaslEE8Fsr/gGFza4TAC2A9NfnZuSY2srQIbt9bwtjHiAayrRVgKse4Q7fA==", "dependencies": { - "@types/node": "*", - "@types/tough-cookie": "*", - "parse5": "^7.0.0" + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/jsdom/node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dev": true, + "node_modules/@smithy/signature-v4": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-4.1.4.tgz", + "integrity": "sha512-72MiK7xYukNsnLJI9NqvUHqTu0ziEsfMsYNlWpiJfuGQnCTFKpckThlEatirvcA/LmT1h7rRO+pJD06PYsPu9Q==", "dependencies": { - "entities": "^4.4.0" + "@smithy/is-array-buffer": "^3.0.0", + "@smithy/protocol-http": "^4.1.3", + "@smithy/types": "^3.4.2", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-middleware": "^3.0.6", + "@smithy/util-uri-escape": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true - }, - "node_modules/@types/keyv": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", - "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", - "license": "MIT", + "node_modules/@smithy/smithy-client": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.3.4.tgz", + "integrity": "sha512-NKw/2XxOW/Rg3rzB90HxsmGok5oS6vRzJgMh/JN4BHaOQQ4q5OuX999GmOGxEp730wbpIXIowfKZmIMXkG4v0Q==", "dependencies": { - "@types/node": "*" + "@smithy/middleware-endpoint": "^3.1.3", + "@smithy/middleware-stack": "^3.0.6", + "@smithy/protocol-http": "^4.1.3", + "@smithy/types": "^3.4.2", + "@smithy/util-stream": "^3.1.8", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/linkify-it": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", - "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", - "license": "MIT" - }, - "node_modules/@types/lodash": { - "version": "4.17.7", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.7.tgz", - "integrity": "sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==" - }, - "node_modules/@types/long": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", - "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==", - "license": "MIT" - }, - "node_modules/@types/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==" - }, - "node_modules/@types/markdown-it": { - "version": "14.1.2", - "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", - "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", - "license": "MIT", + "node_modules/@smithy/types": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.4.2.tgz", + "integrity": "sha512-tHiFcfcVedVBHpmHUEUHOCCih8iZbIAYn9NvPsNzaPm/237I3imdDdZoOC8c87H5HBAVEa06tTgb+OcSWV9g5w==", "dependencies": { - "@types/linkify-it": "^5", - "@types/mdurl": "^2" + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/mdast": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", - "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "node_modules/@smithy/url-parser": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.6.tgz", + "integrity": "sha512-47Op/NU8Opt49KyGpHtVdnmmJMsp2hEwBdyjuFB9M2V5QVOwA7pBhhxKN5z6ztKGrMw76gd8MlbPuzzvaAncuQ==", "dependencies": { - "@types/unist": "*" + "@smithy/querystring-parser": "^3.0.6", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" } }, - "node_modules/@types/mdurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", - "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", - "license": "MIT" - }, - "node_modules/@types/mdx": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", - "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==" - }, - "node_modules/@types/memcached": { - "version": "2.2.10", - "resolved": "https://registry.npmjs.org/@types/memcached/-/memcached-2.2.10.tgz", - "integrity": "sha512-AM9smvZN55Gzs2wRrqeMHVP7KE8KWgCJO/XL5yCly2xF6EKa4YlbpK+cLSAH4NG/Ah64HrlegmGqW8kYws7Vxg==", + "node_modules/@smithy/util-base64": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-3.0.0.tgz", + "integrity": "sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==", "dependencies": { - "@types/node": "*" + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/methods": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@types/methods/-/methods-1.1.4.tgz", - "integrity": "sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==", - "dev": true - }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==" - }, - "node_modules/@types/ms": { - "version": "0.7.34", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", - "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" - }, - "node_modules/@types/mysql": { - "version": "2.15.26", - "resolved": "https://registry.npmjs.org/@types/mysql/-/mysql-2.15.26.tgz", - "integrity": "sha512-DSLCOXhkvfS5WNNPbfn2KdICAmk8lLc+/PNvnPnF7gOdMZCxopXduqv0OQ13y/yA/zXTSikZZqVgybUxOEg6YQ==", + "node_modules/@smithy/util-body-length-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz", + "integrity": "sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ==", "dependencies": { - "@types/node": "*" + "tslib": "^2.6.2" } }, - "node_modules/@types/nock": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/@types/nock/-/nock-11.1.0.tgz", - "integrity": "sha512-jI/ewavBQ7X5178262JQR0ewicPAcJhXS/iFaNJl0VHLfyosZ/kwSrsa6VNQNSO8i9d8SqdRgOtZSOKJ/+iNMw==", - "deprecated": "This is a stub types definition. nock provides its own type definitions, so you do not need this installed.", - "dev": true, + "node_modules/@smithy/util-body-length-node": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-3.0.0.tgz", + "integrity": "sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA==", "dependencies": { - "nock": "*" + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/node": { - "version": "18.16.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.9.tgz", - "integrity": "sha512-IeB32oIV4oGArLrd7znD2rkHQ6EDCM+2Sr76dJnrHwv9OHBTTM6nuDLK9bmikXzPa0ZlWMWtRGo/Uw4mrzQedA==" - }, - "node_modules/@types/node-forge": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", - "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", "dependencies": { - "@types/node": "*" + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/parse-json": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", - "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" - }, - "node_modules/@types/pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew==", - "license": "MIT", + "node_modules/@smithy/util-config-provider": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz", + "integrity": "sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==", "dependencies": { - "@types/node": "*" + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/pg": { - "version": "8.6.1", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.6.1.tgz", - "integrity": "sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w==", + "node_modules/@smithy/util-defaults-mode-browser": { + "version": "3.0.20", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.20.tgz", + "integrity": "sha512-HpYmCpEThQJpCKzwzrGrklhdegRfuXI9keHRrHidbyEMliCdgic6t38MikJeZEkdIcEMhO1g95HIYMzjUzB+xg==", "dependencies": { - "@types/node": "*", - "pg-protocol": "*", - "pg-types": "^2.2.0" + "@smithy/property-provider": "^3.1.6", + "@smithy/smithy-client": "^3.3.4", + "@smithy/types": "^3.4.2", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">= 10.0.0" } }, - "node_modules/@types/pg-pool": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/pg-pool/-/pg-pool-2.0.6.tgz", - "integrity": "sha512-TaAUE5rq2VQYxab5Ts7WZhKNmuN78Q6PiFonTDdpbx8a1H0M1vhy3rhiMjl+e2iHmogyMw7jZF4FrE6eJUy5HQ==", + "node_modules/@smithy/util-defaults-mode-node": { + "version": "3.0.20", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.20.tgz", + "integrity": "sha512-atdsHNtAX0rwTvRRGsrONU0C0XzapH6tI8T1y/OReOvWN7uBwXqqWRft6m8egU2DgeReU0xqT3PHdGCe5VRaaQ==", "dependencies": { - "@types/pg": "*" + "@smithy/config-resolver": "^3.0.8", + "@smithy/credential-provider-imds": "^3.2.3", + "@smithy/node-config-provider": "^3.1.7", + "@smithy/property-provider": "^3.1.6", + "@smithy/smithy-client": "^3.3.4", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">= 10.0.0" } }, - "node_modules/@types/prismjs": { - "version": "1.26.4", - "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.4.tgz", - "integrity": "sha512-rlAnzkW2sZOjbqZ743IHUhFcvzaGbqijwOu8QZnZCjfQzBqFE3s4lOTJEsxikImav9uzz/42I+O7YUs1mWgMlg==" - }, - "node_modules/@types/prop-types": { - "version": "15.7.12", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", - "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==" - }, - "node_modules/@types/qs": { - "version": "6.9.15", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", - "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==" - }, - "node_modules/@types/randombytes": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/randombytes/-/randombytes-2.0.3.tgz", - "integrity": "sha512-+NRgihTfuURllWCiIAhm1wsJqzsocnqXM77V/CalsdJIYSRGEHMnritxh+6EsBklshC+clo1KgnN14qgSGeQdw==", - "license": "MIT", + "node_modules/@smithy/util-endpoints": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-2.1.2.tgz", + "integrity": "sha512-FEISzffb4H8DLzGq1g4MuDpcv6CIG15fXoQzDH9SjpRJv6h7J++1STFWWinilG0tQh9H1v2UKWG19Jjr2B16zQ==", "dependencies": { - "@types/node": "*" + "@smithy/node-config-provider": "^3.1.7", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==" - }, - "node_modules/@types/react": { - "version": "18.2.62", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.62.tgz", - "integrity": "sha512-l3f57BbaEKP0xcFzf+5qRG8/PXykZiuVM6eEoPtqBPCp6dxO3HhDkLIgIyXPhPKNAeXn3KO2pEaNgzaEo/asaw==", + "node_modules/@smithy/util-hex-encoding": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz", + "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==", "dependencies": { - "@types/prop-types": "*", - "@types/scheduler": "*", - "csstype": "^3.0.2" + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/react-dom": { - "version": "18.2.14", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.14.tgz", - "integrity": "sha512-V835xgdSVmyQmI1KLV2BEIUgqEuinxp9O4G6g3FqO/SqLac049E53aysv0oEFD2kHfejeKU+ZqL2bcFWj9gLAQ==", - "devOptional": true, + "node_modules/@smithy/util-middleware": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.6.tgz", + "integrity": "sha512-BxbX4aBhI1O9p87/xM+zWy0GzT3CEVcXFPBRDoHAM+pV0eSW156pR+PSYEz0DQHDMYDsYAflC2bQNz2uaDBUZQ==", "dependencies": { - "@types/react": "*" + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/react-router": { - "version": "5.1.20", - "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz", - "integrity": "sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==", + "node_modules/@smithy/util-retry": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.6.tgz", + "integrity": "sha512-BRZiuF7IwDntAbevqMco67an0Sr9oLQJqqRCsSPZZHYRnehS0LHDAkJk/pSmI7Z8c/1Vet294H7fY2fWUgB+Rg==", "dependencies": { - "@types/history": "^4.7.11", - "@types/react": "*" + "@smithy/service-error-classification": "^3.0.6", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/react-router-config": { - "version": "5.0.11", - "resolved": "https://registry.npmjs.org/@types/react-router-config/-/react-router-config-5.0.11.tgz", - "integrity": "sha512-WmSAg7WgqW7m4x8Mt4N6ZyKz0BubSj/2tVUMsAHp+Yd2AMwcSbeFq9WympT19p5heCFmF97R9eD5uUR/t4HEqw==", + "node_modules/@smithy/util-stream": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.1.8.tgz", + "integrity": "sha512-hoKOqSmb8FD3WLObuB5hwbM7bNIWgcnvkThokTvVq7J5PKjlLUK5qQQcB9zWLHIoSaIlf3VIv2OxZY2wtQjcRQ==", "dependencies": { - "@types/history": "^4.7.11", - "@types/react": "*", - "@types/react-router": "^5.1.0" + "@smithy/fetch-http-handler": "^3.2.8", + "@smithy/node-http-handler": "^3.2.3", + "@smithy/types": "^3.4.2", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/react-router-dom": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz", - "integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==", + "node_modules/@smithy/util-uri-escape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", + "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", "dependencies": { - "@types/history": "^4.7.11", - "@types/react": "*", - "@types/react-router": "*" + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/responselike": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", - "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", - "license": "MIT", + "node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", "dependencies": { - "@types/node": "*" + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" + "node_modules/@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" }, - "node_modules/@types/sax": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.7.tgz", - "integrity": "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==", + "node_modules/@stablelib/aead": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/aead/-/aead-1.0.1.tgz", + "integrity": "sha512-q39ik6sxGHewqtO0nP4BuSe3db5G1fEJE8ukvngS2gLkBXyy6E7pLubhbYgnkDFv6V8cWaxcE4Xn0t6LWcJkyg==" + }, + "node_modules/@stablelib/binary": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/binary/-/binary-1.0.1.tgz", + "integrity": "sha512-ClJWvmL6UBM/wjkvv/7m5VP3GMr9t0osr4yVgLZsLCOz4hGN9gIAFEqnJ0TsSMAN+n840nf2cHZnA5/KFqHC7Q==", "dependencies": { - "@types/node": "*" + "@stablelib/int": "^1.0.1" } }, - "node_modules/@types/scheduler": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.23.0.tgz", - "integrity": "sha512-YIoDCTH3Af6XM5VuwGG/QL/CJqga1Zm3NkU3HZ4ZHK2fRMPYP1VczsTUqtsf43PH/iJNVlPHAo2oWX7BSdB2Hw==" + "node_modules/@stablelib/bytes": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/bytes/-/bytes-1.0.1.tgz", + "integrity": "sha512-Kre4Y4kdwuqL8BR2E9hV/R5sOrUj6NanZaZis0V6lX5yzqC3hBuVSDXUIBqQv/sCpmuWRiHLwqiT1pqqjuBXoQ==" }, - "node_modules/@types/secp256k1": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.6.tgz", - "integrity": "sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==", - "license": "MIT", + "node_modules/@stablelib/chacha": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/chacha/-/chacha-1.0.1.tgz", + "integrity": "sha512-Pmlrswzr0pBzDofdFuVe1q7KdsHKhhU24e8gkEwnTGOmlC7PADzLVxGdn2PoNVBBabdg0l/IfLKg6sHAbTQugg==", "dependencies": { - "@types/node": "*" + "@stablelib/binary": "^1.0.1", + "@stablelib/wipe": "^1.0.1" } }, - "node_modules/@types/send": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", - "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "node_modules/@stablelib/chacha20poly1305": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/chacha20poly1305/-/chacha20poly1305-1.0.1.tgz", + "integrity": "sha512-MmViqnqHd1ymwjOQfghRKw2R/jMIGT3wySN7cthjXCBdO+qErNPUBnRzqNpnvIwg7JBCg3LdeCZZO4de/yEhVA==", "dependencies": { - "@types/mime": "^1", - "@types/node": "*" + "@stablelib/aead": "^1.0.1", + "@stablelib/binary": "^1.0.1", + "@stablelib/chacha": "^1.0.1", + "@stablelib/constant-time": "^1.0.1", + "@stablelib/poly1305": "^1.0.1", + "@stablelib/wipe": "^1.0.1" } }, - "node_modules/@types/serve-index": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", - "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", + "node_modules/@stablelib/constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/constant-time/-/constant-time-1.0.1.tgz", + "integrity": "sha512-tNOs3uD0vSJcK6z1fvef4Y+buN7DXhzHDPqRLSXUel1UfqMB1PWNsnnAezrKfEwTLpN0cGH2p9NNjs6IqeD0eg==" + }, + "node_modules/@stablelib/ed25519": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@stablelib/ed25519/-/ed25519-1.0.3.tgz", + "integrity": "sha512-puIMWaX9QlRsbhxfDc5i+mNPMY+0TmQEskunY1rZEBPi1acBCVQAhnsk/1Hk50DGPtVsZtAWQg4NHGlVaO9Hqg==", "dependencies": { - "@types/express": "*" + "@stablelib/random": "^1.0.2", + "@stablelib/sha512": "^1.0.1", + "@stablelib/wipe": "^1.0.1" } }, - "node_modules/@types/serve-static": { - "version": "1.15.7", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", - "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "node_modules/@stablelib/hash": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/hash/-/hash-1.0.1.tgz", + "integrity": "sha512-eTPJc/stDkdtOcrNMZ6mcMK1e6yBbqRBaNW55XA1jU8w/7QdnCF0CmMmOD1m7VSkBR44PWrMHU2l6r8YEQHMgg==" + }, + "node_modules/@stablelib/hkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/hkdf/-/hkdf-1.0.1.tgz", + "integrity": "sha512-SBEHYE16ZXlHuaW5RcGk533YlBj4grMeg5TooN80W3NpcHRtLZLLXvKyX0qcRFxf+BGDobJLnwkvgEwHIDBR6g==", "dependencies": { - "@types/http-errors": "*", - "@types/node": "*", - "@types/send": "*" + "@stablelib/hash": "^1.0.1", + "@stablelib/hmac": "^1.0.1", + "@stablelib/wipe": "^1.0.1" } }, - "node_modules/@types/sha.js": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/@types/sha.js/-/sha.js-2.4.4.tgz", - "integrity": "sha512-Qukd+D6S2Hm0wLVt2Vh+/eWBIoUt+wF8jWjBsG4F8EFQRwKtYvtXCPcNl2OEUQ1R+eTr3xuSaBYUyM3WD1x/Qw==", - "license": "MIT", + "node_modules/@stablelib/hmac": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/hmac/-/hmac-1.0.1.tgz", + "integrity": "sha512-V2APD9NSnhVpV/QMYgCVMIYKiYG6LSqw1S65wxVoirhU/51ACio6D4yDVSwMzuTJXWZoVHbDdINioBwKy5kVmA==", "dependencies": { - "@types/node": "*" + "@stablelib/constant-time": "^1.0.1", + "@stablelib/hash": "^1.0.1", + "@stablelib/wipe": "^1.0.1" } }, - "node_modules/@types/shimmer": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.2.0.tgz", - "integrity": "sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==" + "node_modules/@stablelib/int": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/int/-/int-1.0.1.tgz", + "integrity": "sha512-byr69X/sDtDiIjIV6m4roLVWnNNlRGzsvxw+agj8CIEazqWGOQp2dTYgQhtyVXV9wpO6WyXRQUzLV/JRNumT2w==" }, - "node_modules/@types/sockjs": { - "version": "0.3.36", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", - "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", + "node_modules/@stablelib/keyagreement": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/keyagreement/-/keyagreement-1.0.1.tgz", + "integrity": "sha512-VKL6xBwgJnI6l1jKrBAfn265cspaWBPAPEc62VBQrWHLqVgNRE09gQ/AnOEyKUWrrqfD+xSQ3u42gJjLDdMDQg==", "dependencies": { - "@types/node": "*" + "@stablelib/bytes": "^1.0.1" } }, - "node_modules/@types/stack-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", - "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==" - }, - "node_modules/@types/statuses": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.5.tgz", - "integrity": "sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/superagent": { - "version": "8.1.7", - "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.7.tgz", - "integrity": "sha512-NmIsd0Yj4DDhftfWvvAku482PZum4DBW7U51OvS8gvOkDDY0WT1jsVyDV3hK+vplrsYw8oDwi9QxOM7U68iwww==", - "dev": true, + "node_modules/@stablelib/poly1305": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/poly1305/-/poly1305-1.0.1.tgz", + "integrity": "sha512-1HlG3oTSuQDOhSnLwJRKeTRSAdFNVB/1djy2ZbS35rBSJ/PFqx9cf9qatinWghC2UbfOYD8AcrtbUQl8WoxabA==", "dependencies": { - "@types/cookiejar": "^2.1.5", - "@types/methods": "^1.1.4", - "@types/node": "*" + "@stablelib/constant-time": "^1.0.1", + "@stablelib/wipe": "^1.0.1" } }, - "node_modules/@types/supertest": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-6.0.2.tgz", - "integrity": "sha512-137ypx2lk/wTQbW6An6safu9hXmajAifU/s7szAHLN/FeIm5w7yR0Wkl9fdJMRSHwOn4HLAI0DaB2TOORuhPDg==", - "dev": true, + "node_modules/@stablelib/random": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@stablelib/random/-/random-1.0.2.tgz", + "integrity": "sha512-rIsE83Xpb7clHPVRlBj8qNe5L8ISQOzjghYQm/dZ7VaM2KHYwMW5adjQjrzTZCchFnNCNhkwtnOBa9HTMJCI8w==", "dependencies": { - "@types/methods": "^1.1.4", - "@types/superagent": "^8.1.0" + "@stablelib/binary": "^1.0.1", + "@stablelib/wipe": "^1.0.1" } }, - "node_modules/@types/tedious": { - "version": "4.0.14", - "resolved": "https://registry.npmjs.org/@types/tedious/-/tedious-4.0.14.tgz", - "integrity": "sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==", + "node_modules/@stablelib/sha256": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/sha256/-/sha256-1.0.1.tgz", + "integrity": "sha512-GIIH3e6KH+91FqGV42Kcj71Uefd/QEe7Dy42sBTeqppXV95ggCcxLTk39bEr+lZfJmp+ghsR07J++ORkRELsBQ==", "dependencies": { - "@types/node": "*" + "@stablelib/binary": "^1.0.1", + "@stablelib/hash": "^1.0.1", + "@stablelib/wipe": "^1.0.1" } }, - "node_modules/@types/tough-cookie": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", - "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", - "dev": true - }, - "node_modules/@types/traverse": { - "version": "0.6.37", - "resolved": "https://registry.npmjs.org/@types/traverse/-/traverse-0.6.37.tgz", - "integrity": "sha512-c90MVeDiUI1FhOZ6rLQ3kDWr50YE8+paDpM+5zbHjbmsqEp2DlMYkqnZnwbK9oI+NvDe8yRajup4jFwnVX6xsA==", - "dev": true + "node_modules/@stablelib/sha512": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/sha512/-/sha512-1.0.1.tgz", + "integrity": "sha512-13gl/iawHV9zvDKciLo1fQ8Bgn2Pvf7OV6amaRVKiq3pjQ3UmEpXxWiAfV8tYjUpeZroBxtyrwtdooQT/i3hzw==", + "dependencies": { + "@stablelib/binary": "^1.0.1", + "@stablelib/hash": "^1.0.1", + "@stablelib/wipe": "^1.0.1" + } }, - "node_modules/@types/triple-beam": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", - "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==" + "node_modules/@stablelib/wipe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/wipe/-/wipe-1.0.1.tgz", + "integrity": "sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg==" }, - "node_modules/@types/trusted-types": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", - "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==" + "node_modules/@stablelib/x25519": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@stablelib/x25519/-/x25519-1.0.3.tgz", + "integrity": "sha512-KnTbKmUhPhHavzobclVJQG5kuivH+qDLpe84iRqX3CLrKp881cF160JvXJ+hjn1aMyCwYOKeIZefIH/P5cJoRw==", + "dependencies": { + "@stablelib/keyagreement": "^1.0.1", + "@stablelib/random": "^1.0.2", + "@stablelib/wipe": "^1.0.1" + } }, - "node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@types/urijs": { - "version": "1.19.25", - "resolved": "https://registry.npmjs.org/@types/urijs/-/urijs-1.19.25.tgz", - "integrity": "sha512-XOfUup9r3Y06nFAZh3WvO0rBU4OtlfPB/vgxpjg+NRdGU6CN6djdc6OEiH+PcqHCY6eFLo9Ista73uarf4gnBg==", - "license": "MIT" + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@types/utf8": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@types/utf8/-/utf8-2.1.6.tgz", - "integrity": "sha512-pRs2gYF5yoKYrgSaira0DJqVg2tFuF+Qjp838xS7K+mJyY2jJzjsrl6y17GbIa4uMRogMbxs+ghNCvKg6XyNrA==", - "license": "MIT" + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", + "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@types/uuid": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.7.tgz", - "integrity": "sha512-WUtIVRUZ9i5dYXefDEAI7sh9/O7jGvHg7Df/5O/gtH3Yabe5odI3UWopVR1qbPXQtvOxWu3mM4XxlYeZtMWF4g==", - "dev": true + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", + "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@types/validator": { - "version": "13.12.0", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.12.0.tgz", - "integrity": "sha512-nH45Lk7oPIJ1RVOF6JgFI6Dy0QpHEzq4QecZhvguxYPDwT8c93prCMqAtiIttm39voZ+DDR+qkNnMpJmMBRqag==" + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", + "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@types/ws": { - "version": "8.5.10", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", - "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", - "dependencies": { - "@types/node": "*" + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", + "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/yargs": { - "version": "17.0.32", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", - "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", - "dependencies": { - "@types/yargs-parser": "*" + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", + "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", - "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==" + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", + "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.0.tgz", - "integrity": "sha512-py1miT6iQpJcs1BiJjm54AMzeuMPBSPuKPlnT8HlfudbcS5rYeX5jajpLf3mrdRh9dA/Ec2FVUY0ifeVNDIhZw==", - "dev": true, + "node_modules/@svgr/babel-preset": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", + "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/type-utils": "7.16.0", - "@typescript-eslint/utils": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" + "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", + "@svgr/babel-plugin-transform-svg-component": "8.0.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": ">=14" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "type": "github", + "url": "https://github.com/sponsors/gregberge" }, "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@typescript-eslint/parser": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.9.0.tgz", - "integrity": "sha512-qHMJfkL5qvgQB2aLvhUSXxbK7OLnDkwPzFalg458pxQgfxKDfT1ZDbHQM/I6mDIf/svlMkj21kzKuQ2ixJlatQ==", - "dev": true, + "node_modules/@svgr/core": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", + "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", "dependencies": { - "@typescript-eslint/scope-manager": "7.9.0", - "@typescript-eslint/types": "7.9.0", - "@typescript-eslint/typescript-estree": "7.9.0", - "@typescript-eslint/visitor-keys": "7.9.0", - "debug": "^4.3.4" + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^8.1.3", + "snake-case": "^3.0.4" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": ">=14" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", + "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", + "dependencies": { + "@babel/types": "^7.21.3", + "entities": "^4.4.0" }, - "peerDependencies": { - "eslint": "^8.56.0" + "engines": { + "node": ">=14" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.9.0.tgz", - "integrity": "sha512-ZwPK4DeCDxr3GJltRz5iZejPFAAr4Wk3+2WIBaj1L5PYK5RgxExu/Y68FFVclN0y6GGwH8q+KgKRCvaTmFBbgQ==", - "dev": true, + "node_modules/@svgr/plugin-jsx": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", + "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", "dependencies": { - "@typescript-eslint/types": "7.9.0", - "@typescript-eslint/visitor-keys": "7.9.0" + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "@svgr/hast-util-to-babel-ast": "8.0.0", + "svg-parser": "^2.0.4" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": ">=14" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.9.0.tgz", - "integrity": "sha512-iESPx2TNLDNGQLyjKhUvIKprlP49XNEK+MvIf9nIO7ZZaZdbnfWKHnXAgufpxqfA0YryH8XToi4+CjBgVnFTSQ==", - "dev": true, + "node_modules/@svgr/plugin-svgo": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-8.1.0.tgz", + "integrity": "sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA==", "dependencies": { - "@typescript-eslint/types": "7.9.0", - "eslint-visitor-keys": "^3.4.3" + "cosmiconfig": "^8.1.3", + "deepmerge": "^4.3.1", + "svgo": "^3.0.2" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": ">=14" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.16.0.tgz", - "integrity": "sha512-8gVv3kW6n01Q6TrI1cmTZ9YMFi3ucDT7i7aI5lEikk2ebk1AEjrwX8MDTdaX5D7fPXMBLvnsaa0IFTAu+jcfOw==", - "dev": true, + "node_modules/@svgr/webpack": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.1.0.tgz", + "integrity": "sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==", "dependencies": { - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0" + "@babel/core": "^7.21.3", + "@babel/plugin-transform-react-constant-elements": "^7.21.3", + "@babel/preset-env": "^7.20.2", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.21.0", + "@svgr/core": "8.1.0", + "@svgr/plugin-jsx": "8.1.0", + "@svgr/plugin-svgo": "8.1.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": ">=14" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "type": "github", + "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/@typescript-eslint/scope-manager/node_modules/@typescript-eslint/types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", - "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", + "node_modules/@swc-node/core": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/@swc-node/core/-/core-1.13.3.tgz", + "integrity": "sha512-OGsvXIid2Go21kiNqeTIn79jcaX4l0G93X2rAnas4LFoDyA9wAwVK7xZdm+QsKoMn5Mus2yFLCc4OtX2dD/PWA==", "dev": true, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": ">= 10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@swc/core": ">= 1.4.13", + "@swc/types": ">= 0.1" } }, - "node_modules/@typescript-eslint/type-utils": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.0.tgz", - "integrity": "sha512-j0fuUswUjDHfqV/UdW6mLtOQQseORqfdmoBNDFOqs9rvNVR2e+cmu6zJu/Ku4SDuqiJko6YnhwcL8x45r8Oqxg==", + "node_modules/@swc-node/register": { + "version": "1.10.9", + "resolved": "https://registry.npmjs.org/@swc-node/register/-/register-1.10.9.tgz", + "integrity": "sha512-iXy2sjP0phPEpK2yivjRC3PAgoLaT4sjSk0LDWCTdcTBJmR4waEog0E6eJbvoOkLkOtWw37SB8vCkl/bbh4+8A==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.16.0", - "@typescript-eslint/utils": "7.16.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" + "@swc-node/core": "^1.13.3", + "@swc-node/sourcemap-support": "^0.5.1", + "colorette": "^2.0.20", + "debug": "^4.3.5", + "oxc-resolver": "^1.10.2", + "pirates": "^4.0.6", + "tslib": "^2.6.3" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" }, "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "@swc/core": ">= 1.4.13", + "typescript": ">= 4.3" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", - "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", + "node_modules/@swc-node/sourcemap-support": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@swc-node/sourcemap-support/-/sourcemap-support-0.5.1.tgz", + "integrity": "sha512-JxIvIo/Hrpv0JCHSyRpetAdQ6lB27oFYhv0PKCNf1g2gUXOjpeR1exrXccRxLMuAV5WAmGFBwRnNOJqN38+qtg==", + "dev": true, + "dependencies": { + "source-map-support": "^0.5.21", + "tslib": "^2.6.3" + } + }, + "node_modules/@swc-node/sourcemap-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=0.10.0" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.0.tgz", - "integrity": "sha512-a5NTvk51ZndFuOLCh5OaJBELYc2O3Zqxfl3Js78VFE1zE46J2AaVuW+rEbVkQznjkmlzWsUI15BG5tQMixzZLw==", + "node_modules/@swc-node/sourcemap-support/node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/@swc/core": { + "version": "1.7.26", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.7.26.tgz", + "integrity": "sha512-f5uYFf+TmMQyYIoxkn/evWhNGuUzC730dFwAKGwBVHHVoPyak1/GvJUm6i1SKl+2Hrj9oN0i3WSoWWZ4pgI8lw==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@swc/counter": "^0.1.3", + "@swc/types": "^0.1.12" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": ">=10" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.7.26", + "@swc/core-darwin-x64": "1.7.26", + "@swc/core-linux-arm-gnueabihf": "1.7.26", + "@swc/core-linux-arm64-gnu": "1.7.26", + "@swc/core-linux-arm64-musl": "1.7.26", + "@swc/core-linux-x64-gnu": "1.7.26", + "@swc/core-linux-x64-musl": "1.7.26", + "@swc/core-win32-arm64-msvc": "1.7.26", + "@swc/core-win32-ia32-msvc": "1.7.26", + "@swc/core-win32-x64-msvc": "1.7.26" + }, + "peerDependencies": { + "@swc/helpers": "*" }, "peerDependenciesMeta": { - "typescript": { + "@swc/helpers": { "optional": true } } }, - "node_modules/@typescript-eslint/type-utils/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "node_modules/@swc/core-darwin-arm64": { + "version": "1.7.26", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.26.tgz", + "integrity": "sha512-FF3CRYTg6a7ZVW4yT9mesxoVVZTrcSWtmZhxKCYJX9brH4CS/7PRPjAKNk6kzWgWuRoglP7hkjQcd6EpMcZEAw==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=10" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "node_modules/@swc/core-darwin-x64": { + "version": "1.7.26", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.7.26.tgz", + "integrity": "sha512-az3cibZdsay2HNKmc4bjf62QVukuiMRh5sfM5kHR/JMTrLyS6vSw7Ihs3UTkZjUxkLTT8ro54LI6sV6sUQUbLQ==", + "cpu": [ + "x64" + ], "dev": true, - "bin": { - "semver": "bin/semver.js" - }, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.7.26", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.7.26.tgz", + "integrity": "sha512-VYPFVJDO5zT5U3RpCdHE5v1gz4mmR8BfHecUZTmD2v1JeFY6fv9KArJUpjrHEEsjK/ucXkQFmJ0jaiWXmpOV9Q==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.7.26", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.7.26.tgz", + "integrity": "sha512-YKevOV7abpjcAzXrhsl+W48Z9mZvgoVs2eP5nY+uoMAdP2b3GxC0Df1Co0I90o2lkzO4jYBpTMcZlmUXLdXn+Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.7.26", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.7.26.tgz", + "integrity": "sha512-3w8iZICMkQQON0uIcvz7+Q1MPOW6hJ4O5ETjA0LSP/tuKqx30hIniCGOgPDnv3UTMruLUnQbtBwVCZTBKR3Rkg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.7.26", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.26.tgz", + "integrity": "sha512-c+pp9Zkk2lqb06bNGkR2Looxrs7FtGDMA4/aHjZcCqATgp348hOKH5WPvNLBl+yPrISuWjbKDVn3NgAvfvpH4w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.7.26", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.7.26.tgz", + "integrity": "sha512-PgtyfHBF6xG87dUSSdTJHwZ3/8vWZfNIXQV2GlwEpslrOkGqy+WaiiyE7Of7z9AvDILfBBBcJvJ/r8u980wAfQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.7.26", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.7.26.tgz", + "integrity": "sha512-9TNXPIJqFynlAOrRD6tUQjMq7KApSklK3R/tXgIxc7Qx+lWu8hlDQ/kVPLpU7PWvMMwC/3hKBW+p5f+Tms1hmA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.7.26", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.7.26.tgz", + "integrity": "sha512-9YngxNcG3177GYdsTum4V98Re+TlCeJEP4kEwEg9EagT5s3YejYdKwVAkAsJszzkXuyRDdnHUpYbTrPG6FiXrQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.7.26", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.26.tgz", + "integrity": "sha512-VR+hzg9XqucgLjXxA13MtV5O3C0bK0ywtLIBw/+a+O+Oc6mxFWHtdUeXDbIi5AiPbn0fjgVJMqYnyjGyyX8u0w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], "engines": { "node": ">=10" } }, - "node_modules/@typescript-eslint/types": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.9.0.tgz", - "integrity": "sha512-oZQD9HEWQanl9UfsbGVcZ2cGaR0YT5476xfWE0oE5kQa2sNK2frxOlkeacLOTh9po4AlUT5rtkGyYM5kew0z5w==", + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" + }, + "node_modules/@swc/helpers": { + "version": "0.5.11", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.11.tgz", + "integrity": "sha512-YNlnKRWF2sVojTpIyzwou9XoTNbzbzONwRhOoniEioF1AtaitTvVZblaQRrAzChWQ1bLYyYSWzM18y4WwgzJ+A==", "dev": true, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "dependencies": { + "tslib": "^2.4.0" } }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.9.0.tgz", - "integrity": "sha512-zBCMCkrb2YjpKV3LA0ZJubtKCDxLttxfdGmwZvTqqWevUPN0FZvSI26FalGFFUZU/9YQK/A4xcQF9o/VVaCKAg==", + "node_modules/@swc/types": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.12.tgz", + "integrity": "sha512-wBJA+SdtkbFhHjTMYH+dEH1y4VpfGdAc2Kw/LK09i9bXd/K6j6PkDcFCEzb6iVfZMkPRrl/q0e3toqTAJdkIVA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.9.0", - "@typescript-eslint/visitor-keys": "7.9.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "@swc/counter": "^0.1.3" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.9.0.tgz", - "integrity": "sha512-iESPx2TNLDNGQLyjKhUvIKprlP49XNEK+MvIf9nIO7ZZaZdbnfWKHnXAgufpxqfA0YryH8XToi4+CjBgVnFTSQ==", - "dev": true, + "node_modules/@szmarczak/http-timer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", + "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", "dependencies": { - "@typescript-eslint/types": "7.9.0", - "eslint-visitor-keys": "^3.4.3" + "defer-to-connect": "^2.0.1" }, "engines": { - "node": "^18.18.0 || >=20.0.0" - }, + "node": ">=14.16" + } + }, + "node_modules/@tanstack/query-core": { + "version": "5.51.9", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.51.9.tgz", + "integrity": "sha512-HsAwaY5J19MD18ykZDS3aVVh+bAt0i7m6uQlFC2b77DLV9djo+xEN7MWQAQQTR8IM+7r/zbozTQ7P0xr0bHuew==", "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, + "node_modules/@tanstack/react-query": { + "version": "5.51.11", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.51.11.tgz", + "integrity": "sha512-4Kq2x0XpDlpvSnaLG+8pHNH60zEc3mBvb3B2tOMDjcPCi/o+Du3p/9qpPLwJOTliVxxPJAP27fuIhLrsRdCr7A==", "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" + "@tanstack/query-core": "5.51.9" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18.0.0" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "node_modules/@testing-library/dom": { + "version": "9.3.4", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.4.tgz", + "integrity": "sha512-FlS4ZWlp97iiNWig0Muq8p+3rVDjRiYE+YKGbAqXOu9nwJFFOdL00kFpz42M+4huzYi86vAK1sOOfyOG45muIQ==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.1.3", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" }, "engines": { - "node": ">=10" + "node": ">=14" } }, - "node_modules/@typescript-eslint/utils": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz", - "integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==", + "node_modules/@testing-library/react": { + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-14.1.2.tgz", + "integrity": "sha512-z4p7DVBTPjKM5qDZ0t5ZjzkpSNb+fZy1u6bzO7kk8oeGagpPCAtgh4cx1syrfp7a+QWkM021jGqjJaxJJnXAZg==", "dev": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/typescript-estree": "7.16.0" + "@babel/runtime": "^7.12.5", + "@testing-library/dom": "^9.0.0", + "@types/react-dom": "^18.0.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=14" }, "peerDependencies": { - "eslint": "^8.56.0" + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", - "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", "dev": true, "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">= 10" } }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.0.tgz", - "integrity": "sha512-a5NTvk51ZndFuOLCh5OaJBELYc2O3Zqxfl3Js78VFE1zE46J2AaVuW+rEbVkQznjkmlzWsUI15BG5tQMixzZLw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, + "node_modules/@tootallnate/quickjs-emscripten": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", + "dev": true + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=10.13.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true + }, + "node_modules/@tybys/wasm-util": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", + "integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "tslib": "^2.4.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "node_modules/@types/acorn": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz", + "integrity": "sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==", + "dependencies": { + "@types/estree": "*" } }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.0.tgz", - "integrity": "sha512-rMo01uPy9C7XxG7AFsxa8zLnWXTF8N3PYclekWSrurvhwiw1eW88mrKiAYe6s53AUY57nTRz8dJsuuXdkAhzCg==", + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true + }, + "node_modules/@types/aws-lambda": { + "version": "8.10.143", + "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.143.tgz", + "integrity": "sha512-u5vzlcR14ge/4pMTTMDQr3MF0wEe38B2F9o84uC4F43vN5DGTy63npRrB6jQhyt+C0lGv4ZfiRcRkqJoZuPnmg==" + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bonjour": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/bunyan": { + "version": "1.8.9", + "resolved": "https://registry.npmjs.org/@types/bunyan/-/bunyan-1.8.9.tgz", + "integrity": "sha512-ZqS9JGpBxVOvsawzmVt30sP++gSQMTejCkIAQ3VdadOcRE8izTyW66hufvwLeH+YEGP6Js2AW7Gz+RMyvrEbmw==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/compression": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@types/compression/-/compression-1.7.5.tgz", + "integrity": "sha512-AAQvK5pxMpaT+nDvhHrsBhLSYG5yQdtkaJE1WYieSNY2mVFKAgmU4ks65rkZD5oqnGCFLyQpUr1CqI4DmUMyDg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.16.0", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "@types/express": "*" } }, - "node_modules/@typescript-eslint/visitor-keys/node_modules/@typescript-eslint/types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", - "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect-history-api-fallback": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", + "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "node_modules/@types/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", "dev": true, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "license": "MIT" + }, + "node_modules/@types/cookiejar": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.5.tgz", + "integrity": "sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==", + "dev": true + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dependencies": { + "@types/ms": "*" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" + "node_modules/@types/duplexify": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/@types/duplexify/-/duplexify-3.6.4.tgz", + "integrity": "sha512-2eahVPsd+dy3CL6FugAzJcxoraWhUghZGEQJns1kTKfCXWKJ5iG/VkaB05wRVrDKHfOFKqb0X0kXh91eE99RZg==", + "dependencies": { + "@types/node": "*" + } }, - "node_modules/@unimodules/core": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@unimodules/core/-/core-7.2.0.tgz", - "integrity": "sha512-Nu+bAd/xG4B2xyYMrmV3LnDr8czUQgV1XhoL3sOOMwGydDJtfpWNodGhPhEMyKq2CXo4X7DDIo8qG6W2fk6XAQ==", - "deprecated": "replaced by the 'expo' package, learn more: https://blog.expo.dev/whats-new-in-expo-modules-infrastructure-7a7cdda81ebc", - "license": "MIT", - "optional": true, + "node_modules/@types/eslint": { + "version": "8.56.10", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", + "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==", "dependencies": { - "expo-modules-core": "~0.4.0" + "@types/estree": "*", + "@types/json-schema": "*" } }, - "node_modules/@unimodules/core/node_modules/compare-versions": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", - "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", - "license": "MIT", - "optional": true + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } }, - "node_modules/@unimodules/core/node_modules/expo-modules-core": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-0.4.10.tgz", - "integrity": "sha512-uCZA3QzF0syRaHwYY99iaNhnye4vSQGsJ/y6IAiesXdbeVahWibX4G1KoKNPUyNsKXIM4tqA+4yByUSvJe4AAw==", - "license": "MIT", - "optional": true, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", "dependencies": { - "compare-versions": "^3.4.0", - "invariant": "^2.2.4" + "@types/estree": "*" } }, - "node_modules/@unimodules/react-native-adapter": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@unimodules/react-native-adapter/-/react-native-adapter-6.5.0.tgz", - "integrity": "sha512-F2J6gVw9a57DTVTQQunp64fqD4HVBkltOpUz1L5lEccNbQlZEA7SjnqKJzXakI7uPhhN76/n+SGb7ihzHw2swQ==", - "deprecated": "replaced by the 'expo' package, learn more: https://blog.expo.dev/whats-new-in-expo-modules-infrastructure-7a7cdda81ebc", - "license": "MIT", - "optional": true, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", "dependencies": { - "expo-modules-autolinking": "^0.3.2", - "expo-modules-core": "~0.4.0" + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" } }, - "node_modules/@unimodules/react-native-adapter/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 10" + "node_modules/@types/express-serve-static-core": { + "version": "4.19.5", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz", + "integrity": "sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/gtag.js": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/@types/gtag.js/-/gtag.js-0.0.12.tgz", + "integrity": "sha512-YQV9bUsemkzG81Ea295/nF/5GijnD2Af7QhEofh7xu+kvCN6RdodgNwwGWXB5GMI3NoyvQo0odNctoH/qLMIpg==" + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/history": { + "version": "4.7.11", + "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", + "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==" + }, + "node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==" + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==" + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==" + }, + "node_modules/@types/http-proxy": { + "version": "1.17.14", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", + "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dependencies": { + "@types/istanbul-lib-coverage": "*" } }, - "node_modules/@unimodules/react-native-adapter/node_modules/compare-versions": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", - "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", - "license": "MIT", - "optional": true - }, - "node_modules/@unimodules/react-native-adapter/node_modules/expo-modules-autolinking": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-0.3.4.tgz", - "integrity": "sha512-Mu3CIMqEAI8aNM18U/l+7CCi+afU8dERrKjDDEx/Hu7XX3v3FcnnP+NuWDLY/e9/ETzwTJaqoRoBuzhawsuLWw==", - "license": "MIT", - "optional": true, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", "dependencies": { - "chalk": "^4.1.0", - "commander": "^7.2.0", - "fast-glob": "^3.2.5", - "find-up": "~5.0.0", - "fs-extra": "^9.1.0" - }, - "bin": { - "expo-modules-autolinking": "bin/expo-modules-autolinking.js" + "@types/istanbul-lib-report": "*" } }, - "node_modules/@unimodules/react-native-adapter/node_modules/expo-modules-core": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-0.4.10.tgz", - "integrity": "sha512-uCZA3QzF0syRaHwYY99iaNhnye4vSQGsJ/y6IAiesXdbeVahWibX4G1KoKNPUyNsKXIM4tqA+4yByUSvJe4AAw==", - "license": "MIT", - "optional": true, + "node_modules/@types/jest": { + "version": "29.5.12", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", + "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", + "dev": true, "dependencies": { - "compare-versions": "^3.4.0", - "invariant": "^2.2.4" + "expect": "^29.0.0", + "pretty-format": "^29.0.0" } }, - "node_modules/@unimodules/react-native-adapter/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "license": "MIT", - "optional": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, + "node_modules/@types/jest/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@unimodules/react-native-adapter/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "license": "MIT", - "optional": true, + "node_modules/@types/jest/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "engines": { - "node": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@unimodules/react-native-adapter/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "license": "MIT", - "optional": true, + "node_modules/@types/jest/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, + "node_modules/@types/jsdom": { + "version": "20.0.1", + "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz", + "integrity": "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==", + "dev": true, "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "@types/node": "*", + "@types/tough-cookie": "*", + "parse5": "^7.0.0" } }, - "node_modules/@unimodules/react-native-adapter/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "license": "MIT", - "optional": true, + "node_modules/@types/jsdom/node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dev": true, "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" + "entities": "^4.4.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/@urql/core": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/@urql/core/-/core-2.3.6.tgz", - "integrity": "sha512-PUxhtBh7/8167HJK6WqBv6Z0piuiaZHQGYbhwpNL9aIQmLROPEdaUYkY4wh45wPQXcTpnd11l0q3Pw+TI11pdw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@graphql-typed-document-node/core": "^3.1.0", - "wonka": "^4.0.14" - }, - "peerDependencies": { - "graphql": "^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" - } + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" }, - "node_modules/@wagmi/connectors": { - "version": "5.3.9", - "resolved": "https://registry.npmjs.org/@wagmi/connectors/-/connectors-5.3.9.tgz", - "integrity": "sha512-TS1nJRfQbwPpeW28fPWkanuMuUJSoAAS0+zEthStq/PmwIDV4VKvOWycERgbl5pVeNtvdtHAstd7QtfhVADBXQ==", + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/@types/lodash": { + "version": "4.17.7", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.7.tgz", + "integrity": "sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==", + "dev": true + }, + "node_modules/@types/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==" + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", "dependencies": { - "@coinbase/wallet-sdk": "4.2.3", - "@metamask/sdk": "0.30.1", - "@safe-global/safe-apps-provider": "0.18.4", - "@safe-global/safe-apps-sdk": "9.1.0", - "@walletconnect/ethereum-provider": "2.17.0", - "cbw-sdk": "npm:@coinbase/wallet-sdk@3.9.3" - }, - "funding": { - "url": "https://github.com/sponsors/wevm" - }, - "peerDependencies": { - "@wagmi/core": "2.14.5", - "typescript": ">=5.0.4", - "viem": "2.x" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "@types/unist": "*" } }, - "node_modules/@wagmi/core": { - "version": "2.14.5", - "resolved": "https://registry.npmjs.org/@wagmi/core/-/core-2.14.5.tgz", - "integrity": "sha512-tkeZYWtBiITQhvKspX4diEEs44rVu+d+dd2DAL5lAeTGS9d/Iu2VAT1G04frnVv49DUPS6zUu6PkCcUpSwS8Xw==", + "node_modules/@types/mdx": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", + "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==" + }, + "node_modules/@types/memcached": { + "version": "2.2.10", + "resolved": "https://registry.npmjs.org/@types/memcached/-/memcached-2.2.10.tgz", + "integrity": "sha512-AM9smvZN55Gzs2wRrqeMHVP7KE8KWgCJO/XL5yCly2xF6EKa4YlbpK+cLSAH4NG/Ah64HrlegmGqW8kYws7Vxg==", "dependencies": { - "eventemitter3": "5.0.1", - "mipd": "0.0.7", - "zustand": "5.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/wevm" - }, - "peerDependencies": { - "@tanstack/query-core": ">=5.0.0", - "typescript": ">=5.0.4", - "viem": "2.x" - }, - "peerDependenciesMeta": { - "@tanstack/query-core": { - "optional": true - }, - "typescript": { - "optional": true - } + "@types/node": "*" } }, - "node_modules/@wagmi/core/node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" + "node_modules/@types/methods": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@types/methods/-/methods-1.1.4.tgz", + "integrity": "sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==", + "dev": true }, - "node_modules/@walletconnect/core": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/@walletconnect/core/-/core-2.17.0.tgz", - "integrity": "sha512-On+uSaCfWdsMIQsECwWHZBmUXfrnqmv6B8SXRRuTJgd8tUpEvBkLQH4X7XkSm3zW6ozEkQTCagZ2ox2YPn3kbw==", + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==" + }, + "node_modules/@types/ms": { + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" + }, + "node_modules/@types/mysql": { + "version": "2.15.26", + "resolved": "https://registry.npmjs.org/@types/mysql/-/mysql-2.15.26.tgz", + "integrity": "sha512-DSLCOXhkvfS5WNNPbfn2KdICAmk8lLc+/PNvnPnF7gOdMZCxopXduqv0OQ13y/yA/zXTSikZZqVgybUxOEg6YQ==", "dependencies": { - "@walletconnect/heartbeat": "1.2.2", - "@walletconnect/jsonrpc-provider": "1.0.14", - "@walletconnect/jsonrpc-types": "1.0.4", - "@walletconnect/jsonrpc-utils": "1.0.8", - "@walletconnect/jsonrpc-ws-connection": "1.0.14", - "@walletconnect/keyvaluestorage": "1.1.1", - "@walletconnect/logger": "2.1.2", - "@walletconnect/relay-api": "1.0.11", - "@walletconnect/relay-auth": "1.0.4", - "@walletconnect/safe-json": "1.0.2", - "@walletconnect/time": "1.0.2", - "@walletconnect/types": "2.17.0", - "@walletconnect/utils": "2.17.0", - "events": "3.3.0", - "lodash.isequal": "4.5.0", - "uint8arrays": "3.1.0" - }, - "engines": { - "node": ">=18" + "@types/node": "*" } }, - "node_modules/@walletconnect/environment": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@walletconnect/environment/-/environment-1.0.1.tgz", - "integrity": "sha512-T426LLZtHj8e8rYnKfzsw1aG6+M0BT1ZxayMdv/p8yM0MU+eJDISqNY3/bccxRr4LrF9csq02Rhqt08Ibl0VRg==", + "node_modules/@types/nock": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@types/nock/-/nock-11.1.0.tgz", + "integrity": "sha512-jI/ewavBQ7X5178262JQR0ewicPAcJhXS/iFaNJl0VHLfyosZ/kwSrsa6VNQNSO8i9d8SqdRgOtZSOKJ/+iNMw==", + "deprecated": "This is a stub types definition. nock provides its own type definitions, so you do not need this installed.", + "dev": true, "dependencies": { - "tslib": "1.14.1" + "nock": "*" } }, - "node_modules/@walletconnect/environment/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "node_modules/@types/node": { + "version": "18.16.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.9.tgz", + "integrity": "sha512-IeB32oIV4oGArLrd7znD2rkHQ6EDCM+2Sr76dJnrHwv9OHBTTM6nuDLK9bmikXzPa0ZlWMWtRGo/Uw4mrzQedA==" }, - "node_modules/@walletconnect/ethereum-provider": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/@walletconnect/ethereum-provider/-/ethereum-provider-2.17.0.tgz", - "integrity": "sha512-b+KTAXOb6JjoxkwpgYQQKPUcTwENGmdEdZoIDLeRicUmZTn/IQKfkMoC2frClB4YxkyoVMtj1oMV2JAax+yu9A==", + "node_modules/@types/node-forge": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", + "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", "dependencies": { - "@walletconnect/jsonrpc-http-connection": "1.0.8", - "@walletconnect/jsonrpc-provider": "1.0.14", - "@walletconnect/jsonrpc-types": "1.0.4", - "@walletconnect/jsonrpc-utils": "1.0.8", - "@walletconnect/modal": "2.7.0", - "@walletconnect/sign-client": "2.17.0", - "@walletconnect/types": "2.17.0", - "@walletconnect/universal-provider": "2.17.0", - "@walletconnect/utils": "2.17.0", - "events": "3.3.0" + "@types/node": "*" } }, - "node_modules/@walletconnect/events": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@walletconnect/events/-/events-1.0.1.tgz", - "integrity": "sha512-NPTqaoi0oPBVNuLv7qPaJazmGHs5JGyO8eEAk5VGKmJzDR7AHzD4k6ilox5kxk1iwiOnFopBOOMLs86Oa76HpQ==", + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" + }, + "node_modules/@types/pg": { + "version": "8.6.1", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.6.1.tgz", + "integrity": "sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w==", "dependencies": { - "keyvaluestorage-interface": "^1.0.0", - "tslib": "1.14.1" + "@types/node": "*", + "pg-protocol": "*", + "pg-types": "^2.2.0" } }, - "node_modules/@walletconnect/events/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/@walletconnect/heartbeat": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@walletconnect/heartbeat/-/heartbeat-1.2.2.tgz", - "integrity": "sha512-uASiRmC5MwhuRuf05vq4AT48Pq8RMi876zV8rr8cV969uTOzWdB/k+Lj5yI2PBtB1bGQisGen7MM1GcZlQTBXw==", + "node_modules/@types/pg-pool": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/pg-pool/-/pg-pool-2.0.6.tgz", + "integrity": "sha512-TaAUE5rq2VQYxab5Ts7WZhKNmuN78Q6PiFonTDdpbx8a1H0M1vhy3rhiMjl+e2iHmogyMw7jZF4FrE6eJUy5HQ==", "dependencies": { - "@walletconnect/events": "^1.0.1", - "@walletconnect/time": "^1.0.2", - "events": "^3.3.0" + "@types/pg": "*" } }, - "node_modules/@walletconnect/jsonrpc-http-connection": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-http-connection/-/jsonrpc-http-connection-1.0.8.tgz", - "integrity": "sha512-+B7cRuaxijLeFDJUq5hAzNyef3e3tBDIxyaCNmFtjwnod5AGis3RToNqzFU33vpVcxFhofkpE7Cx+5MYejbMGw==", + "node_modules/@types/prismjs": { + "version": "1.26.4", + "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.4.tgz", + "integrity": "sha512-rlAnzkW2sZOjbqZ743IHUhFcvzaGbqijwOu8QZnZCjfQzBqFE3s4lOTJEsxikImav9uzz/42I+O7YUs1mWgMlg==" + }, + "node_modules/@types/prop-types": { + "version": "15.7.12", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==" + }, + "node_modules/@types/qs": { + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", + "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==" + }, + "node_modules/@types/react": { + "version": "18.2.62", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.62.tgz", + "integrity": "sha512-l3f57BbaEKP0xcFzf+5qRG8/PXykZiuVM6eEoPtqBPCp6dxO3HhDkLIgIyXPhPKNAeXn3KO2pEaNgzaEo/asaw==", "dependencies": { - "@walletconnect/jsonrpc-utils": "^1.0.6", - "@walletconnect/safe-json": "^1.0.1", - "cross-fetch": "^3.1.4", - "events": "^3.3.0" + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" } }, - "node_modules/@walletconnect/jsonrpc-http-connection/node_modules/cross-fetch": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz", - "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==", + "node_modules/@types/react-dom": { + "version": "18.2.14", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.14.tgz", + "integrity": "sha512-V835xgdSVmyQmI1KLV2BEIUgqEuinxp9O4G6g3FqO/SqLac049E53aysv0oEFD2kHfejeKU+ZqL2bcFWj9gLAQ==", + "devOptional": true, "dependencies": { - "node-fetch": "^2.6.12" + "@types/react": "*" } }, - "node_modules/@walletconnect/jsonrpc-provider": { - "version": "1.0.14", - "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-provider/-/jsonrpc-provider-1.0.14.tgz", - "integrity": "sha512-rtsNY1XqHvWj0EtITNeuf8PHMvlCLiS3EjQL+WOkxEOA4KPxsohFnBDeyPYiNm4ZvkQdLnece36opYidmtbmow==", + "node_modules/@types/react-router": { + "version": "5.1.20", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz", + "integrity": "sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==", "dependencies": { - "@walletconnect/jsonrpc-utils": "^1.0.8", - "@walletconnect/safe-json": "^1.0.2", - "events": "^3.3.0" + "@types/history": "^4.7.11", + "@types/react": "*" } }, - "node_modules/@walletconnect/jsonrpc-types": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-types/-/jsonrpc-types-1.0.4.tgz", - "integrity": "sha512-P6679fG/M+wuWg9TY8mh6xFSdYnFyFjwFelxyISxMDrlbXokorEVXYOxiqEbrU3x1BmBoCAJJ+vtEaEoMlpCBQ==", + "node_modules/@types/react-router-config": { + "version": "5.0.11", + "resolved": "https://registry.npmjs.org/@types/react-router-config/-/react-router-config-5.0.11.tgz", + "integrity": "sha512-WmSAg7WgqW7m4x8Mt4N6ZyKz0BubSj/2tVUMsAHp+Yd2AMwcSbeFq9WympT19p5heCFmF97R9eD5uUR/t4HEqw==", "dependencies": { - "events": "^3.3.0", - "keyvaluestorage-interface": "^1.0.0" + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router": "^5.1.0" } }, - "node_modules/@walletconnect/jsonrpc-utils": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-utils/-/jsonrpc-utils-1.0.8.tgz", - "integrity": "sha512-vdeb03bD8VzJUL6ZtzRYsFMq1eZQcM3EAzT0a3st59dyLfJ0wq+tKMpmGH7HlB7waD858UWgfIcudbPFsbzVdw==", + "node_modules/@types/react-router-dom": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz", + "integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==", "dependencies": { - "@walletconnect/environment": "^1.0.1", - "@walletconnect/jsonrpc-types": "^1.0.3", - "tslib": "1.14.1" + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router": "*" } }, - "node_modules/@walletconnect/jsonrpc-utils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" }, - "node_modules/@walletconnect/jsonrpc-ws-connection": { - "version": "1.0.14", - "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-ws-connection/-/jsonrpc-ws-connection-1.0.14.tgz", - "integrity": "sha512-Jsl6fC55AYcbkNVkwNM6Jo+ufsuCQRqViOQ8ZBPH9pRREHH9welbBiszuTLqEJiQcO/6XfFDl6bzCJIkrEi8XA==", + "node_modules/@types/sax": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.7.tgz", + "integrity": "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==", "dependencies": { - "@walletconnect/jsonrpc-utils": "^1.0.6", - "@walletconnect/safe-json": "^1.0.2", - "events": "^3.3.0", - "ws": "^7.5.1" + "@types/node": "*" } }, - "node_modules/@walletconnect/jsonrpc-ws-connection/node_modules/ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } + "node_modules/@types/scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-YIoDCTH3Af6XM5VuwGG/QL/CJqga1Zm3NkU3HZ4ZHK2fRMPYP1VczsTUqtsf43PH/iJNVlPHAo2oWX7BSdB2Hw==" }, - "node_modules/@walletconnect/keyvaluestorage": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@walletconnect/keyvaluestorage/-/keyvaluestorage-1.1.1.tgz", - "integrity": "sha512-V7ZQq2+mSxAq7MrRqDxanTzu2RcElfK1PfNYiaVnJgJ7Q7G7hTVwF8voIBx92qsRyGHZihrwNPHuZd1aKkd0rA==", + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", "dependencies": { - "@walletconnect/safe-json": "^1.0.1", - "idb-keyval": "^6.2.1", - "unstorage": "^1.9.0" - }, - "peerDependencies": { - "@react-native-async-storage/async-storage": "1.x" - }, - "peerDependenciesMeta": { - "@react-native-async-storage/async-storage": { - "optional": true - } + "@types/mime": "^1", + "@types/node": "*" } }, - "node_modules/@walletconnect/logger": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@walletconnect/logger/-/logger-2.1.2.tgz", - "integrity": "sha512-aAb28I3S6pYXZHQm5ESB+V6rDqIYfsnHaQyzFbwUUBFY4H0OXx/YtTl8lvhUNhMMfb9UxbwEBS253TlXUYJWSw==", + "node_modules/@types/serve-index": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", "dependencies": { - "@walletconnect/safe-json": "^1.0.2", - "pino": "7.11.0" + "@types/express": "*" } }, - "node_modules/@walletconnect/modal": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@walletconnect/modal/-/modal-2.7.0.tgz", - "integrity": "sha512-RQVt58oJ+rwqnPcIvRFeMGKuXb9qkgSmwz4noF8JZGUym3gUAzVs+uW2NQ1Owm9XOJAV+sANrtJ+VoVq1ftElw==", + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", "dependencies": { - "@walletconnect/modal-core": "2.7.0", - "@walletconnect/modal-ui": "2.7.0" + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" } }, - "node_modules/@walletconnect/modal-core": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@walletconnect/modal-core/-/modal-core-2.7.0.tgz", - "integrity": "sha512-oyMIfdlNdpyKF2kTJowTixZSo0PGlCJRdssUN/EZdA6H6v03hZnf09JnwpljZNfir2M65Dvjm/15nGrDQnlxSA==", + "node_modules/@types/shimmer": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.2.0.tgz", + "integrity": "sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==" + }, + "node_modules/@types/sockjs": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", "dependencies": { - "valtio": "1.11.2" + "@types/node": "*" } }, - "node_modules/@walletconnect/modal-ui": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@walletconnect/modal-ui/-/modal-ui-2.7.0.tgz", - "integrity": "sha512-gERYvU7D7K1ANCN/8vUgsE0d2hnRemfAFZ2novm9aZBg7TEd/4EgB+AqbJ+1dc7GhOL6dazckVq78TgccHb7mQ==", + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==" + }, + "node_modules/@types/statuses": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.5.tgz", + "integrity": "sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/superagent": { + "version": "8.1.7", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.7.tgz", + "integrity": "sha512-NmIsd0Yj4DDhftfWvvAku482PZum4DBW7U51OvS8gvOkDDY0WT1jsVyDV3hK+vplrsYw8oDwi9QxOM7U68iwww==", + "dev": true, "dependencies": { - "@walletconnect/modal-core": "2.7.0", - "lit": "2.8.0", - "motion": "10.16.2", - "qrcode": "1.5.3" + "@types/cookiejar": "^2.1.5", + "@types/methods": "^1.1.4", + "@types/node": "*" } }, - "node_modules/@walletconnect/relay-api": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@walletconnect/relay-api/-/relay-api-1.0.11.tgz", - "integrity": "sha512-tLPErkze/HmC9aCmdZOhtVmYZq1wKfWTJtygQHoWtgg722Jd4homo54Cs4ak2RUFUZIGO2RsOpIcWipaua5D5Q==", + "node_modules/@types/supertest": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-6.0.2.tgz", + "integrity": "sha512-137ypx2lk/wTQbW6An6safu9hXmajAifU/s7szAHLN/FeIm5w7yR0Wkl9fdJMRSHwOn4HLAI0DaB2TOORuhPDg==", + "dev": true, "dependencies": { - "@walletconnect/jsonrpc-types": "^1.0.2" + "@types/methods": "^1.1.4", + "@types/superagent": "^8.1.0" } }, - "node_modules/@walletconnect/relay-auth": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@walletconnect/relay-auth/-/relay-auth-1.0.4.tgz", - "integrity": "sha512-kKJcS6+WxYq5kshpPaxGHdwf5y98ZwbfuS4EE/NkQzqrDFm5Cj+dP8LofzWvjrrLkZq7Afy7WrQMXdLy8Sx7HQ==", + "node_modules/@types/tedious": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/@types/tedious/-/tedious-4.0.14.tgz", + "integrity": "sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==", "dependencies": { - "@stablelib/ed25519": "^1.0.2", - "@stablelib/random": "^1.0.1", - "@walletconnect/safe-json": "^1.0.1", - "@walletconnect/time": "^1.0.2", - "tslib": "1.14.1", - "uint8arrays": "^3.0.0" + "@types/node": "*" } }, - "node_modules/@walletconnect/relay-auth/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "dev": true }, - "node_modules/@walletconnect/safe-json": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@walletconnect/safe-json/-/safe-json-1.0.2.tgz", - "integrity": "sha512-Ogb7I27kZ3LPC3ibn8ldyUr5544t3/STow9+lzz7Sfo808YD7SBWk7SAsdBFlYgP2zDRy2hS3sKRcuSRM0OTmA==", - "dependencies": { - "tslib": "1.14.1" - } + "node_modules/@types/traverse": { + "version": "0.6.37", + "resolved": "https://registry.npmjs.org/@types/traverse/-/traverse-0.6.37.tgz", + "integrity": "sha512-c90MVeDiUI1FhOZ6rLQ3kDWr50YE8+paDpM+5zbHjbmsqEp2DlMYkqnZnwbK9oI+NvDe8yRajup4jFwnVX6xsA==", + "dev": true }, - "node_modules/@walletconnect/safe-json/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "node_modules/@types/triple-beam": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", + "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==" }, - "node_modules/@walletconnect/sign-client": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/@walletconnect/sign-client/-/sign-client-2.17.0.tgz", - "integrity": "sha512-sErYwvSSHQolNXni47L3Bm10ptJc1s1YoJvJd34s5E9h9+d3rj7PrhbiW9X82deN+Dm5oA8X9tC4xty1yIBrVg==", + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==" + }, + "node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/@types/uuid": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.7.tgz", + "integrity": "sha512-WUtIVRUZ9i5dYXefDEAI7sh9/O7jGvHg7Df/5O/gtH3Yabe5odI3UWopVR1qbPXQtvOxWu3mM4XxlYeZtMWF4g==", + "dev": true + }, + "node_modules/@types/validator": { + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.12.0.tgz", + "integrity": "sha512-nH45Lk7oPIJ1RVOF6JgFI6Dy0QpHEzq4QecZhvguxYPDwT8c93prCMqAtiIttm39voZ+DDR+qkNnMpJmMBRqag==" + }, + "node_modules/@types/ws": { + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", + "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", "dependencies": { - "@walletconnect/core": "2.17.0", - "@walletconnect/events": "1.0.1", - "@walletconnect/heartbeat": "1.2.2", - "@walletconnect/jsonrpc-utils": "1.0.8", - "@walletconnect/logger": "2.1.2", - "@walletconnect/time": "1.0.2", - "@walletconnect/types": "2.17.0", - "@walletconnect/utils": "2.17.0", - "events": "3.3.0" + "@types/node": "*" } }, - "node_modules/@walletconnect/time": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@walletconnect/time/-/time-1.0.2.tgz", - "integrity": "sha512-uzdd9woDcJ1AaBZRhqy5rNC9laqWGErfc4dxA9a87mPdKOgWMD85mcFo9dIYIts/Jwocfwn07EC6EzclKubk/g==", + "node_modules/@types/yargs": { + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", + "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", "dependencies": { - "tslib": "1.14.1" + "@types/yargs-parser": "*" } }, - "node_modules/@walletconnect/time/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==" }, - "node_modules/@walletconnect/types": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/@walletconnect/types/-/types-2.17.0.tgz", - "integrity": "sha512-i1pn9URpvt9bcjRDkabuAmpA9K7mzyKoLJlbsAujRVX7pfaG7wur7u9Jz0bk1HxvuABL5LHNncTnVKSXKQ5jZA==", + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.0.tgz", + "integrity": "sha512-py1miT6iQpJcs1BiJjm54AMzeuMPBSPuKPlnT8HlfudbcS5rYeX5jajpLf3mrdRh9dA/Ec2FVUY0ifeVNDIhZw==", + "dev": true, "dependencies": { - "@walletconnect/events": "1.0.1", - "@walletconnect/heartbeat": "1.2.2", - "@walletconnect/jsonrpc-types": "1.0.4", - "@walletconnect/keyvaluestorage": "1.1.1", - "@walletconnect/logger": "2.1.2", - "events": "3.3.0" + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.16.0", + "@typescript-eslint/type-utils": "7.16.0", + "@typescript-eslint/utils": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@walletconnect/universal-provider": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/@walletconnect/universal-provider/-/universal-provider-2.17.0.tgz", - "integrity": "sha512-d3V5Be7AqLrvzcdMZSBS8DmGDRdqnyLk1DWmRKAGgR6ieUWykhhUKlvfeoZtvJrIXrY7rUGYpH1X41UtFkW5Pw==", + "node_modules/@typescript-eslint/parser": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.9.0.tgz", + "integrity": "sha512-qHMJfkL5qvgQB2aLvhUSXxbK7OLnDkwPzFalg458pxQgfxKDfT1ZDbHQM/I6mDIf/svlMkj21kzKuQ2ixJlatQ==", + "dev": true, "dependencies": { - "@walletconnect/jsonrpc-http-connection": "1.0.8", - "@walletconnect/jsonrpc-provider": "1.0.14", - "@walletconnect/jsonrpc-types": "1.0.4", - "@walletconnect/jsonrpc-utils": "1.0.8", - "@walletconnect/logger": "2.1.2", - "@walletconnect/sign-client": "2.17.0", - "@walletconnect/types": "2.17.0", - "@walletconnect/utils": "2.17.0", - "events": "3.3.0" + "@typescript-eslint/scope-manager": "7.9.0", + "@typescript-eslint/types": "7.9.0", + "@typescript-eslint/typescript-estree": "7.9.0", + "@typescript-eslint/visitor-keys": "7.9.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@walletconnect/utils": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/@walletconnect/utils/-/utils-2.17.0.tgz", - "integrity": "sha512-1aeQvjwsXy4Yh9G6g2eGmXrEl+BzkNjHRdCrGdMYqFTFa8ROEJfTGsSH3pLsNDlOY94CoBUvJvM55q/PMoN/FQ==", + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.9.0.tgz", + "integrity": "sha512-ZwPK4DeCDxr3GJltRz5iZejPFAAr4Wk3+2WIBaj1L5PYK5RgxExu/Y68FFVclN0y6GGwH8q+KgKRCvaTmFBbgQ==", + "dev": true, "dependencies": { - "@stablelib/chacha20poly1305": "1.0.1", - "@stablelib/hkdf": "1.0.1", - "@stablelib/random": "1.0.2", - "@stablelib/sha256": "1.0.1", - "@stablelib/x25519": "1.0.3", - "@walletconnect/relay-api": "1.0.11", - "@walletconnect/relay-auth": "1.0.4", - "@walletconnect/safe-json": "1.0.2", - "@walletconnect/time": "1.0.2", - "@walletconnect/types": "2.17.0", - "@walletconnect/window-getters": "1.0.1", - "@walletconnect/window-metadata": "1.0.1", - "detect-browser": "5.3.0", - "elliptic": "^6.5.7", - "query-string": "7.1.3", - "uint8arrays": "3.1.0" + "@typescript-eslint/types": "7.9.0", + "@typescript-eslint/visitor-keys": "7.9.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@walletconnect/window-getters": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@walletconnect/window-getters/-/window-getters-1.0.1.tgz", - "integrity": "sha512-vHp+HqzGxORPAN8gY03qnbTMnhqIwjeRJNOMOAzePRg4xVEEE2WvYsI9G2NMjOknA8hnuYbU3/hwLcKbjhc8+Q==", + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.9.0.tgz", + "integrity": "sha512-iESPx2TNLDNGQLyjKhUvIKprlP49XNEK+MvIf9nIO7ZZaZdbnfWKHnXAgufpxqfA0YryH8XToi4+CjBgVnFTSQ==", + "dev": true, "dependencies": { - "tslib": "1.14.1" + "@typescript-eslint/types": "7.9.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@walletconnect/window-getters/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/@walletconnect/window-metadata": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@walletconnect/window-metadata/-/window-metadata-1.0.1.tgz", - "integrity": "sha512-9koTqyGrM2cqFRW517BPY/iEtUDx2r1+Pwwu5m7sJ7ka79wi3EyqhqcICk/yDmv6jAS1rjKgTKXlEhanYjijcA==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.16.0.tgz", + "integrity": "sha512-8gVv3kW6n01Q6TrI1cmTZ9YMFi3ucDT7i7aI5lEikk2ebk1AEjrwX8MDTdaX5D7fPXMBLvnsaa0IFTAu+jcfOw==", + "dev": true, "dependencies": { - "@walletconnect/window-getters": "^1.0.1", - "tslib": "1.14.1" + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@walletconnect/window-metadata/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/@wasmer/wasi": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@wasmer/wasi/-/wasi-1.2.2.tgz", - "integrity": "sha512-39ZB3gefOVhBmkhf7Ta79RRSV/emIV8LhdvcWhP/MOZEjMmtzoZWMzt7phdKj8CUXOze+AwbvGK60lKaKldn1w==", - "license": "MIT" - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", - "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", - "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + "node_modules/@typescript-eslint/scope-manager/node_modules/@typescript-eslint/types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", + "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", + "dev": true, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", - "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==" - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "node_modules/@typescript-eslint/type-utils": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.0.tgz", + "integrity": "sha512-j0fuUswUjDHfqV/UdW6mLtOQQseORqfdmoBNDFOqs9rvNVR2e+cmu6zJu/Ku4SDuqiJko6YnhwcL8x45r8Oqxg==", + "dev": true, "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@xtuc/long": "4.2.2" + "@typescript-eslint/typescript-estree": "7.16.0", + "@typescript-eslint/utils": "7.16.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", - "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.12.1" + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", + "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", + "dev": true, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.0.tgz", + "integrity": "sha512-a5NTvk51ZndFuOLCh5OaJBELYc2O3Zqxfl3Js78VFE1zE46J2AaVuW+rEbVkQznjkmlzWsUI15BG5tQMixzZLw==", + "dev": true, "dependencies": { - "@xtuc/ieee754": "^1.2.0" + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "node_modules/@typescript-eslint/type-utils/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, "dependencies": { - "@xtuc/long": "4.2.2" + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", - "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-opt": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1", - "@webassemblyjs/wast-printer": "1.12.1" + "node_modules/@typescript-eslint/type-utils/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", - "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "node_modules/@typescript-eslint/types": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.9.0.tgz", + "integrity": "sha512-oZQD9HEWQanl9UfsbGVcZ2cGaR0YT5476xfWE0oE5kQa2sNK2frxOlkeacLOTh9po4AlUT5rtkGyYM5kew0z5w==", + "dev": true, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", - "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.9.0.tgz", + "integrity": "sha512-zBCMCkrb2YjpKV3LA0ZJubtKCDxLttxfdGmwZvTqqWevUPN0FZvSI26FalGFFUZU/9YQK/A4xcQF9o/VVaCKAg==", + "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1" + "@typescript-eslint/types": "7.9.0", + "@typescript-eslint/visitor-keys": "7.9.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", - "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/visitor-keys": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.9.0.tgz", + "integrity": "sha512-iESPx2TNLDNGQLyjKhUvIKprlP49XNEK+MvIf9nIO7ZZaZdbnfWKHnXAgufpxqfA0YryH8XToi4+CjBgVnFTSQ==", + "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@typescript-eslint/types": "7.9.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", - "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@xtuc/long": "4.2.2" + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@xmldom/xmldom": { - "version": "0.7.13", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.13.tgz", - "integrity": "sha512-lm2GW5PkosIzccsaZIz7tp8cPADSIlIHWDFTR1N0SzfinhhYgeIQjFMz4rYzanCScr3DqQLeomUDArp6MWKm+g==", - "deprecated": "this version is no longer supported, please update to at least 0.8.*", - "license": "MIT", - "peer": true, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">=10.0.0" + "node": ">=10" } }, - "node_modules/@xrplf/isomorphic": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@xrplf/isomorphic/-/isomorphic-1.0.1.tgz", - "integrity": "sha512-0bIpgx8PDjYdrLFeC3csF305QQ1L7sxaWnL5y71mCvhenZzJgku9QsA+9QCXBC1eNYtxWO/xR91zrXJy2T/ixg==", - "license": "ISC", + "node_modules/@typescript-eslint/utils": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz", + "integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==", + "dev": true, "dependencies": { - "@noble/hashes": "^1.0.0", - "eventemitter3": "5.0.1", - "ws": "^8.13.0" + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.16.0", + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/typescript-estree": "7.16.0" }, "engines": { - "node": ">=16.0.0" + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" } }, - "node_modules/@xrplf/isomorphic/node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "license": "MIT" + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", + "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", + "dev": true, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } }, - "node_modules/@xrplf/secret-numbers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@xrplf/secret-numbers/-/secret-numbers-1.0.0.tgz", - "integrity": "sha512-qsCLGyqe1zaq9j7PZJopK+iGTGRbk6akkg6iZXJJgxKwck0C5x5Gnwlb1HKYGOwPKyrXWpV6a2YmcpNpUFctGg==", - "license": "ISC", + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.0.tgz", + "integrity": "sha512-a5NTvk51ZndFuOLCh5OaJBELYc2O3Zqxfl3Js78VFE1zE46J2AaVuW+rEbVkQznjkmlzWsUI15BG5tQMixzZLw==", + "dev": true, "dependencies": { - "@xrplf/isomorphic": "^1.0.0", - "ripple-keypairs": "^2.0.0" + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" - }, - "node_modules/@yarnpkg/lockfile": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", - "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", - "dev": true - }, - "node_modules/@yarnpkg/parsers": { - "version": "3.0.0-rc.46", - "resolved": "https://registry.npmjs.org/@yarnpkg/parsers/-/parsers-3.0.0-rc.46.tgz", - "integrity": "sha512-aiATs7pSutzda/rq8fnuPwTglyVwjM22bNnK2ZgjrpAjQHSSl3lztd2f9evst1W/qnC58DRz7T7QndUDumAR4Q==", + "node_modules/@typescript-eslint/utils/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "dependencies": { - "js-yaml": "^3.10.0", - "tslib": "^2.4.0" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=14.15.0" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@yarnpkg/parsers/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/@yarnpkg/parsers/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.0.tgz", + "integrity": "sha512-rMo01uPy9C7XxG7AFsxa8zLnWXTF8N3PYclekWSrurvhwiw1eW88mrKiAYe6s53AUY57nTRz8dJsuuXdkAhzCg==", "dev": true, "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "@typescript-eslint/types": "7.16.0", + "eslint-visitor-keys": "^3.4.3" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@yarnpkg/parsers/node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "node_modules/@zkochan/js-yaml": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.7.tgz", - "integrity": "sha512-nrUSn7hzt7J6JWgWGz78ZYI8wj+gdIJdk0Ynjpp8l+trkn58Uqsf6RYrYkEK+3X18EX+TNdtJI0WxAtc+L84SQ==", + "node_modules/@typescript-eslint/visitor-keys/node_modules/@typescript-eslint/types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", + "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", "dev": true, - "dependencies": { - "argparse": "^2.0.1" + "engines": { + "node": "^18.18.0 || >=20.0.0" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/abab": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "deprecated": "Use your platform's native atob() and btoa() methods instead", - "dev": true + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" }, - "node_modules/abitype": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.4.tgz", - "integrity": "sha512-UivtYZOGJGE8rsrM/N5vdRkUpqEZVmuTumfTuolm7m/6O09wprd958rx8kUBwVAAAhQDveGAgD0GJdBuR8s6tw==", + "node_modules/@wagmi/connectors": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/@wagmi/connectors/-/connectors-5.3.9.tgz", + "integrity": "sha512-TS1nJRfQbwPpeW28fPWkanuMuUJSoAAS0+zEthStq/PmwIDV4VKvOWycERgbl5pVeNtvdtHAstd7QtfhVADBXQ==", + "dependencies": { + "@coinbase/wallet-sdk": "4.2.3", + "@metamask/sdk": "0.30.1", + "@safe-global/safe-apps-provider": "0.18.4", + "@safe-global/safe-apps-sdk": "9.1.0", + "@walletconnect/ethereum-provider": "2.17.0", + "cbw-sdk": "npm:@coinbase/wallet-sdk@3.9.3" + }, "funding": { "url": "https://github.com/sponsors/wevm" }, "peerDependencies": { + "@wagmi/core": "2.14.5", "typescript": ">=5.0.4", - "zod": "^3 >=3.22.0" + "viem": "2.x" }, "peerDependenciesMeta": { "typescript": { "optional": true - }, - "zod": { - "optional": true } } }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "license": "MIT", + "node_modules/@wagmi/core": { + "version": "2.14.5", + "resolved": "https://registry.npmjs.org/@wagmi/core/-/core-2.14.5.tgz", + "integrity": "sha512-tkeZYWtBiITQhvKspX4diEEs44rVu+d+dd2DAL5lAeTGS9d/Iu2VAT1G04frnVv49DUPS6zUu6PkCcUpSwS8Xw==", "dependencies": { - "event-target-shim": "^5.0.0" + "eventemitter3": "5.0.1", + "mipd": "0.0.7", + "zustand": "5.0.0" }, - "engines": { - "node": ">=6.5" - } - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" + "funding": { + "url": "https://github.com/sponsors/wevm" }, - "engines": { - "node": ">= 0.6" + "peerDependencies": { + "@tanstack/query-core": ">=5.0.0", + "typescript": ">=5.0.4", + "viem": "2.x" + }, + "peerDependenciesMeta": { + "@tanstack/query-core": { + "optional": true + }, + "typescript": { + "optional": true + } } }, - "node_modules/acorn": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", - "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", - "bin": { - "acorn": "bin/acorn" + "node_modules/@wagmi/core/node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" + }, + "node_modules/@walletconnect/core": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/@walletconnect/core/-/core-2.17.0.tgz", + "integrity": "sha512-On+uSaCfWdsMIQsECwWHZBmUXfrnqmv6B8SXRRuTJgd8tUpEvBkLQH4X7XkSm3zW6ozEkQTCagZ2ox2YPn3kbw==", + "dependencies": { + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-provider": "1.0.14", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/jsonrpc-ws-connection": "1.0.14", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "2.1.2", + "@walletconnect/relay-api": "1.0.11", + "@walletconnect/relay-auth": "1.0.4", + "@walletconnect/safe-json": "1.0.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.17.0", + "@walletconnect/utils": "2.17.0", + "events": "3.3.0", + "lodash.isequal": "4.5.0", + "uint8arrays": "3.1.0" }, "engines": { - "node": ">=0.4.0" + "node": ">=18" } }, - "node_modules/acorn-globals": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", - "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", - "dev": true, + "node_modules/@walletconnect/environment": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@walletconnect/environment/-/environment-1.0.1.tgz", + "integrity": "sha512-T426LLZtHj8e8rYnKfzsw1aG6+M0BT1ZxayMdv/p8yM0MU+eJDISqNY3/bccxRr4LrF9csq02Rhqt08Ibl0VRg==", "dependencies": { - "acorn": "^8.1.0", - "acorn-walk": "^8.0.2" + "tslib": "1.14.1" } }, - "node_modules/acorn-import-attributes": { - "version": "1.9.5", - "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", - "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", - "peerDependencies": { - "acorn": "^8" - } + "node_modules/@walletconnect/environment/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + "node_modules/@walletconnect/ethereum-provider": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/@walletconnect/ethereum-provider/-/ethereum-provider-2.17.0.tgz", + "integrity": "sha512-b+KTAXOb6JjoxkwpgYQQKPUcTwENGmdEdZoIDLeRicUmZTn/IQKfkMoC2frClB4YxkyoVMtj1oMV2JAax+yu9A==", + "dependencies": { + "@walletconnect/jsonrpc-http-connection": "1.0.8", + "@walletconnect/jsonrpc-provider": "1.0.14", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/modal": "2.7.0", + "@walletconnect/sign-client": "2.17.0", + "@walletconnect/types": "2.17.0", + "@walletconnect/universal-provider": "2.17.0", + "@walletconnect/utils": "2.17.0", + "events": "3.3.0" } }, - "node_modules/acorn-walk": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", - "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", + "node_modules/@walletconnect/events": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@walletconnect/events/-/events-1.0.1.tgz", + "integrity": "sha512-NPTqaoi0oPBVNuLv7qPaJazmGHs5JGyO8eEAk5VGKmJzDR7AHzD4k6ilox5kxk1iwiOnFopBOOMLs86Oa76HpQ==", "dependencies": { - "acorn": "^8.11.0" - }, - "engines": { - "node": ">=0.4.0" + "keyvaluestorage-interface": "^1.0.0", + "tslib": "1.14.1" } }, - "node_modules/address": { + "node_modules/@walletconnect/events/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@walletconnect/heartbeat": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", - "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", - "engines": { - "node": ">= 10.0.0" + "resolved": "https://registry.npmjs.org/@walletconnect/heartbeat/-/heartbeat-1.2.2.tgz", + "integrity": "sha512-uASiRmC5MwhuRuf05vq4AT48Pq8RMi876zV8rr8cV969uTOzWdB/k+Lj5yI2PBtB1bGQisGen7MM1GcZlQTBXw==", + "dependencies": { + "@walletconnect/events": "^1.0.1", + "@walletconnect/time": "^1.0.2", + "events": "^3.3.0" } }, - "node_modules/adm-zip": { - "version": "0.5.15", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.15.tgz", - "integrity": "sha512-jYPWSeOA8EFoZnucrKCNihqBjoEGQSU4HKgHYQgKNEQ0pQF9a/DYuo/+fAxY76k4qe75LUlLWpAM1QWcBMTOKw==", - "dev": true, - "engines": { - "node": ">=12.0" + "node_modules/@walletconnect/jsonrpc-http-connection": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-http-connection/-/jsonrpc-http-connection-1.0.8.tgz", + "integrity": "sha512-+B7cRuaxijLeFDJUq5hAzNyef3e3tBDIxyaCNmFtjwnod5AGis3RToNqzFU33vpVcxFhofkpE7Cx+5MYejbMGw==", + "dependencies": { + "@walletconnect/jsonrpc-utils": "^1.0.6", + "@walletconnect/safe-json": "^1.0.1", + "cross-fetch": "^3.1.4", + "events": "^3.3.0" } }, - "node_modules/aes-js": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", - "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==", - "license": "MIT" + "node_modules/@walletconnect/jsonrpc-http-connection/node_modules/cross-fetch": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz", + "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==", + "dependencies": { + "node-fetch": "^2.6.12" + } }, - "node_modules/agent-base": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", - "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", - "engines": { - "node": ">= 14" + "node_modules/@walletconnect/jsonrpc-provider": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-provider/-/jsonrpc-provider-1.0.14.tgz", + "integrity": "sha512-rtsNY1XqHvWj0EtITNeuf8PHMvlCLiS3EjQL+WOkxEOA4KPxsohFnBDeyPYiNm4ZvkQdLnece36opYidmtbmow==", + "dependencies": { + "@walletconnect/jsonrpc-utils": "^1.0.8", + "@walletconnect/safe-json": "^1.0.2", + "events": "^3.3.0" } }, - "node_modules/agentkeepalive": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", - "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", - "license": "MIT", + "node_modules/@walletconnect/jsonrpc-types": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-types/-/jsonrpc-types-1.0.4.tgz", + "integrity": "sha512-P6679fG/M+wuWg9TY8mh6xFSdYnFyFjwFelxyISxMDrlbXokorEVXYOxiqEbrU3x1BmBoCAJJ+vtEaEoMlpCBQ==", "dependencies": { - "humanize-ms": "^1.2.1" - }, - "engines": { - "node": ">= 8.0.0" + "events": "^3.3.0", + "keyvaluestorage-interface": "^1.0.0" } }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "node_modules/@walletconnect/jsonrpc-utils": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-utils/-/jsonrpc-utils-1.0.8.tgz", + "integrity": "sha512-vdeb03bD8VzJUL6ZtzRYsFMq1eZQcM3EAzT0a3st59dyLfJ0wq+tKMpmGH7HlB7waD858UWgfIcudbPFsbzVdw==", "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" + "@walletconnect/environment": "^1.0.1", + "@walletconnect/jsonrpc-types": "^1.0.3", + "tslib": "1.14.1" } }, - "node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "node_modules/@walletconnect/jsonrpc-utils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@walletconnect/jsonrpc-ws-connection": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-ws-connection/-/jsonrpc-ws-connection-1.0.14.tgz", + "integrity": "sha512-Jsl6fC55AYcbkNVkwNM6Jo+ufsuCQRqViOQ8ZBPH9pRREHH9welbBiszuTLqEJiQcO/6XfFDl6bzCJIkrEi8XA==", "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "@walletconnect/jsonrpc-utils": "^1.0.6", + "@walletconnect/safe-json": "^1.0.2", + "events": "^3.3.0", + "ws": "^7.5.1" + } + }, + "node_modules/@walletconnect/jsonrpc-ws-connection/node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "engines": { + "node": ">=8.3.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, - "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "node_modules/@walletconnect/keyvaluestorage": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@walletconnect/keyvaluestorage/-/keyvaluestorage-1.1.1.tgz", + "integrity": "sha512-V7ZQq2+mSxAq7MrRqDxanTzu2RcElfK1PfNYiaVnJgJ7Q7G7hTVwF8voIBx92qsRyGHZihrwNPHuZd1aKkd0rA==", "dependencies": { - "ajv": "^8.0.0" + "@walletconnect/safe-json": "^1.0.1", + "idb-keyval": "^6.2.1", + "unstorage": "^1.9.0" }, "peerDependencies": { - "ajv": "^8.0.0" + "@react-native-async-storage/async-storage": "1.x" }, "peerDependenciesMeta": { - "ajv": { + "@react-native-async-storage/async-storage": { "optional": true } } }, - "node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "node_modules/@walletconnect/logger": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@walletconnect/logger/-/logger-2.1.2.tgz", + "integrity": "sha512-aAb28I3S6pYXZHQm5ESB+V6rDqIYfsnHaQyzFbwUUBFY4H0OXx/YtTl8lvhUNhMMfb9UxbwEBS253TlXUYJWSw==", "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/algo-msgpack-with-bigint": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/algo-msgpack-with-bigint/-/algo-msgpack-with-bigint-2.1.1.tgz", - "integrity": "sha512-F1tGh056XczEaEAqu7s+hlZUDWwOBT70Eq0lfMpBP2YguSQVyxRbprLq5rELXKQOyOaixTWYhMeMQMzP0U5FoQ==", - "license": "ISC", - "engines": { - "node": ">= 10" + "@walletconnect/safe-json": "^1.0.2", + "pino": "7.11.0" } }, - "node_modules/algoliasearch": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.24.0.tgz", - "integrity": "sha512-bf0QV/9jVejssFBmz2HQLxUadxk574t4iwjCKp5E7NBzwKkrDEhKPISIIjAU/p6K5qDx3qoeh4+26zWN1jmw3g==", + "node_modules/@walletconnect/modal": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@walletconnect/modal/-/modal-2.7.0.tgz", + "integrity": "sha512-RQVt58oJ+rwqnPcIvRFeMGKuXb9qkgSmwz4noF8JZGUym3gUAzVs+uW2NQ1Owm9XOJAV+sANrtJ+VoVq1ftElw==", "dependencies": { - "@algolia/cache-browser-local-storage": "4.24.0", - "@algolia/cache-common": "4.24.0", - "@algolia/cache-in-memory": "4.24.0", - "@algolia/client-account": "4.24.0", - "@algolia/client-analytics": "4.24.0", - "@algolia/client-common": "4.24.0", - "@algolia/client-personalization": "4.24.0", - "@algolia/client-search": "4.24.0", - "@algolia/logger-common": "4.24.0", - "@algolia/logger-console": "4.24.0", - "@algolia/recommend": "4.24.0", - "@algolia/requester-browser-xhr": "4.24.0", - "@algolia/requester-common": "4.24.0", - "@algolia/requester-node-http": "4.24.0", - "@algolia/transporter": "4.24.0" + "@walletconnect/modal-core": "2.7.0", + "@walletconnect/modal-ui": "2.7.0" } }, - "node_modules/algoliasearch-helper": { - "version": "3.22.3", - "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.22.3.tgz", - "integrity": "sha512-2eoEz8mG4KHE+DzfrBTrCmDPxVXv7aZZWPojAJFtARpxxMO6lkos1dJ+XDCXdPvq7q3tpYWRi6xXmVQikejtpA==", + "node_modules/@walletconnect/modal-core": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@walletconnect/modal-core/-/modal-core-2.7.0.tgz", + "integrity": "sha512-oyMIfdlNdpyKF2kTJowTixZSo0PGlCJRdssUN/EZdA6H6v03hZnf09JnwpljZNfir2M65Dvjm/15nGrDQnlxSA==", "dependencies": { - "@algolia/events": "^4.0.1" - }, - "peerDependencies": { - "algoliasearch": ">= 3.1 < 6" + "valtio": "1.11.2" } }, - "node_modules/algosdk": { - "version": "1.23.1", - "resolved": "https://registry.npmjs.org/algosdk/-/algosdk-1.23.1.tgz", - "integrity": "sha512-7fKyTd2V6rsac3ADm6N5jJV80cCw+EIBzXVLzfPvKqranjOZtq7xIqwpEkZgBkZ/TJ5wxwTDJVPyswXChv+QPg==", - "license": "MIT", + "node_modules/@walletconnect/modal-ui": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@walletconnect/modal-ui/-/modal-ui-2.7.0.tgz", + "integrity": "sha512-gERYvU7D7K1ANCN/8vUgsE0d2hnRemfAFZ2novm9aZBg7TEd/4EgB+AqbJ+1dc7GhOL6dazckVq78TgccHb7mQ==", "dependencies": { - "algo-msgpack-with-bigint": "^2.1.1", - "buffer": "^6.0.2", - "cross-fetch": "^3.1.5", - "hi-base32": "^0.5.1", - "js-sha256": "^0.9.0", - "js-sha3": "^0.8.0", - "js-sha512": "^0.8.0", - "json-bigint": "^1.0.0", - "tweetnacl": "^1.0.3", - "vlq": "^2.0.4" - }, - "engines": { - "node": ">=14.0.0" + "@walletconnect/modal-core": "2.7.0", + "lit": "2.8.0", + "motion": "10.16.2", + "qrcode": "1.5.3" } }, - "node_modules/algosdk/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", + "node_modules/@walletconnect/relay-api": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@walletconnect/relay-api/-/relay-api-1.0.11.tgz", + "integrity": "sha512-tLPErkze/HmC9aCmdZOhtVmYZq1wKfWTJtygQHoWtgg722Jd4homo54Cs4ak2RUFUZIGO2RsOpIcWipaua5D5Q==", "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" + "@walletconnect/jsonrpc-types": "^1.0.2" } }, - "node_modules/algosdk/node_modules/cross-fetch": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", - "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", - "license": "MIT", + "node_modules/@walletconnect/relay-auth": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@walletconnect/relay-auth/-/relay-auth-1.0.4.tgz", + "integrity": "sha512-kKJcS6+WxYq5kshpPaxGHdwf5y98ZwbfuS4EE/NkQzqrDFm5Cj+dP8LofzWvjrrLkZq7Afy7WrQMXdLy8Sx7HQ==", "dependencies": { - "node-fetch": "^2.7.0" + "@stablelib/ed25519": "^1.0.2", + "@stablelib/random": "^1.0.1", + "@walletconnect/safe-json": "^1.0.1", + "@walletconnect/time": "^1.0.2", + "tslib": "1.14.1", + "uint8arrays": "^3.0.0" } }, - "node_modules/algosdk/node_modules/vlq": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/vlq/-/vlq-2.0.4.tgz", - "integrity": "sha512-aodjPa2wPQFkra1G8CzJBTHXhgk3EVSwxSWXNPr1fgdFLUb8kvLV1iEb6rFgasIsjP82HWI6dsb5Io26DDnasA==", - "license": "MIT" - }, - "node_modules/anser": { - "version": "1.4.10", - "resolved": "https://registry.npmjs.org/anser/-/anser-1.4.10.tgz", - "integrity": "sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==", - "license": "MIT", - "peer": true + "node_modules/@walletconnect/relay-auth/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "node_modules/@walletconnect/safe-json": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@walletconnect/safe-json/-/safe-json-1.0.2.tgz", + "integrity": "sha512-Ogb7I27kZ3LPC3ibn8ldyUr5544t3/STow9+lzz7Sfo808YD7SBWk7SAsdBFlYgP2zDRy2hS3sKRcuSRM0OTmA==", "dependencies": { - "string-width": "^4.1.0" + "tslib": "1.14.1" } }, - "node_modules/ansi-align/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "node_modules/@walletconnect/safe-json/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, - "node_modules/ansi-align/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" + "node_modules/@walletconnect/sign-client": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/@walletconnect/sign-client/-/sign-client-2.17.0.tgz", + "integrity": "sha512-sErYwvSSHQolNXni47L3Bm10ptJc1s1YoJvJd34s5E9h9+d3rj7PrhbiW9X82deN+Dm5oA8X9tC4xty1yIBrVg==", + "dependencies": { + "@walletconnect/core": "2.17.0", + "@walletconnect/events": "1.0.1", + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/logger": "2.1.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.17.0", + "@walletconnect/utils": "2.17.0", + "events": "3.3.0" } }, - "node_modules/ansi-align/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/@walletconnect/time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@walletconnect/time/-/time-1.0.2.tgz", + "integrity": "sha512-uzdd9woDcJ1AaBZRhqy5rNC9laqWGErfc4dxA9a87mPdKOgWMD85mcFo9dIYIts/Jwocfwn07EC6EzclKubk/g==", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" + "tslib": "1.14.1" } }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true, - "engines": { - "node": ">=6" - } + "node_modules/@walletconnect/time/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "devOptional": true, + "node_modules/@walletconnect/types": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/@walletconnect/types/-/types-2.17.0.tgz", + "integrity": "sha512-i1pn9URpvt9bcjRDkabuAmpA9K7mzyKoLJlbsAujRVX7pfaG7wur7u9Jz0bk1HxvuABL5LHNncTnVKSXKQ5jZA==", "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "devOptional": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "@walletconnect/events": "1.0.1", + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "2.1.2", + "events": "3.3.0" } }, - "node_modules/ansi-html-community": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", - "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", - "engines": [ - "node >= 0.8.0" - ], - "bin": { - "ansi-html": "bin/ansi-html" + "node_modules/@walletconnect/universal-provider": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/@walletconnect/universal-provider/-/universal-provider-2.17.0.tgz", + "integrity": "sha512-d3V5Be7AqLrvzcdMZSBS8DmGDRdqnyLk1DWmRKAGgR6ieUWykhhUKlvfeoZtvJrIXrY7rUGYpH1X41UtFkW5Pw==", + "dependencies": { + "@walletconnect/jsonrpc-http-connection": "1.0.8", + "@walletconnect/jsonrpc-provider": "1.0.14", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/logger": "2.1.2", + "@walletconnect/sign-client": "2.17.0", + "@walletconnect/types": "2.17.0", + "@walletconnect/utils": "2.17.0", + "events": "3.3.0" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" + "node_modules/@walletconnect/utils": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/@walletconnect/utils/-/utils-2.17.0.tgz", + "integrity": "sha512-1aeQvjwsXy4Yh9G6g2eGmXrEl+BzkNjHRdCrGdMYqFTFa8ROEJfTGsSH3pLsNDlOY94CoBUvJvM55q/PMoN/FQ==", + "dependencies": { + "@stablelib/chacha20poly1305": "1.0.1", + "@stablelib/hkdf": "1.0.1", + "@stablelib/random": "1.0.2", + "@stablelib/sha256": "1.0.1", + "@stablelib/x25519": "1.0.3", + "@walletconnect/relay-api": "1.0.11", + "@walletconnect/relay-auth": "1.0.4", + "@walletconnect/safe-json": "1.0.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.17.0", + "@walletconnect/window-getters": "1.0.1", + "@walletconnect/window-metadata": "1.0.1", + "detect-browser": "5.3.0", + "elliptic": "^6.5.7", + "query-string": "7.1.3", + "uint8arrays": "3.1.0" } }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@walletconnect/window-getters": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@walletconnect/window-getters/-/window-getters-1.0.1.tgz", + "integrity": "sha512-vHp+HqzGxORPAN8gY03qnbTMnhqIwjeRJNOMOAzePRg4xVEEE2WvYsI9G2NMjOknA8hnuYbU3/hwLcKbjhc8+Q==", "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "tslib": "1.14.1" } }, - "node_modules/ansi-styles/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@walletconnect/window-getters/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@walletconnect/window-metadata": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@walletconnect/window-metadata/-/window-metadata-1.0.1.tgz", + "integrity": "sha512-9koTqyGrM2cqFRW517BPY/iEtUDx2r1+Pwwu5m7sJ7ka79wi3EyqhqcICk/yDmv6jAS1rjKgTKXlEhanYjijcA==", "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "@walletconnect/window-getters": "^1.0.1", + "tslib": "1.14.1" } }, - "node_modules/ansi-styles/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + "node_modules/@walletconnect/window-metadata/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "node_modules/@webassemblyjs/ast": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", + "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" } }, - "node_modules/append-field": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", - "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" - }, - "node_modules/application-config-path": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/application-config-path/-/application-config-path-0.1.1.tgz", - "integrity": "sha512-zy9cHePtMP0YhwG+CfHm0bgwdnga2X3gZexpdCwEj//dpb+TKajtiC8REEUJUSq6Ab4f9cgNy2l8ObXzCXFkEw==", - "license": "MIT", - "optional": true, - "peer": true + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" }, - "node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==" }, - "node_modules/aria-hidden": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.4.tgz", - "integrity": "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==", + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", "dependencies": { - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=10" + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" } }, - "node_modules/aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", - "dev": true, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", + "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", "dependencies": { - "deep-equal": "^2.0.5" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.12.1" } }, - "node_modules/arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", - "engines": { - "node": ">=0.10.0" + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dependencies": { + "@xtuc/ieee754": "^1.2.0" } }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", "dependencies": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@xtuc/long": "4.2.2" } }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" }, - "node_modules/array-includes": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", - "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", - "dev": true, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", + "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-opt": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1", + "@webassemblyjs/wast-printer": "1.12.1" } }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "engines": { - "node": ">=8" + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", + "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, - "node_modules/array.prototype.findlast": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", - "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", - "dev": true, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", + "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1" } }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", - "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", - "dev": true, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", + "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, - "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", - "dev": true, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", + "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@webassemblyjs/ast": "1.12.1", + "@xtuc/long": "4.2.2" } }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + }, + "node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true + }, + "node_modules/@yarnpkg/parsers": { + "version": "3.0.0-rc.46", + "resolved": "https://registry.npmjs.org/@yarnpkg/parsers/-/parsers-3.0.0-rc.46.tgz", + "integrity": "sha512-aiATs7pSutzda/rq8fnuPwTglyVwjM22bNnK2ZgjrpAjQHSSl3lztd2f9evst1W/qnC58DRz7T7QndUDumAR4Q==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "js-yaml": "^3.10.0", + "tslib": "^2.4.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=14.15.0" } }, - "node_modules/array.prototype.toreversed": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz", - "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==", + "node_modules/@yarnpkg/parsers/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "sprintf-js": "~1.0.2" } }, - "node_modules/array.prototype.tosorted": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", - "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "node_modules/@yarnpkg/parsers/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.3", - "es-errors": "^1.3.0", - "es-shim-unscopables": "^1.0.2" + "argparse": "^1.0.7", + "esprima": "^4.0.0" }, - "engines": { - "node": ">= 0.4" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/arraybuffer.prototype.slice": { + "node_modules/@yarnpkg/parsers/node_modules/sprintf-js": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/@zkochan/js-yaml": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.7.tgz", + "integrity": "sha512-nrUSn7hzt7J6JWgWGz78ZYI8wj+gdIJdk0Ynjpp8l+trkn58Uqsf6RYrYkEK+3X18EX+TNdtJI0WxAtc+L84SQ==", + "dev": true, "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.2.1", - "get-intrinsic": "^1.2.3", - "is-array-buffer": "^3.0.4", - "is-shared-array-buffer": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" + "argparse": "^2.0.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/asap": { + "node_modules/abab": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "deprecated": "Use your platform's native atob() and btoa() methods instead", + "dev": true }, - "node_modules/asmcrypto.js": { - "version": "0.22.0", - "resolved": "https://registry.npmjs.org/asmcrypto.js/-/asmcrypto.js-0.22.0.tgz", - "integrity": "sha512-usgMoyXjMbx/ZPdzTSXExhMPur2FTdz/Vo5PVx2gIaBcdAAJNOFlsdgqveM8Cff7W0v+xrf9BwjOV26JSAF9qA==", - "license": "MIT" + "node_modules/abitype": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.4.tgz", + "integrity": "sha512-UivtYZOGJGE8rsrM/N5vdRkUpqEZVmuTumfTuolm7m/6O09wprd958rx8kUBwVAAAhQDveGAgD0GJdBuR8s6tw==", + "funding": { + "url": "https://github.com/sponsors/wevm" + }, + "peerDependencies": { + "typescript": ">=5.0.4", + "zod": "^3 >=3.22.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "zod": { + "optional": true + } + } }, - "node_modules/asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", "license": "MIT", + "peer": true, "dependencies": { - "safer-buffer": "~2.1.0" + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" } }, - "node_modules/asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "dependencies": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" } }, - "node_modules/asn1.js/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "node_modules/asn1js": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.5.tgz", - "integrity": "sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==", - "license": "BSD-3-Clause", - "dependencies": { - "pvtsutils": "^1.3.2", - "pvutils": "^1.1.3", - "tslib": "^2.4.0" + "node_modules/acorn": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "bin": { + "acorn": "bin/acorn" }, "engines": { - "node": ">=12.0.0" + "node": ">=0.4.0" } }, - "node_modules/assert": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-2.0.0.tgz", - "integrity": "sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==", - "license": "MIT", + "node_modules/acorn-globals": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", + "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", + "dev": true, "dependencies": { - "es6-object-assign": "^1.1.0", - "is-nan": "^1.2.1", - "object-is": "^1.0.1", - "util": "^0.12.0" + "acorn": "^8.1.0", + "acorn-walk": "^8.0.2" } }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", - "license": "MIT", - "engines": { - "node": ">=0.8" + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "peerDependencies": { + "acorn": "^8" } }, - "node_modules/ast-types": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", - "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", - "license": "MIT", - "peer": true, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", + "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", "dependencies": { - "tslib": "^2.0.1" + "acorn": "^8.11.0" }, "engines": { - "node": ">=4" - } - }, - "node_modules/ast-types-flow": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", - "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", - "dev": true - }, - "node_modules/astring": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/astring/-/astring-1.8.6.tgz", - "integrity": "sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg==", - "bin": { - "astring": "bin/astring" + "node": ">=0.4.0" } }, - "node_modules/async": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", - "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" - }, - "node_modules/async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", - "license": "MIT" - }, - "node_modules/async-mutex": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.2.6.tgz", - "integrity": "sha512-Hs4R+4SPgamu6rSGW8C7cV9gaWUKEHykfzCCvIRuaVv636Ju10ZdeUbvb4TBEW0INuq2DHZqXbK4Nd3yG4RaRw==", - "dependencies": { - "tslib": "^2.0.0" + "node_modules/address": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", + "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", + "engines": { + "node": ">= 10.0.0" } }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "node_modules/adm-zip": { + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.15.tgz", + "integrity": "sha512-jYPWSeOA8EFoZnucrKCNihqBjoEGQSU4HKgHYQgKNEQ0pQF9a/DYuo/+fAxY76k4qe75LUlLWpAM1QWcBMTOKw==", + "dev": true, "engines": { - "node": ">= 4.0.0" + "node": ">=12.0" } }, - "node_modules/atomic-sleep": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", - "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "node_modules/agent-base": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", "engines": { - "node": ">=8.0.0" + "node": ">= 14" } }, - "node_modules/autoprefixer": { - "version": "10.4.20", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", - "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "dependencies": { - "browserslist": "^4.23.3", - "caniuse-lite": "^1.0.30001646", - "fraction.js": "^4.3.7", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.1", - "postcss-value-parser": "^4.2.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" }, "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.1.0" + "node": ">=8" } }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/avalanche": { - "version": "3.15.3", - "resolved": "https://registry.npmjs.org/avalanche/-/avalanche-3.15.3.tgz", - "integrity": "sha512-Oh63Q/Aj9MGI7vHODoSddpwa5JOgqFDX8ZhTMf2Ly8VFhJqgIa0JI9gynTsIHmxHCcdcDhtMh+7V+XJbX1ZbYw==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "license": "BSD-3-Clause", + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "dependencies": { - "assert": "2.0.0", - "axios": "0.27.2", - "bech32": "2.0.0", - "bip39": "3.0.4", - "bn.js": "5.2.1", - "buffer": "6.0.3", - "create-hash": "1.2.0", - "crypto-browserify": "3.12.0", - "elliptic": "6.5.4", - "ethers": "5.6.9", - "hdkey": "2.0.1", - "isomorphic-ws": "5.0.0", - "randombytes": "^2.1.0", - "store2": "2.13.2", - "stream-browserify": "3.0.0", - "ws": "8.8.0", - "xss": "1.0.13" + "ajv": "^8.0.0" }, - "engines": { - "node": ">=14.0.0" + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } } }, - "node_modules/avalanche/node_modules/@ethersproject/abi": { - "version": "5.6.4", - "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.6.4.tgz", - "integrity": "sha512-TTeZUlCeIHG6527/2goZA6gW5F8Emoc7MrZDC7hhP84aRGvW3TEdTnZR08Ls88YXM1m2SuK42Osw/jSi3uO8gg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", + "node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "dependencies": { - "@ethersproject/address": "^5.6.1", - "@ethersproject/bignumber": "^5.6.2", - "@ethersproject/bytes": "^5.6.1", - "@ethersproject/constants": "^5.6.1", - "@ethersproject/hash": "^5.6.1", - "@ethersproject/keccak256": "^5.6.1", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/strings": "^5.6.1" + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" } }, - "node_modules/avalanche/node_modules/@ethersproject/abstract-provider": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.6.1.tgz", - "integrity": "sha512-BxlIgogYJtp1FS8Muvj8YfdClk3unZH0vRMVX791Z9INBNT/kuACZ9GzaY1Y4yFq+YSy6/w4gzj3HCRKrK9hsQ==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", + "node_modules/algoliasearch": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.24.0.tgz", + "integrity": "sha512-bf0QV/9jVejssFBmz2HQLxUadxk574t4iwjCKp5E7NBzwKkrDEhKPISIIjAU/p6K5qDx3qoeh4+26zWN1jmw3g==", "dependencies": { - "@ethersproject/bignumber": "^5.6.2", - "@ethersproject/bytes": "^5.6.1", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/networks": "^5.6.3", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/transactions": "^5.6.2", - "@ethersproject/web": "^5.6.1" + "@algolia/cache-browser-local-storage": "4.24.0", + "@algolia/cache-common": "4.24.0", + "@algolia/cache-in-memory": "4.24.0", + "@algolia/client-account": "4.24.0", + "@algolia/client-analytics": "4.24.0", + "@algolia/client-common": "4.24.0", + "@algolia/client-personalization": "4.24.0", + "@algolia/client-search": "4.24.0", + "@algolia/logger-common": "4.24.0", + "@algolia/logger-console": "4.24.0", + "@algolia/recommend": "4.24.0", + "@algolia/requester-browser-xhr": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/requester-node-http": "4.24.0", + "@algolia/transporter": "4.24.0" } }, - "node_modules/avalanche/node_modules/@ethersproject/abstract-signer": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.6.2.tgz", - "integrity": "sha512-n1r6lttFBG0t2vNiI3HoWaS/KdOt8xyDjzlP2cuevlWLG6EX0OwcKLyG/Kp/cuwNxdy/ous+R/DEMdTUwWQIjQ==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", + "node_modules/algoliasearch-helper": { + "version": "3.22.3", + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.22.3.tgz", + "integrity": "sha512-2eoEz8mG4KHE+DzfrBTrCmDPxVXv7aZZWPojAJFtARpxxMO6lkos1dJ+XDCXdPvq7q3tpYWRi6xXmVQikejtpA==", "dependencies": { - "@ethersproject/abstract-provider": "^5.6.1", - "@ethersproject/bignumber": "^5.6.2", - "@ethersproject/bytes": "^5.6.1", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/properties": "^5.6.0" + "@algolia/events": "^4.0.1" + }, + "peerDependencies": { + "algoliasearch": ">= 3.1 < 6" } }, - "node_modules/avalanche/node_modules/@ethersproject/address": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.6.1.tgz", - "integrity": "sha512-uOgF0kS5MJv9ZvCz7x6T2EXJSzotiybApn4XlOgoTX0xdtyVIJ7pF+6cGPxiEq/dpBiTfMiw7Yc81JcwhSYA0Q==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], + "node_modules/anser": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/anser/-/anser-1.4.10.tgz", + "integrity": "sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==", "license": "MIT", + "peer": true + }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", "dependencies": { - "@ethersproject/bignumber": "^5.6.2", - "@ethersproject/bytes": "^5.6.1", - "@ethersproject/keccak256": "^5.6.1", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/rlp": "^5.6.1" + "string-width": "^4.1.0" } }, - "node_modules/avalanche/node_modules/@ethersproject/base64": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.6.1.tgz", - "integrity": "sha512-qB76rjop6a0RIYYMiB4Eh/8n+Hxu2NIZm8S/Q7kNo5pmZfXhHGHmS4MinUainiBC54SCyRnwzL+KZjj8zbsSsw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", + "node_modules/ansi-align/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/ansi-align/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-align/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dependencies": { - "@ethersproject/bytes": "^5.6.1" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "engines": { + "node": ">=6" } }, - "node_modules/avalanche/node_modules/@ethersproject/basex": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.6.1.tgz", - "integrity": "sha512-a52MkVz4vuBXR06nvflPMotld1FJWSj2QT0985v7P/emPZO00PucFAkbcmq2vpVU7Ts7umKiSI6SppiLykVWsA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, "dependencies": { - "@ethersproject/bytes": "^5.6.1", - "@ethersproject/properties": "^5.6.0" + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/avalanche/node_modules/@ethersproject/bignumber": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.6.2.tgz", - "integrity": "sha512-v7+EEUbhGqT3XJ9LMPsKvXYHFc8eHxTowFCG/HgJErmq4XHJ2WR7aeyICg3uTOAQ7Icn0GFHAohXEhxQHq4Ubw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bytes": "^5.6.1", - "@ethersproject/logger": "^5.6.0", - "bn.js": "^5.2.1" + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/avalanche/node_modules/@ethersproject/bytes": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.6.1.tgz", - "integrity": "sha512-NwQt7cKn5+ZE4uDn+X5RAXLp46E1chXoaMmrxAyA0rblpxz8t58lVkrHXoRIn0lz1joQElQ8410GqhTqMOwc6g==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "engines": [ + "node >= 0.8.0" ], - "license": "MIT", - "dependencies": { - "@ethersproject/logger": "^5.6.0" + "bin": { + "ansi-html": "bin/ansi-html" } }, - "node_modules/avalanche/node_modules/@ethersproject/constants": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.6.1.tgz", - "integrity": "sha512-QSq9WVnZbxXYFftrjSjZDUshp6/eKp6qrtdBtUCm0QxCV5z1fG/w3kdlcsjMCQuQHUnAclKoK7XpXMezhRDOLg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bignumber": "^5.6.2" + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" } }, - "node_modules/avalanche/node_modules/@ethersproject/contracts": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.6.2.tgz", - "integrity": "sha512-hguUA57BIKi6WY0kHvZp6PwPlWF87MCeB4B7Z7AbUpTxfFXFdn/3b0GmjZPagIHS+3yhcBJDnuEfU4Xz+Ks/8g==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dependencies": { - "@ethersproject/abi": "^5.6.3", - "@ethersproject/abstract-provider": "^5.6.1", - "@ethersproject/abstract-signer": "^5.6.2", - "@ethersproject/address": "^5.6.1", - "@ethersproject/bignumber": "^5.6.2", - "@ethersproject/bytes": "^5.6.1", - "@ethersproject/constants": "^5.6.1", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/transactions": "^5.6.2" + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/avalanche/node_modules/@ethersproject/hash": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.6.1.tgz", - "integrity": "sha512-L1xAHurbaxG8VVul4ankNX5HgQ8PNCTrnVXEiFnE9xoRnaUcgfD12tZINtDinSllxPLCtGwguQxJ5E6keE84pA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", + "node_modules/ansi-styles/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dependencies": { - "@ethersproject/abstract-signer": "^5.6.2", - "@ethersproject/address": "^5.6.1", - "@ethersproject/bignumber": "^5.6.2", - "@ethersproject/bytes": "^5.6.1", - "@ethersproject/keccak256": "^5.6.1", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/strings": "^5.6.1" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/avalanche/node_modules/@ethersproject/hdnode": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.6.2.tgz", - "integrity": "sha512-tERxW8Ccf9CxW2db3WsN01Qao3wFeRsfYY9TCuhmG0xNpl2IO8wgXU3HtWIZ49gUWPggRy4Yg5axU0ACaEKf1Q==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/abstract-signer": "^5.6.2", - "@ethersproject/basex": "^5.6.1", - "@ethersproject/bignumber": "^5.6.2", - "@ethersproject/bytes": "^5.6.1", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/pbkdf2": "^5.6.1", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/sha2": "^5.6.1", - "@ethersproject/signing-key": "^5.6.2", - "@ethersproject/strings": "^5.6.1", - "@ethersproject/transactions": "^5.6.2", - "@ethersproject/wordlists": "^5.6.1" - } - }, - "node_modules/avalanche/node_modules/@ethersproject/json-wallets": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.6.1.tgz", - "integrity": "sha512-KfyJ6Zwz3kGeX25nLihPwZYlDqamO6pfGKNnVMWWfEVVp42lTfCZVXXy5Ie8IZTN0HKwAngpIPi7gk4IJzgmqQ==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/abstract-signer": "^5.6.2", - "@ethersproject/address": "^5.6.1", - "@ethersproject/bytes": "^5.6.1", - "@ethersproject/hdnode": "^5.6.2", - "@ethersproject/keccak256": "^5.6.1", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/pbkdf2": "^5.6.1", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/random": "^5.6.1", - "@ethersproject/strings": "^5.6.1", - "@ethersproject/transactions": "^5.6.2", - "aes-js": "3.0.0", - "scrypt-js": "3.0.1" - } - }, - "node_modules/avalanche/node_modules/@ethersproject/keccak256": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.6.1.tgz", - "integrity": "sha512-bB7DQHCTRDooZZdL3lk9wpL0+XuG3XLGHLh3cePnybsO3V0rdCAOQGpn/0R3aODmnTOOkCATJiD2hnL+5bwthA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", + "node_modules/ansi-styles/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dependencies": { - "@ethersproject/bytes": "^5.6.1", - "js-sha3": "0.8.0" + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/avalanche/node_modules/@ethersproject/logger": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.6.0.tgz", - "integrity": "sha512-BiBWllUROH9w+P21RzoxJKzqoqpkyM1pRnEKG69bulE9TSQD8SAIvTQqIMZmmCO8pUNkgLP1wndX1gKghSpBmg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT" + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" }, - "node_modules/avalanche/node_modules/@ethersproject/networks": { - "version": "5.6.4", - "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.6.4.tgz", - "integrity": "sha512-KShHeHPahHI2UlWdtDMn2lJETcbtaJge4k7XSjDR9h79QTd6yQJmv6Cp2ZA4JdqWnhszAOLSuJEd9C0PRw7hSQ==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/aria-hidden": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.4.tgz", + "integrity": "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==", "dependencies": { - "@ethersproject/logger": "^5.6.0" + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" } }, - "node_modules/avalanche/node_modules/@ethersproject/pbkdf2": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.6.1.tgz", - "integrity": "sha512-k4gRQ+D93zDRPNUfmduNKq065uadC2YjMP/CqwwX5qG6R05f47boq6pLZtV/RnC4NZAYOPH1Cyo54q0c9sshRQ==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", + "node_modules/aria-query": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "dev": true, "dependencies": { - "@ethersproject/bytes": "^5.6.1", - "@ethersproject/sha2": "^5.6.1" + "deep-equal": "^2.0.5" } }, - "node_modules/avalanche/node_modules/@ethersproject/properties": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.6.0.tgz", - "integrity": "sha512-szoOkHskajKePTJSZ46uHUWWkbv7TzP2ypdEK6jGMqJaEt2sb0jCgfBo0gH0m2HBpRixMuJ6TBRaQCF7a9DoCg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/logger": "^5.6.0" + "node_modules/arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/avalanche/node_modules/@ethersproject/providers": { - "version": "5.6.8", - "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.6.8.tgz", - "integrity": "sha512-Wf+CseT/iOJjrGtAOf3ck9zS7AgPmr2fZ3N97r4+YXN3mBePTG2/bJ8DApl9mVwYL+RpYbNxMEkEp4mPGdwG/w==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dependencies": { - "@ethersproject/abstract-provider": "^5.6.1", - "@ethersproject/abstract-signer": "^5.6.2", - "@ethersproject/address": "^5.6.1", - "@ethersproject/base64": "^5.6.1", - "@ethersproject/basex": "^5.6.1", - "@ethersproject/bignumber": "^5.6.2", - "@ethersproject/bytes": "^5.6.1", - "@ethersproject/constants": "^5.6.1", - "@ethersproject/hash": "^5.6.1", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/networks": "^5.6.3", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/random": "^5.6.1", - "@ethersproject/rlp": "^5.6.1", - "@ethersproject/sha2": "^5.6.1", - "@ethersproject/strings": "^5.6.1", - "@ethersproject/transactions": "^5.6.2", - "@ethersproject/web": "^5.6.1", - "bech32": "1.1.4", - "ws": "7.4.6" - } - }, - "node_modules/avalanche/node_modules/@ethersproject/providers/node_modules/bech32": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", - "license": "MIT" - }, - "node_modules/avalanche/node_modules/@ethersproject/providers/node_modules/ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", - "license": "MIT", - "engines": { - "node": ">=8.3.0" + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "engines": { + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/avalanche/node_modules/@ethersproject/random": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.6.1.tgz", - "integrity": "sha512-/wtPNHwbmng+5yi3fkipA8YBT59DdkGRoC2vWk09Dci/q5DlgnMkhIycjHlavrvrjJBkFjO/ueLyT+aUDfc4lA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, "dependencies": { - "@ethersproject/bytes": "^5.6.1", - "@ethersproject/logger": "^5.6.0" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/avalanche/node_modules/@ethersproject/rlp": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.6.1.tgz", - "integrity": "sha512-uYjmcZx+DKlFUk7a5/W9aQVaoEC7+1MOBgNtvNg13+RnuUwT4F0zTovC0tmay5SmRslb29V1B7Y5KCri46WhuQ==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/bytes": "^5.6.1", - "@ethersproject/logger": "^5.6.0" + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "engines": { + "node": ">=8" } }, - "node_modules/avalanche/node_modules/@ethersproject/sha2": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.6.1.tgz", - "integrity": "sha512-5K2GyqcW7G4Yo3uenHegbXRPDgARpWUiXc6RiF7b6i/HXUoWlb7uCARh7BAHg7/qT/Q5ydofNwiZcim9qpjB6g==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, "dependencies": { - "@ethersproject/bytes": "^5.6.1", - "@ethersproject/logger": "^5.6.0", - "hash.js": "1.1.7" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/avalanche/node_modules/@ethersproject/signing-key": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.6.2.tgz", - "integrity": "sha512-jVbu0RuP7EFpw82vHcL+GP35+KaNruVAZM90GxgQnGqB6crhBqW/ozBfFvdeImtmb4qPko0uxXjn8l9jpn0cwQ==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", + "node_modules/array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "dev": true, "dependencies": { - "@ethersproject/bytes": "^5.6.1", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "bn.js": "^5.2.1", - "elliptic": "6.5.4", - "hash.js": "1.1.7" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/avalanche/node_modules/@ethersproject/solidity": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.6.1.tgz", - "integrity": "sha512-KWqVLkUUoLBfL1iwdzUVlkNqAUIFMpbbeH0rgCfKmJp0vFtY4AsaN91gHKo9ZZLkC4UOm3cI3BmMV4N53BOq4g==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, "dependencies": { - "@ethersproject/bignumber": "^5.6.2", - "@ethersproject/bytes": "^5.6.1", - "@ethersproject/keccak256": "^5.6.1", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/sha2": "^5.6.1", - "@ethersproject/strings": "^5.6.1" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/avalanche/node_modules/@ethersproject/strings": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.6.1.tgz", - "integrity": "sha512-2X1Lgk6Jyfg26MUnsHiT456U9ijxKUybz8IM1Vih+NJxYtXhmvKBcHOmvGqpFSVJ0nQ4ZCoIViR8XlRw1v/+Cw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, "dependencies": { - "@ethersproject/bytes": "^5.6.1", - "@ethersproject/constants": "^5.6.1", - "@ethersproject/logger": "^5.6.0" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/avalanche/node_modules/@ethersproject/transactions": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.6.2.tgz", - "integrity": "sha512-BuV63IRPHmJvthNkkt9G70Ullx6AcM+SDc+a8Aw/8Yew6YwT51TcBKEp1P4oOQ/bP25I18JJr7rcFRgFtU9B2Q==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", + "node_modules/array.prototype.toreversed": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz", + "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==", + "dev": true, "dependencies": { - "@ethersproject/address": "^5.6.1", - "@ethersproject/bignumber": "^5.6.2", - "@ethersproject/bytes": "^5.6.1", - "@ethersproject/constants": "^5.6.1", - "@ethersproject/keccak256": "^5.6.1", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/rlp": "^5.6.1", - "@ethersproject/signing-key": "^5.6.2" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" } }, - "node_modules/avalanche/node_modules/@ethersproject/units": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.6.1.tgz", - "integrity": "sha512-rEfSEvMQ7obcx3KWD5EWWx77gqv54K6BKiZzKxkQJqtpriVsICrktIQmKl8ReNToPeIYPnFHpXvKpi068YFZXw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, "dependencies": { - "@ethersproject/bignumber": "^5.6.2", - "@ethersproject/constants": "^5.6.1", - "@ethersproject/logger": "^5.6.0" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" } }, - "node_modules/avalanche/node_modules/@ethersproject/wallet": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.6.2.tgz", - "integrity": "sha512-lrgh0FDQPuOnHcF80Q3gHYsSUODp6aJLAdDmDV0xKCN/T7D99ta1jGVhulg3PY8wiXEngD0DfM0I2XKXlrqJfg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/abstract-provider": "^5.6.1", - "@ethersproject/abstract-signer": "^5.6.2", - "@ethersproject/address": "^5.6.1", - "@ethersproject/bignumber": "^5.6.2", - "@ethersproject/bytes": "^5.6.1", - "@ethersproject/hash": "^5.6.1", - "@ethersproject/hdnode": "^5.6.2", - "@ethersproject/json-wallets": "^5.6.1", - "@ethersproject/keccak256": "^5.6.1", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/random": "^5.6.1", - "@ethersproject/signing-key": "^5.6.2", - "@ethersproject/transactions": "^5.6.2", - "@ethersproject/wordlists": "^5.6.1" - } - }, - "node_modules/avalanche/node_modules/@ethersproject/web": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.6.1.tgz", - "integrity": "sha512-/vSyzaQlNXkO1WV+RneYKqCJwualcUdx/Z3gseVovZP0wIlOFcCE1hkRhKBH8ImKbGQbMl9EAAyJFrJu7V0aqA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", "dependencies": { - "@ethersproject/base64": "^5.6.1", - "@ethersproject/bytes": "^5.6.1", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/strings": "^5.6.1" + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/avalanche/node_modules/@ethersproject/wordlists": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.6.1.tgz", - "integrity": "sha512-wiPRgBpNbNwCQFoCr8bcWO8o5I810cqO6mkdtKfLKFlLxeCWcnzDi4Alu8iyNzlhYuS9npCwivMbRWF19dyblw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" + }, + "node_modules/asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", "dependencies": { - "@ethersproject/bytes": "^5.6.1", - "@ethersproject/hash": "^5.6.1", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/strings": "^5.6.1" + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" } }, - "node_modules/avalanche/node_modules/@types/node": { - "version": "11.11.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-11.11.6.tgz", - "integrity": "sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==", - "license": "MIT" + "node_modules/asn1.js/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" }, - "node_modules/avalanche/node_modules/axios": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "node_modules/ast-types": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", + "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", "license": "MIT", + "peer": true, "dependencies": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" } }, - "node_modules/avalanche/node_modules/bip39": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.0.4.tgz", - "integrity": "sha512-YZKQlb752TrUWqHWj7XAwCSjYEgGAk+/Aas3V7NyjQeZYsztO8JnQUaCWhcnL4T+jL8nvB8typ2jRPzTlgugNw==", - "license": "ISC", - "dependencies": { - "@types/node": "11.11.6", - "create-hash": "^1.1.0", - "pbkdf2": "^3.0.9", - "randombytes": "^2.0.1" + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true + }, + "node_modules/astring": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/astring/-/astring-1.8.6.tgz", + "integrity": "sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg==", + "bin": { + "astring": "bin/astring" } }, - "node_modules/avalanche/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/async": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" + }, + "node_modules/async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", "license": "MIT", + "peer": true + }, + "node_modules/async-mutex": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.2.6.tgz", + "integrity": "sha512-Hs4R+4SPgamu6rSGW8C7cV9gaWUKEHykfzCCvIRuaVv636Ju10ZdeUbvb4TBEW0INuq2DHZqXbK4Nd3yG4RaRw==", "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" + "tslib": "^2.0.0" } }, - "node_modules/avalanche/node_modules/elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "license": "MIT", - "dependencies": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "engines": { + "node": ">= 4.0.0" } }, - "node_modules/avalanche/node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", - "license": "MIT" + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "engines": { + "node": ">=8.0.0" + } }, - "node_modules/avalanche/node_modules/ethers": { - "version": "5.6.9", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.6.9.tgz", - "integrity": "sha512-lMGC2zv9HC5EC+8r429WaWu3uWJUCgUCt8xxKCFqkrFuBDZXDYIdzDUECxzjf2BMF8IVBByY1EBoGSL3RTm8RA==", + "node_modules/autoprefixer": { + "version": "10.4.20", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", + "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", "funding": [ { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + "type": "opencollective", + "url": "https://opencollective.com/postcss/" }, { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], - "license": "MIT", "dependencies": { - "@ethersproject/abi": "5.6.4", - "@ethersproject/abstract-provider": "5.6.1", - "@ethersproject/abstract-signer": "5.6.2", - "@ethersproject/address": "5.6.1", - "@ethersproject/base64": "5.6.1", - "@ethersproject/basex": "5.6.1", - "@ethersproject/bignumber": "5.6.2", - "@ethersproject/bytes": "5.6.1", - "@ethersproject/constants": "5.6.1", - "@ethersproject/contracts": "5.6.2", - "@ethersproject/hash": "5.6.1", - "@ethersproject/hdnode": "5.6.2", - "@ethersproject/json-wallets": "5.6.1", - "@ethersproject/keccak256": "5.6.1", - "@ethersproject/logger": "5.6.0", - "@ethersproject/networks": "5.6.4", - "@ethersproject/pbkdf2": "5.6.1", - "@ethersproject/properties": "5.6.0", - "@ethersproject/providers": "5.6.8", - "@ethersproject/random": "5.6.1", - "@ethersproject/rlp": "5.6.1", - "@ethersproject/sha2": "5.6.1", - "@ethersproject/signing-key": "5.6.2", - "@ethersproject/solidity": "5.6.1", - "@ethersproject/strings": "5.6.1", - "@ethersproject/transactions": "5.6.2", - "@ethersproject/units": "5.6.1", - "@ethersproject/wallet": "5.6.2", - "@ethersproject/web": "5.6.1", - "@ethersproject/wordlists": "5.6.1" - } - }, - "node_modules/avalanche/node_modules/ws": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.8.0.tgz", - "integrity": "sha512-JDAgSYQ1ksuwqfChJusw1LSJ8BizJ2e/vVu5Lxjq3YvNJNlROv1ui4i+c/kUUrPheBvQl4c5UbERhTwKa6QBJQ==", - "license": "MIT", + "browserslist": "^4.23.3", + "caniuse-lite": "^1.0.30001646", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, "engines": { - "node": ">=10.0.0" + "node": "^10 || ^12 || >=14" }, "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "postcss": "^8.1.0" } }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", - "license": "Apache-2.0", + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, "engines": { - "node": "*" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/aws4": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", - "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==", - "license": "MIT" - }, "node_modules/axe-core": { "version": "4.10.0", "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.0.tgz", @@ -33170,24 +22063,6 @@ "deep-equal": "^2.0.5" } }, - "node_modules/b64-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/b64-lite/-/b64-lite-1.4.0.tgz", - "integrity": "sha512-aHe97M7DXt+dkpa8fHlCcm1CnskAHrJqEfMI0KN7dwqlzml/aUe1AGt6lk51HzrSfVD67xOso84sOpr+0wIe2w==", - "license": "MIT", - "dependencies": { - "base-64": "^0.1.0" - } - }, - "node_modules/b64u-lite": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/b64u-lite/-/b64u-lite-1.1.0.tgz", - "integrity": "sha512-929qWGDVCRph7gQVTC6koHqQIpF4vtVaSbwLltFQo44B1bYUquALswZdBKFfrJCPEnsCOvWkJsPdQYZ/Ukhw8A==", - "license": "MIT", - "dependencies": { - "b64-lite": "^1.4.0" - } - }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -33327,23 +22202,6 @@ "node": ">= 6" } }, - "node_modules/babel-plugin-module-resolver": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-4.1.0.tgz", - "integrity": "sha512-MlX10UDheRr3lb3P0WcaIdtCSRlxdQsB1sBqL7W0raF070bGl1HQQq5K3T2vf2XAYie+ww+5AKC/WrkjRO2knA==", - "license": "MIT", - "peer": true, - "dependencies": { - "find-babel-config": "^1.2.0", - "glob": "^7.1.6", - "pkg-up": "^3.1.0", - "reselect": "^4.0.0", - "resolve": "^1.13.1" - }, - "engines": { - "node": ">= 8.0.0" - } - }, "node_modules/babel-plugin-polyfill-corejs2": { "version": "0.4.11", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", @@ -33380,13 +22238,6 @@ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/babel-plugin-react-native-web": { - "version": "0.17.7", - "resolved": "https://registry.npmjs.org/babel-plugin-react-native-web/-/babel-plugin-react-native-web-0.17.7.tgz", - "integrity": "sha512-UBLfIsfU3vi//Ab4i0WSWAfm1whLTK9uJoH0RPZ6a67eS/h9JGYjKy7+1RpHxSBviHi9NIMiYfWseTLjyIsE1g==", - "license": "MIT", - "peer": true - }, "node_modules/babel-plugin-syntax-hermes-parser": { "version": "0.25.1", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.25.1.tgz", @@ -33438,21 +22289,6 @@ "@babel/core": "^7.0.0" } }, - "node_modules/babel-preset-expo": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/babel-preset-expo/-/babel-preset-expo-9.0.2.tgz", - "integrity": "sha512-NKVichCkbmb+ZIJ4hvuxzX3PnvHUKT42NxYIYTsKAfHPUKuaSAawtpsmMThph6pUc0GUYcLvCRql8ZX5A1zYNw==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/plugin-proposal-decorators": "^7.12.9", - "@babel/plugin-transform-react-jsx": "^7.12.17", - "@babel/preset-env": "^7.12.9", - "babel-plugin-module-resolver": "^4.1.0", - "babel-plugin-react-native-web": "~0.17.1", - "metro-react-native-babel-preset": "~0.64.0" - } - }, "node_modules/babel-preset-jest": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", @@ -33482,29 +22318,6 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, - "node_modules/base-64": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/base-64/-/base-64-0.1.0.tgz", - "integrity": "sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA==" - }, - "node_modules/base-x": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.10.tgz", - "integrity": "sha512-7d0s06rR9rYaIWHkpfLIFICM/tkSVdoPC9qYAQRpxn9DdKNWNsKC0uk++akckyLq16Tx2WIinnZ6WRriAt6njQ==", - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/base32.js": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/base32.js/-/base32.js-0.1.0.tgz", - "integrity": "sha512-n3TkB02ixgBOhTvANakDb4xaMXnYUVkNoRFJjQflcqMQhyEKxEHdj3E6N8t8sUQ0mjH/3/JxzlXuz3ul/J90pQ==", - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -33546,6 +22359,7 @@ "version": "5.0.5", "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==", + "dev": true, "engines": { "node": ">=10.0.0" } @@ -33555,60 +22369,6 @@ "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", - "license": "BSD-3-Clause", - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, - "node_modules/bcrypt-pbkdf/node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", - "license": "Unlicense" - }, - "node_modules/bech32": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz", - "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==", - "license": "MIT" - }, - "node_modules/bech32-buffer": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/bech32-buffer/-/bech32-buffer-0.2.1.tgz", - "integrity": "sha512-fCG1TyZuCN48Sdw97p/IR39fvqpFlWDVpG7qnuU1Uc3+Xtc/0uqAp8U7bMW/bGuVF5CcNVIXwxQsWwUr6un6FQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=8" - } - }, - "node_modules/better-opn": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/better-opn/-/better-opn-3.0.2.tgz", - "integrity": "sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "open": "^8.0.4" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/big-integer": { - "version": "1.6.52", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", - "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", - "license": "Unlicense", - "peer": true, - "engines": { - "node": ">=0.6" - } - }, "node_modules/big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", @@ -33617,45 +22377,6 @@ "node": "*" } }, - "node_modules/bigi": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/bigi/-/bigi-1.4.2.tgz", - "integrity": "sha512-ddkU+dFIuEIW8lE7ZwdIAf2UPoM90eaprg5m3YXAVVTmKlqV/9BX4A2M8BOK2yOq6/VgZFVhK6QAxJebhlbhzw==" - }, - "node_modules/bigint-buffer": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/bigint-buffer/-/bigint-buffer-1.1.5.tgz", - "integrity": "sha512-trfYco6AoZ+rKhKnxA0hgX0HAbVP/s808/EuDSe2JDzUnCp/xAsli35Orvk67UrTEcwuxZqYZDmfA2RXJgxVvA==", - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "bindings": "^1.3.0" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/bigint-crypto-utils": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/bigint-crypto-utils/-/bigint-crypto-utils-3.1.4.tgz", - "integrity": "sha512-niSkvARUEe8MiAiH+zKXPkgXzlvGDbOqXL3JDevWaA1TrPhUGSCgV+iedm8qMEBQwvSlMMn8GpSuoUjvsm2QfQ==", - "license": "MIT", - "dependencies": { - "bigint-mod-arith": "^3.1.0" - }, - "engines": { - "node": ">=10.4.0" - } - }, - "node_modules/bigint-mod-arith": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bigint-mod-arith/-/bigint-mod-arith-3.1.2.tgz", - "integrity": "sha512-nx8J8bBeiRR+NlsROFH9jHswW5HO8mgfOSqW0AmjicMMvaONDa8AO+5ViKDUUNytBPWiwfvZP4/Bj4Y3lUfvgQ==", - "license": "MIT", - "engines": { - "node": ">=10.4.0" - } - }, "node_modules/bignumber.js": { "version": "9.1.2", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", @@ -33679,375 +22400,11 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, - "node_modules/bip174": { - "name": "@bitgo-forks/bip174", - "version": "3.1.0-master.4", - "resolved": "https://registry.npmjs.org/@bitgo-forks/bip174/-/bip174-3.1.0-master.4.tgz", - "integrity": "sha512-WDRNzPSdJGDqQNqfN+L5KHNHFDmNOPYnUnT7NkEkfHWn5m1jSOfcf8Swaslt5P0xcSDiERdN2gZxFc6XtOqRYg==", - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/bip32": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bip32/-/bip32-3.1.0.tgz", - "integrity": "sha512-eoeajYEzJ4d6yyVtby8C+XkCeKItiC4Mx56a0M9VaqTMC73SWOm4xVZG7SaR8e/yp4eSyky2XcBpH3DApPdu7Q==", - "license": "MIT", - "dependencies": { - "bs58check": "^2.1.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "ripemd160": "^2.0.2", - "typeforce": "^1.11.5", - "wif": "^2.0.6" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/bip39": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.1.0.tgz", - "integrity": "sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A==", - "license": "ISC", - "dependencies": { - "@noble/hashes": "^1.2.0" - } - }, - "node_modules/bip66": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", - "integrity": "sha512-nemMHz95EmS38a26XbbdxIYj5csHd3RMP3H5bwQknX0WYHF01qhpufP42mLOwVICuH2JmhIhXiWs89MfUGL7Xw==", - "license": "MIT", - "optional": true, - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/bitcoin-ops": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/bitcoin-ops/-/bitcoin-ops-1.4.1.tgz", - "integrity": "sha512-pef6gxZFztEhaE9RY9HmWVmiIHqCb2OyS4HPKkpc6CIiiOa3Qmuoylxc5P2EkU3w+5eTSifI9SEZC88idAIGow==", - "license": "MIT" - }, - "node_modules/bitcoinjs-lib": { - "name": "@bitgo-forks/bitcoinjs-lib", - "version": "7.1.0-master.9", - "resolved": "https://registry.npmjs.org/@bitgo-forks/bitcoinjs-lib/-/bitcoinjs-lib-7.1.0-master.9.tgz", - "integrity": "sha512-iWDwsRZK30tW7jtBiOlOJhuJzZ2THIvdvREBHM2cHG669nGQxNPxpYXmk0Lgm5x4jG4GN1dM6dPR6Car6EtDsA==", - "license": "MIT", - "dependencies": { - "bech32": "^2.0.0", - "bip174": "npm:@bitgo-forks/bip174@3.1.0-master.4", - "bs58check": "^2.1.2", - "create-hash": "^1.1.0", - "fastpriorityqueue": "^0.7.1", - "json5": "^2.2.3", - "ripemd160": "^2.0.2", - "typeforce": "^1.11.3", - "varuint-bitcoin": "^1.1.2", - "wif": "^2.0.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/bitcoinjs-message": { - "name": "@bitgo-forks/bitcoinjs-message", - "version": "1.0.0-master.3", - "resolved": "https://registry.npmjs.org/@bitgo-forks/bitcoinjs-message/-/bitcoinjs-message-1.0.0-master.3.tgz", - "integrity": "sha512-mWMXFSb9pTcbxcvU4cQGkickuhPDnpadHs6eUK6F07pJZ42O4eA3j0anwfTsfpqs8UpSzM8UtrUEG4ao5+/yZg==", - "license": "MIT", - "dependencies": { - "bech32": "^1.1.3", - "bs58check": "^2.1.2", - "buffer-equals": "^1.0.3", - "create-hash": "^1.1.2", - "secp256k1": "5.0.1", - "varuint-bitcoin": "^1.0.1" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/bitcoinjs-message/node_modules/bech32": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", - "license": "MIT" - }, - "node_modules/bitgo": { - "version": "39.23.0", - "resolved": "https://registry.npmjs.org/bitgo/-/bitgo-39.23.0.tgz", - "integrity": "sha512-tXfizVeChDgGPK/DVvi3hqI1dSHa3V3mHJXJft6rfXiW8InY9IahiCw863R020kaVQlZMemmJom3rWgMuIFl2Q==", - "license": "Apache-2.0", - "dependencies": { - "@bitgo/abstract-lightning": "^1.2.38", - "@bitgo/abstract-utxo": "^9.12.0", - "@bitgo/account-lib": "^24.2.0", - "@bitgo/blockapis": "^1.10.9", - "@bitgo/sdk-api": "^1.58.2", - "@bitgo/sdk-coin-ada": "^4.6.0", - "@bitgo/sdk-coin-algo": "^2.1.58", - "@bitgo/sdk-coin-apt": "^1.4.1", - "@bitgo/sdk-coin-arbeth": "^21.0.52", - "@bitgo/sdk-coin-atom": "^13.1.16", - "@bitgo/sdk-coin-avaxc": "^5.2.10", - "@bitgo/sdk-coin-avaxp": "^5.0.59", - "@bitgo/sdk-coin-bch": "^2.1.10", - "@bitgo/sdk-coin-bcha": "^2.2.10", - "@bitgo/sdk-coin-bera": "^2.3.4", - "@bitgo/sdk-coin-bld": "^3.0.29", - "@bitgo/sdk-coin-bsc": "^22.2.13", - "@bitgo/sdk-coin-bsv": "^2.1.10", - "@bitgo/sdk-coin-btc": "^2.4.10", - "@bitgo/sdk-coin-btg": "^2.1.10", - "@bitgo/sdk-coin-celo": "^4.0.11", - "@bitgo/sdk-coin-coredao": "^1.2.12", - "@bitgo/sdk-coin-coreum": "^21.0.29", - "@bitgo/sdk-coin-cspr": "^2.0.60", - "@bitgo/sdk-coin-dash": "^2.1.10", - "@bitgo/sdk-coin-doge": "^2.1.10", - "@bitgo/sdk-coin-dot": "^4.1.38", - "@bitgo/sdk-coin-eos": "^2.1.53", - "@bitgo/sdk-coin-etc": "^2.2.27", - "@bitgo/sdk-coin-eth": "^24.2.49", - "@bitgo/sdk-coin-eth2": "^3.0.59", - "@bitgo/sdk-coin-ethlike": "^1.1.41", - "@bitgo/sdk-coin-ethw": "^20.0.60", - "@bitgo/sdk-coin-hash": "^3.0.29", - "@bitgo/sdk-coin-hbar": "^2.0.60", - "@bitgo/sdk-coin-icp": "^1.1.0", - "@bitgo/sdk-coin-injective": "^3.0.29", - "@bitgo/sdk-coin-islm": "^2.1.10", - "@bitgo/sdk-coin-lnbtc": "^1.1.38", - "@bitgo/sdk-coin-ltc": "^3.1.10", - "@bitgo/sdk-coin-near": "^2.0.60", - "@bitgo/sdk-coin-oas": "^1.1.13", - "@bitgo/sdk-coin-opeth": "^18.1.45", - "@bitgo/sdk-coin-osmo": "^3.0.29", - "@bitgo/sdk-coin-polygon": "^21.0.29", - "@bitgo/sdk-coin-rbtc": "^2.0.60", - "@bitgo/sdk-coin-rune": "^1.1.17", - "@bitgo/sdk-coin-sei": "^3.0.29", - "@bitgo/sdk-coin-sol": "^4.7.17", - "@bitgo/sdk-coin-stx": "^3.3.17", - "@bitgo/sdk-coin-sui": "^5.8.19", - "@bitgo/sdk-coin-tao": "^1.0.2", - "@bitgo/sdk-coin-tia": "^3.0.29", - "@bitgo/sdk-coin-ton": "^3.4.17", - "@bitgo/sdk-coin-trx": "^2.0.60", - "@bitgo/sdk-coin-xlm": "^3.2.34", - "@bitgo/sdk-coin-xrp": "^3.7.2", - "@bitgo/sdk-coin-xtz": "^2.1.58", - "@bitgo/sdk-coin-zec": "^2.1.10", - "@bitgo/sdk-coin-zeta": "^3.0.29", - "@bitgo/sdk-coin-zketh": "^2.0.52", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/sdk-lib-mpc": "^10.1.0", - "@bitgo/sjcl": "^1.0.1", - "@bitgo/statics": "^50.20.0", - "@bitgo/unspents": "^0.47.17", - "@bitgo/utxo-lib": "^11.2.1", - "@types/bluebird": "^3.5.25", - "@types/superagent": "^4.1.3", - "bignumber.js": "^9.1.1", - "bluebird": "^3.5.3", - "fs-extra": "^9.1.0", - "lodash": "^4.17.14", - "openpgp": "5.10.1", - "stellar-sdk": "^10.0.1", - "superagent": "^9.0.1" - }, - "engines": { - "node": ">=18 <21", - "npm": ">=3.10.10" - }, - "optionalDependencies": { - "@ethereumjs/common": "^2.6.5", - "@ethereumjs/tx": "^3.3.0", - "ethereumjs-abi": "^0.6.5", - "ethereumjs-util": "7.1.5" - } - }, - "node_modules/bitgo/node_modules/@bitgo/sdk-coin-sui": { - "version": "5.8.19", - "resolved": "https://registry.npmjs.org/@bitgo/sdk-coin-sui/-/sdk-coin-sui-5.8.19.tgz", - "integrity": "sha512-axpv9x6bOU63F97E3W5lJ97NaEjUxJhv5xVePnw1V4DWCvKGhTS/VxabflRiONY6F1ia8wgAYEGftgWkbXy2Pg==", - "license": "MIT", - "dependencies": { - "@bitgo/blake2b": "^3.2.4", - "@bitgo/sdk-core": "^28.20.0", - "@bitgo/sdk-lib-mpc": "^10.1.0", - "@bitgo/statics": "^50.20.0", - "@mysten/bcs": "^0.7.0", - "bignumber.js": "^9.0.0", - "bs58": "^4.0.1", - "lodash": "^4.17.21", - "superagent": "3.8.2", - "superstruct": "^1.0.3", - "tweetnacl": "^1.0.3" - }, - "engines": { - "node": ">=18 <21" - } - }, - "node_modules/bitgo/node_modules/@bitgo/sdk-coin-sui/node_modules/superagent": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.2.tgz", - "integrity": "sha512-gVH4QfYHcY3P0f/BZzavLreHW3T1v7hG9B+hpMQotGQqurOvhv87GcMCd6LWySmBuf+BDR44TQd0aISjVHLeNQ==", - "deprecated": "Please upgrade to v9.0.0+ as we have fixed a public vulnerability with formidable dependency. Note that v9.0.0+ requires Node.js v14.18.0+. See https://github.com/ladjs/superagent/pull/1800 for insight. This project is supported and maintained by the team at Forward Email @ https://forwardemail.net", - "license": "MIT", - "dependencies": { - "component-emitter": "^1.2.0", - "cookiejar": "^2.1.0", - "debug": "^3.1.0", - "extend": "^3.0.0", - "form-data": "^2.3.1", - "formidable": "^1.1.1", - "methods": "^1.1.1", - "mime": "^1.4.1", - "qs": "^6.5.1", - "readable-stream": "^2.0.5" - }, - "engines": { - "node": ">= 4.0" - } - }, - "node_modules/bitgo/node_modules/@ethereumjs/common": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", - "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", - "license": "MIT", - "optional": true, - "dependencies": { - "crc-32": "^1.2.0", - "ethereumjs-util": "^7.1.5" - } - }, - "node_modules/bitgo/node_modules/@ethereumjs/tx": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.5.2.tgz", - "integrity": "sha512-gQDNJWKrSDGu2w7w0PzVXVBNMzb7wwdDOmOqczmhNjqFxFuIbhVJDwiGEnxFNC2/b8ifcZzY7MLcluizohRzNw==", - "license": "MPL-2.0", "optional": true, "dependencies": { - "@ethereumjs/common": "^2.6.4", - "ethereumjs-util": "^7.1.5" - } - }, - "node_modules/bitgo/node_modules/@types/superagent": { - "version": "4.1.24", - "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.24.tgz", - "integrity": "sha512-mEafCgyKiMFin24SDzWN7yAADt4gt6YawFiNMp0QS5ZPboORfyxFt0s3VzJKhTaKg9py/4FUmrHLTNfJKt9Rbw==", - "license": "MIT", - "dependencies": { - "@types/cookiejar": "*", - "@types/node": "*" - } - }, - "node_modules/bitgo/node_modules/debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/bitgo/node_modules/form-data": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.2.tgz", - "integrity": "sha512-GgwY0PS7DbXqajuGf4OYlsrIu3zgxD6Vvql43IBhm6MahqA5SK/7mwhtNj2AdH2z35YR34ujJ7BN+3fFC3jP5Q==", - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12", - "safe-buffer": "^5.2.1" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/bitgo/node_modules/formidable": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", - "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==", - "deprecated": "Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau", - "license": "MIT", - "funding": { - "url": "https://ko-fi.com/tunnckoCore/commissions" - } - }, - "node_modules/bitgo/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "license": "MIT", - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/bitgo/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "license": "MIT" - }, - "node_modules/bitgo/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/bitgo/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/bitgo/node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "license": "MIT" - }, - "node_modules/bitgo/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" + "file-uri-to-path": "1.0.0" } }, - "node_modules/bitgo/node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "license": "MIT" - }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -34059,25 +22416,6 @@ "readable-stream": "^3.4.0" } }, - "node_modules/blakejs": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", - "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==", - "license": "MIT" - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "license": "MIT" - }, - "node_modules/blueimp-md5": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.19.0.tgz", - "integrity": "sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==", - "license": "MIT", - "peer": true - }, "node_modules/bn.js": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", @@ -34119,121 +22457,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, - "node_modules/bolt11": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/bolt11/-/bolt11-1.4.1.tgz", - "integrity": "sha512-jR0Y+MO+CK2at1Cg5mltLJ+6tdOwNKoTS/DJOBDdzVkQ+R9D6UgZMayTWOsuzY7OgV1gEqlyT5Tzk6t6r4XcNQ==", - "license": "MIT", - "dependencies": { - "@types/bn.js": "^4.11.3", - "bech32": "^1.1.2", - "bitcoinjs-lib": "^6.0.0", - "bn.js": "^4.11.8", - "create-hash": "^1.2.0", - "lodash": "^4.17.11", - "safe-buffer": "^5.1.1", - "secp256k1": "^4.0.2" - } - }, - "node_modules/bolt11/node_modules/@types/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/bolt11/node_modules/base-x": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.0.tgz", - "integrity": "sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw==", - "license": "MIT" - }, - "node_modules/bolt11/node_modules/bech32": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", - "license": "MIT" - }, - "node_modules/bolt11/node_modules/bip174": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bip174/-/bip174-2.1.1.tgz", - "integrity": "sha512-mdFV5+/v0XyNYXjBS6CQPLo9ekCx4gtKZFnJm5PMto7Fs9hTTDpkkzOB7/FtluRI6JbUUAu+snTYfJRgHLZbZQ==", - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/bolt11/node_modules/bitcoinjs-lib": { - "version": "6.1.7", - "resolved": "https://registry.npmjs.org/bitcoinjs-lib/-/bitcoinjs-lib-6.1.7.tgz", - "integrity": "sha512-tlf/r2DGMbF7ky1MgUqXHzypYHakkEnm0SZP23CJKIqNY/5uNAnMbFhMJdhjrL/7anfb/U8+AlpdjPWjPnAalg==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "^1.2.0", - "bech32": "^2.0.0", - "bip174": "^2.1.1", - "bs58check": "^3.0.1", - "typeforce": "^1.11.3", - "varuint-bitcoin": "^1.1.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/bolt11/node_modules/bitcoinjs-lib/node_modules/bech32": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz", - "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==", - "license": "MIT" - }, - "node_modules/bolt11/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", - "license": "MIT" - }, - "node_modules/bolt11/node_modules/bs58": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-5.0.0.tgz", - "integrity": "sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==", - "license": "MIT", - "dependencies": { - "base-x": "^4.0.0" - } - }, - "node_modules/bolt11/node_modules/bs58check": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-3.0.1.tgz", - "integrity": "sha512-hjuuJvoWEybo7Hn/0xOrczQKKEKD63WguEjlhLExYs2wUBcebDC1jDNK17eEAD2lYfw82d5ASC1d7K3SWszjaQ==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "^1.2.0", - "bs58": "^5.0.0" - } - }, - "node_modules/bolt11/node_modules/node-addon-api": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", - "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", - "license": "MIT" - }, - "node_modules/bolt11/node_modules/secp256k1": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.4.tgz", - "integrity": "sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "elliptic": "^6.5.7", - "node-addon-api": "^5.0.0", - "node-gyp-build": "^4.2.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/bonjour-service": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", @@ -34248,17 +22471,6 @@ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" }, - "node_modules/borsh": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/borsh/-/borsh-0.7.0.tgz", - "integrity": "sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA==", - "license": "Apache-2.0", - "dependencies": { - "bn.js": "^5.2.0", - "bs58": "^4.0.0", - "text-encoding-utf-8": "^1.0.2" - } - }, "node_modules/bowser": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", @@ -34296,29 +22508,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/bplist-creator": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.1.0.tgz", - "integrity": "sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg==", - "license": "MIT", - "peer": true, - "dependencies": { - "stream-buffers": "2.2.x" - } - }, - "node_modules/bplist-parser": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.1.tgz", - "integrity": "sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA==", - "license": "MIT", - "peer": true, - "dependencies": { - "big-integer": "1.6.x" - }, - "engines": { - "node": ">= 5.10.0" - } - }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -34343,133 +22532,6 @@ "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" }, - "node_modules/browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "license": "MIT", - "dependencies": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "license": "MIT", - "dependencies": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } - }, - "node_modules/browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "license": "MIT", - "dependencies": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/browserify-rsa": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.1.tgz", - "integrity": "sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==", - "license": "MIT", - "dependencies": { - "bn.js": "^5.2.1", - "randombytes": "^2.1.0", - "safe-buffer": "^5.2.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/browserify-sign": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.3.tgz", - "integrity": "sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw==", - "license": "ISC", - "dependencies": { - "bn.js": "^5.2.1", - "browserify-rsa": "^4.1.0", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "elliptic": "^6.5.5", - "hash-base": "~3.0", - "inherits": "^2.0.4", - "parse-asn1": "^5.1.7", - "readable-stream": "^2.3.8", - "safe-buffer": "^5.2.1" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/browserify-sign/node_modules/hash-base": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.5.tgz", - "integrity": "sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.4", - "safe-buffer": "^5.2.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/browserify-sign/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "license": "MIT" - }, - "node_modules/browserify-sign/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/browserify-sign/node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "license": "MIT" - }, - "node_modules/browserify-sign/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/browserify-sign/node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "license": "MIT" - }, "node_modules/browserslist": { "version": "4.24.2", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", @@ -34513,26 +22575,6 @@ "node": ">= 6" } }, - "node_modules/bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", - "license": "MIT", - "dependencies": { - "base-x": "^3.0.2" - } - }, - "node_modules/bs58check": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", - "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", - "license": "MIT", - "dependencies": { - "bs58": "^4.0.0", - "create-hash": "^1.1.0", - "safe-buffer": "^5.1.2" - } - }, "node_modules/bser": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", @@ -34557,6 +22599,7 @@ "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, "funding": [ { "type": "github", @@ -34576,57 +22619,11 @@ "ieee754": "^1.1.13" } }, - "node_modules/buffer-alloc": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", - "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", - "license": "MIT", - "peer": true, - "dependencies": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" - } - }, - "node_modules/buffer-alloc-unsafe": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", - "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", - "license": "MIT", - "peer": true - }, - "node_modules/buffer-equals": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/buffer-equals/-/buffer-equals-1.0.4.tgz", - "integrity": "sha512-99MsCq0j5+RhubVEtKQgKaD6EM+UP3xJgIvQqwJ3SOLDUekzxMX1ylXBng+Wa2sh7mGT0W6RUly8ojjr1Tt6nA==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/buffer-fill": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", - "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==", - "license": "MIT", - "peer": true - }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, - "node_modules/buffer-to-arraybuffer": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz", - "integrity": "sha512-3dthu5CYiVB1DEJp61FtApNnNndTckcqe4pFcLdvHtrpG+kcyekCJKg4MRiDcFW7A6AODnXB9U4dwQiCW5kzJQ==", - "license": "MIT" - }, - "node_modules/buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", - "license": "MIT" - }, "node_modules/bufferutil": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.8.tgz", @@ -34639,14 +22636,6 @@ "node": ">=6.14.2" } }, - "node_modules/builtins": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", - "integrity": "sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==", - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/bull": { "version": "4.16.4", "resolved": "https://registry.npmjs.org/bull/-/bull-4.16.4.tgz", @@ -34709,27 +22698,6 @@ "node": ">=10.16.0" } }, - "node_modules/bytebuffer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/bytebuffer/-/bytebuffer-5.0.1.tgz", - "integrity": "sha512-IuzSdmADppkZ6DlpycMkm8l9zeEq16fWtLvunEwFiYciR/BHo4E8/xs5piFquG+Za8OWmMqHF8zuRviz2LHvRQ==", - "license": "Apache-2.0", - "dependencies": { - "long": "~3" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/bytebuffer/node_modules/long": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", - "integrity": "sha512-ZYvPPOMqUwPoDsbJaR10iQJYnMuZhRTvHYl62ErLIEX7RgFlziSBUUvrt3OVfc47QlHHpzPZYP17g3Fv7oeJkg==", - "license": "Apache-2.0", - "engines": { - "node": ">=0.6" - } - }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -34738,149 +22706,6 @@ "node": ">= 0.8" } }, - "node_modules/c32check": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/c32check/-/c32check-1.1.3.tgz", - "integrity": "sha512-ADADE/PjAbJRlwpG3ShaOMbBUlJJZO7xaYSRD5Tub6PixQlgR4s36y9cvMf/YRGpkqX+QOxIdMw216iC320q9A==", - "license": "MIT", - "dependencies": { - "base-x": "^3.0.8", - "buffer": "^5.6.0", - "cross-sha256": "^1.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cacache": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", - "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "@npmcli/fs": "^1.0.0", - "@npmcli/move-file": "^1.0.1", - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.1", - "tar": "^6.0.2", - "unique-filename": "^1.1.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/cacache/node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "license": "ISC", - "optional": true, - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/cacache/node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cacache/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cacache/node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cacache/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "license": "MIT", - "optional": true, - "peer": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cacache/node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cacache/node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "license": "ISC", - "optional": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, "node_modules/cache-content-type": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.1.tgz", @@ -35058,156 +22883,6 @@ } ] }, - "node_modules/capability": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/capability/-/capability-0.2.5.tgz", - "integrity": "sha512-rsJZYVCgXd08sPqwmaIqjAd5SUTfonV0z/gDJ8D6cN8wQphky1kkAYEqQ+hmDxTw7UihvBfjUVUSY+DBEe44jg==", - "license": "MIT" - }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", - "license": "Apache-2.0" - }, - "node_modules/cashaddress": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/cashaddress/-/cashaddress-1.1.0.tgz", - "integrity": "sha512-cdqIjZodtErhoQOiojQ1SRqDKh6bOVkLYNJjMmFEUxGoErrO2am8txotXmEi8glvU/y9wzup+LsvEBl8AttUwA==", - "license": "MIT", - "dependencies": { - "bigi": "^1.4.2" - } - }, - "node_modules/casper-js-sdk": { - "version": "2.7.6", - "resolved": "https://registry.npmjs.org/casper-js-sdk/-/casper-js-sdk-2.7.6.tgz", - "integrity": "sha512-sFxcMcxnV+aq/d/BHyA7WfMuNUP9sKyZDKNbF/00TJR6Ii730Xl94HXO3y0YNgM8hOiRH5vqAcxtdxEuRuifmQ==", - "license": "Apache 2.0", - "dependencies": { - "@ethersproject/bignumber": "^5.0.8", - "@ethersproject/bytes": "^5.0.5", - "@ethersproject/constants": "^5.0.5", - "@open-rpc/client-js": "^1.6.2", - "@types/eccrypto": "^1.1.2", - "@types/ws": "^8.2.2", - "blakejs": "^1.1.0", - "eccrypto": "^1.1.6", - "eslint-plugin-prettier": "^3.4.0", - "ethereum-cryptography": "^0.1.3", - "glob": "^7.1.6", - "humanize-duration": "^3.24.0", - "key-encoder": "^2.0.3", - "reflect-metadata": "^0.1.13", - "ts-results": "^3.2.1", - "tweetnacl-ts": "^1.0.3", - "tweetnacl-util": "^0.15.0", - "typedjson": "^1.6.0-rc2", - "webpack": "^5.24.3" - } - }, - "node_modules/casper-js-sdk/node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "license": "MIT", - "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" - } - }, - "node_modules/casper-js-sdk/node_modules/node-addon-api": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", - "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", - "license": "MIT" - }, - "node_modules/casper-js-sdk/node_modules/secp256k1": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.4.tgz", - "integrity": "sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "elliptic": "^6.5.7", - "node-addon-api": "^5.0.0", - "node-gyp-build": "^4.2.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/catharsis": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", - "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", - "license": "MIT", - "dependencies": { - "lodash": "^4.17.15" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/cbor-extract": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cbor-extract/-/cbor-extract-2.2.0.tgz", - "integrity": "sha512-Ig1zM66BjLfTXpNgKpvBePq271BPOvu8MR0Jl080yG7Jsl+wAZunfrwiwA+9ruzm/WEdIV5QF/bjDZTqyAIVHA==", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "dependencies": { - "node-gyp-build-optional-packages": "5.1.1" - }, - "bin": { - "download-cbor-prebuilds": "bin/download-prebuilds.js" - }, - "optionalDependencies": { - "@cbor-extract/cbor-extract-darwin-arm64": "2.2.0", - "@cbor-extract/cbor-extract-darwin-x64": "2.2.0", - "@cbor-extract/cbor-extract-linux-arm": "2.2.0", - "@cbor-extract/cbor-extract-linux-arm64": "2.2.0", - "@cbor-extract/cbor-extract-linux-x64": "2.2.0", - "@cbor-extract/cbor-extract-win32-x64": "2.2.0" - } - }, - "node_modules/cbor-extract/node_modules/node-gyp-build-optional-packages": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.1.1.tgz", - "integrity": "sha512-+P72GAjVAbTxjjwUmwjVrqrdZROD4nf8KgpBoDxqXXTiYZZt/ud60dE5yvCSr9lRO8e8yv6kgJIC0K0PfZFVQw==", - "license": "MIT", - "optional": true, - "dependencies": { - "detect-libc": "^2.0.1" - }, - "bin": { - "node-gyp-build-optional-packages": "bin.js", - "node-gyp-build-optional-packages-optional": "optional.js", - "node-gyp-build-optional-packages-test": "build-test.js" - } - }, - "node_modules/cbor-x": { - "version": "1.5.9", - "resolved": "https://registry.npmjs.org/cbor-x/-/cbor-x-1.5.9.tgz", - "integrity": "sha512-OEI5rEu3MeR0WWNUXuIGkxmbXVhABP+VtgAXzm48c9ulkrsvxshjjk94XSOGphyAKeNGLPfAxxzEtgQ6rEVpYQ==", - "license": "MIT", - "optionalDependencies": { - "cbor-extract": "^2.2.0" - } - }, "node_modules/cbw-sdk": { "name": "@coinbase/wallet-sdk", "version": "3.9.3", @@ -35335,17 +23010,6 @@ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, - "node_modules/charenc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", - "license": "BSD-3-Clause", - "optional": true, - "peer": true, - "engines": { - "node": "*" - } - }, "node_modules/cheerio": { "version": "1.0.0-rc.12", "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", @@ -35416,12 +23080,6 @@ "fsevents": "~2.3.2" } }, - "node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "license": "ISC" - }, "node_modules/chrome-launcher": { "version": "0.15.2", "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.2.tgz", @@ -35491,48 +23149,6 @@ "node": ">=8" } }, - "node_modules/cids": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/cids/-/cids-0.7.5.tgz", - "integrity": "sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA==", - "deprecated": "This module has been superseded by the multiformats module", - "license": "MIT", - "dependencies": { - "buffer": "^5.5.0", - "class-is": "^1.1.0", - "multibase": "~0.6.0", - "multicodec": "^1.0.0", - "multihashes": "~0.4.15" - }, - "engines": { - "node": ">=4.0.0", - "npm": ">=3.0.0" - } - }, - "node_modules/cids/node_modules/multicodec": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-1.0.4.tgz", - "integrity": "sha512-NDd7FeS3QamVtbgfvu5h7fd1IlbaC4EQ0/pgU4zqE2vdHCmBGsUa0TiM8/TdSeG6BMPC92OOCf8F1ocE/Wkrrg==", - "deprecated": "This module has been superseded by the multiformats module", - "license": "MIT", - "dependencies": { - "buffer": "^5.6.0", - "varint": "^5.0.0" - } - }, - "node_modules/cipher-base": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.6.tgz", - "integrity": "sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.4", - "safe-buffer": "^5.2.1" - }, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/citty": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", @@ -35554,12 +23170,6 @@ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==" }, - "node_modules/class-is": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/class-is/-/class-is-1.1.0.tgz", - "integrity": "sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw==", - "license": "MIT" - }, "node_modules/class-transformer": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", @@ -35629,7 +23239,7 @@ "version": "2.6.1", "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", - "devOptional": true, + "dev": true, "engines": { "node": ">=6" }, @@ -35970,7 +23580,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "devOptional": true, + "dev": true, "engines": { "node": ">=0.8" } @@ -36001,27 +23611,6 @@ "node": ">=0.10.0" } }, - "node_modules/clone-response": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", - "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", - "license": "MIT", - "dependencies": { - "mimic-response": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/clone-response/node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/clsx": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", @@ -36154,14 +23743,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/command-exists": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", - "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/commander": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", @@ -36192,17 +23773,7 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/component-type": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/component-type/-/component-type-1.2.2.tgz", - "integrity": "sha512-99VUHREHiN5cLeHm3YLq312p6v+HUEcwtLCAtelvUDI6+SH5g5Cr85oNR2S1o6ywzL0ykMbuwLzM2ANocjEOIA==", - "license": "MIT", - "optional": true, - "peer": true, + "dev": true, "funding": { "url": "https://github.com/sponsors/sindresorhus" } @@ -36543,17 +24114,6 @@ "node": ">= 0.6" } }, - "node_modules/content-hash": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/content-hash/-/content-hash-2.5.2.tgz", - "integrity": "sha512-FvIQKy0S1JaWV10sMsA7TRx8bpU+pqPkhbsfvOJAdjRXvYxEckAwQWGwtRjiaJfh+E0DvcWUGqcdjwMGFjsSdw==", - "license": "ISC", - "dependencies": { - "cids": "^0.7.1", - "multicodec": "^0.5.5", - "multihashes": "^0.4.15" - } - }, "node_modules/content-type": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", @@ -36588,7 +24148,8 @@ "node_modules/cookiejar": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", - "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==" + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", + "dev": true }, "node_modules/cookies": { "version": "0.8.0", @@ -36798,57 +24359,6 @@ } } }, - "node_modules/cosmjs-types": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/cosmjs-types/-/cosmjs-types-0.6.1.tgz", - "integrity": "sha512-fRz6yzElHHBULDyLArF/G1UkkTWW4r3RondBUGnmSsZWYI5NpfDn32MVa5aRmpaaf4tJI2cbnXHs9fykwU7Ttg==", - "license": "Apache-2.0", - "dependencies": { - "long": "^4.0.0", - "protobufjs": "~6.11.2" - } - }, - "node_modules/cosmjs-types/node_modules/long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", - "license": "Apache-2.0" - }, - "node_modules/cosmjs-types/node_modules/protobufjs": { - "version": "6.11.4", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.4.tgz", - "integrity": "sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw==", - "hasInstallScript": true, - "license": "BSD-3-Clause", - "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/long": "^4.0.1", - "@types/node": ">=13.7.0", - "long": "^4.0.0" - }, - "bin": { - "pbjs": "bin/pbjs", - "pbts": "bin/pbts" - } - }, - "node_modules/crc": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", - "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", - "license": "MIT", - "dependencies": { - "buffer": "^5.1.0" - } - }, "node_modules/crc-32": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", @@ -36860,49 +24370,6 @@ "node": ">=0.8" } }, - "node_modules/create-ecdh": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", - "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", - "license": "MIT", - "dependencies": { - "bn.js": "^4.1.0", - "elliptic": "^6.5.3" - } - }, - "node_modules/create-ecdh/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", - "license": "MIT" - }, - "node_modules/create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "license": "MIT", - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "node_modules/create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "license": "MIT", - "dependencies": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, "node_modules/create-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", @@ -36949,15 +24416,6 @@ "node-fetch": "^2.6.12" } }, - "node_modules/cross-sha256": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/cross-sha256/-/cross-sha256-1.2.0.tgz", - "integrity": "sha512-KViLNMDZKV7jwFqjFx+rNhG26amnFYYQ0S+VaFlVvpk8tM+2XbFia/don/SjGHg9WQxnFVi6z64CGPuF3T+nNw==", - "license": "(MIT AND BSD-3-Clause)", - "dependencies": { - "buffer": "^5.6.0" - } - }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -36979,45 +24437,6 @@ "uncrypto": "^0.1.3" } }, - "node_modules/crypt": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", - "license": "BSD-3-Clause", - "optional": true, - "peer": true, - "engines": { - "node": "*" - } - }, - "node_modules/crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "license": "MIT", - "dependencies": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" - }, - "engines": { - "node": "*" - } - }, - "node_modules/crypto-js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", - "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==", - "license": "MIT" - }, "node_modules/crypto-random-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", @@ -37191,12 +24610,6 @@ "node": ">=4" } }, - "node_modules/cssfilter": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/cssfilter/-/cssfilter-0.0.10.tgz", - "integrity": "sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw==", - "license": "MIT" - }, "node_modules/cssnano": { "version": "6.1.2", "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-6.1.2.tgz", @@ -37349,49 +24762,17 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, - "node_modules/d": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", - "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", - "license": "ISC", - "dependencies": { - "es5-ext": "^0.10.64", - "type": "^2.7.2" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/dag-map": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/dag-map/-/dag-map-1.0.2.tgz", - "integrity": "sha512-+LSAiGFwQ9dRnRdOeaj7g47ZFJcOUPukAP8J3A3fuZ1g9Y44BG+P1sgApjLXTQPOzC4+7S9Wr8kXsfpINM4jpw==", - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", "dev": true }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", - "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/data-uri-to-buffer": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", + "dev": true, "engines": { "node": ">= 14" } @@ -37476,15 +24857,6 @@ "node": ">=4.0" } }, - "node_modules/dateformat": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", - "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", - "license": "MIT", - "engines": { - "node": "*" - } - }, "node_modules/debounce": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", @@ -37608,7 +24980,8 @@ "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "devOptional": true }, "node_modules/deepmerge": { "version": "4.3.1", @@ -37661,7 +25034,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "devOptional": true, + "dev": true, "dependencies": { "clone": "^1.0.2" }, @@ -37726,6 +25099,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", + "dev": true, "dependencies": { "ast-types": "^0.13.4", "escodegen": "^2.1.0", @@ -37739,6 +25113,7 @@ "version": "0.13.4", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "dev": true, "dependencies": { "tslib": "^2.0.1" }, @@ -37767,18 +25142,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/delay": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz", - "integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -37817,16 +25180,6 @@ "node": ">=6" } }, - "node_modules/des.js": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz", - "integrity": "sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, "node_modules/destr": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.3.tgz", @@ -37935,6 +25288,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "dev": true, "dependencies": { "asap": "^2.0.0", "wrappy": "1" @@ -37964,23 +25318,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/diffie-hellman": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "license": "MIT", - "dependencies": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - } - }, - "node_modules/diffie-hellman/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", - "license": "MIT" - }, "node_modules/dijkstrajs": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", @@ -38018,6 +25355,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "devOptional": true, "dependencies": { "esutils": "^2.0.2" }, @@ -38052,11 +25390,6 @@ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "node_modules/dom-walk": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", - "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" - }, "node_modules/domelementtype": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", @@ -38183,32 +25516,11 @@ "node": ">=4" } }, - "node_modules/drbg.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/drbg.js/-/drbg.js-1.0.1.tgz", - "integrity": "sha512-F4wZ06PvqxYLFEZKkFxTDcns9oFNk34hvmJSEwdzsxVQ8YI5YaxtACgQatkYgv2VI2CFkUd2Y+xosPQnHv809g==", - "license": "MIT", - "optional": true, - "dependencies": { - "browserify-aes": "^1.0.6", - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/duplexer": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" }, - "node_modules/duplexer3": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz", - "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==", - "license": "BSD-3-Clause" - }, "node_modules/duplexify": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.3.tgz", @@ -38234,92 +25546,6 @@ "wcwidth": ">=1.0.1" } }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", - "license": "MIT", - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/ecc-jsbn/node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", - "license": "MIT" - }, - "node_modules/eccrypto": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/eccrypto/-/eccrypto-1.1.6.tgz", - "integrity": "sha512-d78ivVEzu7Tn0ZphUUaL43+jVPKTMPFGtmgtz1D0LrFn7cY3K8CdrvibuLz2AAkHBLKZtR8DMbB2ukRYFk987A==", - "hasInstallScript": true, - "license": "CC0-1.0", - "dependencies": { - "acorn": "7.1.1", - "elliptic": "6.5.4", - "es6-promise": "4.2.8", - "nan": "2.14.0" - }, - "optionalDependencies": { - "secp256k1": "3.7.1" - } - }, - "node_modules/eccrypto/node_modules/acorn": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz", - "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==", - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/eccrypto/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", - "license": "MIT" - }, - "node_modules/eccrypto/node_modules/elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "license": "MIT", - "dependencies": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/eccrypto/node_modules/secp256k1": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.7.1.tgz", - "integrity": "sha512-1cf8sbnRreXrQFdH6qsg2H71Xw91fCCS9Yp021GnUNJzWJS/py96fS4lHbnTnouLp08Xj6jBoBB6V78Tdbdu5g==", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "dependencies": { - "bindings": "^1.5.0", - "bip66": "^1.1.5", - "bn.js": "^4.11.8", - "create-hash": "^1.2.0", - "drbg.js": "^1.0.1", - "elliptic": "^6.4.1", - "nan": "^2.14.0", - "safe-buffer": "^5.1.2" - }, - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/eciesjs": { "version": "0.3.21", "resolved": "https://registry.npmjs.org/eciesjs/-/eciesjs-0.3.21.tgz", @@ -38331,30 +25557,6 @@ "secp256k1": "^5.0.1" } }, - "node_modules/ecpair": { - "name": "@bitgo/ecpair", - "version": "2.1.0-rc.0", - "resolved": "https://registry.npmjs.org/@bitgo/ecpair/-/ecpair-2.1.0-rc.0.tgz", - "integrity": "sha512-qPZetcEA1Lzzm9NsqsGF9NGorAGaXrv20eZjopLUjsdwftWcsYTE7lwzE/Xjdf4fcq6G4+vjrCudWAMGNfJqOQ==", - "license": "MIT", - "dependencies": { - "randombytes": "^2.1.0", - "typeforce": "^1.18.0", - "wif": "^2.0.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/ecurve": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/ecurve/-/ecurve-1.0.5.tgz", - "integrity": "sha512-1Z3Zu5Nh5LSVGnwEnie1LDoHZByZxG2tk3wftkqeVHrfujmR8O+dOh96HVPxRPh4BjRWX0Z9mpwCYv/O/njgDw==", - "license": "MIT", - "dependencies": { - "bigi": "^1.1.0" - } - }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -38455,29 +25657,6 @@ "node": ">= 0.8" } }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "license": "MIT", - "peer": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, - "node_modules/encoding/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "license": "MIT", - "peer": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -38561,142 +25740,6 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/env-editor": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/env-editor/-/env-editor-0.4.2.tgz", - "integrity": "sha512-ObFo8v4rQJAE59M69QzwloxPZtd33TpYEIjtKD1rrFDcM1Gd7IkDxEBU+HriziN6HSHQnBJi8Dmy+JWkav5HKA==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eol": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/eol/-/eol-0.5.1.tgz", - "integrity": "sha512-mlG6+lv5G7pXnSK/k7jh7B++h3nIxoNdevctYQWfd14UUvowwseRWpYdqXdYeumDwPAp69DorsnK/eWK9lm4AA==", - "license": "MIT" - }, - "node_modules/eosjs": { - "version": "21.0.4", - "resolved": "https://registry.npmjs.org/eosjs/-/eosjs-21.0.4.tgz", - "integrity": "sha512-XbuIoidplA1hHIejy7VQ+hmBfC6T28kYFaQMsn6G1DMTg1CFwUzxwzUvZg/dGNPuf7hgPxOpaQvAUsdidTgGhQ==", - "license": "MIT", - "dependencies": { - "bn.js": "5.2.0", - "elliptic": "6.5.4", - "hash.js": "1.1.7", - "pako": "2.0.3" - } - }, - "node_modules/eosjs-ecc": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eosjs-ecc/-/eosjs-ecc-4.0.7.tgz", - "integrity": "sha512-uuqhqnrDy9XTpKfkhiZqRDUTCCI9oWBalVK5IosL7kpYwA9I3lm68INYFLyWsHpF2xwHqPql8MrMYJ3zfOn5Qg==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "7.6.0", - "bigi": "1.4.2", - "browserify-aes": "1.0.6", - "bs58": "4.0.1", - "bytebuffer": "5.0.1", - "create-hash": "1.1.3", - "create-hmac": "1.1.6", - "ecurve": "1.0.5", - "randombytes": "2.0.5" - } - }, - "node_modules/eosjs-ecc/node_modules/@babel/runtime": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.0.tgz", - "integrity": "sha512-89eSBLJsxNxOERC0Op4vd+0Bqm6wRMqMbFtV3i0/fbaWw/mJ8Q3eBvgX0G4SyrOOLCtbu98HspF8o09MRT+KzQ==", - "license": "MIT", - "dependencies": { - "regenerator-runtime": "^0.13.2" - } - }, - "node_modules/eosjs-ecc/node_modules/browserify-aes": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.0.6.tgz", - "integrity": "sha512-MMvWM6jpfsiuzY2Y+pRJvHRac3x3rHWQisWoz1dJaF9qDFsD8HdVxB7MyZKeLKeEt0fEjrXXZ0mxgTHSoJusug==", - "license": "MIT", - "dependencies": { - "buffer-xor": "^1.0.2", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.0", - "inherits": "^2.0.1" - } - }, - "node_modules/eosjs-ecc/node_modules/create-hash": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", - "integrity": "sha512-snRpch/kwQhcdlnZKYanNF1m0RDlrCdSKQaH87w1FCFPVPNCQ/Il9QJKAX2jVBZddRdaHBMC+zXa9Gw9tmkNUA==", - "license": "MIT", - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "sha.js": "^2.4.0" - } - }, - "node_modules/eosjs-ecc/node_modules/create-hmac": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", - "integrity": "sha512-23osI7H2SH6Zm4g7A7BTM9+3XicGZkemw00eEhrFViR3EdGru+azj2fMKf9J2zWMGO7AfPgYRdIRL96kkdy8QA==", - "license": "MIT", - "dependencies": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "node_modules/eosjs-ecc/node_modules/randombytes": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz", - "integrity": "sha512-8T7Zn1AhMsQ/HI1SjcCfT/t4ii3eAqco3yOcSzS4mozsOz69lHLsoMXmF9nZgnFanYscnSlUSgs8uZyKzpE6kg==", - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/eosjs-ecc/node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", - "license": "MIT" - }, - "node_modules/eosjs/node_modules/bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", - "license": "MIT" - }, - "node_modules/eosjs/node_modules/elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "license": "MIT", - "dependencies": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/eosjs/node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", - "license": "MIT" - }, "node_modules/errno": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", @@ -38724,17 +25767,6 @@ "integrity": "sha512-JM8N6PytDbmIYm1IhPWlo8vr3NtfjhDY/1MhD/a5b/aad/USE8a0+NsqE9d5n+GVGmuNkPQWm4bFQWv18d8tMg==", "dev": true }, - "node_modules/error-polyfill": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/error-polyfill/-/error-polyfill-0.1.3.tgz", - "integrity": "sha512-XHJk60ufE+TG/ydwp4lilOog549iiQF2OAPhkk9DdiYWMrltz5yhDz/xnKuenNwP7gy3dsibssO5QpVhkrSzzg==", - "license": "MIT", - "dependencies": { - "capability": "^0.2.5", - "o3": "^1.0.3", - "u3": "^0.1.1" - } - }, "node_modules/error-stack-parser": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", @@ -38922,79 +25954,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es5-ext": { - "version": "0.10.64", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", - "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", - "hasInstallScript": true, - "license": "ISC", - "dependencies": { - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.3", - "esniff": "^2.0.1", - "next-tick": "^1.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", - "license": "MIT", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/es6-object-assign": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", - "integrity": "sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw==", - "license": "MIT" - }, - "node_modules/es6-promise": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", - "license": "MIT" - }, - "node_modules/es6-promisify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", - "integrity": "sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==", - "license": "MIT", - "dependencies": { - "es6-promise": "^4.0.3" - } - }, - "node_modules/es6-symbol": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz", - "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==", - "license": "ISC", - "dependencies": { - "d": "^1.0.2", - "ext": "^1.7.0" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "license": "ISC", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -39034,6 +25993,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dev": true, "dependencies": { "esprima": "^4.0.1", "estraverse": "^5.2.0", @@ -39054,6 +26014,7 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, "optional": true, "engines": { "node": ">=0.10.0" @@ -39063,6 +26024,7 @@ "version": "8.57.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "devOptional": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -39642,27 +26604,6 @@ "node": "*" } }, - "node_modules/eslint-plugin-prettier": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz", - "integrity": "sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==", - "license": "MIT", - "dependencies": { - "prettier-linter-helpers": "^1.0.0" - }, - "engines": { - "node": ">=6.0.0" - }, - "peerDependencies": { - "eslint": ">=5.0.0", - "prettier": ">=1.13.0" - }, - "peerDependenciesMeta": { - "eslint-config-prettier": { - "optional": true - } - } - }, "node_modules/eslint-plugin-react": { "version": "7.34.3", "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.3.tgz", @@ -39762,6 +26703,7 @@ "version": "7.2.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "devOptional": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -39777,6 +26719,7 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "devOptional": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -39788,6 +26731,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "devOptional": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -39803,6 +26747,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "devOptional": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -39812,6 +26757,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "devOptional": true, "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -39827,6 +26773,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "devOptional": true, "dependencies": { "is-glob": "^4.0.3" }, @@ -39838,6 +26785,7 @@ "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "devOptional": true, "dependencies": { "type-fest": "^0.20.2" }, @@ -39851,12 +26799,14 @@ "node_modules/eslint/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "devOptional": true }, "node_modules/eslint/node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "devOptional": true, "dependencies": { "p-locate": "^5.0.0" }, @@ -39871,6 +26821,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "devOptional": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -39882,6 +26833,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "devOptional": true, "dependencies": { "p-limit": "^3.0.2" }, @@ -39896,6 +26848,7 @@ "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "devOptional": true, "engines": { "node": ">=10" }, @@ -39903,25 +26856,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/esniff": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", - "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", - "license": "ISC", - "dependencies": { - "d": "^1.0.1", - "es5-ext": "^0.10.62", - "event-emitter": "^0.3.5", - "type": "^2.7.2" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/espree": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "devOptional": true, "dependencies": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", @@ -39950,6 +26889,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "devOptional": true, "dependencies": { "estraverse": "^5.1.0" }, @@ -40134,22 +27074,6 @@ "node": ">=10" } }, - "node_modules/eth-ens-namehash": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz", - "integrity": "sha512-VWEI1+KJfz4Km//dadyvBBoBeSQ0MHTXPvr8UIXiLW6IanxvAV+DmlZAijZwAyggqGUfwQBeHf7tc9wzc1piSw==", - "license": "ISC", - "dependencies": { - "idna-uts46-hx": "^2.3.1", - "js-sha3": "^0.5.7" - } - }, - "node_modules/eth-ens-namehash/node_modules/js-sha3": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", - "integrity": "sha512-GII20kjaPX0zJ8wzkTbNDYMY7msuZcTWk8S5UOh6806Jq/wz1J8/bnr8uGU0DAUmYDjj2Mr4X1cW8v/GLYnR+g==", - "license": "MIT" - }, "node_modules/eth-json-rpc-filters": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/eth-json-rpc-filters/-/eth-json-rpc-filters-6.0.1.tgz", @@ -40176,23 +27100,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eth-lib": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", - "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", - "license": "MIT", - "dependencies": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "node_modules/eth-lib/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", - "license": "MIT" - }, "node_modules/eth-query": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/eth-query/-/eth-query-2.1.2.tgz", @@ -40210,15 +27117,6 @@ "fast-safe-stringify": "^2.0.6" } }, - "node_modules/ethereum-bloom-filters": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.2.0.tgz", - "integrity": "sha512-28hyiE7HVsWubqhpVLVmZXFd4ITeHi+BUu05o9isf0GUpMtzBUi+8/gFrGaGYzvGAJQmJ3JKj77Mk9G98T84rA==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "^1.4.0" - } - }, "node_modules/ethereum-cryptography": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", @@ -40254,325 +27152,6 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/ethereumjs-abi": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz", - "integrity": "sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==", - "deprecated": "This library has been deprecated and usage is discouraged.", - "license": "MIT", - "dependencies": { - "bn.js": "^4.11.8", - "ethereumjs-util": "^6.0.0" - } - }, - "node_modules/ethereumjs-abi/node_modules/@types/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/ethereumjs-abi/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", - "license": "MIT" - }, - "node_modules/ethereumjs-abi/node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "license": "MIT", - "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" - } - }, - "node_modules/ethereumjs-abi/node_modules/ethereumjs-util": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", - "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", - "license": "MPL-2.0", - "dependencies": { - "@types/bn.js": "^4.11.3", - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "0.1.6", - "rlp": "^2.2.3" - } - }, - "node_modules/ethereumjs-abi/node_modules/node-addon-api": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", - "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", - "license": "MIT" - }, - "node_modules/ethereumjs-abi/node_modules/secp256k1": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.4.tgz", - "integrity": "sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "elliptic": "^6.5.7", - "node-addon-api": "^5.0.0", - "node-gyp-build": "^4.2.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/ethereumjs-common": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/ethereumjs-common/-/ethereumjs-common-1.5.2.tgz", - "integrity": "sha512-hTfZjwGX52GS2jcVO6E2sx4YuFnf0Fhp5ylo4pEPhEffNln7vS59Hr5sLnp3/QCazFLluuBZ+FZ6J5HTp0EqCA==", - "deprecated": "New package name format for new versions: @ethereumjs/common. Please update.", - "license": "MIT" - }, - "node_modules/ethereumjs-tx": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz", - "integrity": "sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw==", - "deprecated": "New package name format for new versions: @ethereumjs/tx. Please update.", - "license": "MPL-2.0", - "dependencies": { - "ethereumjs-common": "^1.5.0", - "ethereumjs-util": "^6.0.0" - } - }, - "node_modules/ethereumjs-tx/node_modules/@types/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/ethereumjs-tx/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", - "license": "MIT" - }, - "node_modules/ethereumjs-tx/node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "license": "MIT", - "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" - } - }, - "node_modules/ethereumjs-tx/node_modules/ethereumjs-util": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", - "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", - "license": "MPL-2.0", - "dependencies": { - "@types/bn.js": "^4.11.3", - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "0.1.6", - "rlp": "^2.2.3" - } - }, - "node_modules/ethereumjs-tx/node_modules/node-addon-api": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", - "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", - "license": "MIT" - }, - "node_modules/ethereumjs-tx/node_modules/secp256k1": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.4.tgz", - "integrity": "sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "elliptic": "^6.5.7", - "node-addon-api": "^5.0.0", - "node-gyp-build": "^4.2.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/ethereumjs-util": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz", - "integrity": "sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==", - "license": "MPL-2.0", - "dependencies": { - "@types/bn.js": "^5.1.0", - "bn.js": "^5.1.2", - "create-hash": "^1.1.2", - "ethereum-cryptography": "^0.1.3", - "rlp": "^2.2.4" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/ethereumjs-util/node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "license": "MIT", - "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" - } - }, - "node_modules/ethereumjs-util/node_modules/node-addon-api": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", - "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", - "license": "MIT" - }, - "node_modules/ethereumjs-util/node_modules/secp256k1": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.4.tgz", - "integrity": "sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "elliptic": "^6.5.7", - "node-addon-api": "^5.0.0", - "node-gyp-build": "^4.2.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/ethers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", - "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/abi": "5.7.0", - "@ethersproject/abstract-provider": "5.7.0", - "@ethersproject/abstract-signer": "5.7.0", - "@ethersproject/address": "5.7.0", - "@ethersproject/base64": "5.7.0", - "@ethersproject/basex": "5.7.0", - "@ethersproject/bignumber": "5.7.0", - "@ethersproject/bytes": "5.7.0", - "@ethersproject/constants": "5.7.0", - "@ethersproject/contracts": "5.7.0", - "@ethersproject/hash": "5.7.0", - "@ethersproject/hdnode": "5.7.0", - "@ethersproject/json-wallets": "5.7.0", - "@ethersproject/keccak256": "5.7.0", - "@ethersproject/logger": "5.7.0", - "@ethersproject/networks": "5.7.1", - "@ethersproject/pbkdf2": "5.7.0", - "@ethersproject/properties": "5.7.0", - "@ethersproject/providers": "5.7.2", - "@ethersproject/random": "5.7.0", - "@ethersproject/rlp": "5.7.0", - "@ethersproject/sha2": "5.7.0", - "@ethersproject/signing-key": "5.7.0", - "@ethersproject/solidity": "5.7.0", - "@ethersproject/strings": "5.7.0", - "@ethersproject/transactions": "5.7.0", - "@ethersproject/units": "5.7.0", - "@ethersproject/wallet": "5.7.0", - "@ethersproject/web": "5.7.1", - "@ethersproject/wordlists": "5.7.0" - } - }, - "node_modules/ethjs-unit": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", - "integrity": "sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw==", - "license": "MIT", - "dependencies": { - "bn.js": "4.11.6", - "number-to-bn": "1.7.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/ethjs-unit/node_modules/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==", - "license": "MIT" - }, - "node_modules/ethjs-util": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", - "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", - "license": "MIT", - "dependencies": { - "is-hex-prefixed": "1.0.0", - "strip-hex-prefix": "1.0.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, "node_modules/eval": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/eval/-/eval-0.1.8.tgz", @@ -40585,21 +27164,12 @@ "node": ">= 0.8" } }, - "node_modules/event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", - "license": "MIT", - "dependencies": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, "node_modules/event-target-shim": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", "license": "MIT", + "peer": true, "engines": { "node": ">=6" } @@ -40622,33 +27192,6 @@ "node": ">=0.8.x" } }, - "node_modules/eventsource": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.1.2.tgz", - "integrity": "sha512-xAH3zWhgO2/3KIniEKYPr8plNSzlGINOUqYj0m0u7AB81iRw8b/3E73W6AuU+6klLbaSFmZnaETQ2lXPfAydrA==", - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "license": "MIT", - "dependencies": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/exec-async": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/exec-async/-/exec-async-2.2.0.tgz", - "integrity": "sha512-87OpwcEiMia/DeiKFzaQNBNFeN3XkkpYIh9FyOqq5mS2oKv3CBE67PXoEKcr6nodWdXNogTiQ0jE2NGuoffXPw==", - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -40708,406 +27251,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/expo": { - "version": "44.0.6", - "resolved": "https://registry.npmjs.org/expo/-/expo-44.0.6.tgz", - "integrity": "sha512-iHnra6uD5kXZgdSUrvxZ3sLjg1FtgtA4p4uaSKVQ39IaMHJBngo8RKqFUJ+BF2kPDpBLJ251eLlhgYUlnAyuag==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/runtime": "^7.14.0", - "@expo/metro-config": "~0.2.6", - "@expo/vector-icons": "^12.0.4", - "babel-preset-expo": "~9.0.2", - "cross-spawn": "^6.0.5", - "expo-application": "~4.0.2", - "expo-asset": "~8.4.6", - "expo-constants": "~13.0.2", - "expo-file-system": "~13.1.3", - "expo-font": "~10.0.5", - "expo-keep-awake": "~10.0.2", - "expo-modules-autolinking": "0.5.5", - "expo-modules-core": "0.6.5", - "fbemitter": "^2.1.1", - "invariant": "^2.2.4", - "md5-file": "^3.2.3", - "pretty-format": "^26.5.2", - "uuid": "^3.4.0" - }, - "bin": { - "expo": "bin/cli.js" - }, - "optionalDependencies": { - "expo-error-recovery": "~3.0.5" - } - }, - "node_modules/expo-application": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/expo-application/-/expo-application-4.0.2.tgz", - "integrity": "sha512-ngTaFplTkWn0X45gMC+VNXGyJfGxX4wOwKmtr17rNMVWOQUhhLlyMkTj9bAamzsuwZh35l3S/eD/N1aMWWUwMw==", - "license": "MIT", - "peer": true, - "peerDependencies": { - "expo": "*" - } - }, - "node_modules/expo-asset": { - "version": "8.4.6", - "resolved": "https://registry.npmjs.org/expo-asset/-/expo-asset-8.4.6.tgz", - "integrity": "sha512-Kpzcmmf1lceHnZkAdJOvq7l7SU/hCL59vAj2xUZS66U6lFkUf7LNEA/NzILA56loCd4cka5ShYlWs+BMchyFDQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "blueimp-md5": "^2.10.0", - "invariant": "^2.2.4", - "md5-file": "^3.2.3", - "path-browserify": "^1.0.0", - "url-parse": "^1.4.4" - } - }, - "node_modules/expo-constants": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-13.0.2.tgz", - "integrity": "sha512-vGs/kI65vplPFvG8z4W1ariGEtVHHp9Avl28G0zJprt2v/q1E/BnXjwvFSBPc1GB+Zb/7crWSHWRwjaFULBjsg==", - "license": "MIT", - "peer": true, - "dependencies": { - "@expo/config": "^6.0.6", - "uuid": "^3.3.2" - }, - "peerDependencies": { - "expo": "*" - } - }, - "node_modules/expo-constants/node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "license": "MIT", - "peer": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/expo-crypto": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/expo-crypto/-/expo-crypto-10.2.0.tgz", - "integrity": "sha512-YVFp+DJXBtt4t6oZXepnzb+xwpKzFbXn3B9Oma1Tfh6J0rIlm/I20UW/5apdvEdbj44fxJ5DsiZeyADI3bcZkQ==", - "license": "MIT", - "peerDependencies": { - "expo": "*" - } - }, - "node_modules/expo-error-recovery": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/expo-error-recovery/-/expo-error-recovery-3.0.5.tgz", - "integrity": "sha512-VM6OOecjt0aPu5/eCdGGJfNjvAZIemaQym0JF/+SA5IlLiPpEfbVCDTO/5yiS8Zb5fKpeABx+GCRmtfnFqvRRw==", - "license": "MIT", - "optional": true, - "peer": true, - "peerDependencies": { - "expo": "*" - } - }, - "node_modules/expo-file-system": { - "version": "13.1.4", - "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-13.1.4.tgz", - "integrity": "sha512-/C2FKCzrdWuEt4m8Pzl9J4MhKgfU0denVLbqoKjidv8DnsLQrscFNlLhXuiooqWwsxB2OWAtGEVnPGJBWVuNEQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "@expo/config-plugins": "^4.0.2", - "uuid": "^3.4.0" - }, - "peerDependencies": { - "expo": "*" - } - }, - "node_modules/expo-file-system/node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "license": "MIT", - "peer": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/expo-font": { - "version": "10.0.5", - "resolved": "https://registry.npmjs.org/expo-font/-/expo-font-10.0.5.tgz", - "integrity": "sha512-x9YwM0xLkDdSvFjeNbyuh33Q1Hk3uc2jbMuuAN5W2ZVcUZqG0M8GCX/KV/D/7rYqdXKbliQA5r44MyDwZe/XRw==", - "license": "MIT", - "peer": true, - "dependencies": { - "fontfaceobserver": "^2.1.0" - }, - "peerDependencies": { - "expo": "*" - } - }, - "node_modules/expo-keep-awake": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-10.0.2.tgz", - "integrity": "sha512-Ro1lgyKldbFs4mxhWM+goX9sg0S2SRR8FiJJeOvaRzf8xNhrZfWA00Zpr+/3ocCoWQ3eEL+X9UF4PXXHf0KoOg==", - "license": "MIT", - "peer": true, - "peerDependencies": { - "expo": "*" - } - }, - "node_modules/expo-modules-autolinking": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-0.5.5.tgz", - "integrity": "sha512-bILEG0Fg+ZhIhdEaShHzsEN1WC0hUmXJ5Kcd4cd+8rVk1Ead9vRZxA/yLx1cNBDCOwMe0GAMrhF7TKT+A1P+YA==", - "license": "MIT", - "peer": true, - "dependencies": { - "chalk": "^4.1.0", - "commander": "^7.2.0", - "fast-glob": "^3.2.5", - "find-up": "^5.0.0", - "fs-extra": "^9.1.0" - }, - "bin": { - "expo-modules-autolinking": "bin/expo-modules-autolinking.js" - } - }, - "node_modules/expo-modules-autolinking/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/expo-modules-autolinking/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "license": "MIT", - "peer": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/expo-modules-autolinking/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/expo-modules-autolinking/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "license": "MIT", - "peer": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/expo-modules-autolinking/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "license": "MIT", - "peer": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/expo-modules-core": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-0.6.5.tgz", - "integrity": "sha512-h/9+SJ3m8XkDUV1QrPO8WeXaeRYWLBJrOqhokDyhgWUYSqe6JOuRx1ZkoGq/GmTiwjouRDbXPsXUBiU9HWLYyA==", - "license": "MIT", - "peer": true, - "dependencies": { - "compare-versions": "^3.4.0", - "invariant": "^2.2.4" - } - }, - "node_modules/expo-modules-core/node_modules/compare-versions": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", - "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", - "license": "MIT", - "peer": true - }, - "node_modules/expo-random": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/expo-random/-/expo-random-12.3.0.tgz", - "integrity": "sha512-q+AsTfGNT+Q+fb2sRrYtRkI3g5tV4H0kuYXM186aueILGO/vLn/YYFa7xFZj1IZ8LJZg2h96JDPDpsqHfRG2mQ==", - "deprecated": "This package is now deprecated in favor of expo-crypto, which provides the same functionality. To migrate, replace all imports from expo-random with imports from expo-crypto.", - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.0" - }, - "peerDependencies": { - "expo": "*" - } - }, - "node_modules/expo/node_modules/@jest/types": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", - "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^15.0.0", - "chalk": "^4.0.0" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/expo/node_modules/@types/yargs": { - "version": "15.0.19", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.19.tgz", - "integrity": "sha512-2XUaGVmyQjgyAZldf0D0c14vvo/yv0MhQBSTJcejMMaitsn3nxCB6TmH4G0ZQf+uxROOa9mpanoSm8h6SG/1ZA==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/expo/node_modules/cross-spawn": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", - "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", - "license": "MIT", - "peer": true, - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/expo/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/expo/node_modules/pretty-format": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", - "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/types": "^26.6.2", - "ansi-regex": "^5.0.0", - "ansi-styles": "^4.0.0", - "react-is": "^17.0.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/expo/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/expo/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", - "license": "MIT", - "peer": true, - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expo/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expo/node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "license": "MIT", - "peer": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/expo/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "license": "ISC", - "peer": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, "node_modules/exponential-backoff": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", @@ -41174,15 +27317,6 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, - "node_modules/ext": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", - "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", - "license": "ISC", - "dependencies": { - "type": "^2.7.2" - } - }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -41237,44 +27371,16 @@ "node": ">=0.6.0" } }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", - "engines": [ - "node >=0.6.0" - ], - "license": "MIT" - }, - "node_modules/eyes": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", - "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==", - "engines": { - "node": "> 0.1.90" - } - }, - "node_modules/fast-copy": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.2.tgz", - "integrity": "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==", - "license": "MIT" - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, - "node_modules/fast-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "license": "Apache-2.0" - }, "node_modules/fast-glob": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -41294,7 +27400,8 @@ "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "devOptional": true }, "node_modules/fast-redact": { "version": "3.5.0", @@ -41309,12 +27416,6 @@ "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" }, - "node_modules/fast-stable-stringify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fast-stable-stringify/-/fast-stable-stringify-1.0.0.tgz", - "integrity": "sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag==", - "license": "MIT" - }, "node_modules/fast-url-parser": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", @@ -41344,12 +27445,6 @@ "fxparser": "src/cli/cli.js" } }, - "node_modules/fastpriorityqueue": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/fastpriorityqueue/-/fastpriorityqueue-0.7.5.tgz", - "integrity": "sha512-3Pa0n9gwy8yIbEsT3m2j/E9DXgWvvjfiZjjqcJ+AdNKTAlVMIuFYrYG5Y3RHEM8O6cwv9hOpOWY/NaMfywoQVA==", - "license": "Apache-2.0" - }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", @@ -41389,90 +27484,6 @@ "bser": "2.1.1" } }, - "node_modules/fbemitter": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fbemitter/-/fbemitter-2.1.1.tgz", - "integrity": "sha512-hd8PgD+Q6RQtlcGrkM9oY3MFIjq6CA6wurCK1TKn2eaA76Ww4VAOihmq98NyjRhjJi/axgznZnh9lF8+TcTsNQ==", - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "fbjs": "^0.8.4" - } - }, - "node_modules/fbjs": { - "version": "0.8.18", - "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.18.tgz", - "integrity": "sha512-EQaWFK+fEPSoibjNy8IxUtaFOMXcWsY0JaVrQoZR9zC8N2Ygf9iDITPWjUTVIax95b6I742JFLqASHfsag/vKA==", - "license": "MIT", - "peer": true, - "dependencies": { - "core-js": "^1.0.0", - "isomorphic-fetch": "^2.1.1", - "loose-envify": "^1.0.0", - "object-assign": "^4.1.0", - "promise": "^7.1.1", - "setimmediate": "^1.0.5", - "ua-parser-js": "^0.7.30" - } - }, - "node_modules/fbjs-css-vars": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz", - "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==", - "license": "MIT", - "optional": true, - "peer": true - }, - "node_modules/fbjs/node_modules/core-js": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", - "integrity": "sha512-ZiPp9pZlgxpWRu0M+YWbm6+aQ84XEfH1JRXvfOc/fILWI0VKhLC2LX13X1NYq4fULzLMq7Hfh43CSo2/aIaUPA==", - "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", - "license": "MIT", - "peer": true - }, - "node_modules/fbjs/node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fbjs/node_modules/isomorphic-fetch": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", - "integrity": "sha512-9c4TNAKYXM5PRyVcwUZrF3W09nQ+sO7+jydgs4ZGW9dhsLG2VOlISJABombdQqQRXCwuYG3sYV/puGf5rp0qmA==", - "license": "MIT", - "peer": true, - "dependencies": { - "node-fetch": "^1.0.1", - "whatwg-fetch": ">=0.10.0" - } - }, - "node_modules/fbjs/node_modules/node-fetch": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", - "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "encoding": "^0.1.11", - "is-stream": "^1.0.1" - } - }, - "node_modules/fbjs/node_modules/promise": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", - "license": "MIT", - "peer": true, - "dependencies": { - "asap": "~2.0.3" - } - }, "node_modules/fecha": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", @@ -41489,37 +27500,6 @@ "node": ">=0.4.0" } }, - "node_modules/fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "paypal", - "url": "https://paypal.me/jimmywarting" - } - ], - "license": "MIT", - "dependencies": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - }, - "engines": { - "node": "^12.20 || >= 14.13" - } - }, - "node_modules/fetch-retry": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/fetch-retry/-/fetch-retry-4.1.1.tgz", - "integrity": "sha512-e6eB7zN6UBSwGVwrbWVH+gdLnkW9WwHhmq2YDK1Sh30pzx1onRVGBvogTlUeWxwTa+L86NYdo4hFkh7O8ZjSnA==", - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -41548,6 +27528,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "devOptional": true, "dependencies": { "flat-cache": "^3.0.4" }, @@ -41622,7 +27603,8 @@ "node_modules/file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "optional": true }, "node_modules/filelist": { "version": "1.0.4", @@ -41700,43 +27682,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, - "node_modules/find-babel-config": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-1.2.2.tgz", - "integrity": "sha512-oK59njMyw2y3yxto1BCfVK7MQp/OYf4FleHu0RgosH3riFJ1aOuo/7naLDLAObfrgn3ueFhw5sAT/cp0QuJI3Q==", - "license": "MIT", - "peer": true, - "dependencies": { - "json5": "^1.0.2", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/find-babel-config/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "license": "MIT", - "peer": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/find-babel-config/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=4" - } - }, "node_modules/find-cache-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-4.0.0.tgz", @@ -41788,17 +27733,6 @@ "node": ">=8" } }, - "node_modules/find-yarn-workspace-root": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", - "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", - "license": "Apache-2.0", - "optional": true, - "peer": true, - "dependencies": { - "micromatch": "^4.0.2" - } - }, "node_modules/flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", @@ -41811,6 +27745,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "devOptional": true, "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.3", @@ -41823,7 +27758,8 @@ "node_modules/flatted": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==" + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "devOptional": true }, "node_modules/flow-enums-runtime": { "version": "0.0.6", @@ -41866,13 +27802,6 @@ } } }, - "node_modules/fontfaceobserver": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/fontfaceobserver/-/fontfaceobserver-2.3.0.tgz", - "integrity": "sha512-6FPvD/IVyT4ZlNe7Wcn5Fb/4ChigpucKYSvD6a+0iMoLn2inpo711eyIcKjmDtE5XNcgAkSH9uN/nfAeZzHEfg==", - "license": "BSD-2-Clause", - "peer": true - }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -41904,6 +27833,7 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", + "dev": true, "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" @@ -41919,6 +27849,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, "engines": { "node": ">=14" }, @@ -41926,15 +27857,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", - "license": "Apache-2.0", - "engines": { - "node": "*" - } - }, "node_modules/fork-ts-checker-webpack-plugin": { "version": "7.2.13", "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-7.2.13.tgz", @@ -42121,22 +28043,11 @@ "node": ">=0.4.x" } }, - "node_modules/formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "license": "MIT", - "dependencies": { - "fetch-blob": "^3.1.2" - }, - "engines": { - "node": ">=12.20.0" - } - }, "node_modules/formidable": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.1.tgz", "integrity": "sha512-WJWKelbRHN41m5dumb0/k8TeAx7Id/y3a+Z7QfhxP/htI9Js5zYaEDtG8uMgG0vM0lOlqnmjE99/kfpOYi/0Og==", + "dev": true, "dependencies": { "dezalgo": "^1.0.4", "hexoid": "^1.0.0", @@ -42154,12 +28065,6 @@ "node": ">= 0.6" } }, - "node_modules/fp-ts": { - "version": "2.16.9", - "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-2.16.9.tgz", - "integrity": "sha512-+I2+FnVB+tVaxcYyQkHUq7ZdKScaBlX53A41mxQtpIccsfyv8PzdzP7fzp2AY832T4aoK6UZ5WRX/ebGd8uZuQ==", - "license": "MIT" - }, "node_modules/fraction.js": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", @@ -42172,17 +28077,6 @@ "url": "https://github.com/sponsors/rawify" } }, - "node_modules/freeport-async": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/freeport-async/-/freeport-async-2.0.0.tgz", - "integrity": "sha512-K7od3Uw45AJg00XUmy15+Hae2hOcgKcmN3/EF6Y7i01O0gaqiRx8sUSpsb9+BRNL8RPBrhzPsVfy8q9ADlJuWQ==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -42247,31 +28141,6 @@ "node": ">=14.14" } }, - "node_modules/fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", - "license": "ISC", - "dependencies": { - "minipass": "^2.6.0" - } - }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", - "license": "ISC", - "dependencies": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "node_modules/fs-minipass/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "license": "ISC" - }, "node_modules/fs-monkey": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", @@ -42491,6 +28360,7 @@ "version": "6.0.4", "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.4.tgz", "integrity": "sha512-E1b1lFFLvLgak2whF2xDBcOy6NLVGZBqqjJjsIhvopKfWWEi64pLVTWWehV8KlLerZkfNTA95sTe2OdJKm1OzQ==", + "dev": true, "dependencies": { "basic-ftp": "^5.0.2", "data-uri-to-buffer": "^6.0.2", @@ -42500,25 +28370,6 @@ "node": ">= 14" } }, - "node_modules/getenv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/getenv/-/getenv-1.0.0.tgz", - "integrity": "sha512-7yetJWqbS9sbn0vIfliPsFgoXMKn/YMF+Wuiog97x+urnSRRRZ7xB+uVkwGKzRgq9CDFfMQnE9ruL5DHv9c6Xg==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", - "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0" - } - }, "node_modules/github-slugger": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.5.0.tgz", @@ -42580,16 +28431,6 @@ "node": "*" } }, - "node_modules/global": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", - "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", - "license": "MIT", - "dependencies": { - "min-document": "^2.19.0", - "process": "^0.11.10" - } - }, "node_modules/global-dirs": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", @@ -42758,35 +28599,19 @@ "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "devOptional": true }, "node_modules/graphql": { "version": "16.9.0", "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.9.0.tgz", "integrity": "sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" } }, - "node_modules/graphql-tag": { - "version": "2.12.6", - "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz", - "integrity": "sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" - } - }, "node_modules/gray-matter": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", @@ -42890,51 +28715,6 @@ "node": ">=0.10.0" } }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", - "license": "ISC", - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", - "license": "MIT", - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/har-validator/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/har-validator/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "license": "MIT" - }, "node_modules/harmony-reflect": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/harmony-reflect/-/harmony-reflect-1.6.2.tgz", @@ -43024,20 +28804,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/hash.js": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", @@ -43236,38 +29002,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/hdkey": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hdkey/-/hdkey-2.0.1.tgz", - "integrity": "sha512-c+tl9PHG9/XkGgG0tD7CJpRVaE0jfZizDNmnErUAKQ4EjQSOcOUcV3EN9ZEZS8pZ4usaeiiK0H7stzuzna8feA==", - "license": "MIT", - "dependencies": { - "bs58check": "^2.1.2", - "safe-buffer": "^5.1.1", - "secp256k1": "^4.0.0" - } - }, - "node_modules/hdkey/node_modules/node-addon-api": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", - "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", - "license": "MIT" - }, - "node_modules/hdkey/node_modules/secp256k1": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.4.tgz", - "integrity": "sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "elliptic": "^6.5.7", - "node-addon-api": "^5.0.0", - "node-gyp-build": "^4.2.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -43283,12 +29017,6 @@ "dev": true, "license": "MIT" }, - "node_modules/help-me": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", - "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==", - "license": "MIT" - }, "node_modules/hermes-estree": { "version": "0.25.1", "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", @@ -43310,6 +29038,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", + "dev": true, "engines": { "node": ">=8" } @@ -43319,12 +29048,6 @@ "resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz", "integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==" }, - "node_modules/hi-base32": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/hi-base32/-/hi-base32-0.5.1.tgz", - "integrity": "sha512-EmBBpvdYh/4XxsnUybsPag6VikPYnN30td+vQk+GI3qpahVEG9+gTkG0aXVxTjBqQ5T6ijbWIu77O+C5WFWsnA==", - "license": "MIT" - }, "node_modules/history": { "version": "4.10.1", "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", @@ -43669,12 +29392,6 @@ "node": ">= 0.8" } }, - "node_modules/http-https": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/http-https/-/http-https-1.0.0.tgz", - "integrity": "sha512-o0PWwVCSp3O0wS6FvNr6xfBCHgt0m1tvPLFOCc2iFDKTRAXhB7m8klDf7ErowFH8POa6dVdGatKU5I1YYwzUyg==", - "license": "ISC" - }, "node_modules/http-parser-js": { "version": "0.5.8", "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", @@ -43789,21 +29506,6 @@ "node": ">= 0.12.0" } }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", - "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, "node_modules/http2-wrapper": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", @@ -43836,21 +29538,6 @@ "node": ">=10.17.0" } }, - "node_modules/humanize-duration": { - "version": "3.32.1", - "resolved": "https://registry.npmjs.org/humanize-duration/-/humanize-duration-3.32.1.tgz", - "integrity": "sha512-inh5wue5XdfObhu/IGEMiA1nUXigSGcaKNemcbLRKa7jXYGDZXr3LoT9pTIzq2hPEbld7w/qv9h+ikWGz8fL1g==", - "license": "Unlicense" - }, - "node_modules/humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.0.0" - } - }, "node_modules/hyperdyperid": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz", @@ -43929,27 +29616,6 @@ "node": ">=4" } }, - "node_modules/idna-uts46-hx": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz", - "integrity": "sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA==", - "license": "MIT", - "dependencies": { - "punycode": "2.1.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/idna-uts46-hx/node_modules/punycode": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz", - "integrity": "sha512-Yxz2kRwT90aPiWEMHVYnEf4+rhwF1tBmmZ4KepCP+Wkium9JxtWnUm1nqGwpiAHr/tnTSeHqr3wb++jgSkXjhA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -44095,14 +29761,6 @@ "node": ">=8" } }, - "node_modules/infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "license": "ISC", - "optional": true, - "peer": true - }, "node_modules/infima": { "version": "0.2.0-alpha.43", "resolved": "https://registry.npmjs.org/infima/-/infima-0.2.0-alpha.43.tgz", @@ -44131,12 +29789,6 @@ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, - "node_modules/injectpromise": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/injectpromise/-/injectpromise-1.0.0.tgz", - "integrity": "sha512-qNq5wy4qX4uWHcVFOEU+RqZkoVG65FhvGkyDWbuBxILMjK6A1LFf5A1mgXZkD4nRx5FCorD81X/XvPKp/zVfPA==", - "license": "MIT" - }, "node_modules/inline-style-parser": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", @@ -44234,174 +29886,6 @@ "node": ">=8" } }, - "node_modules/internal-ip": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", - "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "default-gateway": "^4.2.0", - "ipaddr.js": "^1.9.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/internal-ip/node_modules/cross-spawn": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", - "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/internal-ip/node_modules/default-gateway": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", - "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==", - "license": "BSD-2-Clause", - "optional": true, - "peer": true, - "dependencies": { - "execa": "^1.0.0", - "ip-regex": "^2.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/internal-ip/node_modules/execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/internal-ip/node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/internal-ip/node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/internal-ip/node_modules/npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "path-key": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/internal-ip/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/internal-ip/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/internal-ip/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/internal-ip/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/internal-ip/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, "node_modules/internal-slot": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", @@ -44431,28 +29915,6 @@ "loose-envify": "^1.0.0" } }, - "node_modules/io-ts": { - "name": "@bitgo-forks/io-ts", - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@bitgo-forks/io-ts/-/io-ts-2.1.4.tgz", - "integrity": "sha512-jCt3WPfDM+wM0SJMGJkY0TS6JmaQ78ATAYtsppJYJfts8geOS/N/UftwAROXwv6azKAMz8uo163t6dWWwfsYug==", - "license": "MIT", - "peerDependencies": { - "fp-ts": "^2.0.0" - } - }, - "node_modules/io-ts-types": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/io-ts-types/-/io-ts-types-0.5.19.tgz", - "integrity": "sha512-kQOYYDZG5vKre+INIDZbLeDJe+oM+4zLpUkjXyTMyUfoCpjJNyi29ZLkuEAwcPufaYo3yu/BsemZtbdD+NtRfQ==", - "license": "MIT", - "peerDependencies": { - "fp-ts": "^2.0.0", - "io-ts": "^2.0.0", - "monocle-ts": "^2.0.0", - "newtype-ts": "^0.3.2" - } - }, "node_modules/ioredis": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.4.1.tgz", @@ -44480,6 +29942,7 @@ "version": "9.0.5", "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "dev": true, "dependencies": { "jsbn": "1.1.0", "sprintf-js": "^1.1.3" @@ -44488,17 +29951,6 @@ "node": ">= 12" } }, - "node_modules/ip-regex": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", - "integrity": "sha512-58yWmlHpp7VYfcdTwMTvwMmqx/Elfxjd9RXTDyMsbL7lLWmhMylLEqiYVLKuLzOZqVgiWXD9MfR62Vv89VRxkw==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=4" - } - }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -44766,12 +30218,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-function": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", - "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==", - "license": "MIT" - }, "node_modules/is-generator-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", @@ -44806,16 +30252,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-hex-prefixed": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", - "integrity": "sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA==", - "license": "MIT", - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, "node_modules/is-hexadecimal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", @@ -44880,45 +30316,6 @@ "node": ">=8" } }, - "node_modules/is-invalid-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-invalid-path/-/is-invalid-path-0.1.0.tgz", - "integrity": "sha512-aZMG0T3F34mTg4eTdszcGXx54oiZ4NtHSft3hWNJMGJXUUqdIj3cOZuHcU0nCWWcY3jd7yRe/3AEm3vSNTpBGQ==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "is-glob": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-invalid-path/node_modules/is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-invalid-path/node_modules/is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "is-extglob": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-map": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", @@ -44931,22 +30328,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-nan": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", - "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-negative-zero": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", @@ -45062,12 +30443,6 @@ "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", "dev": true }, - "node_modules/is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", - "license": "MIT" - }, "node_modules/is-reference": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.2.tgz", @@ -45214,20 +30589,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-valid-path": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-valid-path/-/is-valid-path-0.1.1.tgz", - "integrity": "sha512-+kwPrVDu9Ms03L90Qaml+79+6DZHqHyRoANI6IsZJ/g8frhnfchDOBCa0RbQ6/kdHt5CS5OeIEyrYznNuVN+8A==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "is-invalid-path": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-weakmap": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", @@ -45333,41 +30694,11 @@ "node": ">=0.10.0" } }, - "node_modules/isomorphic-fetch": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz", - "integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==", - "license": "MIT", - "dependencies": { - "node-fetch": "^2.6.1", - "whatwg-fetch": "^3.4.1" - } - }, - "node_modules/isomorphic-webcrypto": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/isomorphic-webcrypto/-/isomorphic-webcrypto-2.3.8.tgz", - "integrity": "sha512-XddQSI0WYlSCjxtm1AI8kWQOulf7hAN3k3DclF1sxDJZqOe0pcsOt675zvWW91cZH9hYs3nlA3Ev8QK5i80SxQ==", - "license": "MIT", - "dependencies": { - "@peculiar/webcrypto": "^1.0.22", - "asmcrypto.js": "^0.22.0", - "b64-lite": "^1.3.1", - "b64u-lite": "^1.0.1", - "msrcrypto": "^1.5.6", - "str2buf": "^1.3.0", - "webcrypto-shim": "^0.1.4" - }, - "optionalDependencies": { - "@unimodules/core": "*", - "@unimodules/react-native-adapter": "*", - "expo-random": "*", - "react-native-securerandom": "^0.1.1" - } - }, "node_modules/isomorphic-ws": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", + "dev": true, "peerDependencies": { "ws": "*" } @@ -45386,12 +30717,6 @@ "ws": "*" } }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", - "license": "MIT" - }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", @@ -45554,92 +30879,6 @@ "node": "*" } }, - "node_modules/jayson": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/jayson/-/jayson-4.1.3.tgz", - "integrity": "sha512-LtXh5aYZodBZ9Fc3j6f2w+MTNcnxteMOrb+QgIouguGOulWi0lieEkOUg+HkjjFs0DGoWDds6bi4E9hpNFLulQ==", - "license": "MIT", - "dependencies": { - "@types/connect": "^3.4.33", - "@types/node": "^12.12.54", - "@types/ws": "^7.4.4", - "commander": "^2.20.3", - "delay": "^5.0.0", - "es6-promisify": "^5.0.0", - "eyes": "^0.1.8", - "isomorphic-ws": "^4.0.1", - "json-stringify-safe": "^5.0.1", - "JSONStream": "^1.3.5", - "uuid": "^8.3.2", - "ws": "^7.5.10" - }, - "bin": { - "jayson": "bin/jayson.js" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jayson/node_modules/@types/node": { - "version": "12.20.55", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", - "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", - "license": "MIT" - }, - "node_modules/jayson/node_modules/@types/ws": { - "version": "7.4.7", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", - "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/jayson/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "license": "MIT" - }, - "node_modules/jayson/node_modules/isomorphic-ws": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", - "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", - "license": "MIT", - "peerDependencies": { - "ws": "*" - } - }, - "node_modules/jayson/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/jayson/node_modules/ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "license": "MIT", - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", @@ -46645,14 +31884,6 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/jimp-compact": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/jimp-compact/-/jimp-compact-0.16.1.tgz", - "integrity": "sha512-dZ6Ra7u1G8c4Letq/B5EzAxj4tLFHL+cGtdpR+PVm4yzPDj+lCk+AbivWt1eOM+ikzkowtyV7qSqX6qr3t71Ww==", - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/jiti": { "version": "1.21.6", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", @@ -46673,14 +31904,6 @@ "@sideway/pinpoint": "^2.0.0" } }, - "node_modules/join-component": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/join-component/-/join-component-1.1.0.tgz", - "integrity": "sha512-bF7vcQxbODoGK1imE2P9GS9aw4zD0Sd+Hni68IMZLj7zRnquH7dXUmMw9hDI5S/Jzt7q+IyTXN0rSg2GI0IKhQ==", - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/jose": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/jose/-/jose-5.5.0.tgz", @@ -46689,64 +31912,11 @@ "url": "https://github.com/sponsors/panva" } }, - "node_modules/joycon": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", - "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/js-base64": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.7.tgz", - "integrity": "sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==", - "license": "BSD-3-Clause" - }, - "node_modules/js-sha256": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.9.0.tgz", - "integrity": "sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA==", - "license": "MIT" - }, - "node_modules/js-sha3": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", - "license": "MIT" - }, - "node_modules/js-sha512": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/js-sha512/-/js-sha512-0.8.0.tgz", - "integrity": "sha512-PWsmefG6Jkodqt+ePTvBZCSMFgN7Clckjd0O7su3I0+BW2QWUTJNzjktHsztGLhncP2h8mcF9V9Y2Ha59pAViQ==", - "license": "MIT" - }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, - "node_modules/js-xdr": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/js-xdr/-/js-xdr-1.3.0.tgz", - "integrity": "sha512-fjLTm2uBtFvWsE3l2J14VjTuuB8vJfeTtYuNS7LiLHDWIX2kt0l1pqq9334F8kODUkKPMuULjEcbGbkFFwhx5g==", - "deprecated": "⚠️ This package has moved to @stellar/js-xdr! 🚚", - "license": "Apache-2.0", - "dependencies": { - "lodash": "^4.17.5", - "long": "^2.2.3" - } - }, - "node_modules/js-xdr/node_modules/long": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/long/-/long-2.4.0.tgz", - "integrity": "sha512-ijUtjmO/n2A5PaosNG9ZGDsQ3vxJg7ZW8vsY8Kp0f2yIZWhSJvjmegV7t+9RPQKxKrvj8yKGehhS+po14hPLGQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=0.6" - } - }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -46758,19 +31928,11 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/js2xmlparser": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", - "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", - "license": "Apache-2.0", - "dependencies": { - "xmlcreate": "^2.0.4" - } - }, "node_modules/jsbn": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", - "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "dev": true }, "node_modules/jsc-android": { "version": "250231.0.0", @@ -46854,56 +32016,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/jsdoc": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.4.tgz", - "integrity": "sha512-zeFezwyXeG4syyYHbvh1A967IAqq/67yXtXvuL5wnqCkFZe8I0vKfm+EO+YEvLguo6w9CDUbrAXVtJSHh2E8rw==", - "license": "Apache-2.0", - "dependencies": { - "@babel/parser": "^7.20.15", - "@jsdoc/salty": "^0.2.1", - "@types/markdown-it": "^14.1.1", - "bluebird": "^3.7.2", - "catharsis": "^0.9.0", - "escape-string-regexp": "^2.0.0", - "js2xmlparser": "^4.0.2", - "klaw": "^3.0.0", - "markdown-it": "^14.1.0", - "markdown-it-anchor": "^8.6.7", - "marked": "^4.0.10", - "mkdirp": "^1.0.4", - "requizzle": "^0.2.3", - "strip-json-comments": "^3.1.0", - "underscore": "~1.13.2" - }, - "bin": { - "jsdoc": "jsdoc.js" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/jsdoc/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/jsdoc/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "license": "MIT", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/jsdom": { "version": "20.0.3", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz", @@ -47044,57 +32156,6 @@ "resolved": "https://registry.npmjs.org/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz", "integrity": "sha512-RJ9YYNCkhVDBuP4zN5BBtYAzEl03yq/jIIsyif0JY9qyJuQQZNeDK7anAPKKlyEtLSj2s8h6hNh2F8zO5q7ScA==" }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "license": "(AFL-2.1 OR BSD-3-Clause)" - }, - "node_modules/json-schema-deref-sync": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/json-schema-deref-sync/-/json-schema-deref-sync-0.13.0.tgz", - "integrity": "sha512-YBOEogm5w9Op337yb6pAT6ZXDqlxAsQCanM3grid8lMWNxRJO/zWEJi3ZzqDL8boWfwhTFym5EFrNgWwpqcBRg==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "clone": "^2.1.2", - "dag-map": "~1.0.0", - "is-valid-path": "^0.1.1", - "lodash": "^4.17.13", - "md5": "~2.2.0", - "memory-cache": "~0.2.0", - "traverse": "~0.6.6", - "valid-url": "~1.0.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/json-schema-deref-sync/node_modules/clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/json-schema-deref-sync/node_modules/md5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", - "integrity": "sha512-PlGG4z5mBANDGCKsYQe0CaUYHdZYZt8ZPZLmEt+Urf0W4GlpTX4HescwHU+dc9+Z/G/vZKYZYFrwgm9VxK6QOQ==", - "license": "BSD-3-Clause", - "optional": true, - "peer": true, - "dependencies": { - "charenc": "~0.0.1", - "crypt": "~0.0.1", - "is-buffer": "~1.1.1" - } - }, "node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", @@ -47103,12 +32164,14 @@ "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "devOptional": true }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true }, "node_modules/json5": { "version": "2.2.3", @@ -47168,46 +32231,6 @@ "graceful-fs": "^4.1.6" } }, - "node_modules/jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", - "engines": [ - "node >= 0.2.0" - ], - "license": "MIT" - }, - "node_modules/JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "license": "(MIT OR Apache-2.0)", - "dependencies": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - }, - "bin": { - "JSONStream": "bin.js" - }, - "engines": { - "node": "*" - } - }, - "node_modules/jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "license": "MIT", - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -47223,15 +32246,6 @@ "node": ">=4.0" } }, - "node_modules/jwt-decode": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", - "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, "node_modules/keccak": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.4.tgz", @@ -47246,24 +32260,6 @@ "node": ">=10.0.0" } }, - "node_modules/key-encoder": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/key-encoder/-/key-encoder-2.0.3.tgz", - "integrity": "sha512-fgBtpAGIr/Fy5/+ZLQZIPPhsZEcbSlYu/Wu96tNDFNSjSACw5lEIOFeaVdQ/iwrb8oxjlWi6wmWdH76hV6GZjg==", - "license": "MIT", - "dependencies": { - "@types/elliptic": "^6.4.9", - "asn1.js": "^5.0.1", - "bn.js": "^4.11.8", - "elliptic": "^6.4.1" - } - }, - "node_modules/key-encoder/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", - "license": "MIT" - }, "node_modules/keygrip": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz", @@ -47297,15 +32293,6 @@ "node": ">=0.10.0" } }, - "node_modules/klaw": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", - "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.1.9" - } - }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -47604,6 +32591,7 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "devOptional": true, "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -47617,36 +32605,6 @@ "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.11.4.tgz", "integrity": "sha512-F/R50HQuWWYcmU/esP5jrH5LiWYaN7DpN0a/99U8+mnGGtnx8kmRE+649dQh3v+CowXXZc8vpkf5AmYkO0AQ7Q==" }, - "node_modules/libsodium": { - "version": "0.7.15", - "resolved": "https://registry.npmjs.org/libsodium/-/libsodium-0.7.15.tgz", - "integrity": "sha512-sZwRknt/tUpE2AwzHq3jEyUU5uvIZHtSssktXq7owd++3CSgn8RGrv6UZJJBpP7+iBghBqe7Z06/2M31rI2NKw==", - "license": "ISC" - }, - "node_modules/libsodium-sumo": { - "version": "0.7.15", - "resolved": "https://registry.npmjs.org/libsodium-sumo/-/libsodium-sumo-0.7.15.tgz", - "integrity": "sha512-5tPmqPmq8T8Nikpm1Nqj0hBHvsLFCXvdhBFV7SGOitQPZAA6jso8XoL0r4L7vmfKXr486fiQInvErHtEvizFMw==", - "license": "ISC" - }, - "node_modules/libsodium-wrappers": { - "version": "0.7.15", - "resolved": "https://registry.npmjs.org/libsodium-wrappers/-/libsodium-wrappers-0.7.15.tgz", - "integrity": "sha512-E4anqJQwcfiC6+Yrl01C1m8p99wEhLmJSs0VQqST66SbQXXBoaJY0pF4BNjRYa/sOQAxx6lXAaAFIlx+15tXJQ==", - "license": "ISC", - "dependencies": { - "libsodium": "^0.7.15" - } - }, - "node_modules/libsodium-wrappers-sumo": { - "version": "0.7.15", - "resolved": "https://registry.npmjs.org/libsodium-wrappers-sumo/-/libsodium-wrappers-sumo-0.7.15.tgz", - "integrity": "sha512-aSWY8wKDZh5TC7rMvEdTHoyppVq/1dTSAeAR7H6pzd6QRT3vQWcT5pGwCotLcpPEOLXX6VvqihSPkpEhYAjANA==", - "license": "ISC", - "dependencies": { - "libsodium-sumo": "^0.7.15" - } - }, "node_modules/license-webpack-plugin": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-4.0.2.tgz", @@ -47712,15 +32670,6 @@ "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, - "node_modules/linkify-it": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", - "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", - "license": "MIT", - "dependencies": { - "uc.micro": "^2.0.0" - } - }, "node_modules/lint-staged": { "version": "15.2.0", "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.0.tgz", @@ -48163,13 +33112,6 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, - "node_modules/lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==", - "license": "MIT", - "peer": true - }, "node_modules/lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", @@ -48191,13 +33133,6 @@ "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==" }, - "node_modules/lodash.frompairs": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.frompairs/-/lodash.frompairs-4.0.1.tgz", - "integrity": "sha512-dvqe2I+cO5MzXCMhUnfYFa9MD+/760yx2aTAN1lqEcEkf896TxgrX373igVdqSJj6tQd0jnSLE1UMuKufqqxFw==", - "license": "MIT", - "peer": true - }, "node_modules/lodash.isarguments": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", @@ -48208,13 +33143,6 @@ "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" }, - "node_modules/lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", - "license": "MIT", - "peer": true - }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -48223,42 +33151,8 @@ "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" - }, - "node_modules/lodash.omit": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", - "integrity": "sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg==", - "license": "MIT", - "peer": true - }, - "node_modules/lodash.pick": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", - "integrity": "sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q==", - "license": "MIT", - "peer": true - }, - "node_modules/lodash.template": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", - "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", - "license": "MIT", - "peer": true, - "dependencies": { - "lodash._reinterpolate": "^3.0.0", - "lodash.templatesettings": "^4.0.0" - } - }, - "node_modules/lodash.templatesettings": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", - "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "lodash._reinterpolate": "^3.0.0" - } + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "devOptional": true }, "node_modules/lodash.throttle": { "version": "4.1.1", @@ -48575,15 +33469,6 @@ "node": ">=10" } }, - "node_modules/lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", - "license": "MIT", - "dependencies": { - "es5-ext": "~0.10.2" - } - }, "node_modules/luxon": { "version": "3.4.4", "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.4.tgz", @@ -48601,17 +33486,6 @@ "lz-string": "bin/bin.js" } }, - "node_modules/macaroon": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/macaroon/-/macaroon-3.0.4.tgz", - "integrity": "sha512-Tja2jvupseKxltPZbu5RPSz2Pgh6peYA3O46YCTcYL8PI1VqtGwDqRhGfP8pows26xx9wTiygk+en62Bq+Y8JA==", - "license": "BSD-3-Clause", - "dependencies": { - "sjcl": "^1.0.6", - "tweetnacl": "^1.0.0", - "tweetnacl-util": "^0.15.0" - } - }, "node_modules/magic-string": { "version": "0.30.0", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.0.tgz", @@ -48676,33 +33550,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/markdown-it": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", - "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1", - "entities": "^4.4.0", - "linkify-it": "^5.0.0", - "mdurl": "^2.0.0", - "punycode.js": "^2.3.1", - "uc.micro": "^2.1.0" - }, - "bin": { - "markdown-it": "bin/markdown-it.mjs" - } - }, - "node_modules/markdown-it-anchor": { - "version": "8.6.7", - "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz", - "integrity": "sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==", - "license": "Unlicense", - "peerDependencies": { - "@types/markdown-it": "*", - "markdown-it": "*" - } - }, "node_modules/markdown-table": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz", @@ -48712,18 +33559,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/marked": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", - "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", - "license": "MIT", - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 12" - } - }, "node_modules/marky": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.5.tgz", @@ -48731,54 +33566,6 @@ "license": "Apache-2.0", "peer": true }, - "node_modules/md5": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", - "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", - "license": "BSD-3-Clause", - "optional": true, - "peer": true, - "dependencies": { - "charenc": "0.0.2", - "crypt": "0.0.2", - "is-buffer": "~1.1.6" - } - }, - "node_modules/md5-file": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/md5-file/-/md5-file-3.2.3.tgz", - "integrity": "sha512-3Tkp1piAHaworfcCgH0jKbTvj1jWWFgbvh2cXaNCgHwyTCBxxvD1Y04rmfpvdPm1P4oXMOpm6+2H7sr7v9v8Fw==", - "license": "MIT", - "peer": true, - "dependencies": { - "buffer-alloc": "^1.1.0" - }, - "bin": { - "md5-file": "cli.js" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "license": "MIT", - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/md5hex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/md5hex/-/md5hex-1.0.0.tgz", - "integrity": "sha512-c2YOUbp33+6thdCUi34xIyOU/a7bvGKj/3DB1iaPMTuPHf/Q2d5s4sn1FaCOO43XkXggnb08y5W2PU8UNYNLKQ==", - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/mdast-util-directive": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/mdast-util-directive/-/mdast-util-directive-3.0.0.tgz", @@ -49162,12 +33949,6 @@ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" }, - "node_modules/mdurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", - "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", - "license": "MIT" - }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -49194,30 +33975,6 @@ "license": "MIT", "peer": true }, - "node_modules/memoizee": { - "version": "0.4.15", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", - "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", - "license": "ISC", - "dependencies": { - "d": "^1.0.1", - "es5-ext": "^0.10.53", - "es6-weak-map": "^2.0.3", - "event-emitter": "^0.3.5", - "is-promise": "^2.2.2", - "lru-queue": "^0.1.0", - "next-tick": "^1.1.0", - "timers-ext": "^0.1.7" - } - }, - "node_modules/memory-cache": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/memory-cache/-/memory-cache-0.2.0.tgz", - "integrity": "sha512-OcjA+jzjOYzKmKS6IQVALHLVz+rNTMPoJvCztFaZxwG14wtAW7VRZjwTQu06vKCYOxh4jVnik7ya0SXTB0W+xA==", - "license": "BSD-2-Clause", - "optional": true, - "peer": true - }, "node_modules/merge-deep": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/merge-deep/-/merge-deep-3.0.3.tgz", @@ -49539,67 +34296,6 @@ "node": ">=18.18" } }, - "node_modules/metro-react-native-babel-preset": { - "version": "0.64.0", - "resolved": "https://registry.npmjs.org/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.64.0.tgz", - "integrity": "sha512-HcZ0RWQRuJfpPiaHyFQJzcym+/dDIVUPwUAXWoub/C4GkGu+mPjp8vqK6g0FxokCnnI2TK0gZTza2IDfiNNscQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/core": "^7.0.0", - "@babel/plugin-proposal-class-properties": "^7.0.0", - "@babel/plugin-proposal-export-default-from": "^7.0.0", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0", - "@babel/plugin-proposal-object-rest-spread": "^7.0.0", - "@babel/plugin-proposal-optional-catch-binding": "^7.0.0", - "@babel/plugin-proposal-optional-chaining": "^7.0.0", - "@babel/plugin-syntax-dynamic-import": "^7.0.0", - "@babel/plugin-syntax-export-default-from": "^7.0.0", - "@babel/plugin-syntax-flow": "^7.2.0", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.0.0", - "@babel/plugin-syntax-optional-chaining": "^7.0.0", - "@babel/plugin-transform-arrow-functions": "^7.0.0", - "@babel/plugin-transform-block-scoping": "^7.0.0", - "@babel/plugin-transform-classes": "^7.0.0", - "@babel/plugin-transform-computed-properties": "^7.0.0", - "@babel/plugin-transform-destructuring": "^7.0.0", - "@babel/plugin-transform-exponentiation-operator": "^7.0.0", - "@babel/plugin-transform-flow-strip-types": "^7.0.0", - "@babel/plugin-transform-for-of": "^7.0.0", - "@babel/plugin-transform-function-name": "^7.0.0", - "@babel/plugin-transform-literals": "^7.0.0", - "@babel/plugin-transform-modules-commonjs": "^7.0.0", - "@babel/plugin-transform-object-assign": "^7.0.0", - "@babel/plugin-transform-parameters": "^7.0.0", - "@babel/plugin-transform-react-display-name": "^7.0.0", - "@babel/plugin-transform-react-jsx": "^7.0.0", - "@babel/plugin-transform-react-jsx-self": "^7.0.0", - "@babel/plugin-transform-react-jsx-source": "^7.0.0", - "@babel/plugin-transform-regenerator": "^7.0.0", - "@babel/plugin-transform-runtime": "^7.0.0", - "@babel/plugin-transform-shorthand-properties": "^7.0.0", - "@babel/plugin-transform-spread": "^7.0.0", - "@babel/plugin-transform-sticky-regex": "^7.0.0", - "@babel/plugin-transform-template-literals": "^7.0.0", - "@babel/plugin-transform-typescript": "^7.5.0", - "@babel/plugin-transform-unicode-regex": "^7.0.0", - "@babel/template": "^7.0.0", - "react-refresh": "^0.4.0" - }, - "peerDependencies": { - "@babel/core": "*" - } - }, - "node_modules/metro-react-native-babel-preset/node_modules/react-refresh": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.4.3.tgz", - "integrity": "sha512-Hwln1VNuGl/6bVwnd0Xdn1e84gT/8T9aYNL+HAKDArLCS7LWjwr7StE30IEYbIkx0Vi3vs+coQxe+SQDbGbbpA==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/metro-resolver": { "version": "0.81.1", "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.81.1.tgz", @@ -49840,72 +34536,11 @@ "node": ">=12" } }, - "node_modules/micro-eth-signer": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/micro-eth-signer/-/micro-eth-signer-0.7.2.tgz", - "integrity": "sha512-uFH23nqPNdg2KZ9ZdvLG4GO3bTAOWRhwGTsecY4Et2IdQOJ26x6inu8lJ9oyslnYL/0o1vnETCGhMimMvO0SqQ==", - "license": "MIT", - "dependencies": { - "@ethereumjs/rlp": "5.0.0", - "@noble/curves": "~1.3.0", - "@noble/hashes": "~1.3.3", - "@scure/base": "~1.1.5", - "micro-packed": "~0.5.1" - } - }, - "node_modules/micro-eth-signer/node_modules/@ethereumjs/rlp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-5.0.0.tgz", - "integrity": "sha512-WuS1l7GJmB0n0HsXLozCoEFc9IwYgf3l0gCkKVYgR67puVF1O4OpEaN0hWmm1c+iHUHFCKt1hJrvy5toLg+6ag==", - "license": "MPL-2.0", - "bin": { - "rlp": "bin/rlp" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/micro-eth-signer/node_modules/@noble/curves": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz", - "integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "1.3.3" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/micro-eth-signer/node_modules/@noble/hashes": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", - "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", - "license": "MIT", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/micro-ftch": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/micro-ftch/-/micro-ftch-0.3.1.tgz", "integrity": "sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg==" }, - "node_modules/micro-packed": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/micro-packed/-/micro-packed-0.5.3.tgz", - "integrity": "sha512-zWRoH+qUb/ZMp9gVZhexvRGCENDM5HEQF4sflqpdilUHWK2/zKR7/MT8GBctnTwbhNJwy1iuk5q6+TYP7/twYA==", - "license": "MIT", - "dependencies": { - "@scure/base": "~1.1.5" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/micromark": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.0.tgz", @@ -51589,25 +36224,6 @@ "node": ">=8.6" } }, - "node_modules/miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "license": "MIT", - "dependencies": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - }, - "bin": { - "miller-rabin": "bin/miller-rabin" - } - }, - "node_modules/miller-rabin/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", - "license": "MIT" - }, "node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -51657,14 +36273,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/min-document": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", - "integrity": "sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==", - "dependencies": { - "dom-walk": "^0.1.0" - } - }, "node_modules/mini-css-extract-plugin": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.0.tgz", @@ -51721,119 +36329,11 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, "engines": { "node": ">=16 || 14 >=14.17" } }, - "node_modules/minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-collect/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-flush/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-pipeline/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", - "license": "MIT", - "dependencies": { - "minipass": "^2.9.0" - } - }, - "node_modules/minizlib/node_modules/minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", - "license": "ISC", - "dependencies": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "node_modules/minizlib/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "license": "ISC" - }, "node_modules/mipd": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/mipd/-/mipd-0.0.7.tgz", @@ -51884,19 +36384,6 @@ "mkdirp": "bin/cmd.js" } }, - "node_modules/mkdirp-promise": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz", - "integrity": "sha512-Hepn5kb1lJPtVW84RFT40YG1OddBNTOVUZR2bzQUHc+Z03en8/3uX0+060JDhcEzyO08HmipsN9DcnFMxhIL9w==", - "deprecated": "This package is broken and no longer maintained. 'mkdirp' itself supports promises now, please switch to that.", - "license": "ISC", - "dependencies": { - "mkdirp": "*" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/mlly": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.3.tgz", @@ -51908,21 +36395,6 @@ "ufo": "^1.5.4" } }, - "node_modules/mock-fs": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-4.14.0.tgz", - "integrity": "sha512-qYvlv/exQ4+svI3UOvPUpLDF0OMX5euvUH0Ny4N5QyRyhNdgAgUrVH3iUINSzEPLvx0kbo/Bp28GJKIqvE7URw==", - "license": "MIT" - }, - "node_modules/mock-socket": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/mock-socket/-/mock-socket-9.3.1.tgz", - "integrity": "sha512-qxBgB7Qa2sEQgHFjj0dSigq7fX4k6Saisd5Nelwp2q8mlbAFh5dHV9JTTlF8viYJLSSWgMCZFUom8PJcMNBoJw==", - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, "node_modules/module-details-from-path": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.3.tgz", @@ -51935,15 +36407,6 @@ "license": "MIT", "peer": true }, - "node_modules/monocle-ts": { - "version": "2.3.13", - "resolved": "https://registry.npmjs.org/monocle-ts/-/monocle-ts-2.3.13.tgz", - "integrity": "sha512-D5Ygd3oulEoAm3KuGO0eeJIrhFf1jlQIoEVV2DYsZUMz42j4tGxgct97Aq68+F8w4w4geEnwFa8HayTS/7lpKQ==", - "license": "MIT", - "peerDependencies": { - "fp-ts": "^2.5.0" - } - }, "node_modules/motion": { "version": "10.16.2", "resolved": "https://registry.npmjs.org/motion/-/motion-10.16.2.tgz", @@ -51999,12 +36462,6 @@ "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" } }, - "node_modules/msrcrypto": { - "version": "1.5.8", - "resolved": "https://registry.npmjs.org/msrcrypto/-/msrcrypto-1.5.8.tgz", - "integrity": "sha512-ujZ0TRuozHKKm6eGbKHfXef7f+esIhEckmThVnz7RNyiOJd7a6MXj2JGBoL9cnPDW+JMG16MoTUh5X+XXjI66Q==", - "license": "Apache-2.0" - }, "node_modules/msw": { "version": "2.6.8", "resolved": "https://registry.npmjs.org/msw/-/msw-2.6.8.tgz", @@ -52138,17 +36595,6 @@ "node": ">= 6.0.0" } }, - "node_modules/multibase": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-0.6.1.tgz", - "integrity": "sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw==", - "deprecated": "This module has been superseded by the multiformats module", - "license": "MIT", - "dependencies": { - "base-x": "^3.0.8", - "buffer": "^5.5.0" - } - }, "node_modules/multicast-dns": { "version": "7.2.5", "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", @@ -52161,134 +36607,17 @@ "multicast-dns": "cli.js" } }, - "node_modules/multicodec": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-0.5.7.tgz", - "integrity": "sha512-PscoRxm3f+88fAtELwUnZxGDkduE2HD9Q6GHUOywQLjOGT/HAdhjLDYNZ1e7VR0s0TP0EwZ16LNUTFpoBGivOA==", - "deprecated": "This module has been superseded by the multiformats module", - "license": "MIT", - "dependencies": { - "varint": "^5.0.0" - } - }, "node_modules/multiformats": { "version": "9.9.0", "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.9.0.tgz", "integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==" }, - "node_modules/multihashes": { - "version": "0.4.21", - "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-0.4.21.tgz", - "integrity": "sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw==", - "license": "MIT", - "dependencies": { - "buffer": "^5.5.0", - "multibase": "^0.7.0", - "varint": "^5.0.0" - } - }, - "node_modules/multihashes/node_modules/multibase": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-0.7.0.tgz", - "integrity": "sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg==", - "deprecated": "This module has been superseded by the multiformats module", - "license": "MIT", - "dependencies": { - "base-x": "^3.0.8", - "buffer": "^5.5.0" - } - }, - "node_modules/mustache": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", - "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", - "license": "MIT", - "bin": { - "mustache": "bin/mustache" - } - }, "node_modules/mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, - "node_modules/mv": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz", - "integrity": "sha512-at/ZndSy3xEGJ8i0ygALh8ru9qy7gWW1cmkaqBN29JmMlIvM//MEO9y1sk/avxuwnPcfhkejkLsuPxH81BrkSg==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "mkdirp": "~0.5.1", - "ncp": "~2.0.0", - "rimraf": "~2.4.0" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/mv/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/mv/node_modules/glob": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", - "integrity": "sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mv/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mv/node_modules/rimraf": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", - "integrity": "sha512-J5xnxTyqaiw06JjMftq7L9ouA448dw/E7dKghkP9WpKNuwmARNNg+Gk8/u5ryb9N/Yo2+z3MCwuqFK/+qPOPfQ==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "glob": "^6.0.1" - }, - "bin": { - "rimraf": "bin.js" - } - }, "node_modules/mylas": { "version": "2.1.13", "resolved": "https://registry.npmjs.org/mylas/-/mylas-2.1.13.tgz", @@ -52306,30 +36635,13 @@ "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, - "node_modules/nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", - "license": "MIT" - }, - "node_modules/nano-json-stream-parser": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz", - "integrity": "sha512-9MqxMH/BSJC7dnLsEMPyfN5Dvoo49IsPFYMcHw3Bcfc2kN0lpHRBSzlMSVx4HGyJ7s9B31CyBTVehWJoQ8Ctew==", - "license": "MIT" - }, - "node_modules/nanoassert": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/nanoassert/-/nanoassert-2.0.0.tgz", - "integrity": "sha512-7vO7n28+aYO4J+8w96AzhmU8G+Y/xpPDJz/se19ICsqj/momRbb9mh9ZUtkoJ5X3nTnPdhEJyc0qnM6yAsHBaA==", - "license": "ISC" - }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -52350,88 +36662,8 @@ "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" - }, - "node_modules/ncp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", - "integrity": "sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA==", - "license": "MIT", - "optional": true, - "peer": true, - "bin": { - "ncp": "bin/ncp" - } - }, - "node_modules/near-api-js": { - "version": "0.44.2", - "resolved": "https://registry.npmjs.org/near-api-js/-/near-api-js-0.44.2.tgz", - "integrity": "sha512-eMnc4V+geggapEUa3nU2p8HSHn/njtloI4P2mceHQWO8vDE1NGpnAw8FuTBrLmXSgIv9m6oocgFc9t3VNf5zwg==", - "license": "(MIT AND Apache-2.0)", - "dependencies": { - "bn.js": "5.2.0", - "borsh": "^0.6.0", - "bs58": "^4.0.0", - "depd": "^2.0.0", - "error-polyfill": "^0.1.3", - "http-errors": "^1.7.2", - "js-sha256": "^0.9.0", - "mustache": "^4.0.0", - "node-fetch": "^2.6.1", - "text-encoding-utf-8": "^1.0.2", - "tweetnacl": "^1.0.1" - } - }, - "node_modules/near-api-js/node_modules/bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", - "license": "MIT" - }, - "node_modules/near-api-js/node_modules/borsh": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/borsh/-/borsh-0.6.0.tgz", - "integrity": "sha512-sl5k89ViqsThXQpYa9XDtz1sBl3l1lI313cFUY1HKr+wvMILnb+58xpkqTNrYbelh99dY7K8usxoCusQmqix9Q==", - "license": "Apache-2.0", - "dependencies": { - "bn.js": "^5.2.0", - "bs58": "^4.0.0", - "text-encoding-utf-8": "^1.0.2" - } - }, - "node_modules/near-api-js/node_modules/http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", - "license": "MIT", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/near-api-js/node_modules/http-errors/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/near-api-js/node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "devOptional": true }, "node_modules/needle": { "version": "3.3.1", @@ -52476,14 +36708,6 @@ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, - "node_modules/nested-error-stacks": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.0.1.tgz", - "integrity": "sha512-SrQrok4CATudVzBS7coSz26QRSmlK9TzzoFbeKfcPBUFPjcQM9Rqvr/DlJkOrwI/0KcgvMub1n1g5Jt9EgRn4A==", - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/nestjs-zod": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/nestjs-zod/-/nestjs-zod-3.0.0.tgz", @@ -52517,20 +36741,11 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "dev": true, "engines": { "node": ">= 0.4.0" } }, - "node_modules/newtype-ts": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/newtype-ts/-/newtype-ts-0.3.5.tgz", - "integrity": "sha512-v83UEQMlVR75yf1OUdoSFssjitxzjZlqBAjiGQ4WJaML8Jdc68LJ+BaSAXUmKY4bNzp7hygkKLYTsDi14PxI2g==", - "license": "MIT", - "peerDependencies": { - "fp-ts": "^2.0.0", - "monocle-ts": "^2.0.0" - } - }, "node_modules/next": { "version": "14.2.4", "resolved": "https://registry.npmjs.org/next/-/next-14.2.4.tgz", @@ -52580,12 +36795,6 @@ } } }, - "node_modules/next-tick": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", - "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", - "license": "ISC" - }, "node_modules/next/node_modules/@swc/helpers": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", @@ -52622,13 +36831,6 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "license": "MIT", - "peer": true - }, "node_modules/no-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", @@ -52638,13 +36840,6 @@ "tslib": "^2.0.3" } }, - "node_modules/noble-bls12-381": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/noble-bls12-381/-/noble-bls12-381-0.7.2.tgz", - "integrity": "sha512-Z5isbU6opuWPL3dxsGqO5BdOE8WP1XUM7HFIn/xeE5pATTnml/PEIy4MFQQrktHiitkuJdsCDtzEOnS9eIpC3Q==", - "deprecated": "Switch to @noble/curves for security updates", - "license": "MIT" - }, "node_modules/nock": { "version": "13.5.4", "resolved": "https://registry.npmjs.org/nock/-/nock-13.5.4.tgz", @@ -52670,25 +36865,6 @@ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" }, - "node_modules/node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "github", - "url": "https://paypal.me/jimmywarting" - } - ], - "license": "MIT", - "engines": { - "node": ">=10.5.0" - } - }, "node_modules/node-emoji": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.1.3.tgz", @@ -52897,26 +37073,6 @@ "license": "MIT", "peer": true }, - "node_modules/number-to-bn": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", - "integrity": "sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig==", - "license": "MIT", - "dependencies": { - "bn.js": "4.11.6", - "strip-hex-prefix": "1.0.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/number-to-bn/node_modules/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==", - "license": "MIT" - }, "node_modules/nwsapi": { "version": "2.2.12", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.12.tgz", @@ -53068,24 +37224,6 @@ "node": ">=12" } }, - "node_modules/o3": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/o3/-/o3-1.0.3.tgz", - "integrity": "sha512-f+4n+vC6s4ysy7YO7O2gslWZBUu8Qj2i2OUJOvjRxQva7jVjYjB29jrr9NCjmxZQR0gzrOcv1RnqoYOeMs5VRQ==", - "license": "MIT", - "dependencies": { - "capability": "^0.2.5" - } - }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "license": "Apache-2.0", - "engines": { - "node": "*" - } - }, "node_modules/ob1": { "version": "0.81.1", "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.81.1.tgz", @@ -53173,6 +37311,7 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "dev": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1" @@ -53289,15 +37428,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/oboe": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/oboe/-/oboe-2.1.5.tgz", - "integrity": "sha512-zRFWiF+FoicxEs3jNI/WYUrVEgA7DeET/InK0XQuudGHRg8iIob3cNPrJTKaz4004uaA9Pbe+Dwa8iluhjLZWA==", - "license": "BSD", - "dependencies": { - "http-https": "^1.0.0" - } - }, "node_modules/obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", @@ -53402,22 +37532,11 @@ "opener": "bin/opener-bin.js" } }, - "node_modules/openpgp": { - "version": "5.10.1", - "resolved": "https://registry.npmjs.org/openpgp/-/openpgp-5.10.1.tgz", - "integrity": "sha512-SR5Ft+ej51d0+p53ld5Ney0Yiz0y8Mh1YYLJrvpRMbTaNhvS1QcDX0Oq1rW9sjBnQXtgrpWw2Zve3rm7K5C/pw==", - "license": "LGPL-3.0+", - "dependencies": { - "asn1.js": "^5.0.0" - }, - "engines": { - "node": ">= 8.0.0" - } - }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "devOptional": true, "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", @@ -53452,39 +37571,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", - "devOptional": true, + "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, "node_modules/outvariant": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz", @@ -53522,17 +37617,6 @@ "node": ">=12.20" } }, - "node_modules/p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=4" - } - }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -53610,6 +37694,7 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.1.0.tgz", "integrity": "sha512-Z5FnLVVZSnX7WjBg0mhDtydeRZ1xMcATZThjySQUHqr+0ksP8kqaw23fNKkaaN/Z8gwLUs/W7xdl0I75eP2Xyw==", + "dev": true, "dependencies": { "@tootallnate/quickjs-emscripten": "^0.23.0", "agent-base": "^7.1.2", @@ -53628,6 +37713,7 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" @@ -53640,6 +37726,7 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", + "dev": true, "dependencies": { "degenerator": "^5.0.0", "netmask": "^2.0.2" @@ -53668,7 +37755,8 @@ "node_modules/package-json-from-dist": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", - "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==" + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "dev": true }, "node_modules/package-json/node_modules/semver": { "version": "7.6.2", @@ -53681,24 +37769,6 @@ "node": ">=10" } }, - "node_modules/paillier-bigint": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/paillier-bigint/-/paillier-bigint-3.3.0.tgz", - "integrity": "sha512-Aa8a75dODYOGxLYQhi1Y0Xsi0Vbl+5gzPvaVfxuCA/zT8CK/keXv5CA2Ddn5AV9VxmTkpIEdYs40hv1rkFcODg==", - "license": "MIT", - "dependencies": { - "bigint-crypto-utils": "^3.0.17" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/pako": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pako/-/pako-2.0.3.tgz", - "integrity": "sha512-WjR1hOeg+kki3ZIOjaf4b5WVcay1jaliKSYiEaB1XzwhMQZJxRdQRv0V31EKBYlxb4T7SK3hjfc/jxyU64BoSw==", - "license": "(MIT AND Zlib)" - }, "node_modules/param-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", @@ -53719,53 +37789,6 @@ "node": ">=6" } }, - "node_modules/parse-asn1": { - "version": "5.1.7", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.7.tgz", - "integrity": "sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg==", - "license": "ISC", - "dependencies": { - "asn1.js": "^4.10.1", - "browserify-aes": "^1.2.0", - "evp_bytestokey": "^1.0.3", - "hash-base": "~3.0", - "pbkdf2": "^3.1.2", - "safe-buffer": "^5.2.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/parse-asn1/node_modules/asn1.js": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", - "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", - "license": "MIT", - "dependencies": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/parse-asn1/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", - "license": "MIT" - }, - "node_modules/parse-asn1/node_modules/hash-base": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.5.tgz", - "integrity": "sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.4", - "safe-buffer": "^5.2.1" - }, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/parse-entities": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.1.tgz", @@ -53790,12 +37813,6 @@ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" }, - "node_modules/parse-headers": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.5.tgz", - "integrity": "sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA==", - "license": "MIT" - }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -53841,37 +37858,6 @@ "node": ">=0.10.0" } }, - "node_modules/parse-png": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/parse-png/-/parse-png-2.1.0.tgz", - "integrity": "sha512-Nt/a5SfCLiTnQAjx3fHlqp8hRgTL3z7kTQZzvIMS9uCAepnCyjpdEc6M/sz69WqMBdaDBw9sF1F1UaHROYzGkQ==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "pngjs": "^3.3.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/parse-png/node_modules/pngjs": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", - "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/parse-srcset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", - "integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==", - "license": "MIT" - }, "node_modules/parse5": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", @@ -53918,25 +37904,6 @@ "tslib": "^2.0.3" } }, - "node_modules/password-prompt": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/password-prompt/-/password-prompt-1.1.3.tgz", - "integrity": "sha512-HkrjG2aJlvF0t2BMH0e2LB/EHf3Lcq3fNMzy4GYHcQblAvOl+QQji1Lx7WRBMqpVK8p+KR7bCg7oqAMXtdgqyw==", - "license": "0BSD", - "optional": true, - "peer": true, - "dependencies": { - "ansi-escapes": "^4.3.2", - "cross-spawn": "^7.0.3" - } - }, - "node_modules/path-browserify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", - "license": "MIT", - "peer": true - }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -53975,6 +37942,7 @@ "version": "1.11.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" @@ -53989,7 +37957,8 @@ "node_modules/path-scurry/node_modules/lru-cache": { "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true }, "node_modules/path-to-regexp": { "version": "3.2.0", @@ -54009,28 +37978,6 @@ "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==" }, - "node_modules/pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", - "license": "MIT", - "dependencies": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", - "license": "MIT" - }, "node_modules/periscopic": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz", @@ -54144,99 +38091,6 @@ "split2": "^4.0.0" } }, - "node_modules/pino-pretty": { - "version": "10.3.1", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-10.3.1.tgz", - "integrity": "sha512-az8JbIYeN/1iLj2t0jR9DV48/LQ3RC6hZPpapKPkb84Q+yTidMCpgWxIT3N0flnBDilyBQ1luWNpOeJptjdp/g==", - "license": "MIT", - "dependencies": { - "colorette": "^2.0.7", - "dateformat": "^4.6.3", - "fast-copy": "^3.0.0", - "fast-safe-stringify": "^2.1.1", - "help-me": "^5.0.0", - "joycon": "^3.1.1", - "minimist": "^1.2.6", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^1.0.0", - "pump": "^3.0.0", - "readable-stream": "^4.0.0", - "secure-json-parse": "^2.4.0", - "sonic-boom": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "bin": { - "pino-pretty": "bin.js" - } - }, - "node_modules/pino-pretty/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/pino-pretty/node_modules/on-exit-leak-free": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", - "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/pino-pretty/node_modules/pino-abstract-transport": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz", - "integrity": "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==", - "license": "MIT", - "dependencies": { - "readable-stream": "^4.0.0", - "split2": "^4.0.0" - } - }, - "node_modules/pino-pretty/node_modules/readable-stream": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", - "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", - "license": "MIT", - "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/pino-pretty/node_modules/sonic-boom": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.1.tgz", - "integrity": "sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg==", - "license": "MIT", - "dependencies": { - "atomic-sleep": "^1.0.0" - } - }, "node_modules/pino-std-serializers": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-4.0.0.tgz", @@ -54429,41 +38283,6 @@ "node": ">=12" } }, - "node_modules/plist": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", - "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "@xmldom/xmldom": "^0.8.8", - "base64-js": "^1.5.1", - "xmlbuilder": "^15.1.1" - }, - "engines": { - "node": ">=10.4.0" - } - }, - "node_modules/plist/node_modules/@xmldom/xmldom": { - "version": "0.8.10", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", - "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/plist/node_modules/xmlbuilder": { - "version": "15.1.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", - "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8.0" - } - }, "node_modules/pluralize": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", @@ -54521,12 +38340,6 @@ "ms": "^2.1.1" } }, - "node_modules/poseidon-lite": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/poseidon-lite/-/poseidon-lite-0.2.1.tgz", - "integrity": "sha512-xIr+G6HeYfOhCuswdqcFpSX47SPhm0EpisWJ6h7fHlWwaVIvH3dLnejpatrtw6Xc6HaLrpq05y7VRfvDmDGIog==", - "license": "MIT" - }, "node_modules/possible-typed-array-names": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", @@ -55252,23 +39065,16 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "devOptional": true, "engines": { "node": ">= 0.8.0" } }, - "node_modules/prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/prettier": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "dev": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -55279,18 +39085,6 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "license": "MIT", - "dependencies": { - "fast-diff": "^1.1.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/prettier-plugin-organize-imports": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-3.2.4.tgz", @@ -55311,20 +39105,6 @@ } } }, - "node_modules/pretty-bytes": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", - "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/pretty-error": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", @@ -55413,15 +39193,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", - "license": "MIT", - "engines": { - "node": ">= 0.6.0" - } - }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -55432,17 +39203,6 @@ "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-1.0.0.tgz", "integrity": "sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==" }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/promise": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", @@ -55453,14 +39213,6 @@ "asap": "~2.0.6" } }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", - "license": "ISC", - "optional": true, - "peer": true - }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -55492,6 +39244,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", + "dev": true, "engines": { "node": ">= 8" } @@ -55533,169 +39286,6 @@ "node": ">=12.0.0" } }, - "node_modules/protobufjs-cli": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/protobufjs-cli/-/protobufjs-cli-1.1.3.tgz", - "integrity": "sha512-MqD10lqF+FMsOayFiNOdOGNlXc4iKDCf0ZQPkPR+gizYh9gqUeGTWulABUCdI+N67w5RfJ6xhgX4J8pa8qmMXQ==", - "license": "BSD-3-Clause", - "dependencies": { - "chalk": "^4.0.0", - "escodegen": "^1.13.0", - "espree": "^9.0.0", - "estraverse": "^5.1.0", - "glob": "^8.0.0", - "jsdoc": "^4.0.0", - "minimist": "^1.2.0", - "semver": "^7.1.2", - "tmp": "^0.2.1", - "uglify-js": "^3.7.7" - }, - "bin": { - "pbjs": "bin/pbjs", - "pbts": "bin/pbts" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "protobufjs": "^7.0.0" - } - }, - "node_modules/protobufjs-cli/node_modules/escodegen": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", - "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", - "license": "BSD-2-Clause", - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=4.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "node_modules/protobufjs-cli/node_modules/escodegen/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/protobufjs-cli/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/protobufjs-cli/node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "license": "MIT", - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/protobufjs-cli/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/protobufjs-cli/node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "license": "MIT", - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/protobufjs-cli/node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/protobufjs-cli/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/protobufjs-cli/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "license": "BSD-3-Clause", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/protobufjs-cli/node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "license": "MIT", - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -55712,6 +39302,7 @@ "version": "6.4.0", "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz", "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==", + "dev": true, "dependencies": { "agent-base": "^7.0.2", "debug": "^4.3.4", @@ -55730,6 +39321,7 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" @@ -55742,6 +39334,7 @@ "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, "engines": { "node": ">=12" } @@ -55766,27 +39359,8 @@ "node_modules/psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" - }, - "node_modules/public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "license": "MIT", - "dependencies": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/public-encrypt/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", - "license": "MIT" + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "dev": true }, "node_modules/pump": { "version": "3.0.2", @@ -55802,15 +39376,6 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" }, - "node_modules/punycode.js": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", - "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/pupa": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/pupa/-/pupa-3.1.0.tgz", @@ -55841,30 +39406,6 @@ } ] }, - "node_modules/pvtsutils": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.6.tgz", - "integrity": "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==", - "license": "MIT", - "dependencies": { - "tslib": "^2.8.1" - } - }, - "node_modules/pvtsutils/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/pvutils": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", - "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==", - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/qr-code-styling": { "version": "1.8.4", "resolved": "https://registry.npmjs.org/qr-code-styling/-/qr-code-styling-1.8.4.tgz", @@ -55898,16 +39439,6 @@ "resolved": "https://registry.npmjs.org/qrcode-generator/-/qrcode-generator-1.4.4.tgz", "integrity": "sha512-HM7yY8O2ilqhmULxGMpcHSF1EhJJ9yBj8gvDEuZ6M+KGJ0YY2hKpnXvRD+hZPLrDVck3ExIGhmPtSdcjC+guuw==" }, - "node_modules/qrcode-terminal": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/qrcode-terminal/-/qrcode-terminal-0.11.0.tgz", - "integrity": "sha512-Uu7ii+FQy4Qf82G4xu7ShHhjhGahEpCWc3x8UavY3CTcWV+ufmmCtwkr7ZKsX42jdL0kr1B5FKUeqJvAn51jzQ==", - "optional": true, - "peer": true, - "bin": { - "qrcode-terminal": "bin/qrcode-terminal.js" - } - }, "node_modules/qrcode-terminal-nooctal": { "version": "0.12.1", "resolved": "https://registry.npmjs.org/qrcode-terminal-nooctal/-/qrcode-terminal-nooctal-0.12.1.tgz", @@ -56045,7 +39576,8 @@ "node_modules/querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true }, "node_modules/queue": { "version": "6.0.2", @@ -56131,16 +39663,6 @@ "safe-buffer": "^5.1.0" } }, - "node_modules/randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "license": "MIT", - "dependencies": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" - } - }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -56515,7 +40037,8 @@ "node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true }, "node_modules/react-json-view-lite": { "version": "1.4.0", @@ -56616,19 +40139,6 @@ } } }, - "node_modules/react-native-securerandom": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/react-native-securerandom/-/react-native-securerandom-0.1.1.tgz", - "integrity": "sha512-CozcCx0lpBLevxiXEb86kwLRalBCHNjiGPlw3P7Fi27U6ZLdfjOCNRHD1LtBKcvPvI3TvkBXB3GOtLvqaYJLGw==", - "license": "MIT", - "optional": true, - "dependencies": { - "base64-js": "*" - }, - "peerDependencies": { - "react-native": "*" - } - }, "node_modules/react-native-webview": { "version": "11.26.1", "resolved": "https://registry.npmjs.org/react-native-webview/-/react-native-webview-11.26.1.tgz", @@ -56974,12 +40484,6 @@ "license": "BSD", "peer": true }, - "node_modules/readonly-date": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/readonly-date/-/readonly-date-1.0.0.tgz", - "integrity": "sha512-tMKIV7hlk0h4mO3JTmmVuIlJVXjKk3Sep9Bf5OH0O+758ruuVkUy2J9SttDLm91IEX/WHlXPSpxMGjPj4beMIQ==", - "license": "Apache-2.0" - }, "node_modules/real-require": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.1.0.tgz", @@ -57358,14 +40862,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/remove-trailing-slash": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/remove-trailing-slash/-/remove-trailing-slash-0.1.1.tgz", - "integrity": "sha512-o4S4Qh6L2jpnCy83ysZDau+VORNvnFw07CKSAymkd6ICNVEPisMyzlc00KlvvicsxKck94SEwhDnMNdICzO+tA==", - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/renderkid": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", @@ -57459,93 +40955,6 @@ "entities": "^2.0.0" } }, - "node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "license": "Apache-2.0", - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/request/node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/request/node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/request/node_modules/qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/request/node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "license": "BSD-3-Clause", - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/request/node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "license": "MIT", - "bin": { - "uuid": "bin/uuid" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -57588,53 +40997,11 @@ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, - "node_modules/requireg": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/requireg/-/requireg-0.2.2.tgz", - "integrity": "sha512-nYzyjnFcPNGR3lx9lwPPPnuQxv6JWEZd2Ci0u9opN7N5zUEPIhY/GbL3vMGOr2UXwEg9WwSyV9X9Y/kLFgPsOg==", - "optional": true, - "peer": true, - "dependencies": { - "nested-error-stacks": "~2.0.1", - "rc": "~1.2.7", - "resolve": "~1.7.1" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/requireg/node_modules/resolve": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", - "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "path-parse": "^1.0.5" - } - }, "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" }, - "node_modules/requizzle": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz", - "integrity": "sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw==", - "license": "MIT", - "dependencies": { - "lodash": "^4.17.21" - } - }, - "node_modules/reselect": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", - "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==", - "license": "MIT", - "peer": true - }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -57828,105 +41195,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "license": "MIT", - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "node_modules/ripemd160-min": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/ripemd160-min/-/ripemd160-min-0.0.6.tgz", - "integrity": "sha512-+GcJgQivhs6S9qvLogusiTcS9kQUfgR75whKuy5jIhuiOfQuJ8fjqxV6EGD5duH1Y/FawFUMtMhyeq3Fbnib8A==", - "engines": { - "node": ">=8" - } - }, - "node_modules/ripple-address-codec": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ripple-address-codec/-/ripple-address-codec-5.0.0.tgz", - "integrity": "sha512-de7osLRH/pt5HX2xw2TRJtbdLLWHu0RXirpQaEeCnWKY5DYHykh3ETSkofvm0aX0LJiV7kwkegJxQkmbO94gWw==", - "license": "ISC", - "dependencies": { - "@scure/base": "^1.1.3", - "@xrplf/isomorphic": "^1.0.0" - }, - "engines": { - "node": ">= 16" - } - }, - "node_modules/ripple-binary-codec": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ripple-binary-codec/-/ripple-binary-codec-2.1.0.tgz", - "integrity": "sha512-q0GAx+hj3UVcDbhXVjk7qeNfgUMehlElYJwiCuIBwqs/51GVTOwLr39Ht3eNsX5ow2xPRaC5mqHwcFDvLRm6cA==", - "license": "ISC", - "dependencies": { - "@xrplf/isomorphic": "^1.0.1", - "bignumber.js": "^9.0.0", - "ripple-address-codec": "^5.0.0" - }, - "engines": { - "node": ">= 16" - } - }, - "node_modules/ripple-keypairs": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ripple-keypairs/-/ripple-keypairs-2.0.0.tgz", - "integrity": "sha512-b5rfL2EZiffmklqZk1W+dvSy97v3V/C7936WxCCgDynaGPp7GE6R2XO7EU9O2LlM/z95rj870IylYnOQs+1Rag==", - "license": "ISC", - "dependencies": { - "@noble/curves": "^1.0.0", - "@xrplf/isomorphic": "^1.0.0", - "ripple-address-codec": "^5.0.0" - }, - "engines": { - "node": ">= 16" - } - }, - "node_modules/rlp": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.7.tgz", - "integrity": "sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==", - "license": "MPL-2.0", - "dependencies": { - "bn.js": "^5.2.0" - }, - "bin": { - "rlp": "bin/rlp" - } - }, - "node_modules/rpc-websockets": { - "version": "7.11.2", - "resolved": "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-7.11.2.tgz", - "integrity": "sha512-pL9r5N6AVHlMN/vT98+fcO+5+/UcPLf/4tq+WUaid/PPUGS/ttJ3y8e9IqmaWKtShNAysMSjkczuEA49NuV7UQ==", - "license": "LGPL-3.0-only", - "dependencies": { - "eventemitter3": "^4.0.7", - "uuid": "^8.3.2", - "ws": "^8.5.0" - }, - "funding": { - "type": "paypal", - "url": "https://paypal.me/kozjak" - }, - "optionalDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - } - }, - "node_modules/rpc-websockets/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/rtl-detect": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/rtl-detect/-/rtl-detect-1.1.2.tgz", @@ -58036,14 +41304,6 @@ } ] }, - "node_modules/safe-json-stringify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz", - "integrity": "sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg==", - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/safe-regex-test": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", @@ -58073,29 +41333,6 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, - "node_modules/sanitize-html": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.14.0.tgz", - "integrity": "sha512-CafX+IUPxZshXqqRaG9ZClSlfPVjSxI0td7n07hk8QO2oO+9JDnlcL8iM8TWeOXOIBFgIOx6zioTzM53AOMn3g==", - "license": "MIT", - "dependencies": { - "deepmerge": "^4.2.2", - "escape-string-regexp": "^4.0.0", - "htmlparser2": "^8.0.0", - "is-plain-object": "^5.0.0", - "parse-srcset": "^1.0.2", - "postcss": "^8.3.11" - } - }, - "node_modules/sanitize-html/node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/sass": { "version": "1.77.8", "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.8.tgz", @@ -58168,13 +41405,6 @@ "node": ">=v12.22.7" } }, - "node_modules/scale-ts": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/scale-ts/-/scale-ts-1.6.1.tgz", - "integrity": "sha512-PBMc2AWc6wSEqJYBDPcyCLUj9/tMKnLX70jLOSndMtcUoLQucP/DM0vnQo1wJAYjTrQiq8iG9rD0q6wFzgjH7g==", - "license": "MIT", - "optional": true - }, "node_modules/scheduler": { "version": "0.23.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", @@ -58201,12 +41431,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/scrypt-js": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", - "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==", - "license": "MIT" - }, "node_modules/search-insights": { "version": "2.17.3", "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.17.3.tgz", @@ -58220,6 +41444,7 @@ "integrity": "sha512-lDFs9AAIaWP9UCdtWrotXWWF9t8PWgQDcxqgAnpM9rMqxb3Oaq2J0thzPVSxBwdJgyQtkU/sYtFtbM1RSt/iYA==", "hasInstallScript": true, "license": "MIT", + "peer": true, "dependencies": { "elliptic": "^6.5.7", "node-addon-api": "^5.0.0", @@ -58233,13 +41458,8 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", - "license": "MIT" - }, - "node_modules/secrets.js-grempe": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/secrets.js-grempe/-/secrets.js-grempe-1.1.0.tgz", - "integrity": "sha512-OsbpZUFTjvQPKHpseAbFPY82U3mVNP4G3WSbJiDtMLjzwsV52MTdc6rTwIooIkg3klf5eCrg62ZuGIz5GaW02A==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/section-matter": { "version": "1.0.0", @@ -58259,12 +41479,6 @@ "integrity": "sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==", "dev": true }, - "node_modules/secure-json-parse": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", - "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==", - "license": "BSD-3-Clause" - }, "node_modules/select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", @@ -58541,22 +41755,6 @@ "node": ">= 0.8.0" } }, - "node_modules/servify": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/servify/-/servify-0.1.12.tgz", - "integrity": "sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw==", - "license": "MIT", - "dependencies": { - "body-parser": "^1.16.0", - "cors": "^2.8.1", - "express": "^4.14.0", - "request": "^2.79.0", - "xhr": "^2.3.3" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -58592,12 +41790,6 @@ "node": ">= 0.4" } }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", - "license": "MIT" - }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -58723,70 +41915,6 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, - "node_modules/simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/simple-get": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.2.tgz", - "integrity": "sha512-Ijd/rV5o+mSBBs4F/x9oDPtTx9Zb6X9brmnXvMW4J7IR15ngi9q5xxqWBKU744jTZiaXtxaPL7uHG6vtN8kUkw==", - "license": "MIT", - "dependencies": { - "decompress-response": "^3.3.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, - "node_modules/simple-get/node_modules/decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", - "license": "MIT", - "dependencies": { - "mimic-response": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/simple-get/node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/simple-plist": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/simple-plist/-/simple-plist-1.3.1.tgz", - "integrity": "sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw==", - "license": "MIT", - "peer": true, - "dependencies": { - "bplist-creator": "0.1.0", - "bplist-parser": "0.3.1", - "plist": "^3.0.5" - } - }, "node_modules/simple-swizzle": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", @@ -58841,15 +41969,6 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==" }, - "node_modules/sjcl": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/sjcl/-/sjcl-1.0.8.tgz", - "integrity": "sha512-LzIjEQ0S0DpIgnxMEayM1rq9aGwGRG4OnZhCdjx7glTaJtf4zRfpg87ImfjSJjoW9vKpagd82McDOwbRT5kQKQ==", - "license": "(BSD-2-Clause OR GPL-2.0-only)", - "engines": { - "node": "*" - } - }, "node_modules/skin-tone": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/skin-tone/-/skin-tone-2.0.0.tgz", @@ -58897,35 +42016,16 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/slugify": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.6.tgz", - "integrity": "sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8.0.0" - } - }, "node_modules/smart-buffer": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" } }, - "node_modules/smoldot": { - "version": "2.0.26", - "resolved": "https://registry.npmjs.org/smoldot/-/smoldot-2.0.26.tgz", - "integrity": "sha512-F+qYmH4z2s2FK+CxGj8moYcd1ekSIKH8ywkdqlOz88Dat35iB1DIYL11aILN46YSGMzQW/lbJNS307zBSDN5Ig==", - "license": "GPL-3.0-or-later WITH Classpath-exception-2.0", - "optional": true, - "dependencies": { - "ws": "^8.8.1" - } - }, "node_modules/snake-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", @@ -58983,6 +42083,7 @@ "version": "2.8.3", "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "dev": true, "dependencies": { "ip-address": "^9.0.5", "smart-buffer": "^4.2.0" @@ -58996,6 +42097,7 @@ "version": "8.0.5", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", + "dev": true, "dependencies": { "agent-base": "^7.1.2", "debug": "^4.3.4", @@ -59005,17 +42107,6 @@ "node": ">= 14" } }, - "node_modules/sodium-native": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-3.4.1.tgz", - "integrity": "sha512-PaNN/roiFWzVVTL6OqjzYct38NSXewdl2wz8SRB51Br/MLIJPrbM3XexhVWkq7D3UWMysfrhKVf1v1phZq6MeQ==", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "dependencies": { - "node-gyp-build": "^4.3.0" - } - }, "node_modules/sonic-boom": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-2.8.0.tgz", @@ -59146,20 +42237,6 @@ "wbuf": "^1.7.3" } }, - "node_modules/split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "through": "2" - }, - "engines": { - "node": "*" - } - }, "node_modules/split-on-first": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", @@ -59192,71 +42269,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/sshpk": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", - "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", - "license": "MIT", - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sshpk/node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", - "license": "MIT" - }, - "node_modules/sshpk/node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", - "license": "Unlicense" - }, - "node_modules/ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "minipass": "^3.1.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/ssri/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", @@ -59337,83 +42349,6 @@ "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==" }, - "node_modules/stellar-base": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/stellar-base/-/stellar-base-8.2.2.tgz", - "integrity": "sha512-YVCIuJXU1bPn+vU0ded+g0D99DcpYXH9CEXfpYEDc4Gf04h65YjOVhGojQBm1hqVHq3rKT7m1tgfNACkU84FTA==", - "deprecated": "⚠️ This package has moved to @stellar/stellar-base! 🚚", - "license": "Apache-2.0", - "dependencies": { - "base32.js": "^0.1.0", - "bignumber.js": "^4.0.0", - "crc": "^3.5.0", - "js-xdr": "^1.1.3", - "lodash": "^4.17.21", - "sha.js": "^2.3.6", - "tweetnacl": "^1.0.3" - }, - "optionalDependencies": { - "sodium-native": "^3.3.0" - } - }, - "node_modules/stellar-base/node_modules/bignumber.js": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-4.1.0.tgz", - "integrity": "sha512-eJzYkFYy9L4JzXsbymsFn3p54D+llV27oTQ+ziJG7WFRheJcNZilgVXMG0LoZtlQSKBsJdWtLFqOD0u+U0jZKA==", - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/stellar-sdk": { - "version": "10.4.1", - "resolved": "https://registry.npmjs.org/stellar-sdk/-/stellar-sdk-10.4.1.tgz", - "integrity": "sha512-Wdm2UoLuN9SNrSEHO0R/I+iZuRwUkfny1xg4akhGCpO8LQZw8QzuMTJvbEoMT3sHT4/eWYiteVLp7ND21xZf5A==", - "deprecated": "⚠️ This package has moved to @stellar/stellar-sdk! 🚚", - "license": "Apache-2.0", - "dependencies": { - "@types/eventsource": "^1.1.2", - "@types/node": ">= 8", - "@types/randombytes": "^2.0.0", - "@types/urijs": "^1.19.6", - "axios": "0.25.0", - "bignumber.js": "^4.0.0", - "detect-node": "^2.0.4", - "es6-promise": "^4.2.4", - "eventsource": "^1.1.1", - "lodash": "^4.17.21", - "randombytes": "^2.1.0", - "stellar-base": "^8.2.2", - "toml": "^2.3.0", - "tslib": "^1.10.0", - "urijs": "^1.19.1", - "utility-types": "^3.7.0" - } - }, - "node_modules/stellar-sdk/node_modules/axios": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz", - "integrity": "sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.14.7" - } - }, - "node_modules/stellar-sdk/node_modules/bignumber.js": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-4.1.0.tgz", - "integrity": "sha512-eJzYkFYy9L4JzXsbymsFn3p54D+llV27oTQ+ziJG7WFRheJcNZilgVXMG0LoZtlQSKBsJdWtLFqOD0u+U0jZKA==", - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/stellar-sdk/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "license": "0BSD" - }, "node_modules/steno": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/steno/-/steno-4.0.2.tgz", @@ -59437,38 +42372,6 @@ "node": ">= 0.4" } }, - "node_modules/store2": { - "version": "2.13.2", - "resolved": "https://registry.npmjs.org/store2/-/store2-2.13.2.tgz", - "integrity": "sha512-CMtO2Uneg3SAz/d6fZ/6qbqqQHi2ynq6/KzMD/26gTkiEShCcpqFfTHgOxsE0egAq6SX3FmN4CeSqn8BzXQkJg==", - "license": "(MIT OR GPL-3.0)" - }, - "node_modules/str2buf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/str2buf/-/str2buf-1.3.0.tgz", - "integrity": "sha512-xIBmHIUHYZDP4HyoXGHYNVmxlXLXDrtFHYT0eV6IOdEj3VO9ccaF1Ejl9Oq8iFjITllpT8FhaXb4KsNmw+3EuA==", - "license": "MIT" - }, - "node_modules/stream-browserify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", - "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", - "license": "MIT", - "dependencies": { - "inherits": "~2.0.4", - "readable-stream": "^3.5.0" - } - }, - "node_modules/stream-buffers": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz", - "integrity": "sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==", - "license": "Unlicense", - "peer": true, - "engines": { - "node": ">= 0.10.0" - } - }, "node_modules/stream-shift": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", @@ -59535,12 +42438,6 @@ "dev": true, "license": "MIT" }, - "node_modules/strict-event-emitter-types": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strict-event-emitter-types/-/strict-event-emitter-types-2.0.0.tgz", - "integrity": "sha512-Nk/brWYpD85WlOgzw5h173aci0Teyv8YdIAEtV+N88nDB0dLlazZyJMIsN6eo1/AR61l+p6CJTG1JIyFaoNEEA==", - "license": "ISC" - }, "node_modules/strict-uri-encode": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", @@ -59600,6 +42497,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -59612,12 +42510,14 @@ "node_modules/string-width-cjs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { "node": ">=8" } @@ -59771,6 +42671,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -59795,17 +42696,6 @@ "node": ">=0.10.0" } }, - "node_modules/strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", @@ -59814,19 +42704,6 @@ "node": ">=6" } }, - "node_modules/strip-hex-prefix": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", - "integrity": "sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==", - "license": "MIT", - "dependencies": { - "is-hex-prefixed": "1.0.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -59860,14 +42737,6 @@ "node": ">=4" } }, - "node_modules/structured-headers": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/structured-headers/-/structured-headers-0.4.1.tgz", - "integrity": "sha512-0MP/Cxx5SzeeZ10p/bZI0S6MpgD+yxAhi1BOQ34jgnMXsCq3j1t6tQnZu+KdlL7dvJTLT3g9xN8tl10TqgFMcg==", - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/style-loader": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz", @@ -59998,6 +42867,7 @@ "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", @@ -60019,6 +42889,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, "engines": { "node": ">= 6" } @@ -60027,6 +42898,7 @@ "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", @@ -60046,6 +42918,7 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, "dependencies": { "@isaacs/cliui": "^8.0.2" }, @@ -60059,12 +42932,14 @@ "node_modules/sucrase/node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true }, "node_modules/sucrase/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -60075,19 +42950,11 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/sudo-prompt": { - "version": "8.2.5", - "resolved": "https://registry.npmjs.org/sudo-prompt/-/sudo-prompt-8.2.5.tgz", - "integrity": "sha512-rlBo3HU/1zAJUrkY6jNxDOC9eVYliG6nS4JA8u8KAshITd07tafMc/Br7xQwCSseXwJ2iCcHCE8SNWX3q8Z+kw==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/superagent": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/superagent/-/superagent-9.0.2.tgz", "integrity": "sha512-xuW7dzkUpcJq7QnhOsnNUgtYp3xRwpt2F7abdRYIpCsAt0hhUqia0EdxyXZQQpNmGtsCzYHryaKSV3q3GJnq7w==", + "dev": true, "dependencies": { "component-emitter": "^1.3.0", "cookiejar": "^2.1.4", @@ -60107,6 +42974,7 @@ "version": "2.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, "bin": { "mime": "cli.js" }, @@ -60146,21 +43014,6 @@ "node": ">=8" } }, - "node_modules/supports-hyperlinks": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", - "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -60214,225 +43067,6 @@ "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.17.14.tgz", "integrity": "sha512-CVbSfaLpstV65OnSjbXfVd6Sta3q3F7Cj/yYuvHMp1P90LztOLs6PfUnKEVAeiIVQt9u2SaPwv0LiH/OyMjHRw==" }, - "node_modules/swarm-js": { - "version": "0.1.42", - "resolved": "https://registry.npmjs.org/swarm-js/-/swarm-js-0.1.42.tgz", - "integrity": "sha512-BV7c/dVlA3R6ya1lMlSSNPLYrntt0LUq4YMgy3iwpCIc6rZnS5W2wUoctarZ5pXlpKtxDDf9hNziEkcfrxdhqQ==", - "license": "MIT", - "dependencies": { - "bluebird": "^3.5.0", - "buffer": "^5.0.5", - "eth-lib": "^0.1.26", - "fs-extra": "^4.0.2", - "got": "^11.8.5", - "mime-types": "^2.1.16", - "mkdirp-promise": "^5.0.1", - "mock-fs": "^4.1.0", - "setimmediate": "^1.0.5", - "tar": "^4.0.2", - "xhr-request": "^1.0.1" - } - }, - "node_modules/swarm-js/node_modules/@szmarczak/http-timer": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", - "license": "MIT", - "dependencies": { - "defer-to-connect": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/swarm-js/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", - "license": "MIT" - }, - "node_modules/swarm-js/node_modules/cacheable-lookup": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", - "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", - "license": "MIT", - "engines": { - "node": ">=10.6.0" - } - }, - "node_modules/swarm-js/node_modules/cacheable-request": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", - "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", - "license": "MIT", - "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^4.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^6.0.1", - "responselike": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/swarm-js/node_modules/eth-lib": { - "version": "0.1.29", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.29.tgz", - "integrity": "sha512-bfttrr3/7gG4E02HoWTDUcDDslN003OlOoBxk9virpAZQ1ja/jDgwkWB8QfJF7ojuEowrqy+lzp9VcJG7/k5bQ==", - "license": "MIT", - "dependencies": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "nano-json-stream-parser": "^0.1.2", - "servify": "^0.1.12", - "ws": "^3.0.0", - "xhr-request-promise": "^0.1.2" - } - }, - "node_modules/swarm-js/node_modules/fs-extra": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", - "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "node_modules/swarm-js/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "license": "MIT", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/swarm-js/node_modules/got": { - "version": "11.8.6", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", - "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", - "license": "MIT", - "dependencies": { - "@sindresorhus/is": "^4.0.0", - "@szmarczak/http-timer": "^4.0.5", - "@types/cacheable-request": "^6.0.1", - "@types/responselike": "^1.0.0", - "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.2", - "decompress-response": "^6.0.0", - "http2-wrapper": "^1.0.0-beta.5.2", - "lowercase-keys": "^2.0.0", - "p-cancelable": "^2.0.0", - "responselike": "^2.0.0" - }, - "engines": { - "node": ">=10.19.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" - } - }, - "node_modules/swarm-js/node_modules/http2-wrapper": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", - "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", - "license": "MIT", - "dependencies": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.0.0" - }, - "engines": { - "node": ">=10.19.0" - } - }, - "node_modules/swarm-js/node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "license": "MIT", - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/swarm-js/node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/swarm-js/node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/swarm-js/node_modules/p-cancelable": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/swarm-js/node_modules/responselike": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", - "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", - "license": "MIT", - "dependencies": { - "lowercase-keys": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/swarm-js/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "license": "MIT" - }, - "node_modules/swarm-js/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "license": "MIT", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/swarm-js/node_modules/ws": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", - "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", - "license": "MIT", - "dependencies": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0", - "ultron": "~1.1.0" - } - }, "node_modules/swr": { "version": "2.2.5", "resolved": "https://registry.npmjs.org/swr/-/swr-2.2.5.tgz", @@ -60445,15 +43079,6 @@ "react": "^16.11.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/symbol-observable": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-2.0.3.tgz", - "integrity": "sha512-sQV7phh2WCYAn81oAkakC5qjq2Ml0g8ozqz03wOGnx9dDlG1de6yrF+0RAzSJD8fPUow3PTSMf2SAbOGxb93BA==", - "license": "MIT", - "engines": { - "node": ">=0.10" - } - }, "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", @@ -60591,24 +43216,6 @@ "node": ">=6" } }, - "node_modules/tar": { - "version": "4.4.19", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", - "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", - "license": "ISC", - "dependencies": { - "chownr": "^1.1.4", - "fs-minipass": "^1.2.7", - "minipass": "^2.9.0", - "minizlib": "^1.3.3", - "mkdirp": "^0.5.5", - "safe-buffer": "^5.2.1", - "yallist": "^3.1.1" - }, - "engines": { - "node": ">=4.5" - } - }, "node_modules/tar-stream": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", @@ -60625,117 +43232,6 @@ "node": ">=6" } }, - "node_modules/tar/node_modules/minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", - "license": "ISC", - "dependencies": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "node_modules/tar/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "license": "ISC" - }, - "node_modules/tcomb": { - "version": "3.2.29", - "resolved": "https://registry.npmjs.org/tcomb/-/tcomb-3.2.29.tgz", - "integrity": "sha512-di2Hd1DB2Zfw6StGv861JoAF5h/uQVu/QJp2g8KVbtfKnoHdBQl5M32YWq6mnSYBQ1vFFrns5B1haWJL7rKaOQ==", - "license": "MIT" - }, - "node_modules/temp-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", - "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/tempy": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.7.1.tgz", - "integrity": "sha512-vXPxwOyaNVi9nyczO16mxmHGpl6ASC5/TVhRRHpqeYHvKQm58EaWNvZXxAhR0lYYnBOQFjXjhzeLsaXdjxLjRg==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "del": "^6.0.0", - "is-stream": "^2.0.0", - "temp-dir": "^2.0.0", - "type-fest": "^0.16.0", - "unique-string": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/tempy/node_modules/crypto-random-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/tempy/node_modules/type-fest": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", - "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", - "license": "(MIT OR CC0-1.0)", - "optional": true, - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/tempy/node_modules/unique-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "crypto-random-string": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/terminal-link": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", - "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "ansi-escapes": "^4.2.1", - "supports-hyperlinks": "^2.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/terser": { "version": "5.31.2", "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.2.tgz", @@ -60913,11 +43409,6 @@ "node": "*" } }, - "node_modules/text-encoding-utf-8": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz", - "integrity": "sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==" - }, "node_modules/text-hex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", @@ -60932,6 +43423,7 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, "dependencies": { "any-promise": "^1.0.0" } @@ -60940,6 +43432,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, "dependencies": { "thenify": ">= 3.1.0 < 4" }, @@ -60977,35 +43470,14 @@ "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true }, "node_modules/thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" }, - "node_modules/timed-out": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", - "integrity": "sha512-G7r3AhovYtr5YKOWQkta8RKAPb+J9IsO4uVmzjl8AZwfhs8UcUwTiD6gcJYSgOtzyjvQKrKYn41syHbUWMkafA==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/timers-ext": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.8.tgz", - "integrity": "sha512-wFH7+SEAcKfJpfLPkrgMPvvwnEtj8W4IurvEyrKsDleXnKLCDw71w8jltvfLa8Rm4qQxxT4jmDBYbJG/z7qoww==", - "license": "ISC", - "dependencies": { - "es5-ext": "^0.10.64", - "next-tick": "^1.1.0" - }, - "engines": { - "node": ">=0.12" - } - }, "node_modules/tiny-invariant": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", @@ -61029,15 +43501,6 @@ "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==" }, - "node_modules/to-readable-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", - "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -61057,76 +43520,6 @@ "node": ">=0.6" } }, - "node_modules/toml": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/toml/-/toml-2.3.6.tgz", - "integrity": "sha512-gVweAectJU3ebq//Ferr2JUY4WKSDe5N+z0FvjDncLGyHmIDoxgY/2Ie4qfEIDm4IS7OA6Rmdm7pdEEdMcV/xQ==", - "license": "MIT" - }, - "node_modules/tonweb": { - "version": "0.0.62", - "resolved": "https://registry.npmjs.org/tonweb/-/tonweb-0.0.62.tgz", - "integrity": "sha512-Uwu2DQwmVkI85WVLzqIqUvqNk++N97e2EH3hKb+Tvq3fA6pcEP7AugcNr1xU33GmajtLT9vquMo7/kNcnS1Fuw==", - "license": "MIT", - "dependencies": { - "@ledgerhq/hw-transport-web-ble": "5.48.0", - "@ledgerhq/hw-transport-webhid": "5.48.0", - "@ledgerhq/hw-transport-webusb": "5.48.0", - "bn.js": "5.1.1", - "ethjs-unit": "0.1.6", - "isomorphic-webcrypto": "2.3.8", - "node-fetch": "2.6.7", - "tweetnacl": "1.0.3" - } - }, - "node_modules/tonweb/node_modules/bn.js": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.1.tgz", - "integrity": "sha512-IUTD/REb78Z2eodka1QZyyEk66pciRcP6Sroka0aI3tG/iwIdYLrBD62RsubR7vqdt3WyX8p4jxeatzmRSphtA==", - "license": "MIT" - }, - "node_modules/tonweb/node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/tonweb/node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT" - }, - "node_modules/tonweb/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause" - }, - "node_modules/tonweb/node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "node_modules/totalist": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", @@ -61247,49 +43640,6 @@ "node": ">= 14.0.0" } }, - "node_modules/tronweb": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/tronweb/-/tronweb-5.1.0.tgz", - "integrity": "sha512-8a+mYKVUzsUWjeTHSAKcxAp82FseFTLlNLoLQ0KIL1rIt6Dy5whcyJwYatxUktbaztl55lnImHbupkKqMdIj1w==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.0.0", - "@tronweb3/google-protobuf": "^3.21.2", - "axios": "^0.26.1", - "bignumber.js": "^9.0.1", - "elliptic": "^6.5.4", - "ethers": "^5.4.4", - "eventemitter3": "^3.1.0", - "injectpromise": "^1.0.0", - "lodash": "^4.17.21", - "semver": "^5.6.0", - "validator": "^13.7.0" - } - }, - "node_modules/tronweb/node_modules/axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.14.8" - } - }, - "node_modules/tronweb/node_modules/eventemitter3": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", - "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==", - "license": "MIT" - }, - "node_modules/tronweb/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, "node_modules/trough": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", @@ -61323,7 +43673,8 @@ "node_modules/ts-interface-checker": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", - "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true }, "node_modules/ts-jest": { "version": "29.2.3", @@ -61466,12 +43817,6 @@ "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true }, - "node_modules/ts-results": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/ts-results/-/ts-results-3.3.0.tgz", - "integrity": "sha512-FWqxGX2NHp5oCyaMd96o2y2uMQmSu8Dey6kvyuFdRJ2AzfmWo3kWa4UsPlCGlfQ/qu03m09ZZtppMoY8EMHuiA==", - "license": "MIT" - }, "node_modules/tsc-alias": { "version": "1.8.8", "resolved": "https://registry.npmjs.org/tsc-alias/-/tsc-alias-1.8.8.tgz", @@ -61549,55 +43894,11 @@ "node": ">=0.6.x" } }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "license": "Apache-2.0", - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", - "license": "Unlicense" - }, - "node_modules/tweetnacl-ts": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl-ts/-/tweetnacl-ts-1.0.3.tgz", - "integrity": "sha512-C5I/dWf6xjAXaCDlf84T4HvozU/8ycAlq5WRllF1hAeeq5390tfXD+bNas5bhEV0HMSOx8bsQYpLjPl8wfnEeQ==", - "license": "UNLICENSED", - "dependencies": { - "tslib": "^1" - } - }, - "node_modules/tweetnacl-ts/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "license": "0BSD" - }, - "node_modules/tweetnacl-util": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz", - "integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==", - "license": "Unlicense" - }, - "node_modules/type": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz", - "integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==", - "license": "ISC" - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "devOptional": true, "dependencies": { "prelude-ls": "^1.2.1" }, @@ -61743,21 +44044,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/typedjson": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/typedjson/-/typedjson-1.8.0.tgz", - "integrity": "sha512-taVJVGebQDagEmVc3Cu6vVVLkWLnxqPcTrkVgbpAsI02ZDDrnHy5zvt1JVqXv4/yztBgZAX1oR07+bkiusGJLQ==", - "license": "MIT", - "dependencies": { - "tslib": "^2.0.1" - } - }, - "node_modules/typeforce": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz", - "integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==", - "license": "MIT" - }, "node_modules/typescript": { "version": "5.4.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", @@ -61770,45 +44056,6 @@ "node": ">=14.17" } }, - "node_modules/u3": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/u3/-/u3-0.1.1.tgz", - "integrity": "sha512-+J5D5ir763y+Am/QY6hXNRlwljIeRMZMGs0cT6qqZVVzzT3X3nFPXVyPOFRMOR4kupB0T8JnCdpWdp6Q/iXn3w==", - "license": "MIT" - }, - "node_modules/ua-parser-js": { - "version": "0.7.40", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.40.tgz", - "integrity": "sha512-us1E3K+3jJppDBa3Tl0L3MOJiGhe1C6P0+nIvQAFYbxlMAx0h81eOwLmU57xgqToduDDPx3y5QsdjPfDu+FgOQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/ua-parser-js" - }, - { - "type": "paypal", - "url": "https://paypal.me/faisalman" - }, - { - "type": "github", - "url": "https://github.com/sponsors/faisalman" - } - ], - "license": "MIT", - "peer": true, - "bin": { - "ua-parser-js": "script/cli.js" - }, - "engines": { - "node": "*" - } - }, - "node_modules/uc.micro": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", - "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", - "license": "MIT" - }, "node_modules/ufo": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz", @@ -61818,6 +44065,7 @@ "version": "3.18.0", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.18.0.tgz", "integrity": "sha512-SyVVbcNBCk0dzr9XL/R/ySrmYf0s372K6/hFklzgcp2lBFyXtw4I7BOdDjlLhE1aVqaI/SHWXWmYdlZxuyF38A==", + "optional": true, "bin": { "uglifyjs": "bin/uglifyjs" }, @@ -61844,12 +44092,6 @@ "multiformats": "^9.4.2" } }, - "node_modules/ultron": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", - "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", - "license": "MIT" - }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -61869,12 +44111,6 @@ "resolved": "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz", "integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==" }, - "node_modules/underscore": { - "version": "1.13.7", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz", - "integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==", - "license": "MIT" - }, "node_modules/unenv": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/unenv/-/unenv-1.10.0.tgz", @@ -61980,28 +44216,6 @@ "node": ">= 0.8.0" } }, - "node_modules/unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "unique-slug": "^2.0.0" - } - }, - "node_modules/unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "imurmurhash": "^0.1.4" - } - }, "node_modules/unique-string": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", @@ -62371,12 +44585,6 @@ "node": ">=6" } }, - "node_modules/urijs": { - "version": "1.19.11", - "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.11.tgz", - "integrity": "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==", - "license": "MIT" - }, "node_modules/url-join": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", @@ -62458,29 +44666,12 @@ "version": "1.5.10", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dev": true, "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" } }, - "node_modules/url-parse-lax": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", - "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==", - "license": "MIT", - "dependencies": { - "prepend-http": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/url-set-query": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-set-query/-/url-set-query-1.0.0.tgz", - "integrity": "sha512-3AChu4NiXquPfeckE5R5cGdiHCMWJx1dwCWOmWIL4KHAziJNOFIYJlpGFeKDvwLPHovZRCxK3cYlwzqI9Vp+Gg==", - "license": "MIT" - }, "node_modules/use-callback-ref": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.2.tgz", @@ -62556,12 +44747,6 @@ "node": ">=6.14.2" } }, - "node_modules/utf8": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", - "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==", - "license": "MIT" - }, "node_modules/util": { "version": "0.12.5", "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", @@ -62632,13 +44817,6 @@ "node": ">=10.12.0" } }, - "node_modules/valid-url": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz", - "integrity": "sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA==", - "optional": true, - "peer": true - }, "node_modules/validate-npm-package-name": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", @@ -62693,21 +44871,6 @@ "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" }, - "node_modules/varint": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz", - "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==", - "license": "MIT" - }, - "node_modules/varuint-bitcoin": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/varuint-bitcoin/-/varuint-bitcoin-1.1.2.tgz", - "integrity": "sha512-4EVb+w4rx+YfVM32HQX42AbbT7/1f5zwAYhIujKXKk8NQK+JfRVl3pqT3hjNn/L+RstigmGGKVwHA/P0wgITZw==", - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.1" - } - }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -62716,26 +44879,6 @@ "node": ">= 0.8" } }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", - "engines": [ - "node >=0.6.0" - ], - "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "node_modules/verror/node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", - "license": "MIT" - }, "node_modules/vfile": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", @@ -62955,7 +45098,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "devOptional": true, + "dev": true, "dependencies": { "defaults": "^1.0.3" } @@ -62969,734 +45112,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/web-streams-polyfill": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", - "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/web3": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3/-/web3-1.3.6.tgz", - "integrity": "sha512-jEpPhnL6GDteifdVh7ulzlPrtVQeA30V9vnki9liYlUvLV82ZM7BNOQJiuzlDePuE+jZETZSP/0G/JlUVt6pOA==", - "hasInstallScript": true, - "license": "LGPL-3.0", - "dependencies": { - "web3-bzz": "1.3.6", - "web3-core": "1.3.6", - "web3-eth": "1.3.6", - "web3-eth-personal": "1.3.6", - "web3-net": "1.3.6", - "web3-shh": "1.3.6", - "web3-utils": "1.3.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-bzz": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.3.6.tgz", - "integrity": "sha512-ibHdx1wkseujFejrtY7ZyC0QxQ4ATXjzcNUpaLrvM6AEae8prUiyT/OloG9FWDgFD2CPLwzKwfSQezYQlANNlw==", - "hasInstallScript": true, - "license": "LGPL-3.0", - "dependencies": { - "@types/node": "^12.12.6", - "got": "9.6.0", - "swarm-js": "^0.1.40", - "underscore": "1.12.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-bzz/node_modules/@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/web3-bzz/node_modules/@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", - "license": "MIT", - "dependencies": { - "defer-to-connect": "^1.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/web3-bzz/node_modules/@types/node": { - "version": "12.20.55", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", - "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", - "license": "MIT" - }, - "node_modules/web3-bzz/node_modules/cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "license": "MIT", - "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/web3-bzz/node_modules/cacheable-request/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "license": "MIT", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/web3-bzz/node_modules/cacheable-request/node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/web3-bzz/node_modules/decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", - "license": "MIT", - "dependencies": { - "mimic-response": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/web3-bzz/node_modules/defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", - "license": "MIT" - }, - "node_modules/web3-bzz/node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "license": "MIT", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/web3-bzz/node_modules/got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "license": "MIT", - "dependencies": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/web3-bzz/node_modules/json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==", - "license": "MIT" - }, - "node_modules/web3-bzz/node_modules/keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", - "license": "MIT", - "dependencies": { - "json-buffer": "3.0.0" - } - }, - "node_modules/web3-bzz/node_modules/lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/web3-bzz/node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/web3-bzz/node_modules/normalize-url": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", - "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/web3-bzz/node_modules/p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/web3-bzz/node_modules/responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", - "license": "MIT", - "dependencies": { - "lowercase-keys": "^1.0.0" - } - }, - "node_modules/web3-bzz/node_modules/underscore": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", - "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", - "license": "MIT" - }, - "node_modules/web3-core": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.3.6.tgz", - "integrity": "sha512-gkLDM4T1Sc0T+HZIwxrNrwPg0IfWI0oABSglP2X5ZbBAYVUeEATA0o92LWV8BeF+okvKXLK1Fek/p6axwM/h3Q==", - "license": "LGPL-3.0", - "dependencies": { - "@types/bn.js": "^4.11.5", - "@types/node": "^12.12.6", - "bignumber.js": "^9.0.0", - "web3-core-helpers": "1.3.6", - "web3-core-method": "1.3.6", - "web3-core-requestmanager": "1.3.6", - "web3-utils": "1.3.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-core-helpers": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.3.6.tgz", - "integrity": "sha512-nhtjA2ZbkppjlxTSwG0Ttu6FcPkVu1rCN5IFAOVpF/L0SEt+jy+O5l90+cjDq0jAYvlBwUwnbh2mR9hwDEJCNA==", - "license": "LGPL-3.0", - "dependencies": { - "underscore": "1.12.1", - "web3-eth-iban": "1.3.6", - "web3-utils": "1.3.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-core-helpers/node_modules/underscore": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", - "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", - "license": "MIT" - }, - "node_modules/web3-core-method": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.3.6.tgz", - "integrity": "sha512-RyegqVGxn0cyYW5yzAwkPlsSEynkdPiegd7RxgB4ak1eKk2Cv1q2x4C7D2sZjeeCEF+q6fOkVmo2OZNqS2iQxg==", - "license": "LGPL-3.0", - "dependencies": { - "@ethersproject/transactions": "^5.0.0-beta.135", - "underscore": "1.12.1", - "web3-core-helpers": "1.3.6", - "web3-core-promievent": "1.3.6", - "web3-core-subscriptions": "1.3.6", - "web3-utils": "1.3.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-core-method/node_modules/underscore": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", - "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", - "license": "MIT" - }, - "node_modules/web3-core-promievent": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.3.6.tgz", - "integrity": "sha512-Z+QzfyYDTXD5wJmZO5wwnRO8bAAHEItT1XNSPVb4J1CToV/I/SbF7CuF8Uzh2jns0Cm1109o666H7StFFvzVKw==", - "license": "LGPL-3.0", - "dependencies": { - "eventemitter3": "4.0.4" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-core-promievent/node_modules/eventemitter3": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz", - "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==", - "license": "MIT" - }, - "node_modules/web3-core-requestmanager": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.3.6.tgz", - "integrity": "sha512-2rIaeuqeo7QN1Eex7aXP0ZqeteJEPWXYFS/M3r3LXMiV8R4STQBKE+//dnHJXoo2ctzEB5cgd+7NaJM8S3gPyA==", - "license": "LGPL-3.0", - "dependencies": { - "underscore": "1.12.1", - "util": "^0.12.0", - "web3-core-helpers": "1.3.6", - "web3-providers-http": "1.3.6", - "web3-providers-ipc": "1.3.6", - "web3-providers-ws": "1.3.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-core-requestmanager/node_modules/underscore": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", - "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", - "license": "MIT" - }, - "node_modules/web3-core-subscriptions": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.3.6.tgz", - "integrity": "sha512-wi9Z9X5X75OKvxAg42GGIf81ttbNR2TxzkAsp1g+nnp5K8mBwgZvXrIsDuj7Z7gx72Y45mWJADCWjk/2vqNu8g==", - "license": "LGPL-3.0", - "dependencies": { - "eventemitter3": "4.0.4", - "underscore": "1.12.1", - "web3-core-helpers": "1.3.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-core-subscriptions/node_modules/eventemitter3": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz", - "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==", - "license": "MIT" - }, - "node_modules/web3-core-subscriptions/node_modules/underscore": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", - "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", - "license": "MIT" - }, - "node_modules/web3-core/node_modules/@types/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/web3-core/node_modules/@types/node": { - "version": "12.20.55", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", - "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", - "license": "MIT" - }, - "node_modules/web3-eth": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.3.6.tgz", - "integrity": "sha512-9+rnywRRpyX3C4hfsAQXPQh6vHh9XzQkgLxo3gyeXfbhbShUoq2gFVuy42vsRs//6JlsKdyZS7Z3hHPHz2wreA==", - "license": "LGPL-3.0", - "dependencies": { - "underscore": "1.12.1", - "web3-core": "1.3.6", - "web3-core-helpers": "1.3.6", - "web3-core-method": "1.3.6", - "web3-core-subscriptions": "1.3.6", - "web3-eth-abi": "1.3.6", - "web3-eth-accounts": "1.3.6", - "web3-eth-contract": "1.3.6", - "web3-eth-ens": "1.3.6", - "web3-eth-iban": "1.3.6", - "web3-eth-personal": "1.3.6", - "web3-net": "1.3.6", - "web3-utils": "1.3.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-eth-abi": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.3.6.tgz", - "integrity": "sha512-Or5cRnZu6WzgScpmbkvC6bfNxR26hqiKK4i8sMPFeTUABQcb/FU3pBj7huBLYbp9dH+P5W79D2MqwbWwjj9DoQ==", - "license": "LGPL-3.0", - "dependencies": { - "@ethersproject/abi": "5.0.7", - "underscore": "1.12.1", - "web3-utils": "1.3.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-eth-abi/node_modules/@ethersproject/abi": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.0.7.tgz", - "integrity": "sha512-Cqktk+hSIckwP/W8O47Eef60VwmoSC/L3lY0+dIBhQPCNn9E4V7rwmm2aFrNRRDJfFlGuZ1khkQUOc3oBX+niw==", - "license": "MIT", - "dependencies": { - "@ethersproject/address": "^5.0.4", - "@ethersproject/bignumber": "^5.0.7", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/constants": "^5.0.4", - "@ethersproject/hash": "^5.0.4", - "@ethersproject/keccak256": "^5.0.3", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/properties": "^5.0.3", - "@ethersproject/strings": "^5.0.4" - } - }, - "node_modules/web3-eth-abi/node_modules/underscore": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", - "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", - "license": "MIT" - }, - "node_modules/web3-eth-accounts": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.3.6.tgz", - "integrity": "sha512-Ilr0hG6ONbCdSlVKffasCmNwftD5HsNpwyQASevocIQwHdTlvlwO0tb3oGYuajbKOaDzNTwXfz25bttAEoFCGA==", - "license": "LGPL-3.0", - "dependencies": { - "crypto-browserify": "3.12.0", - "eth-lib": "0.2.8", - "ethereumjs-common": "^1.3.2", - "ethereumjs-tx": "^2.1.1", - "scrypt-js": "^3.0.1", - "underscore": "1.12.1", - "uuid": "3.3.2", - "web3-core": "1.3.6", - "web3-core-helpers": "1.3.6", - "web3-core-method": "1.3.6", - "web3-utils": "1.3.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-eth-accounts/node_modules/underscore": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", - "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", - "license": "MIT" - }, - "node_modules/web3-eth-accounts/node_modules/uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "license": "MIT", - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/web3-eth-contract": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.3.6.tgz", - "integrity": "sha512-8gDaRrLF2HCg+YEZN1ov0zN35vmtPnGf3h1DxmJQK5Wm2lRMLomz9rsWsuvig3UJMHqZAQKD7tOl3ocJocQsmA==", - "license": "LGPL-3.0", - "dependencies": { - "@types/bn.js": "^4.11.5", - "underscore": "1.12.1", - "web3-core": "1.3.6", - "web3-core-helpers": "1.3.6", - "web3-core-method": "1.3.6", - "web3-core-promievent": "1.3.6", - "web3-core-subscriptions": "1.3.6", - "web3-eth-abi": "1.3.6", - "web3-utils": "1.3.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-eth-contract/node_modules/@types/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/web3-eth-contract/node_modules/underscore": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", - "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", - "license": "MIT" - }, - "node_modules/web3-eth-ens": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.3.6.tgz", - "integrity": "sha512-n27HNj7lpSkRxTgSx+Zo7cmKAgyg2ElFilaFlUu/X2CNH23lXfcPm2bWssivH9z0ndhg0OyR4AYFZqPaqDHkJA==", - "license": "LGPL-3.0", - "dependencies": { - "content-hash": "^2.5.2", - "eth-ens-namehash": "2.0.8", - "underscore": "1.12.1", - "web3-core": "1.3.6", - "web3-core-helpers": "1.3.6", - "web3-core-promievent": "1.3.6", - "web3-eth-abi": "1.3.6", - "web3-eth-contract": "1.3.6", - "web3-utils": "1.3.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-eth-ens/node_modules/underscore": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", - "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", - "license": "MIT" - }, - "node_modules/web3-eth-iban": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.3.6.tgz", - "integrity": "sha512-nfMQaaLA/zsg5W4Oy/EJQbs8rSs1vBAX6b/35xzjYoutXlpHMQadujDx2RerTKhSHqFXSJeQAfE+2f6mdhYkRQ==", - "license": "LGPL-3.0", - "dependencies": { - "bn.js": "^4.11.9", - "web3-utils": "1.3.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-eth-iban/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", - "license": "MIT" - }, - "node_modules/web3-eth-personal": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.3.6.tgz", - "integrity": "sha512-pOHU0+/h1RFRYoh1ehYBehRbcKWP4OSzd4F7mDljhHngv6W8ewMHrAN8O1ol9uysN2MuCdRE19qkRg5eNgvzFQ==", - "license": "LGPL-3.0", - "dependencies": { - "@types/node": "^12.12.6", - "web3-core": "1.3.6", - "web3-core-helpers": "1.3.6", - "web3-core-method": "1.3.6", - "web3-net": "1.3.6", - "web3-utils": "1.3.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-eth-personal/node_modules/@types/node": { - "version": "12.20.55", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", - "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", - "license": "MIT" - }, - "node_modules/web3-eth/node_modules/underscore": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", - "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", - "license": "MIT" - }, - "node_modules/web3-net": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.3.6.tgz", - "integrity": "sha512-KhzU3wMQY/YYjyMiQzbaLPt2kut88Ncx2iqjy3nw28vRux3gVX0WOCk9EL/KVJBiAA/fK7VklTXvgy9dZnnipw==", - "license": "LGPL-3.0", - "dependencies": { - "web3-core": "1.3.6", - "web3-core-method": "1.3.6", - "web3-utils": "1.3.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-providers-http": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.3.6.tgz", - "integrity": "sha512-OQkT32O1A06dISIdazpGLveZcOXhEo5cEX6QyiSQkiPk/cjzDrXMw4SKZOGQbbS1+0Vjizm1Hrp7O8Vp2D1M5Q==", - "license": "LGPL-3.0", - "dependencies": { - "web3-core-helpers": "1.3.6", - "xhr2-cookies": "1.1.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-providers-ipc": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.3.6.tgz", - "integrity": "sha512-+TVsSd2sSVvVgHG4s6FXwwYPPT91boKKcRuEFXqEfAbUC5t52XOgmyc2LNiD9LzPhed65FbV4LqICpeYGUvSwA==", - "license": "LGPL-3.0", - "dependencies": { - "oboe": "2.1.5", - "underscore": "1.12.1", - "web3-core-helpers": "1.3.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-providers-ipc/node_modules/underscore": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", - "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", - "license": "MIT" - }, - "node_modules/web3-providers-ws": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.3.6.tgz", - "integrity": "sha512-bk7MnJf5or0Re2zKyhR3L3CjGululLCHXx4vlbc/drnaTARUVvi559OI5uLytc/1k5HKUUyENAxLvetz2G1dnQ==", - "license": "LGPL-3.0", - "dependencies": { - "eventemitter3": "4.0.4", - "underscore": "1.12.1", - "web3-core-helpers": "1.3.6", - "websocket": "^1.0.32" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-providers-ws/node_modules/eventemitter3": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz", - "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==", - "license": "MIT" - }, - "node_modules/web3-providers-ws/node_modules/underscore": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", - "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", - "license": "MIT" - }, - "node_modules/web3-shh": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.3.6.tgz", - "integrity": "sha512-9zRo415O0iBslxBnmu9OzYjNErzLnzOsy+IOvSpIreLYbbAw0XkDWxv3SfcpKnTIWIACBR4AYMIxmmyi5iB3jw==", - "hasInstallScript": true, - "license": "LGPL-3.0", - "dependencies": { - "web3-core": "1.3.6", - "web3-core-method": "1.3.6", - "web3-core-subscriptions": "1.3.6", - "web3-net": "1.3.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-utils": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.6.tgz", - "integrity": "sha512-hHatFaQpkQgjGVER17gNx8u1qMyaXFZtM0y0XLGH1bzsjMPlkMPLRcYOrZ00rOPfTEuYFOdrpGOqZXVmGrMZRg==", - "license": "LGPL-3.0", - "dependencies": { - "bn.js": "^4.11.9", - "eth-lib": "0.2.8", - "ethereum-bloom-filters": "^1.0.6", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randombytes": "^2.1.0", - "underscore": "1.12.1", - "utf8": "3.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-utils/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", - "license": "MIT" - }, - "node_modules/web3-utils/node_modules/underscore": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", - "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", - "license": "MIT" - }, - "node_modules/webcrypto-core": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.8.1.tgz", - "integrity": "sha512-P+x1MvlNCXlKbLSOY4cYrdreqPG5hbzkmawbcXLKN/mf6DZW0SdNNkZ+sjwsqVkI4A4Ko2sPZmkZtCKY58w83A==", - "license": "MIT", - "dependencies": { - "@peculiar/asn1-schema": "^2.3.13", - "@peculiar/json-schema": "^1.1.12", - "asn1js": "^3.0.5", - "pvtsutils": "^1.3.5", - "tslib": "^2.7.0" - } - }, - "node_modules/webcrypto-core/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/webcrypto-shim": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/webcrypto-shim/-/webcrypto-shim-0.1.7.tgz", - "integrity": "sha512-JAvAQR5mRNRxZW2jKigWMjCMkjSdmP5cColRP1U/pTg69VgHXEi1orv5vVpJ55Zc5MIaPc1aaurzd9pjv2bveg==", - "license": "MIT" - }, "node_modules/webextension-polyfill": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/webextension-polyfill/-/webextension-polyfill-0.10.0.tgz", @@ -64055,23 +45470,6 @@ "webpack": "3 || 4 || 5" } }, - "node_modules/websocket": { - "version": "1.0.35", - "resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.35.tgz", - "integrity": "sha512-/REy6amwPZl44DDzvRCkaI1q1bIiQB0mEFQLUrhz3z2EK91cp3n72rAjUlrTP0zV22HJIUOVHQGPxhFRjxjt+Q==", - "license": "Apache-2.0", - "dependencies": { - "bufferutil": "^4.0.1", - "debug": "^2.2.0", - "es5-ext": "^0.10.63", - "typedarray-to-buffer": "^3.1.5", - "utf-8-validate": "^5.0.2", - "yaeti": "^0.0.6" - }, - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/websocket-driver": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", @@ -64093,21 +45491,6 @@ "node": ">=0.8.0" } }, - "node_modules/websocket/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/websocket/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, "node_modules/whatwg-encoding": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", @@ -64136,7 +45519,8 @@ "version": "3.6.20", "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/whatwg-mimetype": { "version": "3.0.0", @@ -64270,15 +45654,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/wif": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/wif/-/wif-2.0.6.tgz", - "integrity": "sha512-HIanZn1zmduSF+BQhkE+YXIbEiH0xPr1012QbFEGB0xsKqJii0/SqJjyn8dFv6y36kOznMgMB+LGcbZTJ1xACQ==", - "license": "MIT", - "dependencies": { - "bs58check": "<3.0.0" - } - }, "node_modules/wildcard": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", @@ -64326,18 +45701,11 @@ "node": ">=0.1.90" } }, - "node_modules/wonka": { - "version": "4.0.15", - "resolved": "https://registry.npmjs.org/wonka/-/wonka-4.0.15.tgz", - "integrity": "sha512-U0IUQHKXXn6PFo9nqsHphVCE5m3IntqZNB9Jjn7EB1lrR7YTDY3YWgFvEvwniTzXSvOH/XMzAZaIfJF/LvHYXg==", - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -64368,6 +45736,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -64383,12 +45752,14 @@ "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { "node": ">=8" } @@ -64397,6 +45768,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -64479,30 +45851,6 @@ } } }, - "node_modules/xcode": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/xcode/-/xcode-3.0.1.tgz", - "integrity": "sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==", - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "simple-plist": "^1.1.0", - "uuid": "^7.0.3" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/xcode/node_modules/uuid": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", - "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", - "license": "MIT", - "peer": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/xdg-basedir": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz", @@ -64514,74 +45862,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/xhr": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.6.0.tgz", - "integrity": "sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA==", - "license": "MIT", - "dependencies": { - "global": "~4.4.0", - "is-function": "^1.0.1", - "parse-headers": "^2.0.0", - "xtend": "^4.0.0" - } - }, - "node_modules/xhr-request": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/xhr-request/-/xhr-request-1.1.0.tgz", - "integrity": "sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA==", - "license": "MIT", - "dependencies": { - "buffer-to-arraybuffer": "^0.0.5", - "object-assign": "^4.1.1", - "query-string": "^5.0.1", - "simple-get": "^2.7.0", - "timed-out": "^4.0.1", - "url-set-query": "^1.0.0", - "xhr": "^2.0.4" - } - }, - "node_modules/xhr-request-promise": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/xhr-request-promise/-/xhr-request-promise-0.1.3.tgz", - "integrity": "sha512-YUBytBsuwgitWtdRzXDDkWAXzhdGB8bYm0sSzMPZT7Z2MBjMSTHFsyCT1yCRATY+XC69DUrQraRAEgcoCRaIPg==", - "license": "MIT", - "dependencies": { - "xhr-request": "^1.1.0" - } - }, - "node_modules/xhr-request/node_modules/query-string": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", - "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", - "license": "MIT", - "dependencies": { - "decode-uri-component": "^0.2.0", - "object-assign": "^4.1.0", - "strict-uri-encode": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/xhr-request/node_modules/strict-uri-encode": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", - "integrity": "sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/xhr2-cookies": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz", - "integrity": "sha512-hjXUA6q+jl/bd8ADHcVfFsSPIf+tyLIjuO9TwJC9WI6JP2zKcS7C+p56I9kCLLsaCiNT035iYvEUUzdEFj/8+g==", - "license": "MIT", - "dependencies": { - "cookiejar": "^2.1.1" - } - }, "node_modules/xml-js": { "version": "1.6.11", "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz", @@ -64602,52 +45882,12 @@ "node": ">=12" } }, - "node_modules/xml2js": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", - "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", - "license": "MIT", - "peer": true, - "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/xml2js/node_modules/xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/xmlbuilder": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-14.0.0.tgz", - "integrity": "sha512-ts+B2rSe4fIckR6iquDjsKbQFK2NlUk6iG5nf14mDEyldgoc2nEKZ3jZWMPTxGQwVgToSjt6VGIho1H8/fNFTg==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8.0" - } - }, "node_modules/xmlchars": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", "dev": true }, - "node_modules/xmlcreate": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", - "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", - "license": "Apache-2.0" - }, "node_modules/xmlhttprequest-ssl": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz", @@ -64656,64 +45896,6 @@ "node": ">=0.4.0" } }, - "node_modules/xrpl": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xrpl/-/xrpl-4.0.0.tgz", - "integrity": "sha512-VZm1lQWHQ6PheAAFGdH+ISXKvqB2hZDQ0w4ZcdAEtmqZQXtSIVQHOKPz95rEgGANbos7+XClxJ73++joPhA8Cw==", - "license": "ISC", - "dependencies": { - "@scure/bip32": "^1.3.1", - "@scure/bip39": "^1.2.1", - "@xrplf/isomorphic": "^1.0.1", - "@xrplf/secret-numbers": "^1.0.0", - "bignumber.js": "^9.0.0", - "eventemitter3": "^5.0.1", - "ripple-address-codec": "^5.0.0", - "ripple-binary-codec": "^2.1.0", - "ripple-keypairs": "^2.0.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/xrpl/node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "license": "MIT" - }, - "node_modules/xss": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/xss/-/xss-1.0.13.tgz", - "integrity": "sha512-clu7dxTm1e8Mo5fz3n/oW3UCXBfV89xZ72jM8yzo1vR/pIS0w3sgB3XV2H8Vm6zfGnHL0FzvLJPJEBhd86/z4Q==", - "license": "MIT", - "dependencies": { - "commander": "^2.20.3", - "cssfilter": "0.0.10" - }, - "bin": { - "xss": "bin/xss" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/xss/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "license": "MIT" - }, - "node_modules/xstream": { - "version": "11.14.0", - "resolved": "https://registry.npmjs.org/xstream/-/xstream-11.14.0.tgz", - "integrity": "sha512-1bLb+kKKtKPbgTK6i/BaoAn03g47PpFstlbe1BA+y3pNS/LfvcaghS5BFf9+EE1J+KwSQsEpfJvFN5GqFtiNmw==", - "license": "MIT", - "dependencies": { - "globalthis": "^1.0.1", - "symbol-observable": "^2.0.3" - } - }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -64730,15 +45912,6 @@ "node": ">=10" } }, - "node_modules/yaeti": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", - "integrity": "sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug==", - "license": "MIT", - "engines": { - "node": ">=0.10.32" - } - }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", diff --git a/package.json b/package.json index 72a96e9e5..7bba43f77 100644 --- a/package.json +++ b/package.json @@ -73,9 +73,6 @@ }, "dependencies": { "@aws-crypto/client-node": "4.0.1", - "@bitgo/public-types": "4.11.2", - "@bitgo/sdk-api": "1.58.2", - "@bitgo/sdk-core": "28.20.0", "@bull-board/api": "5.20.1", "@bull-board/express": "5.20.1", "@bull-board/nestjs": "5.20.1", @@ -120,7 +117,6 @@ "@tanstack/react-query": "5.51.11", "axios": "1.7.7", "axios-retry": "4.5.0", - "bitgo": "39.23.0", "bull": "4.16.4", "cache-manager": "6.3.2", "class-transformer": "0.5.1", From ec91a129f5a2245416df959bd32c8d8108b542d8 Mon Sep 17 00:00:00 2001 From: Matt Schoch Date: Tue, 4 Feb 2025 13:11:30 +0100 Subject: [PATCH 114/120] Feature/nar 2067 declarative config engine (#124) * Declarative Config for Engine; app-level * Clients move to normalized table, db encryption & integrity, declarative client config * Fixing tests --- .../src/client/__test__/e2e/client.spec.ts | 26 +- .../src/client/core/type/client.type.ts | 37 +- .../integration/cluster.service.spec.ts | 25 +- .../core/service/cluster.service.ts | 4 +- .../http/client/policy-engine.client.ts | 10 +- apps/policy-engine/.env.default | 36 +- apps/policy-engine/.env.template | 85 +++++ apps/policy-engine/.env.test.default | 4 + .../policy-engine/src/client/client.module.ts | 55 +++ .../client/core/service/bootstrap.service.ts | 101 ++++++ .../core/service/client.service.ts | 99 ++++-- .../http/rest/controller/client.controller.ts | 5 +- .../http/rest/dto/create-client.dto.ts | 3 +- .../repository/client.repository.ts | 247 +++++++++++++ .../src/engine/__test__/e2e/client.spec.ts | 87 +++-- .../engine/__test__/e2e/evaluation.spec.ts | 63 ++-- .../src/engine/__test__/e2e/provision.spec.ts | 91 ----- .../core/factory/signing-service.factory.ts | 4 +- .../integration/engine.service.spec.ts | 63 ---- .../__test__/unit/bootstrap.service.spec.ts | 72 ++-- .../__test__/unit/client.service.spec.ts | 57 +-- .../__test__/unit/evaluation.service.spec.ts | 27 +- .../__test__/unit/provision.service.spec.ts | 110 ------ .../engine/core/service/bootstrap.service.ts | 48 --- .../src/engine/core/service/engine.service.ts | 38 +- .../engine/core/service/evaluation.service.ts | 12 +- .../engine/core/service/provision.service.ts | 161 ++++++--- .../policy-engine/src/engine/engine.module.ts | 41 +-- .../rest/controller/provision.controller.ts | 47 --- .../client.repository.spec.ts | 68 +--- .../__test__/unit/engine.repository.spec.ts | 46 --- .../repository/client.repository.ts | 121 ------- .../repository/engine.repository.ts | 57 ++- .../policy-engine/src/policy-engine.config.ts | 327 ++++++++++++++--- .../policy-engine/src/policy-engine.module.ts | 70 ++-- .../encryption-module-option.factory.ts | 8 +- .../__test__/unit/admin-api-key.guard.spec.ts | 10 +- .../__test__/unit/client-secret.guard.spec.ts | 25 +- .../src/shared/guard/admin-api-key.guard.ts | 2 +- .../src/shared/guard/client-secret.guard.ts | 4 +- .../module/key-value/key-value.module.ts | 8 +- .../persistence/exception/parse.exception.ts | 11 + .../exception/persistence.exception.ts | 1 + .../module/persistence/persistence.module.ts | 46 ++- .../migration.sql | 41 +++ .../20250131171229_client_hmac/migration.sql | 2 + .../module/persistence/schema/schema.prisma | 41 ++- .../src/shared/module/persistence/seed.ts | 11 +- .../persistence/service/prisma.service.ts | 335 +++++++++++++++++- .../src/shared/type/domain.type.ts | 84 ++++- apps/vault/src/app.service.ts | 3 +- .../src/client/__test__/e2e/client.spec.ts | 2 +- .../src/client/core/service/client.service.ts | 2 +- apps/vault/src/main.config.ts | 2 +- apps/vault/src/provision.service.ts | 6 +- apps/vault/src/shared/type/domain.type.ts | 2 +- config/policy-engine-config.example.yaml | 168 +++++++++ config/policy-engine-config.template.yaml | 179 ++++++++++ config/vault-config.example.yaml | 3 +- config/vault-config.template.yaml | 1 - docker-compose.mpc.yml | 6 + .../0-create-client.ts | 66 ++++ .../src/lib/type/client.type.ts | 28 -- 63 files changed, 2377 insertions(+), 1067 deletions(-) create mode 100644 apps/policy-engine/.env.template create mode 100644 apps/policy-engine/src/client/client.module.ts create mode 100644 apps/policy-engine/src/client/core/service/bootstrap.service.ts rename apps/policy-engine/src/{engine => client}/core/service/client.service.ts (79%) rename apps/policy-engine/src/{engine => client}/http/rest/controller/client.controller.ts (91%) rename apps/policy-engine/src/{engine => client}/http/rest/dto/create-client.dto.ts (60%) create mode 100644 apps/policy-engine/src/client/persistence/repository/client.repository.ts delete mode 100644 apps/policy-engine/src/engine/__test__/e2e/provision.spec.ts delete mode 100644 apps/policy-engine/src/engine/core/service/__test__/integration/engine.service.spec.ts delete mode 100644 apps/policy-engine/src/engine/core/service/__test__/unit/provision.service.spec.ts delete mode 100644 apps/policy-engine/src/engine/core/service/bootstrap.service.ts delete mode 100644 apps/policy-engine/src/engine/http/rest/controller/provision.controller.ts rename apps/policy-engine/src/engine/persistence/repository/__test__/{unit => integration}/client.repository.spec.ts (64%) delete mode 100644 apps/policy-engine/src/engine/persistence/repository/__test__/unit/engine.repository.spec.ts delete mode 100644 apps/policy-engine/src/engine/persistence/repository/client.repository.ts create mode 100644 apps/policy-engine/src/shared/module/persistence/exception/parse.exception.ts create mode 100644 apps/policy-engine/src/shared/module/persistence/exception/persistence.exception.ts create mode 100644 apps/policy-engine/src/shared/module/persistence/schema/migrations/20250131164306_engine_db_normalization/migration.sql create mode 100644 apps/policy-engine/src/shared/module/persistence/schema/migrations/20250131171229_client_hmac/migration.sql create mode 100644 config/policy-engine-config.example.yaml create mode 100644 config/policy-engine-config.template.yaml create mode 100644 examples/approvals-by-spending-limit/0-create-client.ts diff --git a/apps/armory/src/client/__test__/e2e/client.spec.ts b/apps/armory/src/client/__test__/e2e/client.spec.ts index 75aa1d96b..6c141cc73 100644 --- a/apps/armory/src/client/__test__/e2e/client.spec.ts +++ b/apps/armory/src/client/__test__/e2e/client.spec.ts @@ -1,7 +1,7 @@ import { ConfigModule, ConfigService } from '@narval/config-module' import { LoggerModule, OpenTelemetryModule, REQUEST_HEADER_ADMIN_API_KEY, secret } from '@narval/nestjs-shared' -import { DataStoreConfiguration, HttpSource, PublicClient, Source, SourceType } from '@narval/policy-engine-shared' -import { getPublicKey, privateKeyToJwk } from '@narval/signature' +import { DataStoreConfiguration, HttpSource, Source, SourceType } from '@narval/policy-engine-shared' +import { SigningAlg, getPublicKey, privateKeyToJwk } from '@narval/signature' import { HttpStatus, INestApplication } from '@nestjs/common' import { Test, TestingModule } from '@nestjs/testing' import nock from 'nock' @@ -12,6 +12,7 @@ import { Config, load } from '../../../armory.config' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { ClientModule } from '../../client.module' import { ClientService } from '../../core/service/client.service' +import { PolicyEnginePublicClient } from '../../core/type/client.type' import { CreateClientRequestDto } from '../../http/rest/dto/create-client.dto' // TODO: (@wcalderipe, 16/05/24) Evaluate testcontainers @@ -31,13 +32,26 @@ const mockPolicyEngineServer = (url: string, clientId: string) => { keys: [getPublicKey(privateKeyToJwk(generatePrivateKey()))] } - const createClientResponse: PublicClient = { + const createClientResponse: PolicyEnginePublicClient = { clientId, - clientSecret: secret.generate(), + name: 'Acme', + configurationSource: 'dynamic', + baseUrl: null, + auth: { + disabled: false, + local: { + clientSecret: secret.generate() + } + }, createdAt: new Date(), updatedAt: new Date(), - signer: { - publicKey: getPublicKey(privateKeyToJwk(generatePrivateKey())) + decisionAttestation: { + disabled: false, + signer: { + alg: SigningAlg.EIP191, + keyId: 'acme-key-ie', + publicKey: getPublicKey(privateKeyToJwk(generatePrivateKey())) + } }, dataStore: { entity: dataStoreConfig, diff --git a/apps/armory/src/client/core/type/client.type.ts b/apps/armory/src/client/core/type/client.type.ts index f474d9003..8982f467a 100644 --- a/apps/armory/src/client/core/type/client.type.ts +++ b/apps/armory/src/client/core/type/client.type.ts @@ -1,5 +1,5 @@ import { DataStoreConfiguration } from '@narval/policy-engine-shared' -import { jwkSchema, publicKeySchema } from '@narval/signature' +import { jwkSchema, publicKeySchema, SigningAlg } from '@narval/signature' import { z } from 'zod' export const PolicyEngineNode = z.object({ @@ -61,3 +61,38 @@ export const PublicClient = Client.extend({ }) }) export type PublicClient = z.infer + +export const PolicyEnginePublicClient = z.object({ + clientId: z.string(), + name: z.string(), + configurationSource: z.literal('declarative').or(z.literal('dynamic')), // Declarative = comes from config file, Dynamic = created at runtime + baseUrl: z.string().nullable(), + + auth: z.object({ + disabled: z.boolean(), + local: z + .object({ + clientSecret: z.string().nullable() + }) + .nullable() + }), + + dataStore: z.object({ + entity: DataStoreConfiguration, + policy: DataStoreConfiguration + }), + + decisionAttestation: z.object({ + disabled: z.boolean(), + signer: z + .object({ + alg: z.nativeEnum(SigningAlg), + keyId: z.string().nullable().describe('Unique id of the signer key. Matches the kid in both jwks'), + publicKey: publicKeySchema.optional() + }) + .nullable() + }), + createdAt: z.coerce.date(), + updatedAt: z.coerce.date() +}) +export type PolicyEnginePublicClient = z.infer diff --git a/apps/armory/src/policy-engine/core/service/__test__/integration/cluster.service.spec.ts b/apps/armory/src/policy-engine/core/service/__test__/integration/cluster.service.spec.ts index d3f8dbb79..b53d4766d 100644 --- a/apps/armory/src/policy-engine/core/service/__test__/integration/cluster.service.spec.ts +++ b/apps/armory/src/policy-engine/core/service/__test__/integration/cluster.service.spec.ts @@ -12,7 +12,6 @@ import { Decision, EvaluationRequest, EvaluationResponse, - PublicClient, Request, Source, SourceType @@ -26,6 +25,7 @@ import { v4 as uuid } from 'uuid' import { generatePrivateKey } from 'viem/accounts' import { generateSignTransactionRequest } from '../../../../../__test__/fixture/authorization-request.fixture' import { Config, load } from '../../../../../armory.config' +import { PolicyEnginePublicClient } from '../../../../../client/core/type/client.type' import { PersistenceModule } from '../../../../../shared/module/persistence/persistence.module' import { TestPrismaService } from '../../../../../shared/module/persistence/service/test-prisma.service' import { PolicyEngineClient } from '../../../../http/client/policy-engine.client' @@ -88,13 +88,26 @@ describe(ClusterService.name, () => { keys: [getPublicKey(privateKeyToJwk(generatePrivateKey()))] } - const createClientResponse: PublicClient = { + const createClientResponse: PolicyEnginePublicClient = { clientId, - clientSecret: secret.generate(), + name: 'Acme', + configurationSource: 'dynamic', + baseUrl: null, + auth: { + disabled: false, + local: { + clientSecret: secret.generate() + } + }, createdAt: new Date(), updatedAt: new Date(), - signer: { - publicKey: getPublicKey(privateKeyToJwk(generatePrivateKey())) + decisionAttestation: { + disabled: false, + signer: { + alg: SigningAlg.EIP191, + keyId: 'acme-key-ie', + publicKey: getPublicKey(privateKeyToJwk(generatePrivateKey())) + } }, dataStore: { entity: dataStoreConfig, @@ -118,7 +131,7 @@ describe(ClusterService.name, () => { clientId, clientSecret: expect.any(String), url: nodeUrl, - publicKey: createClientResponse.signer.publicKey + publicKey: createClientResponse.decisionAttestation.signer?.publicKey }) }) diff --git a/apps/armory/src/policy-engine/core/service/cluster.service.ts b/apps/armory/src/policy-engine/core/service/cluster.service.ts index d431fb7a6..eb3f0f110 100644 --- a/apps/armory/src/policy-engine/core/service/cluster.service.ts +++ b/apps/armory/src/policy-engine/core/service/cluster.service.ts @@ -68,8 +68,8 @@ export class ClusterService { return { id: uuid(), clientId: client.clientId, - clientSecret: client.clientSecret, - publicKey: client.signer.publicKey, + clientSecret: client.auth.local?.clientSecret, + publicKey: client.decisionAttestation.signer?.publicKey, url: node } } diff --git a/apps/armory/src/policy-engine/http/client/policy-engine.client.ts b/apps/armory/src/policy-engine/http/client/policy-engine.client.ts index df5183a1b..01d00c5b9 100644 --- a/apps/armory/src/policy-engine/http/client/policy-engine.client.ts +++ b/apps/armory/src/policy-engine/http/client/policy-engine.client.ts @@ -3,12 +3,12 @@ import { CreateClient, EvaluationRequest, EvaluationResponse, - PublicClient, SerializedEvaluationRequest } from '@narval/policy-engine-shared' import { HttpService } from '@nestjs/axios' import { HttpStatus, Injectable } from '@nestjs/common' import { catchError, lastValueFrom, map, tap } from 'rxjs' +import { PolicyEnginePublicClient } from '../../../client/core/type/client.type' import { ApplicationException } from '../../../shared/exception/application.exception' export class PolicyEngineClientException extends ApplicationException {} @@ -62,9 +62,7 @@ export class PolicyEngineClient { host: string data: CreateClient adminApiKey: string - clientId?: string - clientSecret?: string - }): Promise { + }): Promise { this.logger.log('Sending create client request', option) return lastValueFrom( @@ -74,7 +72,7 @@ export class PolicyEngineClient { method: 'POST', data: option.data, headers: { - ...this.getHeaders(option), + ...this.getHeaders(option.data), 'x-api-key': option.adminApiKey } }) @@ -87,7 +85,7 @@ export class PolicyEngineClient { response: response.data }) }), - map((response) => PublicClient.parse(response.data)), + map((response) => PolicyEnginePublicClient.parse(response.data)), catchError((error) => { throw new PolicyEngineClientException({ message: 'Create client request failed', diff --git a/apps/policy-engine/.env.default b/apps/policy-engine/.env.default index ec2b76f8b..0945c3672 100644 --- a/apps/policy-engine/.env.default +++ b/apps/policy-engine/.env.default @@ -1,15 +1,7 @@ NODE_ENV=development -PORT=3010 - -APP_UID=local-dev-engine-instance-1 - -# OPTIONAL: Sets the admin API key instead of generating a new one during the -# provision. -# -# Key should be hashed, like this: `echo -n "my-api-key" | openssl dgst -sha256 | awk '{print $2}'` -# Plain text API key: engine-admin-api-key -ADMIN_API_KEY=dde1fba05d6b0b1a40f2cd9f480f6dcc37a6980bcff3db54377a46b056dc472c +# Relative path to the config file from where the node process is started, defaults to `./config/policy-engine-config.yaml` +CONFIG_FILE_RELATIVE_PATH="./config/policy-engine-config.local.yaml" # === Database === @@ -25,30 +17,6 @@ APP_DATABASE_PORT=5432 APP_DATABASE_NAME=engine -# === Encryption === - -RESOURCE_PATH=./apps/policy-engine/src/resource - -# Determine the encryption module keyring type. -# Either "awskms" or "raw". -KEYRING_TYPE=raw - -# If using raw keyring, master password for encrypting data -MASTER_PASSWORD=unsafe-local-dev-master-password - -# If using awskms keyring, provide the ARN of the KMS encryption key instead of a master password -MASTER_AWS_KMS_ARN= - -# Either "simple" or "mpc" -SIGNING_PROTOCOL=simple - -# === MPC === - -# If SIGNING_PROTOCOL is set to "mpc", the application MUST configure a TSM. -TSM_URL= -TSM_API_KEY= -TSM_PLAYER_COUNT= - # === OpenTelemetry configuration === # See https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/ diff --git a/apps/policy-engine/.env.template b/apps/policy-engine/.env.template new file mode 100644 index 000000000..35de2be38 --- /dev/null +++ b/apps/policy-engine/.env.template @@ -0,0 +1,85 @@ +# Template of all the available ENV variables. + +# === Node environment === + +NODE_ENV=development + +# === Server === + +PORT=3010 + +# === Application === + +APP_UID=local-dev-engine-instance-1 + +# === Config === + +# Absolute path to the config file. If not set, uses the relative path. +# CONFIG_FILE_ABSOLUTE_PATH="/config/vault-config.yaml" + +# Relative path to the config file from where the node process is started, defaults to `./config/vault-config.yaml` +CONFIG_FILE_RELATIVE_PATH="./config/policy-engine-config.local.yaml" + +# === Admin API key === + +# OPTIONAL: Sets the admin API key instead of generating a new one during the +# provision. +# +# Key should be hashed, like this: `echo -n "engine-admin-api-key" | openssl dgst -sha256 | awk '{print $2}'` +# Plain text API key: engine-admin-api-key +ADMIN_API_KEY=dde1fba05d6b0b1a40f2cd9f480f6dcc37a6980bcff3db54377a46b056dc472c + +# === Database === + +# APP db connection string +APP_DATABASE_URL=postgresql://postgres:postgres@localhost:5432/engine?schema=public + +# Migrator db credentials. +# host/port/name should be the same, username&password may be different +APP_DATABASE_USERNAME=postgres +APP_DATABASE_PASSWORD=postgres +APP_DATABASE_HOST=host.docker.internal +APP_DATABASE_PORT=5432 +APP_DATABASE_NAME=engine + +# === Base URL === +# Base URL where the Policy Engine is deployed. +BASE_URL=http://localhost:3010 + +# === Encryption === + +RESOURCE_PATH=./apps/policy-engine/src/resource + +# Determine the encryption module keyring type. +# Either "awskms" or "raw". +KEYRING_TYPE=raw + +# If using raw keyring, master password for encrypting data +MASTER_PASSWORD=unsafe-local-dev-master-password + +# If using awskms keyring, provide the ARN of the KMS encryption key instead of a master password +MASTER_AWS_KMS_ARN= + +# HMAC secret for integrity verification of data in the database. +HMAC_SECRET="unsafe-local-test-hmac-secret" + +# Either "simple" or "mpc" +SIGNING_PROTOCOL=simple + +# === MPC === + +# If SIGNING_PROTOCOL is set to "mpc", the application MUST configure a TSM. +TSM_URL= +TSM_API_KEY= +TSM_PLAYER_COUNT= + +# === OpenTelemetry configuration === + +# See https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/ +OTEL_SDK_DISABLED=true +# OTEL Collector container HTTP port. +OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 +OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf +OTEL_LOGS_EXPORTER=otlp +OTEL_LOG_LEVEL=error +OTEL_RESOURCE_ATTRIBUTES=deployment.environment=local diff --git a/apps/policy-engine/.env.test.default b/apps/policy-engine/.env.test.default index 4556a53f8..4fa3af8e2 100644 --- a/apps/policy-engine/.env.test.default +++ b/apps/policy-engine/.env.test.default @@ -11,6 +11,10 @@ APP_UID="local-dev-engine-instance-1" MASTER_PASSWORD="unsafe-local-test-master-password" +HMAC_SECRET="unsafe-local-test-hmac-secret" + +BASE_URL="http://localhost:3010" + KEYRING_TYPE="raw" RESOURCE_PATH=./apps/policy-engine/src/resource diff --git a/apps/policy-engine/src/client/client.module.ts b/apps/policy-engine/src/client/client.module.ts new file mode 100644 index 000000000..dc6859de3 --- /dev/null +++ b/apps/policy-engine/src/client/client.module.ts @@ -0,0 +1,55 @@ +import { ConfigService } from '@narval/config-module' +import { HttpModule } from '@nestjs/axios' +import { forwardRef, Module, OnApplicationBootstrap, ValidationPipe } from '@nestjs/common' +import { APP_PIPE } from '@nestjs/core' +import { ZodValidationPipe } from 'nestjs-zod' +import { DataStoreRepositoryFactory } from '../engine/core/factory/data-store-repository.factory' +import { signingServiceFactory } from '../engine/core/factory/signing-service.factory' +import { DataStoreService } from '../engine/core/service/data-store.service' +import { FileSystemDataStoreRepository } from '../engine/persistence/repository/file-system-data-store.repository' +import { HttpDataStoreRepository } from '../engine/persistence/repository/http-data-store.repository' +import { AppModule } from '../policy-engine.module' +import { AdminApiKeyGuard } from '../shared/guard/admin-api-key.guard' +import { KeyValueModule } from '../shared/module/key-value/key-value.module' +import { PersistenceModule } from '../shared/module/persistence/persistence.module' +import { BootstrapService } from './core/service/bootstrap.service' +import { ClientService } from './core/service/client.service' +import { ClientController } from './http/rest/controller/client.controller' +import { ClientRepository } from './persistence/repository/client.repository' + +@Module({ + imports: [HttpModule, KeyValueModule, PersistenceModule, forwardRef(() => AppModule)], + controllers: [ClientController], + providers: [ + AdminApiKeyGuard, + BootstrapService, + DataStoreRepositoryFactory, + DataStoreService, + FileSystemDataStoreRepository, + HttpDataStoreRepository, + ClientRepository, + ClientService, + { + provide: 'SigningService', + useFactory: signingServiceFactory, + inject: [ConfigService] + }, + { + // DEPRECATE: Use Zod generated DTOs to validate request and responses. + provide: APP_PIPE, + useClass: ValidationPipe + }, + { + provide: APP_PIPE, + useClass: ZodValidationPipe + } + ], + exports: [ClientService, ClientRepository] +}) +export class ClientModule implements OnApplicationBootstrap { + constructor(private bootstrapService: BootstrapService) {} + + async onApplicationBootstrap() { + await this.bootstrapService.boot() + } +} diff --git a/apps/policy-engine/src/client/core/service/bootstrap.service.ts b/apps/policy-engine/src/client/core/service/bootstrap.service.ts new file mode 100644 index 000000000..0ff40d811 --- /dev/null +++ b/apps/policy-engine/src/client/core/service/bootstrap.service.ts @@ -0,0 +1,101 @@ +import { ConfigService } from '@narval/config-module' +import { LoggerService } from '@narval/nestjs-shared' +import { Injectable } from '@nestjs/common' +import { Config } from '../../../policy-engine.config' +import { Client } from '../../../shared/type/domain.type' +import { ClientService } from './client.service' + +@Injectable() +export class BootstrapService { + constructor( + private configService: ConfigService, + private clientService: ClientService, + private logger: LoggerService + ) {} + + async boot(): Promise { + this.logger.log('Start bootstrap') + + await this.persistDeclarativeClients() + + await this.syncClients() + + // TEMPORARY: Migrate the key-value format of the Client config into the table format. + // Can be removed once this runs once. + await this.clientService.migrateV1Data() + + this.logger.log('Bootstrap end') + } + + private async persistDeclarativeClients(): Promise { + const clients = this.configService.get('clients') + if (!clients) return + + // Given ClientConfig type, build the Client type + const declarativeClients: Client[] = clients.map((client) => ({ + clientId: client.clientId, + name: client.name, + configurationSource: 'declarative', + baseUrl: client.baseUrl, + auth: { + disabled: client.auth.disabled, + local: client.auth.local?.clientSecret + ? { + clientSecret: client.auth.local?.clientSecret + } + : null + }, + dataStore: { + entity: { + data: { + type: 'HTTP', + url: client.dataStore.entity.data.url + }, + signature: { + type: 'HTTP', + url: client.dataStore.entity.signature.url + }, + keys: client.dataStore.entity.publicKeys + }, + policy: { + data: { + type: 'HTTP', + url: client.dataStore.policy.data.url + }, + signature: { + type: 'HTTP', + url: client.dataStore.policy.signature.url + }, + keys: client.dataStore.policy.publicKeys + } + }, + decisionAttestation: { + disabled: client.decisionAttestation.disabled, + signer: client.decisionAttestation.signer || null + }, + createdAt: new Date(), + updatedAt: new Date() + })) + + for (const client of declarativeClients) { + await this.clientService.save(client) + } + } + + private async syncClients(): Promise { + const clients = await this.clientService.findAll() + + this.logger.log('Start syncing clients data stores', { + clientsCount: clients.length + }) + + // TODO: (@wcalderipe, 07/03/24) maybe change the execution to parallel? + for (const client of clients) { + await this.clientService.syncDataStore(client.clientId) + this.logger.log(`Client public key`, { + clientId: client.clientId, + publicKey: client.decisionAttestation.signer?.publicKey + }) + } + } +} diff --git a/apps/policy-engine/src/engine/core/service/client.service.ts b/apps/policy-engine/src/client/core/service/client.service.ts similarity index 79% rename from apps/policy-engine/src/engine/core/service/client.service.ts rename to apps/policy-engine/src/client/core/service/client.service.ts index 08c820d73..2e9b4a456 100644 --- a/apps/policy-engine/src/engine/core/service/client.service.ts +++ b/apps/policy-engine/src/client/core/service/client.service.ts @@ -1,14 +1,13 @@ import { LoggerService, OTEL_ATTR_CLIENT_ID, TraceService, secret } from '@narval/nestjs-shared' import { DataStoreConfiguration, EntityStore, PolicyStore } from '@narval/policy-engine-shared' -import { hash } from '@narval/signature' +import { SigningAlg, hash } from '@narval/signature' import { HttpStatus, Inject, Injectable } from '@nestjs/common' import { SpanStatusCode } from '@opentelemetry/api' -import { v4 as uuid } from 'uuid' +import { DataStoreService } from '../../../engine/core/service/data-store.service' +import { SigningService } from '../../../engine/core/service/signing.service.interface' import { ApplicationException } from '../../../shared/exception/application.exception' import { Client } from '../../../shared/type/domain.type' import { ClientRepository } from '../../persistence/repository/client.repository' -import { DataStoreService } from './data-store.service' -import { SigningService } from './signing.service.interface' @Injectable() export class ClientService { @@ -20,6 +19,35 @@ export class ClientService { @Inject('SigningService') private signingService: SigningService ) {} + // Temporary function to migrate data from V1 to V2 + async migrateV1Data(): Promise { + const clientsV1 = await this.clientRepository.findAllV1() + for (const clientV1 of clientsV1) { + const client: Client = { + clientId: clientV1.clientId, + name: clientV1.clientId, + configurationSource: 'dynamic', + baseUrl: null, + auth: { + disabled: false, + local: { + clientSecret: clientV1.clientSecret + } + }, + dataStore: clientV1.dataStore, + decisionAttestation: { + disabled: false, + signer: clientV1.signer + }, + createdAt: clientV1.createdAt, + updatedAt: clientV1.updatedAt + } + this.logger.info('Migrating client', { clientV1, client }) + await this.clientRepository.save(client) + await this.clientRepository.deleteV1(clientV1.clientId) + } + } + async findById(clientId: string): Promise { const span = this.traceService.startSpan(`${ClientService.name}.findById`, { attributes: { @@ -33,7 +61,7 @@ export class ClientService { } async create(input: { - clientId?: string + clientId: string clientSecret?: string unsafeKeyId?: string entityDataStore: DataStoreConfiguration @@ -41,9 +69,26 @@ export class ClientService { allowSelfSignedData?: boolean }): Promise { const span = this.traceService.startSpan(`${ClientService.name}.create`) + const clientId = input.clientId + + const exists = await this.clientRepository.findById(input.clientId) + + if (exists && exists.configurationSource === 'dynamic') { + const exception = new ApplicationException({ + message: 'Client already exist', + suggestedHttpStatusCode: HttpStatus.BAD_REQUEST, + context: { clientId: input.clientId } + }) + + span.recordException(exception) + span.setStatus({ code: SpanStatusCode.ERROR }) + span.end() + + throw exception + } + const now = new Date() const { unsafeKeyId, entityDataStore, policyDataStore, allowSelfSignedData } = input - const clientId = input.clientId || uuid() // If we are generating the secret, we'll want to return the full thing to // the user one time. const fullClientSecret = input.clientSecret || secret.generate() @@ -56,6 +101,7 @@ export class ClientService { const keypair = await this.signingService.generateKey(keyId, sessionId) const signer = { keyId: keypair.publicKey.kid, + alg: SigningAlg.EIP191, ...keypair } @@ -69,12 +115,23 @@ export class ClientService { const client = await this.save( { clientId, - clientSecret, + name: clientId, + configurationSource: 'dynamic', + baseUrl: null, + auth: { + disabled: false, + local: { + clientSecret + } + }, dataStore: { entity: entityDataStore, policy: policyDataStore }, - signer, + decisionAttestation: { + disabled: false, + signer + }, createdAt: now, updatedAt: now }, @@ -82,12 +139,12 @@ export class ClientService { ) span.end() - - return { - ...client, - // If we generated a new secret, we need to include it in the response the first time. - ...(!input.clientSecret ? { clientSecret: fullClientSecret } : {}) + if (!input.clientSecret && !client.auth?.disabled && client.auth?.local?.clientSecret) { + client.auth.local = { + clientSecret: fullClientSecret + } } + return client } async save(client: Client, options?: { syncAfter?: boolean }): Promise { @@ -97,22 +154,6 @@ export class ClientService { const syncAfter = options?.syncAfter ?? true - const exists = await this.clientRepository.findById(client.clientId) - - if (exists) { - const exception = new ApplicationException({ - message: 'Client already exist', - suggestedHttpStatusCode: HttpStatus.BAD_REQUEST, - context: { clientId: client.clientId } - }) - - span.recordException(exception) - span.setStatus({ code: SpanStatusCode.ERROR }) - span.end() - - throw exception - } - try { await this.clientRepository.save(client) diff --git a/apps/policy-engine/src/engine/http/rest/controller/client.controller.ts b/apps/policy-engine/src/client/http/rest/controller/client.controller.ts similarity index 91% rename from apps/policy-engine/src/engine/http/rest/controller/client.controller.ts rename to apps/policy-engine/src/client/http/rest/controller/client.controller.ts index 134f89bd3..cc7242176 100644 --- a/apps/policy-engine/src/engine/http/rest/controller/client.controller.ts +++ b/apps/policy-engine/src/client/http/rest/controller/client.controller.ts @@ -1,11 +1,12 @@ import { Body, Controller, HttpCode, HttpStatus, Post } from '@nestjs/common' import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger' +import { v4 as uuid } from 'uuid' +import { SyncResponseDto } from '../../../../engine/http/rest/dto/sync-response.dto' import { AdminGuard } from '../../../../shared/decorator/admin-guard.decorator' import { ClientGuard } from '../../../../shared/decorator/client-guard.decorator' import { ClientId } from '../../../../shared/decorator/client-id.decorator' import { ClientService } from '../../../core/service/client.service' import { CreateClientRequestDto, CreateClientResponseDto } from '../dto/create-client.dto' -import { SyncResponseDto } from '../dto/sync-response.dto' @Controller({ path: '/clients', @@ -26,7 +27,7 @@ export class ClientController { }) async create(@Body() body: CreateClientRequestDto): Promise { const client = await this.clientService.create({ - clientId: body.clientId, + clientId: body.clientId || uuid(), clientSecret: body.clientSecret, unsafeKeyId: body.keyId, entityDataStore: body.entityDataStore, diff --git a/apps/policy-engine/src/engine/http/rest/dto/create-client.dto.ts b/apps/policy-engine/src/client/http/rest/dto/create-client.dto.ts similarity index 60% rename from apps/policy-engine/src/engine/http/rest/dto/create-client.dto.ts rename to apps/policy-engine/src/client/http/rest/dto/create-client.dto.ts index 9f504f024..14acfef50 100644 --- a/apps/policy-engine/src/engine/http/rest/dto/create-client.dto.ts +++ b/apps/policy-engine/src/client/http/rest/dto/create-client.dto.ts @@ -1,5 +1,6 @@ -import { CreateClient, PublicClient } from '@narval/policy-engine-shared' +import { CreateClient } from '@narval/policy-engine-shared' import { createZodDto } from 'nestjs-zod' +import { PublicClient } from '../../../../shared/type/domain.type' export class CreateClientRequestDto extends createZodDto(CreateClient) {} diff --git a/apps/policy-engine/src/client/persistence/repository/client.repository.ts b/apps/policy-engine/src/client/persistence/repository/client.repository.ts new file mode 100644 index 000000000..1f5486535 --- /dev/null +++ b/apps/policy-engine/src/client/persistence/repository/client.repository.ts @@ -0,0 +1,247 @@ +import { coerce } from '@narval/nestjs-shared' +import { EntityStore, PolicyStore } from '@narval/policy-engine-shared' +import { privateKeySchema } from '@narval/signature' +import { Injectable } from '@nestjs/common' +import { Prisma } from '@prisma/client/policy-engine' +import { compact } from 'lodash/fp' +import { SigningAlg, publicKeySchema } from 'packages/signature/src/lib/types' +import { z } from 'zod' +import { EncryptKeyValueService } from '../../../shared/module/key-value/core/service/encrypt-key-value.service' +import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' +import { Client, ClientV1 } from '../../../shared/type/domain.type' + +const ClientListIndex = z.array(z.string()) + +export function clientObjectToPrisma(client: Client): Prisma.ClientCreateInput { + return { + clientId: client.clientId, + name: client.name, + configurationSource: client.configurationSource, + baseUrl: client.baseUrl, + authDisabled: client.auth.disabled, + clientSecret: client.auth.local?.clientSecret, + + dataStoreEntityDataUrl: client.dataStore.entity.data.url, + dataStoreEntitySignatureUrl: client.dataStore.entity.signature.url, + dataStoreEntityPublicKeys: JSON.stringify(client.dataStore.entity.keys), + dataStorePolicyDataUrl: client.dataStore.policy.data.url, + dataStorePolicySignatureUrl: client.dataStore.policy.signature.url, + dataStorePolicyPublicKeys: JSON.stringify(client.dataStore.policy.keys), + + decisionAttestationDisabled: client.decisionAttestation.disabled, + signerAlg: client.decisionAttestation.signer?.alg, + signerKeyId: client.decisionAttestation.signer?.keyId, + signerPublicKey: JSON.stringify(client.decisionAttestation.signer?.publicKey), + signerPrivateKey: JSON.stringify(client.decisionAttestation.signer?.privateKey), + + createdAt: client.createdAt, + updatedAt: client.updatedAt + } +} + +function prismaToClientObject(prismaClient: Prisma.ClientGetPayload): Client { + return Client.parse({ + clientId: prismaClient.clientId, + name: prismaClient.name, + configurationSource: prismaClient.configurationSource as 'declarative' | 'dynamic', + baseUrl: prismaClient.baseUrl, + auth: { + disabled: prismaClient.authDisabled, + local: prismaClient.clientSecret + ? { + clientSecret: prismaClient.clientSecret + } + : null + }, + dataStore: { + entity: { + data: { + url: prismaClient.dataStoreEntityDataUrl, + type: prismaClient.dataStoreEntityDataUrl.startsWith('https') ? 'HTTPS' : 'HTTP' + }, + signature: { + url: prismaClient.dataStoreEntitySignatureUrl, + type: prismaClient.dataStoreEntitySignatureUrl.startsWith('https') ? 'HTTPS' : 'HTTP' + }, + keys: JSON.parse(prismaClient.dataStoreEntityPublicKeys) + }, + policy: { + data: { + url: prismaClient.dataStorePolicyDataUrl, + type: prismaClient.dataStorePolicyDataUrl.startsWith('https') ? 'HTTPS' : 'HTTP' + }, + signature: { + url: prismaClient.dataStorePolicySignatureUrl, + type: prismaClient.dataStorePolicySignatureUrl.startsWith('https') ? 'HTTPS' : 'HTTP' + }, + keys: JSON.parse(prismaClient.dataStorePolicyPublicKeys) + } + }, + decisionAttestation: { + disabled: prismaClient.decisionAttestationDisabled, + signer: prismaClient.signerAlg + ? { + alg: prismaClient.signerAlg as SigningAlg, + keyId: prismaClient.signerKeyId, + publicKey: prismaClient.signerPublicKey + ? publicKeySchema.parse(JSON.parse(prismaClient.signerPublicKey)) + : undefined, + privateKey: prismaClient.signerPrivateKey + ? privateKeySchema.parse(JSON.parse(prismaClient.signerPrivateKey)) + : undefined + } + : null + }, + createdAt: prismaClient.createdAt, + updatedAt: prismaClient.updatedAt + }) +} + +@Injectable() +export class ClientRepository { + constructor( + private encryptKeyValueService: EncryptKeyValueService, + private prismaService: PrismaService + ) {} + + async findById(clientId: string): Promise { + const value = await this.prismaService.client.findUnique({ + where: { clientId } + }) + + if (value) { + return prismaToClientObject(value) + } + + return null + } + async findAll(): Promise { + const clients = await this.prismaService.client.findMany({}) + return clients.map(prismaToClientObject) + } + + // Upsert the Client + async save(client: Client): Promise { + const clientData = clientObjectToPrisma(client) + + await this.prismaService.client.upsert({ + where: { clientId: client.clientId }, + update: clientData, + create: clientData + }) + + return client + } + + /** @deprecated */ + async findByIdV1(clientId: string): Promise { + const value = await this.encryptKeyValueService.get(this.getKey(clientId)) + + if (value) { + return coerce.decode(ClientV1, value) + } + + return null + } + + /** @deprecated */ + async saveV1(client: ClientV1): Promise { + await this.encryptKeyValueService.set(this.getKey(client.clientId), coerce.encode(ClientV1, client)) + await this.index(client) + + return client + } + + /** @deprecated */ + async getClientListIndex(): Promise { + const index = await this.encryptKeyValueService.get(this.getIndexKey()) + + if (index) { + return coerce.decode(ClientListIndex, index) + } + + return [] + } + + async saveEntityStore(clientId: string, store: EntityStore): Promise { + return this.encryptKeyValueService.set(this.getEntityStoreKey(clientId), coerce.encode(EntityStore, store)) + } + + async findEntityStore(clientId: string): Promise { + const value = await this.encryptKeyValueService.get(this.getEntityStoreKey(clientId)) + + if (value) { + return coerce.decode(EntityStore, value) + } + + return null + } + + async savePolicyStore(clientId: string, store: PolicyStore): Promise { + return this.encryptKeyValueService.set(this.getPolicyStoreKey(clientId), coerce.encode(PolicyStore, store)) + } + + async findPolicyStore(clientId: string): Promise { + const value = await this.encryptKeyValueService.get(this.getPolicyStoreKey(clientId)) + + if (value) { + return coerce.decode(PolicyStore, value) + } + + return null + } + + // TODO: (@wcalderipe, 07/03/24) we need to rethink this strategy. If we use a + // SQL database, this could generate a massive amount of queries; thus, + // degrading the performance. + // + // An option is to move these general queries `findBy`, findAll`, etc to the + // KeyValeuRepository implementation letting each implementation pick the best + // strategy to solve the problem (e.g. where query in SQL) + /** @deprecated */ + async findAllV1(): Promise { + const ids = await this.getClientListIndex() + const clients = await Promise.all(ids.map((id) => this.findByIdV1(id))) + + return compact(clients) + } + + /** @deprecated */ + getKey(clientId: string): string { + return `client:${clientId}` + } + + /** @deprecated */ + getIndexKey(): string { + return 'client:list-index' + } + + /** @deprecated */ + private async index(client: ClientV1): Promise { + const currentIndex = await this.getClientListIndex() + + await this.encryptKeyValueService.set( + this.getIndexKey(), + coerce.encode(ClientListIndex, [...currentIndex, client.clientId]) + ) + + return true + } + + getEntityStoreKey(clientId: string): string { + return `client:${clientId}:entity-store` + } + + getPolicyStoreKey(clientId: string): string { + return `client:${clientId}:policy-store` + } + + async deleteV1(clientId: string): Promise { + await this.encryptKeyValueService.delete(this.getKey(clientId)) + // Remove the client from the index + const currentIndex = await this.getClientListIndex() + + const newIndex = currentIndex.filter((id) => id !== clientId) + await this.encryptKeyValueService.set(this.getIndexKey(), coerce.encode(ClientListIndex, newIndex)) + } +} diff --git a/apps/policy-engine/src/engine/__test__/e2e/client.spec.ts b/apps/policy-engine/src/engine/__test__/e2e/client.spec.ts index b2d3ada8e..2b0ffddc0 100644 --- a/apps/policy-engine/src/engine/__test__/e2e/client.spec.ts +++ b/apps/policy-engine/src/engine/__test__/e2e/client.spec.ts @@ -1,4 +1,3 @@ -import { ConfigModule, ConfigService } from '@narval/config-module' import { EncryptionModuleOptionProvider } from '@narval/encryption-module' import { LoggerModule, @@ -20,15 +19,16 @@ import { Test, TestingModule } from '@nestjs/testing' import request from 'supertest' import { v4 as uuid } from 'uuid' import { generatePrivateKey } from 'viem/accounts' -import { Config, load } from '../../../policy-engine.config' +import { ClientService } from '../../../client/core/service/client.service' +import { CreateClientRequestDto } from '../../../client/http/rest/dto/create-client.dto' +import { ClientRepository } from '../../../client/persistence/repository/client.repository' +import { PolicyEngineModule } from '../../../policy-engine.module' +import { KeyValueRepository } from '../../../shared/module/key-value/core/repository/key-value.repository' +import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' import { getTestRawAesKeyring } from '../../../shared/testing/encryption.testing' import { Client } from '../../../shared/type/domain.type' -import { ClientService } from '../../core/service/client.service' -import { EngineService } from '../../core/service/engine.service' -import { EngineModule } from '../../engine.module' -import { CreateClientRequestDto } from '../../http/rest/dto/create-client.dto' -import { ClientRepository } from '../../persistence/repository/client.repository' +import { ProvisionService } from '../../core/service/provision.service' describe('Client', () => { let app: INestApplication @@ -36,8 +36,6 @@ describe('Client', () => { let testPrismaService: TestPrismaService let clientRepository: ClientRepository let clientService: ClientService - let engineService: EngineService - let configService: ConfigService let dataStoreConfiguration: DataStoreConfiguration let createClientPayload: CreateClientRequestDto @@ -52,16 +50,14 @@ describe('Client', () => { beforeAll(async () => { module = await Test.createTestingModule({ - imports: [ - LoggerModule.forTest(), - ConfigModule.forRoot({ - load: [load], - isGlobal: true - }), - OpenTelemetryModule.forTest(), - EngineModule - ] + imports: [PolicyEngineModule] }) + .overrideModule(LoggerModule) + .useModule(LoggerModule.forTest()) + .overrideModule(OpenTelemetryModule) + .useModule(OpenTelemetryModule.forTest()) + .overrideProvider(KeyValueRepository) + .useValue(new InMemoryKeyValueRepository()) .overrideProvider(EncryptionModuleOptionProvider) .useValue({ keyring: getTestRawAesKeyring() @@ -70,11 +66,9 @@ describe('Client', () => { app = module.createNestApplication() - engineService = module.get(EngineService) clientService = module.get(ClientService) clientRepository = module.get(ClientRepository) testPrismaService = module.get(TestPrismaService) - configService = module.get>(ConfigService) const jwk = secp256k1PrivateKeyToJwk(generatePrivateKey()) @@ -102,11 +96,8 @@ describe('Client', () => { beforeEach(async () => { await testPrismaService.truncateAll() - await engineService.save({ - id: configService.get('engine.id'), - masterKey: 'unsafe-test-master-key', - adminApiKey: secret.hash(adminApiKey) - }) + const provisionService = module.get(ProvisionService) + await provisionService.provision(secret.hash(adminApiKey)) jest.spyOn(clientService, 'syncDataStore').mockResolvedValue(true) }) @@ -119,13 +110,25 @@ describe('Client', () => { .send(createClientPayload) const actualClient = await clientRepository.findById(clientId) - const hex = await privateKeyToHex(actualClient?.signer.privateKey as PrivateKey) + const hex = await privateKeyToHex(actualClient?.decisionAttestation.signer?.privateKey as PrivateKey) const actualPublicKey = secp256k1PrivateKeyToPublicJwk(hex) expect(body).toEqual({ ...actualClient, - clientSecret: expect.any(String), - signer: { publicKey: actualPublicKey }, + auth: { + disabled: false, + local: { + clientSecret: expect.any(String) + } + }, + decisionAttestation: { + ...actualClient?.decisionAttestation, + signer: { + publicKey: actualPublicKey, + alg: actualClient?.decisionAttestation.signer?.alg, + keyId: actualClient?.decisionAttestation.signer?.keyId + } + }, createdAt: actualClient?.createdAt.toISOString(), updatedAt: actualClient?.updatedAt.toISOString() }) @@ -140,7 +143,7 @@ describe('Client', () => { .set(REQUEST_HEADER_ADMIN_API_KEY, adminApiKey) .send({ ...createClientPayload, clientSecret }) - expect(body.clientSecret).toEqual(clientSecret) + expect(body.auth.local?.clientSecret).toEqual(clientSecret) }) it('creates a new client with engine key in the entity and policy keys for self-signed data', async () => { @@ -150,13 +153,25 @@ describe('Client', () => { .send({ ...createClientPayload, allowSelfSignedData: true }) const actualClient = await clientRepository.findById(clientId) - const hex = await privateKeyToHex(actualClient?.signer.privateKey as PrivateKey) + const hex = await privateKeyToHex(actualClient?.decisionAttestation.signer?.privateKey as PrivateKey) const actualPublicKey = secp256k1PrivateKeyToPublicJwk(hex) expect(body).toEqual({ ...actualClient, - clientSecret: expect.any(String), - signer: { publicKey: actualPublicKey }, + auth: { + disabled: false, + local: { + clientSecret: expect.any(String) + } + }, + decisionAttestation: { + ...actualClient?.decisionAttestation, + signer: { + publicKey: actualPublicKey, + alg: actualClient?.decisionAttestation.signer?.alg, + keyId: actualClient?.decisionAttestation.signer?.keyId + } + }, createdAt: actualClient?.createdAt.toISOString(), updatedAt: actualClient?.updatedAt.toISOString() }) @@ -178,11 +193,10 @@ describe('Client', () => { .set(REQUEST_HEADER_ADMIN_API_KEY, adminApiKey) .send(createClientPayload) - expect(body.signer.key).not.toBeDefined() - expect(body.signer.type).not.toBeDefined() + expect(body.decisionAttestation.signer.privateKey).not.toBeDefined() // The JWK private key is stored in the key's `d` property. // See also https://datatracker.ietf.org/doc/html/rfc7517#appendix-A.2 - expect(body.signer.publicKey.d).not.toBeDefined() + expect(body.decisionAttestation.signer.publicKey.d).not.toBeDefined() }) it('responds with an error when clientId already exist', async () => { @@ -238,8 +252,7 @@ describe('Client', () => { const { status, body } = await request(app.getHttpServer()) .post('/clients/sync') .set(REQUEST_HEADER_CLIENT_ID, client.clientId) - .set(REQUEST_HEADER_CLIENT_SECRET, client.clientSecret) - .send(createClientPayload) + .set(REQUEST_HEADER_CLIENT_SECRET, client.auth.local?.clientSecret || '') expect(body).toEqual({ success: true }) expect(status).toEqual(HttpStatus.OK) diff --git a/apps/policy-engine/src/engine/__test__/e2e/evaluation.spec.ts b/apps/policy-engine/src/engine/__test__/e2e/evaluation.spec.ts index a47f486e4..f37931fe4 100644 --- a/apps/policy-engine/src/engine/__test__/e2e/evaluation.spec.ts +++ b/apps/policy-engine/src/engine/__test__/e2e/evaluation.spec.ts @@ -1,10 +1,10 @@ -import { ConfigModule, ConfigService } from '@narval/config-module' import { EncryptionModuleOptionProvider } from '@narval/encryption-module' import { LoggerModule, OpenTelemetryModule, REQUEST_HEADER_CLIENT_ID, - REQUEST_HEADER_CLIENT_SECRET + REQUEST_HEADER_CLIENT_SECRET, + secret } from '@narval/nestjs-shared' import { Action, @@ -18,7 +18,7 @@ import { SourceType, Then } from '@narval/policy-engine-shared' -import { PrivateKey, secp256k1PrivateKeyToJwk, secp256k1PrivateKeyToPublicJwk } from '@narval/signature' +import { PrivateKey, SigningAlg, secp256k1PrivateKeyToJwk, secp256k1PrivateKeyToPublicJwk } from '@narval/signature' import { HttpStatus, INestApplication } from '@nestjs/common' import { Test, TestingModule } from '@nestjs/testing' import { randomBytes } from 'crypto' @@ -27,8 +27,8 @@ import request from 'supertest' import { v4 as uuid } from 'uuid' import { generatePrivateKey } from 'viem/accounts' import { sepolia } from 'viem/chains' -import { EngineService } from '../../../engine/core/service/engine.service' -import { Config, load } from '../../../policy-engine.config' +import { ClientService } from '../../../client/core/service/client.service' +import { PolicyEngineModule } from '../../../policy-engine.module' import { KeyValueRepository } from '../../../shared/module/key-value/core/repository/key-value.repository' import { InMemoryKeyValueRepository } from '../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' @@ -44,8 +44,7 @@ import { generateSignUserOperationRequest } from '../../../shared/testing/evaluation.testing' import { Client } from '../../../shared/type/domain.type' -import { ClientService } from '../../core/service/client.service' -import { EngineModule } from '../../engine.module' +import { ProvisionService } from '../../core/service/provision.service' describe('Evaluation', () => { let app: INestApplication @@ -66,16 +65,12 @@ describe('Evaluation', () => { beforeAll(async () => { module = await Test.createTestingModule({ - imports: [ - LoggerModule.forTest(), - ConfigModule.forRoot({ - load: [load], - isGlobal: true - }), - OpenTelemetryModule.forTest(), - EngineModule - ] + imports: [PolicyEngineModule] }) + .overrideModule(LoggerModule) + .useModule(LoggerModule.forTest()) + .overrideModule(OpenTelemetryModule) + .useModule(OpenTelemetryModule.forTest()) .overrideProvider(KeyValueRepository) .useValue(new InMemoryKeyValueRepository()) .overrideProvider(EncryptionModuleOptionProvider) @@ -86,8 +81,6 @@ describe('Evaluation', () => { app = module.createNestApplication() - const engineService = module.get(EngineService) - const configService = module.get>(ConfigService) clientService = module.get(ClientService) testPrismaService = module.get(TestPrismaService) @@ -101,24 +94,34 @@ describe('Evaluation', () => { keys: [privateKey] } - await engineService.save({ - id: configService.get('engine.id'), - masterKey: 'unsafe-test-master-key', - adminApiKey - }) + const provisionService = module.get(ProvisionService) + await provisionService.provision(secret.hash(adminApiKey)) const clientSignerKey = generatePrivateKey() client = await clientService.save( { clientId, - clientSecret: randomBytes(42).toString('hex'), + name: 'test-client', + configurationSource: 'dynamic', + baseUrl: null, + auth: { + disabled: false, + local: { + clientSecret: randomBytes(42).toString('hex') + } + }, dataStore: { entity: dataStoreConfiguration, policy: dataStoreConfiguration }, - signer: { - publicKey: secp256k1PrivateKeyToPublicJwk(clientSignerKey), - privateKey: secp256k1PrivateKeyToJwk(clientSignerKey) + decisionAttestation: { + disabled: false, + signer: { + alg: SigningAlg.EIP191, + keyId: 'test-key-id', + publicKey: secp256k1PrivateKeyToPublicJwk(clientSignerKey), + privateKey: secp256k1PrivateKeyToJwk(clientSignerKey) + } }, createdAt: new Date(), updatedAt: new Date() @@ -146,7 +149,7 @@ describe('Evaluation', () => { const { body } = await request(app.getHttpServer()) .post('/evaluations') .set(REQUEST_HEADER_CLIENT_ID, client.clientId) - .set(REQUEST_HEADER_CLIENT_SECRET, client.clientSecret) + .set(REQUEST_HEADER_CLIENT_SECRET, client.auth.local?.clientSecret || '') .send(serializedPayload) expect(body).toMatchObject({ @@ -197,7 +200,7 @@ describe('Evaluation', () => { const { status, body } = await request(app.getHttpServer()) .post('/evaluations') .set(REQUEST_HEADER_CLIENT_ID, client.clientId) - .set(REQUEST_HEADER_CLIENT_SECRET, client.clientSecret) + .set(REQUEST_HEADER_CLIENT_SECRET, client.auth.local?.clientSecret || '') .send(payload) expect(body).toEqual({ @@ -292,7 +295,7 @@ describe('Evaluation', () => { const { status, body } = await request(app.getHttpServer()) .post('/evaluations') .set(REQUEST_HEADER_CLIENT_ID, client.clientId) - .set(REQUEST_HEADER_CLIENT_SECRET, client.clientSecret) + .set(REQUEST_HEADER_CLIENT_SECRET, client.auth.local?.clientSecret || '') .send(payload) expect(body).toMatchObject({ diff --git a/apps/policy-engine/src/engine/__test__/e2e/provision.spec.ts b/apps/policy-engine/src/engine/__test__/e2e/provision.spec.ts deleted file mode 100644 index 8b8c4081d..000000000 --- a/apps/policy-engine/src/engine/__test__/e2e/provision.spec.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { ConfigModule } from '@narval/config-module' -import { LoggerModule, OpenTelemetryModule, secret } from '@narval/nestjs-shared' -import { INestApplication } from '@nestjs/common' -import { Test, TestingModule } from '@nestjs/testing' -import request from 'supertest' -import { Config, load } from '../../../policy-engine.config' -import { TestPrismaService } from '../../../shared/module/persistence/service/test-prisma.service' -import { EngineService } from '../../core/service/engine.service' -import { ProvisionService } from '../../core/service/provision.service' -import { EngineModule } from '../../engine.module' - -const ENDPOINT = '/apps/activate' - -const testConfigLoad = (): Config => ({ - ...load(), - engine: { - id: 'local-dev-engine-instance-1', - adminApiKeyHash: undefined - } -}) - -describe('Provision', () => { - let app: INestApplication - let module: TestingModule - let engineService: EngineService - let provisionService: ProvisionService - let testPrismaService: TestPrismaService - - beforeAll(async () => { - module = await Test.createTestingModule({ - imports: [ - LoggerModule.forTest(), - ConfigModule.forRoot({ - load: [testConfigLoad], - isGlobal: true - }), - OpenTelemetryModule.forTest(), - EngineModule - ] - }).compile() - - app = module.createNestApplication() - - engineService = app.get(EngineService) - provisionService = app.get(ProvisionService) - testPrismaService = app.get(TestPrismaService) - - await app.init() - }) - - beforeEach(async () => { - await testPrismaService.truncateAll() - await provisionService.provision() - }) - - afterAll(async () => { - await testPrismaService.truncateAll() - await module.close() - await app.close() - }) - - describe(`POST ${ENDPOINT}`, () => { - it('responds with activated app state', async () => { - const { body } = await request(app.getHttpServer()).post(ENDPOINT).send() - - expect(body).toEqual({ - state: 'READY', - app: { - appId: 'local-dev-engine-instance-1', - adminApiKey: expect.any(String) - } - }) - }) - - it('responds already provisioned', async () => { - await request(app.getHttpServer()).post(ENDPOINT).send() - - const { body } = await request(app.getHttpServer()).post(ENDPOINT).send() - - expect(body).toEqual({ state: 'ACTIVATED' }) - }) - - it('does not respond with hashed admin API key', async () => { - const { body } = await request(app.getHttpServer()).post(ENDPOINT).send() - - const actualEngine = await engineService.getEngineOrThrow() - - expect(secret.hash(body.app.adminApiKey)).toEqual(actualEngine.adminApiKey) - }) - }) -}) diff --git a/apps/policy-engine/src/engine/core/factory/signing-service.factory.ts b/apps/policy-engine/src/engine/core/factory/signing-service.factory.ts index d766aea07..f13fe3844 100644 --- a/apps/policy-engine/src/engine/core/factory/signing-service.factory.ts +++ b/apps/policy-engine/src/engine/core/factory/signing-service.factory.ts @@ -25,14 +25,14 @@ const loadArmoryMpcSigningService = () => { } export const signingServiceFactory = async (configService: ConfigService): Promise => { - const protocol = configService.get('signingProtocol') + const protocol = configService.get('decisionAttestation.protocol') if (protocol === 'simple') { return new SimpleSigningService() } if (protocol === 'mpc') { - const tsm = configService.get('tsm') + const tsm = configService.get('decisionAttestation.tsm') if (!tsm) { throw new Error('Missing TSM config') diff --git a/apps/policy-engine/src/engine/core/service/__test__/integration/engine.service.spec.ts b/apps/policy-engine/src/engine/core/service/__test__/integration/engine.service.spec.ts deleted file mode 100644 index 7577ca760..000000000 --- a/apps/policy-engine/src/engine/core/service/__test__/integration/engine.service.spec.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { ConfigModule, ConfigService } from '@narval/config-module' -import { secret } from '@narval/nestjs-shared' -import { Test } from '@nestjs/testing' -import { Config, load } from '../../../../../policy-engine.config' -import { KeyValueRepository } from '../../../../../shared/module/key-value/core/repository/key-value.repository' -import { KeyValueService } from '../../../../../shared/module/key-value/core/service/key-value.service' -import { InMemoryKeyValueRepository } from '../../../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' -import { EngineRepository } from '../../../../persistence/repository/engine.repository' -import { EngineService } from '../../engine.service' - -describe(EngineService.name, () => { - let service: EngineService - let configService: ConfigService - - beforeEach(async () => { - const module = await Test.createTestingModule({ - imports: [ConfigModule.forRoot({ load: [load] })], - providers: [ - EngineService, - EngineRepository, - KeyValueService, - { - provide: KeyValueRepository, - useClass: InMemoryKeyValueRepository - } - ] - }).compile() - - service = module.get(EngineService) - configService = module.get>(ConfigService) - }) - - describe('save', () => { - const id = 'test-engine' - - const adminApiKey = secret.hash('test-admin-api-key') - - const engine = { - id, - adminApiKey, - activated: true - } - - it('returns the given secret key', async () => { - const actualEngine = await service.save(engine) - - expect(actualEngine.adminApiKey).toEqual(engine.adminApiKey) - }) - - // IMPORTANT: The admin API key is hashed by the caller not the service. That - // allows us to have a determistic configuration file which is useful for - // automations like development or cloud set up. - it('does not hash the admin api key', async () => { - jest.spyOn(configService, 'get').mockReturnValue(id) - - await service.save(engine) - - const actualEngine = await service.getEngine() - - expect(actualEngine?.adminApiKey).toEqual(adminApiKey) - }) - }) -}) diff --git a/apps/policy-engine/src/engine/core/service/__test__/unit/bootstrap.service.spec.ts b/apps/policy-engine/src/engine/core/service/__test__/unit/bootstrap.service.spec.ts index 1f504b460..0aea1375d 100644 --- a/apps/policy-engine/src/engine/core/service/__test__/unit/bootstrap.service.spec.ts +++ b/apps/policy-engine/src/engine/core/service/__test__/unit/bootstrap.service.spec.ts @@ -1,22 +1,18 @@ import { ConfigModule } from '@narval/config-module' -import { EncryptionException, EncryptionService } from '@narval/encryption-module' +import { EncryptionService } from '@narval/encryption-module' import { LoggerModule } from '@narval/nestjs-shared' import { HttpSource, SourceType } from '@narval/policy-engine-shared' -import { Alg, privateKeyToJwk } from '@narval/signature' +import { Alg, SigningAlg, privateKeyToJwk, secp256k1PrivateKeyToPublicJwk } from '@narval/signature' import { Test } from '@nestjs/testing' import { MockProxy, mock } from 'jest-mock-extended' import { generatePrivateKey } from 'viem/accounts' -import { EngineService } from '../../../../../engine/core/service/engine.service' -import { EngineRepository } from '../../../../../engine/persistence/repository/engine.repository' +import { BootstrapService } from '../../../../../client/core/service/bootstrap.service' +import { ClientService } from '../../../../../client/core/service/client.service' import { load } from '../../../../../policy-engine.config' import { KeyValueRepository } from '../../../../../shared/module/key-value/core/repository/key-value.repository' -import { KeyValueService } from '../../../../../shared/module/key-value/core/service/key-value.service' import { InMemoryKeyValueRepository } from '../../../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { getTestRawAesKeyring } from '../../../../../shared/testing/encryption.testing' import { Client } from '../../../../../shared/type/domain.type' -import { BootstrapException } from '../../../exception/bootstrap.exception' -import { BootstrapService } from '../../bootstrap.service' -import { ClientService } from '../../client.service' describe(BootstrapService.name, () => { let bootstrapService: BootstrapService @@ -41,23 +37,53 @@ describe(BootstrapService.name, () => { } } + const clientOneSignerKey = generatePrivateKey() const clientOne: Client = { dataStore, clientId: 'test-client-one-id', - clientSecret: 'unsafe-client-secret', - signer: { - privateKey: privateKeyToJwk(generatePrivateKey(), Alg.ES256K) + name: 'test-client-one', + configurationSource: 'dynamic', + baseUrl: null, + auth: { + disabled: false, + local: { + clientSecret: 'unsafe-client-secret' + } + }, + decisionAttestation: { + disabled: false, + signer: { + alg: SigningAlg.EIP191, + keyId: 'test-key-id', + publicKey: secp256k1PrivateKeyToPublicJwk(clientOneSignerKey), + privateKey: privateKeyToJwk(clientOneSignerKey, Alg.ES256K) + } }, createdAt: new Date(), updatedAt: new Date() } + const clientTwoSignerKey = generatePrivateKey() const clientTwo: Client = { dataStore, clientId: 'test-client-two-id', - clientSecret: 'unsafe-client-secret', - signer: { - privateKey: privateKeyToJwk(generatePrivateKey(), Alg.ES256K) + name: 'test-client-two', + configurationSource: 'dynamic', + baseUrl: null, + auth: { + disabled: false, + local: { + clientSecret: 'unsafe-client-secret' + } + }, + decisionAttestation: { + disabled: false, + signer: { + alg: SigningAlg.EIP191, + keyId: 'test-key-id-2', + publicKey: secp256k1PrivateKeyToPublicJwk(clientTwoSignerKey), + privateKey: privateKeyToJwk(clientTwoSignerKey, Alg.ES256K) + } }, createdAt: new Date(), updatedAt: new Date() @@ -80,9 +106,6 @@ describe(BootstrapService.name, () => { ], providers: [ BootstrapService, - EngineRepository, - EngineService, - KeyValueService, { provide: KeyValueRepository, useClass: InMemoryKeyValueRepository @@ -108,20 +131,5 @@ describe(BootstrapService.name, () => { expect(clientServiceMock.syncDataStore).toHaveBeenNthCalledWith(1, clientOne.clientId) expect(clientServiceMock.syncDataStore).toHaveBeenNthCalledWith(2, clientTwo.clientId) }) - - it('checks if the encryption keyring is configured', async () => { - await bootstrapService.boot() - - expect(encryptionServiceMock.getKeyring).toHaveBeenCalledTimes(1) - }) - - it('throws when encryption keyring is not configure', async () => { - encryptionServiceMock.getKeyring.mockImplementation(() => { - throw new EncryptionException('Something went wrong') - }) - - await expect(() => bootstrapService.boot()).rejects.toThrow(BootstrapException) - await expect(() => bootstrapService.boot()).rejects.toThrow('Encryption keyring not found') - }) }) }) diff --git a/apps/policy-engine/src/engine/core/service/__test__/unit/client.service.spec.ts b/apps/policy-engine/src/engine/core/service/__test__/unit/client.service.spec.ts index 7aead373c..d61ce82c2 100644 --- a/apps/policy-engine/src/engine/core/service/__test__/unit/client.service.spec.ts +++ b/apps/policy-engine/src/engine/core/service/__test__/unit/client.service.spec.ts @@ -1,23 +1,23 @@ import { EncryptionModule } from '@narval/encryption-module' -import { LoggerModule, StatefulTraceService, TraceService, secret } from '@narval/nestjs-shared' +import { LoggerModule, StatefulTraceService, TraceService } from '@narval/nestjs-shared' import { DataStoreConfiguration, FIXTURE, HttpSource, SourceType } from '@narval/policy-engine-shared' -import { Alg, getPublicKey, privateKeyToJwk } from '@narval/signature' +import { Alg, SigningAlg, getPublicKey, privateKeyToJwk, secp256k1PrivateKeyToPublicJwk } from '@narval/signature' import { Test } from '@nestjs/testing' import { MockProxy, mock } from 'jest-mock-extended' import { generatePrivateKey } from 'viem/accounts' +import { ClientService } from '../../../../../client/core/service/client.service' +import { ClientRepository } from '../../../../../client/persistence/repository/client.repository' import { KeyValueRepository } from '../../../../../shared/module/key-value/core/repository/key-value.repository' import { EncryptKeyValueService } from '../../../../../shared/module/key-value/core/service/encrypt-key-value.service' import { InMemoryKeyValueRepository } from '../../../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' import { getTestRawAesKeyring } from '../../../../../shared/testing/encryption.testing' import { Client } from '../../../../../shared/type/domain.type' -import { ClientRepository } from '../../../../persistence/repository/client.repository' -import { ClientService } from '../../client.service' import { DataStoreService } from '../../data-store.service' import { SimpleSigningService } from '../../signing-basic.service' describe(ClientService.name, () => { let clientService: ClientService - let clientRepository: ClientRepository + let clientRepositoryMock: MockProxy let dataStoreServiceMock: MockProxy const clientId = 'test-client-id' @@ -33,15 +33,30 @@ describe(ClientService.name, () => { keys: [getPublicKey(privateKeyToJwk(generatePrivateKey()))] } + const clientSignerKey = generatePrivateKey() const client: Client = { clientId, - clientSecret: secret.hash('test-client-secret'), + name: 'test-client', + configurationSource: 'dynamic', + baseUrl: null, + auth: { + disabled: false, + local: { + clientSecret: 'unsafe-client-secret' + } + }, dataStore: { entity: dataStoreConfiguration, policy: dataStoreConfiguration }, - signer: { - privateKey: privateKeyToJwk(generatePrivateKey(), Alg.ES256K) + decisionAttestation: { + disabled: false, + signer: { + alg: SigningAlg.EIP191, + keyId: 'test-key-id', + publicKey: secp256k1PrivateKeyToPublicJwk(clientSignerKey), + privateKey: privateKeyToJwk(clientSignerKey, Alg.ES256K) + } }, createdAt: new Date(), updatedAt: new Date() @@ -60,6 +75,7 @@ describe(ClientService.name, () => { beforeEach(async () => { dataStoreServiceMock = mock() + clientRepositoryMock = mock() dataStoreServiceMock.fetch.mockResolvedValue(stores) const module = await Test.createTestingModule({ @@ -71,7 +87,6 @@ describe(ClientService.name, () => { ], providers: [ ClientService, - ClientRepository, EncryptKeyValueService, { provide: DataStoreService, @@ -88,37 +103,35 @@ describe(ClientService.name, () => { { provide: TraceService, useClass: StatefulTraceService + }, + { + provide: ClientRepository, + useValue: clientRepositoryMock } ] }).compile() clientService = module.get(ClientService) - clientRepository = module.get(ClientRepository) }) describe('save', () => { + beforeEach(async () => { + clientRepositoryMock.save.mockResolvedValue(client) + clientRepositoryMock.findById.mockResolvedValue(client) + }) it('does not hash the client secret because it is already hashed', async () => { await clientService.save(client) const actualClient = await clientService.findById(client.clientId) - expect(actualClient?.clientSecret).toEqual(client.clientSecret) + expect(actualClient?.auth.local?.clientSecret).toEqual(client.auth.local?.clientSecret) }) }) describe('syncDataStore', () => { beforeEach(async () => { - await clientRepository.save(client) - }) - - it('saves entity and policy stores', async () => { - expect(await clientRepository.findEntityStore(clientId)).toEqual(null) - expect(await clientRepository.findPolicyStore(clientId)).toEqual(null) - - await clientService.syncDataStore(clientId) - - expect(await clientRepository.findEntityStore(clientId)).toEqual(stores.entity) - expect(await clientRepository.findPolicyStore(clientId)).toEqual(stores.policy) + clientRepositoryMock.save.mockResolvedValue(client) + clientRepositoryMock.findById.mockResolvedValue(client) }) it('fetches the data stores once', async () => { diff --git a/apps/policy-engine/src/engine/core/service/__test__/unit/evaluation.service.spec.ts b/apps/policy-engine/src/engine/core/service/__test__/unit/evaluation.service.spec.ts index 866a7ba36..401c50beb 100644 --- a/apps/policy-engine/src/engine/core/service/__test__/unit/evaluation.service.spec.ts +++ b/apps/policy-engine/src/engine/core/service/__test__/unit/evaluation.service.spec.ts @@ -1,7 +1,6 @@ import { LoggerModule, OpenTelemetryModule } from '@narval/nestjs-shared' import { Action, - Client, DataStoreConfiguration, Decision, EntityUtil, @@ -12,13 +11,14 @@ import { Request, SignTransactionAction } from '@narval/policy-engine-shared' -import { Alg, PrivateKey, decodeJwt, generateJwk, getPublicKey, nowSeconds } from '@narval/signature' +import { Alg, PrivateKey, SigningAlg, decodeJwt, generateJwk, getPublicKey, nowSeconds } from '@narval/signature' import { Test } from '@nestjs/testing' import { MockProxy, mock } from 'jest-mock-extended' +import { ClientService } from '../../../../../client/core/service/client.service' import { OpenPolicyAgentEngine } from '../../../../../open-policy-agent/core/open-policy-agent.engine' import { ApplicationException } from '../../../../../shared/exception/application.exception' +import { Client } from '../../../../../shared/type/domain.type' import { OpenPolicyAgentEngineFactory } from '../../../factory/open-policy-agent-engine.factory' -import { ClientService } from '../../client.service' import { EvaluationService, buildPermitTokenPayload } from '../../evaluation.service' import { SimpleSigningService } from '../../signing-basic.service' @@ -168,14 +168,27 @@ describe(EvaluationService.name, () => { client = { clientId: 'test-client-id', - clientSecret: 'test-client-secret', + name: 'test-client-name', + configurationSource: 'dynamic', + baseUrl: null, + auth: { + disabled: false, + local: { + clientSecret: 'test-client-secret' + } + }, dataStore: { entity: {} as DataStoreConfiguration, policy: {} as DataStoreConfiguration }, - signer: { - publicKey: getPublicKey(clientSignerPrivateKey), - privateKey: clientSignerPrivateKey + decisionAttestation: { + disabled: false, + signer: { + publicKey: getPublicKey(clientSignerPrivateKey), + privateKey: clientSignerPrivateKey, + alg: SigningAlg.EIP191, + keyId: 'test-key-id' + } }, createdAt: new Date(), updatedAt: new Date() diff --git a/apps/policy-engine/src/engine/core/service/__test__/unit/provision.service.spec.ts b/apps/policy-engine/src/engine/core/service/__test__/unit/provision.service.spec.ts deleted file mode 100644 index ff08fba2c..000000000 --- a/apps/policy-engine/src/engine/core/service/__test__/unit/provision.service.spec.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { ConfigService } from '@narval/config-module' -import { LoggerModule, secret } from '@narval/nestjs-shared' -import { Test, TestingModule } from '@nestjs/testing' -import { MockProxy, mock } from 'jest-mock-extended' -import { Config } from '../../../../../policy-engine.config' -import { KeyValueRepository } from '../../../../../shared/module/key-value/core/repository/key-value.repository' -import { KeyValueService } from '../../../../../shared/module/key-value/core/service/key-value.service' -import { InMemoryKeyValueRepository } from '../../../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' -import { EngineRepository } from '../../../../persistence/repository/engine.repository' -import { EngineService } from '../../engine.service' -import { ProvisionService } from '../../provision.service' - -const mockConfigService = (config: { keyring: Config['keyring']; engineId: string; adminApiKeyHash?: string }) => { - const m = mock>() - - m.get.calledWith('keyring').mockReturnValue(config.keyring) - m.get.calledWith('engine.id').mockReturnValue(config.engineId) - m.get.calledWith('engine.adminApiKeyHash').mockReturnValue(config.adminApiKeyHash) - - return m -} - -describe(ProvisionService.name, () => { - let module: TestingModule - let provisionService: ProvisionService - let engineService: EngineService - let configServiceMock: MockProxy> - - const config = { - engineId: 'test-engine-id', - keyring: { - type: 'raw', - masterPassword: 'test-master-password' - } satisfies Config['keyring'] - } - - beforeEach(async () => { - configServiceMock = mockConfigService(config) - - module = await Test.createTestingModule({ - imports: [LoggerModule.forTest()], - providers: [ - ProvisionService, - EngineService, - EngineRepository, - KeyValueService, - { - provide: ConfigService, - useValue: configServiceMock - }, - { - provide: KeyValueRepository, - useClass: InMemoryKeyValueRepository - } - ] - }).compile() - - provisionService = module.get(ProvisionService) - engineService = module.get(EngineService) - }) - - describe('on first boot', () => { - describe('when admin api key is set', () => { - const adminApiKey = 'test-admin-api-key' - - beforeEach(async () => { - configServiceMock.get.calledWith('engine.adminApiKeyHash').mockReturnValue(secret.hash(adminApiKey)) - }) - - it('saves the activated engine', async () => { - await provisionService.provision() - - const actualEngine = await engineService.getEngine() - - expect(actualEngine).toEqual({ - id: config.engineId, - adminApiKey: secret.hash(adminApiKey), - masterKey: expect.any(String) - }) - }) - }) - - describe('when admin api key is not set', () => { - it('saves the provisioned engine', async () => { - await provisionService.provision() - - const actualEngine = await engineService.getEngine() - - expect(actualEngine?.adminApiKey).toEqual(undefined) - expect(actualEngine).toEqual({ - id: config.engineId, - masterKey: expect.any(String) - }) - }) - }) - }) - - describe('on boot', () => { - it('skips provision and returns the existing engine', async () => { - const actualEngine = await engineService.save({ - id: config.engineId, - masterKey: 'test-master-key' - }) - - const engine = await provisionService.provision() - - expect(actualEngine).toEqual(engine) - }) - }) -}) diff --git a/apps/policy-engine/src/engine/core/service/bootstrap.service.ts b/apps/policy-engine/src/engine/core/service/bootstrap.service.ts deleted file mode 100644 index 6a68d277d..000000000 --- a/apps/policy-engine/src/engine/core/service/bootstrap.service.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { EncryptionService } from '@narval/encryption-module' -import { LoggerService } from '@narval/nestjs-shared' -import { Injectable } from '@nestjs/common' -import { BootstrapException } from '../exception/bootstrap.exception' -import { ClientService } from './client.service' - -@Injectable() -export class BootstrapService { - constructor( - private clientService: ClientService, - private encryptionService: EncryptionService, - private logger: LoggerService - ) {} - - async boot(): Promise { - this.logger.log('Start bootstrap') - - await this.checkEncryptionConfiguration() - await this.syncClients() - - this.logger.log('Bootstrap end') - } - - private async checkEncryptionConfiguration(): Promise { - this.logger.log('Check encryption configuration') - - try { - this.encryptionService.getKeyring() - this.logger.log('Encryption keyring configured') - } catch (error) { - throw new BootstrapException('Encryption keyring not found', { origin: error }) - } - } - - private async syncClients(): Promise { - const clients = await this.clientService.findAll() - - this.logger.log('Start syncing clients data stores', { - clientsCount: clients.length - }) - - // TODO: (@wcalderipe, 07/03/24) maybe change the execution to parallel? - for (const client of clients) { - await this.clientService.syncDataStore(client.clientId) - this.logger.log(`Client public key`, { clientId: client.clientId, publicKey: client.signer.publicKey }) - } - } -} diff --git a/apps/policy-engine/src/engine/core/service/engine.service.ts b/apps/policy-engine/src/engine/core/service/engine.service.ts index 321030f37..8af7306c5 100644 --- a/apps/policy-engine/src/engine/core/service/engine.service.ts +++ b/apps/policy-engine/src/engine/core/service/engine.service.ts @@ -1,15 +1,18 @@ import { ConfigService } from '@narval/config-module' +import { LoggerService } from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' import { Config } from '../../../policy-engine.config' import { Engine } from '../../../shared/type/domain.type' import { EngineRepository } from '../../persistence/repository/engine.repository' import { EngineNotProvisionedException } from '../exception/engine-not-provisioned.exception' +import { ProvisionException } from '../exception/provision.exception' @Injectable() export class EngineService { constructor( private configService: ConfigService, - private engineRepository: EngineRepository + private engineRepository: EngineRepository, + private logger: LoggerService ) {} async getEngineOrThrow(): Promise { @@ -23,10 +26,15 @@ export class EngineService { } async getEngine(): Promise { - const engine = await this.engineRepository.findById(this.getId()) + const apps = await this.engineRepository.findAll() - if (engine) { - return engine + const app = apps?.find((app) => app.id === this.getId()) + if (apps?.length && apps.length > 1) { + throw new ProvisionException('Multiple app instances found; this can lead to data corruption') + } + + if (app) { + return app } return null @@ -42,6 +50,26 @@ export class EngineService { } private getId(): string { - return this.configService.get('engine.id') + return this.configService.get('app.id') + } + + /** Temporary migration function, converting the key-value format of the App config into the table format */ + async migrateV1Data(): Promise { + const appV1 = await this.engineRepository.findByIdV1(this.getId()) + const appV2 = await this.engineRepository.findById(this.getId()) + if (appV1 && !appV2) { + this.logger.log('Migrating App V1 data to V2') + const keyring = this.configService.get('keyring') + const app = Engine.parse({ + id: appV1.id, + adminApiKeyHash: appV1.adminApiKey, + encryptionMasterKey: appV1.masterKey, + encryptionKeyringType: appV1.masterKey ? 'raw' : 'awskms', + encryptionMasterAwsKmsArn: keyring.type === 'awskms' ? keyring.encryptionMasterAwsKmsArn : null, + authDisabled: false + }) + await this.engineRepository.save(app) + this.logger.log('App V1 data migrated to V2 Successfully') + } } } diff --git a/apps/policy-engine/src/engine/core/service/evaluation.service.ts b/apps/policy-engine/src/engine/core/service/evaluation.service.ts index 36feea796..2bea62f9a 100644 --- a/apps/policy-engine/src/engine/core/service/evaluation.service.ts +++ b/apps/policy-engine/src/engine/core/service/evaluation.service.ts @@ -1,11 +1,11 @@ import { TraceService } from '@narval/nestjs-shared' import { Action, Decision, EvaluationRequest, EvaluationResponse } from '@narval/policy-engine-shared' -import { Payload, SigningAlg, hash, nowSeconds, signJwt } from '@narval/signature' +import { Payload, hash, nowSeconds, signJwt } from '@narval/signature' import { HttpStatus, Inject, Injectable } from '@nestjs/common' +import { ClientService } from '../../../client/core/service/client.service' import { ApplicationException } from '../../../shared/exception/application.exception' import { OpenPolicyAgentEngineFactory } from '../factory/open-policy-agent-engine.factory' import { buildTransactionRequestHashWildcard } from '../util/wildcard-transaction-fields.util' -import { ClientService } from './client.service' import { SigningService } from './signing.service.interface' export async function buildPermitTokenPayload(clientId: string, evaluation: EvaluationResponse): Promise { @@ -105,7 +105,7 @@ export class EvaluationService { }) } - if (!client.signer?.publicKey) { + if (!client.decisionAttestation?.signer?.publicKey) { throw new ApplicationException({ message: 'Client signer is not configured', suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, @@ -151,9 +151,9 @@ export class EvaluationService { const jwt = await signJwt( jwtPayload, - client.signer.publicKey, - { alg: SigningAlg.EIP191 }, - this.signingService.buildSignerEip191(client.signer, evaluation.sessionId) + client.decisionAttestation.signer.publicKey, + { alg: client.decisionAttestation.signer.alg }, + this.signingService.buildSignerEip191(client.decisionAttestation.signer, evaluation.sessionId) // TODO: non-EIP191 ) buildAccessTokenSpan.end() diff --git a/apps/policy-engine/src/engine/core/service/provision.service.ts b/apps/policy-engine/src/engine/core/service/provision.service.ts index e44e98f67..f32cfce39 100644 --- a/apps/policy-engine/src/engine/core/service/provision.service.ts +++ b/apps/policy-engine/src/engine/core/service/provision.service.ts @@ -1,6 +1,7 @@ import { ConfigService } from '@narval/config-module' -import { generateKeyEncryptionKey, generateMasterKey } from '@narval/encryption-module' +import { decryptMasterKey, generateKeyEncryptionKey, generateMasterKey } from '@narval/encryption-module' import { LoggerService } from '@narval/nestjs-shared' +import { toBytes } from '@narval/policy-engine-shared' import { Injectable } from '@nestjs/common' import { Config } from '../../../policy-engine.config' import { Engine } from '../../../shared/type/domain.type' @@ -20,65 +21,141 @@ export class ProvisionService { private logger: LoggerService ) {} - // NOTE: The `adminApiKeyHash` argument is for test convinience in case it + // Provision the application if it's not already provisioned. + // Update configuration if needed. + // 1. Check if we have an App reference; App is initialized once. + // 2. Check if we have Encryption set up; Encryption is initialized once. + // 3. Auth can be updated, so change it if it's changed. + + // NOTE: The `adminApiKeyHash` argument is for test convenience in case it // needs to provision the application. async provision(adminApiKeyHash?: string): Promise { - const engine = await this.engineService.getEngine() - - const isNotProvisioned = !engine || !engine.adminApiKey - - if (isNotProvisioned) { - this.logger.log('Start app provision') - const provisionedEngine: Engine = await this.withMasterKey(engine || { id: this.getId() }) - - const apiKey = adminApiKeyHash || this.getAdminApiKeyHash() - - if (apiKey) { - return this.engineService.save({ - ...provisionedEngine, - adminApiKey: apiKey - }) + return this.run({ + adminApiKeyHash, + setupEncryption: async (app, thisApp, keyring) => { + await this.setupEncryption(app, thisApp, keyring) + await this.verifyRawEncryption(thisApp, keyring) } + }) + } - return this.engineService.save(provisionedEngine) - } + /** + * Core provisioning logic that sets up or updates the application + * configuration. This includes handling encryption setup and admin + * authentication settings. + * + * @param params Configuration parameters for the provisioning process + * + * @param params.adminApiKeyHash Optional hash of the admin API key for + * authentication + * + * @param params.setupEncryption Optional callback to customize encryption + * setup. Receives current app state, new app config, and keyring + * configuration. **Useful for disabling encryption during tests.** + * + * @returns Promise The provisioned application configuration + * + * @throws ProvisionException If app is already provisioned with different ID + * or if encryption setup fails + */ + protected async run(params: { + adminApiKeyHash?: string + setupEncryption?: (app: Engine | null, thisApp: Engine, keyring: Config['keyring']) => Promise + }): Promise { + const { adminApiKeyHash, setupEncryption } = params + + // TEMPORARY: Migrate the key-value format of the App config into the table format. + // Can be removed once this runs once. + await this.engineService.migrateV1Data() + + // Actually provision the new one; will not overwrite anything if this started from a migration + const app = await this.engineService.getEngine() + const keyring = this.configService.get('keyring') - this.logger.log('App already provisioned') + const thisApp: Engine = { ...(app || { id: this.getId(), encryptionKeyringType: keyring.type }) } + if (app && app.id !== this.getId()) { + throw new ProvisionException('App already provisioned with a different ID', { + current: this.getId(), + saved: app.id + }) + } - return engine - } + if (setupEncryption) { + await setupEncryption(app, thisApp, keyring) + } - private async withMasterKey(engine: Engine): Promise { - if (engine.masterKey) { - this.logger.log('Skip master key set up because it already exists') + // Now set the Auth if needed + thisApp.adminApiKeyHash = adminApiKeyHash || this.getAdminApiKeyHash() || null // fallback to null so we _unset_ it if it's not provided. - return engine + // If we have an app already & the adminApiKeyHash has changed, just log that we're changing it. + if (app && thisApp.adminApiKeyHash !== app?.adminApiKeyHash) { + this.logger.log('Admin API Key has been changed', { + previous: app?.adminApiKeyHash, + current: thisApp.adminApiKeyHash + }) } - const keyring = this.configService.get('keyring') - - if (keyring.type === 'raw') { - this.logger.log('Generate and save engine master key') + // Check if we disabled all auth + thisApp.authDisabled = this.configService.get('app.auth.disabled') + if (thisApp.authDisabled) { + thisApp.adminApiKeyHash = null + } - const { masterPassword } = keyring - const kek = generateKeyEncryptionKey(masterPassword, this.getId()) - const masterKey = await generateMasterKey(kek) + this.logger.log('App configuration saved') - return { ...engine, masterKey } - } else if (keyring.type === 'awskms' && keyring.masterAwsKmsArn) { - this.logger.log('Using AWS KMS for encryption') + return this.engineService.save(thisApp) + } - return engine - } else { - throw new ProvisionException('Unsupported keyring type') + protected async setupEncryption(app: Engine | null, thisApp: Engine, keyring: Config['keyring']) { + // No encryption set up yet, so initialize encryption + if (!app?.encryptionKeyringType || (!app.encryptionMasterKey && !app.encryptionMasterAwsKmsArn)) { + thisApp.encryptionKeyringType = keyring.type + + if (keyring.type === 'awskms' && keyring.encryptionMasterAwsKmsArn) { + this.logger.log('Using AWS KMS for encryption') + thisApp.encryptionMasterAwsKmsArn = keyring.encryptionMasterAwsKmsArn + } else if (keyring.type === 'raw') { + // If we have the masterKey set in config, we'll save that. + // Otherwise, we'll generate a new one. + if (keyring.encryptionMasterKey) { + this.logger.log('Using provided master key') + thisApp.encryptionMasterKey = keyring.encryptionMasterKey + } else { + this.logger.log('Generating master encryption key') + const { encryptionMasterPassword } = keyring + const kek = generateKeyEncryptionKey(encryptionMasterPassword, thisApp.id) + const masterKey = await generateMasterKey(kek) // Encrypted master encryption key + thisApp.encryptionMasterKey = masterKey + } + } else { + throw new ProvisionException('Unsupported keyring type') + } } } - private getAdminApiKeyHash(): string | undefined { - return this.configService.get('engine.adminApiKeyHash') + protected async verifyRawEncryption(thisApp: Engine, keyring: Config['keyring']) { + // if raw encryption, verify the encryptionMasterPassword in config is the valid kek for the encryptionMasterKey + if (thisApp?.encryptionKeyringType === 'raw' && keyring.type === 'raw' && thisApp.encryptionMasterKey) { + try { + const kek = generateKeyEncryptionKey(keyring.encryptionMasterPassword, thisApp.id) + await decryptMasterKey(kek, toBytes(thisApp.encryptionMasterKey)) + this.logger.log('Master Encryption Key Verified') + } catch (error) { + this.logger.error( + 'Master Encryption Key Verification Failed; check the encryptionMasterPassword is the one that encrypted the masterKey', + { error } + ) + throw new ProvisionException('Master Encryption Key Verification Failed', { error }) + } + } } + private getAdminApiKeyHash(): string | null | undefined { + const localAuth = this.configService.get('app.auth.local') + + return localAuth?.adminApiKeyHash + } private getId(): string { - return this.configService.get('engine.id') + return this.configService.get('app.id') } } diff --git a/apps/policy-engine/src/engine/engine.module.ts b/apps/policy-engine/src/engine/engine.module.ts index 937cec0e8..3577f11f8 100644 --- a/apps/policy-engine/src/engine/engine.module.ts +++ b/apps/policy-engine/src/engine/engine.module.ts @@ -1,55 +1,30 @@ import { ConfigService } from '@narval/config-module' -import { EncryptionModule } from '@narval/encryption-module' -import { HttpModule, LoggerService } from '@narval/nestjs-shared' +import { HttpModule } from '@narval/nestjs-shared' import { Module, ValidationPipe } from '@nestjs/common' import { APP_INTERCEPTOR, APP_PIPE } from '@nestjs/core' import { ZodSerializerInterceptor, ZodValidationPipe } from 'nestjs-zod' -import { EncryptionModuleOptionFactory } from '../shared/factory/encryption-module-option.factory' +import { ClientModule } from '../client/client.module' import { AdminApiKeyGuard } from '../shared/guard/admin-api-key.guard' import { KeyValueModule } from '../shared/module/key-value/key-value.module' +import { PersistenceModule } from '../shared/module/persistence/persistence.module' import { AppController } from './app.controller' -import { DataStoreRepositoryFactory } from './core/factory/data-store-repository.factory' import { OpenPolicyAgentEngineFactory } from './core/factory/open-policy-agent-engine.factory' import { signingServiceFactory } from './core/factory/signing-service.factory' -import { BootstrapService } from './core/service/bootstrap.service' -import { ClientService } from './core/service/client.service' -import { DataStoreService } from './core/service/data-store.service' import { EngineService } from './core/service/engine.service' import { EvaluationService } from './core/service/evaluation.service' -import { ProvisionService } from './core/service/provision.service' -import { ClientController } from './http/rest/controller/client.controller' import { EvaluationController } from './http/rest/controller/evaluation.controller' -import { ProvisionController } from './http/rest/controller/provision.controller' -import { ClientRepository } from './persistence/repository/client.repository' import { EngineRepository } from './persistence/repository/engine.repository' -import { FileSystemDataStoreRepository } from './persistence/repository/file-system-data-store.repository' -import { HttpDataStoreRepository } from './persistence/repository/http-data-store.repository' @Module({ - imports: [ - HttpModule.register(), - KeyValueModule, - EncryptionModule.registerAsync({ - imports: [EngineModule], - inject: [ConfigService, EngineService, LoggerService], - useClass: EncryptionModuleOptionFactory - }) - ], - controllers: [ProvisionController, AppController, ClientController, EvaluationController], + imports: [HttpModule.register(), PersistenceModule, KeyValueModule, ClientModule], + controllers: [AppController, EvaluationController], providers: [ AdminApiKeyGuard, - BootstrapService, - ClientRepository, - ClientService, - DataStoreRepositoryFactory, - DataStoreService, + OpenPolicyAgentEngineFactory, EngineRepository, EngineService, EvaluationService, - FileSystemDataStoreRepository, - HttpDataStoreRepository, - OpenPolicyAgentEngineFactory, - ProvisionService, + { provide: 'SigningService', useFactory: signingServiceFactory, @@ -69,6 +44,6 @@ import { HttpDataStoreRepository } from './persistence/repository/http-data-stor useClass: ZodSerializerInterceptor } ], - exports: [EngineService, ProvisionService, BootstrapService] + exports: [EngineService] }) export class EngineModule {} diff --git a/apps/policy-engine/src/engine/http/rest/controller/provision.controller.ts b/apps/policy-engine/src/engine/http/rest/controller/provision.controller.ts deleted file mode 100644 index fd3705da5..000000000 --- a/apps/policy-engine/src/engine/http/rest/controller/provision.controller.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { secret } from '@narval/nestjs-shared' -import { Controller, Post } from '@nestjs/common' -import { ApiExcludeController } from '@nestjs/swagger' -import { EngineService } from '../../../core/service/engine.service' - -type Response = - | { state: 'ACTIVATED' } - | { - state: 'READY' - app: { - appId: string - adminApiKey?: string - } - } - -@Controller({ - path: '/apps/activate', - version: '1' -}) -@ApiExcludeController() -export class ProvisionController { - constructor(private engineService: EngineService) {} - - @Post() - async activate(): Promise { - const engine = await this.engineService.getEngineOrThrow() - - if (engine.adminApiKey) { - return { state: 'ACTIVATED' } - } - - const adminApiKey = secret.generate() - - await this.engineService.save({ - ...engine, - adminApiKey: secret.hash(adminApiKey) - }) - - return { - state: 'READY', - app: { - appId: engine.id, - adminApiKey - } - } - } -} diff --git a/apps/policy-engine/src/engine/persistence/repository/__test__/unit/client.repository.spec.ts b/apps/policy-engine/src/engine/persistence/repository/__test__/integration/client.repository.spec.ts similarity index 64% rename from apps/policy-engine/src/engine/persistence/repository/__test__/unit/client.repository.spec.ts rename to apps/policy-engine/src/engine/persistence/repository/__test__/integration/client.repository.spec.ts index 71aeea7d8..f24781e65 100644 --- a/apps/policy-engine/src/engine/persistence/repository/__test__/unit/client.repository.spec.ts +++ b/apps/policy-engine/src/engine/persistence/repository/__test__/integration/client.repository.spec.ts @@ -1,25 +1,14 @@ import { EncryptionModule } from '@narval/encryption-module' -import { - Action, - Criterion, - DataStoreConfiguration, - EntityStore, - FIXTURE, - HttpSource, - PolicyStore, - SourceType, - Then -} from '@narval/policy-engine-shared' -import { Alg, getPublicKey, privateKeyToJwk } from '@narval/signature' +import { Action, Criterion, EntityStore, FIXTURE, PolicyStore, Then } from '@narval/policy-engine-shared' import { Test } from '@nestjs/testing' -import { generatePrivateKey } from 'viem/accounts' +import { ClientRepository } from '../../../../../client/persistence/repository/client.repository' import { KeyValueRepository } from '../../../../../shared/module/key-value/core/repository/key-value.repository' import { EncryptKeyValueService } from '../../../../../shared/module/key-value/core/service/encrypt-key-value.service' import { KeyValueService } from '../../../../../shared/module/key-value/core/service/key-value.service' import { InMemoryKeyValueRepository } from '../../../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' +import { PrismaService } from '../../../../../shared/module/persistence/service/prisma.service' +import { TestPrismaService } from '../../../../../shared/module/persistence/service/test-prisma.service' import { getTestRawAesKeyring } from '../../../../../shared/testing/encryption.testing' -import { Client } from '../../../../../shared/type/domain.type' -import { ClientRepository } from '../../client.repository' describe(ClientRepository.name, () => { let repository: ClientRepository @@ -43,6 +32,10 @@ describe(ClientRepository.name, () => { { provide: KeyValueRepository, useValue: inMemoryKeyValueRepository + }, + { + provide: PrismaService, + useValue: TestPrismaService } ] }).compile() @@ -50,51 +43,6 @@ describe(ClientRepository.name, () => { repository = module.get(ClientRepository) }) - describe('save', () => { - const now = new Date() - - const dataStoreSource: HttpSource = { - type: SourceType.HTTP, - url: 'a-url-that-doesnt-need-to-exist-for-the-purpose-of-this-test' - } - - const dataStoreConfiguration: DataStoreConfiguration = { - data: dataStoreSource, - signature: dataStoreSource, - keys: [getPublicKey(privateKeyToJwk(generatePrivateKey(), Alg.ES256K))] - } - - const client: Client = { - clientId, - clientSecret: 'test-client-secret', - signer: { - privateKey: privateKeyToJwk(generatePrivateKey(), Alg.ES256K) - }, - dataStore: { - entity: dataStoreConfiguration, - policy: dataStoreConfiguration - }, - createdAt: now, - updatedAt: now - } - - it('saves a new client', async () => { - await repository.save(client) - - const value = await inMemoryKeyValueRepository.get(repository.getKey(client.clientId)) - const actualClient = await repository.findById(client.clientId) - - expect(value).not.toEqual(null) - expect(client).toEqual(actualClient) - }) - - it('indexes the new client', async () => { - await repository.save(client) - - expect(await repository.getClientListIndex()).toEqual([client.clientId]) - }) - }) - describe('saveEntityStore', () => { const store: EntityStore = { data: FIXTURE.ENTITIES, diff --git a/apps/policy-engine/src/engine/persistence/repository/__test__/unit/engine.repository.spec.ts b/apps/policy-engine/src/engine/persistence/repository/__test__/unit/engine.repository.spec.ts deleted file mode 100644 index dc514e314..000000000 --- a/apps/policy-engine/src/engine/persistence/repository/__test__/unit/engine.repository.spec.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { Test } from '@nestjs/testing' -import { KeyValueRepository } from '../../../../../shared/module/key-value/core/repository/key-value.repository' -import { KeyValueService } from '../../../../../shared/module/key-value/core/service/key-value.service' -import { InMemoryKeyValueRepository } from '../../../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository' -import { Engine } from '../../../../../shared/type/domain.type' -import { EngineRepository } from '../../engine.repository' - -describe(EngineRepository.name, () => { - let repository: EngineRepository - let inMemoryKeyValueRepository: InMemoryKeyValueRepository - - beforeEach(async () => { - inMemoryKeyValueRepository = new InMemoryKeyValueRepository() - - const module = await Test.createTestingModule({ - providers: [ - KeyValueService, - EngineRepository, - { - provide: KeyValueRepository, - useValue: inMemoryKeyValueRepository - } - ] - }).compile() - - repository = module.get(EngineRepository) - }) - - const engine: Engine = { - id: 'test-engine-id', - adminApiKey: 'unsafe-test-admin-api-key', - masterKey: 'unsafe-test-master-key' - } - - describe('save', () => { - it('saves a new engine', async () => { - await repository.save(engine) - - const value = await inMemoryKeyValueRepository.get(repository.getEngineKey(engine.id)) - const actualEngine = await repository.findById(engine.id) - - expect(value).not.toEqual(null) - expect(engine).toEqual(actualEngine) - }) - }) -}) diff --git a/apps/policy-engine/src/engine/persistence/repository/client.repository.ts b/apps/policy-engine/src/engine/persistence/repository/client.repository.ts deleted file mode 100644 index d6beec0d6..000000000 --- a/apps/policy-engine/src/engine/persistence/repository/client.repository.ts +++ /dev/null @@ -1,121 +0,0 @@ -import { coerce } from '@narval/nestjs-shared' -import { EntityStore, PolicyStore } from '@narval/policy-engine-shared' -import { Injectable } from '@nestjs/common' -import { compact } from 'lodash/fp' -import { z } from 'zod' -import { EncryptKeyValueService } from '../../../shared/module/key-value/core/service/encrypt-key-value.service' -import { Client } from '../../../shared/type/domain.type' - -const ClientListIndex = z.array(z.string()) - -@Injectable() -export class ClientRepository { - constructor(private encryptKeyValueService: EncryptKeyValueService) {} - - async findById(clientId: string): Promise { - const value = await this.encryptKeyValueService.get(this.getKey(clientId)) - - if (value) { - return coerce.decode(Client, value) - } - - return null - } - - async save(client: Client): Promise { - await this.encryptKeyValueService.set(this.getKey(client.clientId), coerce.encode(Client, client)) - await this.index(client) - - return client - } - - async getClientListIndex(): Promise { - const index = await this.encryptKeyValueService.get(this.getIndexKey()) - - if (index) { - return coerce.decode(ClientListIndex, index) - } - - return [] - } - - async saveEntityStore(clientId: string, store: EntityStore): Promise { - return this.encryptKeyValueService.set(this.getEntityStoreKey(clientId), coerce.encode(EntityStore, store)) - } - - async findEntityStore(clientId: string): Promise { - const value = await this.encryptKeyValueService.get(this.getEntityStoreKey(clientId)) - - if (value) { - return coerce.decode(EntityStore, value) - } - - return null - } - - async savePolicyStore(clientId: string, store: PolicyStore): Promise { - return this.encryptKeyValueService.set(this.getPolicyStoreKey(clientId), coerce.encode(PolicyStore, store)) - } - - async findPolicyStore(clientId: string): Promise { - const value = await this.encryptKeyValueService.get(this.getPolicyStoreKey(clientId)) - - if (value) { - return coerce.decode(PolicyStore, value) - } - - return null - } - - // TODO: (@wcalderipe, 07/03/24) we need to rethink this strategy. If we use a - // SQL database, this could generate a massive amount of queries; thus, - // degrading the performance. - // - // An option is to move these general queries `findBy`, findAll`, etc to the - // KeyValeuRepository implementation letting each implementation pick the best - // strategy to solve the problem (e.g. where query in SQL) - async findAll(): Promise { - const ids = await this.getClientListIndex() - const clients = await Promise.all(ids.map((id) => this.findById(id))) - - return compact(clients) - } - - async clear(): Promise { - try { - const ids = await this.getClientListIndex() - await Promise.all(ids.map((id) => this.encryptKeyValueService.delete(id))) - - return true - } catch { - return false - } - } - - getKey(clientId: string): string { - return `client:${clientId}` - } - - getIndexKey(): string { - return 'client:list-index' - } - - getEntityStoreKey(clientId: string): string { - return `client:${clientId}:entity-store` - } - - getPolicyStoreKey(clientId: string): string { - return `client:${clientId}:policy-store` - } - - private async index(client: Client): Promise { - const currentIndex = await this.getClientListIndex() - - await this.encryptKeyValueService.set( - this.getIndexKey(), - coerce.encode(ClientListIndex, [...currentIndex, client.clientId]) - ) - - return true - } -} diff --git a/apps/policy-engine/src/engine/persistence/repository/engine.repository.ts b/apps/policy-engine/src/engine/persistence/repository/engine.repository.ts index 21a2253d9..177927c50 100644 --- a/apps/policy-engine/src/engine/persistence/repository/engine.repository.ts +++ b/apps/policy-engine/src/engine/persistence/repository/engine.repository.ts @@ -1,28 +1,75 @@ import { coerce } from '@narval/nestjs-shared' import { Injectable } from '@nestjs/common' import { KeyValueService } from '../../../shared/module/key-value/core/service/key-value.service' -import { Engine } from '../../../shared/type/domain.type' +import { PrismaService } from '../../../shared/module/persistence/service/prisma.service' +import { Engine, EngineV1 } from '../../../shared/type/domain.type' @Injectable() export class EngineRepository { - constructor(private keyValueService: KeyValueService) {} + constructor( + private keyValueService: KeyValueService, + private prismaService: PrismaService + ) {} - async findById(id: string): Promise { + /** @deprecated */ + async findByIdV1(id: string): Promise { const value = await this.keyValueService.get(this.getEngineKey(id)) if (value) { - return coerce.decode(Engine, value) + return coerce.decode(EngineV1, value) + } + + return null + } + + async findById(id: string): Promise { + const value = await this.prismaService.engine.findUnique({ where: { id } }) + + if (value) { + return Engine.parse(value) } return null } + async findAll(): Promise { + const values = await this.prismaService.engine.findMany() + + return values.map((value) => Engine.parse(value)) + } + + /** @deprecated */ + async saveV1(engine: EngineV1): Promise { + await this.keyValueService.set(this.getEngineKey(engine.id), coerce.encode(EngineV1, engine)) + + return engine + } + async save(engine: Engine): Promise { - await this.keyValueService.set(this.getEngineKey(engine.id), coerce.encode(Engine, engine)) + const engineData = { + id: engine.id, + encryptionKeyringType: engine.encryptionKeyringType, + encryptionMasterKey: engine.encryptionMasterKey, + encryptionMasterAwsKmsArn: engine.encryptionMasterAwsKmsArn, + authDisabled: !!engine.authDisabled, + adminApiKeyHash: engine.adminApiKeyHash + } + + // You cannot update the encryption details; that will cause data corruption. + // Key rotation must be a separate process. + await this.prismaService.engine.upsert({ + where: { id: engine.id }, + update: { + authDisabled: engine.authDisabled, + adminApiKeyHash: engine.adminApiKeyHash + }, + create: engineData + }) return engine } + /** @deprecated */ getEngineKey(id: string): string { return `engine:${id}` } diff --git a/apps/policy-engine/src/policy-engine.config.ts b/apps/policy-engine/src/policy-engine.config.ts index 7f87429f4..96ec458e4 100644 --- a/apps/policy-engine/src/policy-engine.config.ts +++ b/apps/policy-engine/src/policy-engine.config.ts @@ -1,3 +1,8 @@ +import { LoggerService } from '@narval/nestjs-shared' +import { privateKeySchema, publicKeySchema, SigningAlg } from '@narval/signature' +import fs from 'fs' +import path from 'path' +import { parse } from 'yaml' import { z } from 'zod' export enum Env { @@ -6,71 +11,283 @@ export enum Env { PRODUCTION = 'production' } -const configSchema = z.object({ - env: z.nativeEnum(Env), - port: z.coerce.number(), - cors: z.array(z.string()).optional(), - resourcePath: z.string(), - database: z.object({ - url: z.string().startsWith('postgresql:') - }), - engine: z.object({ - id: z.string(), - adminApiKeyHash: z.string().optional(), - masterKey: z.string().optional() +const CONFIG_VERSION_LATEST = '1' +const logger = new LoggerService() + +const AppLocalAuthConfigSchema = z.object({ + adminApiKeyHash: z.string().nullable().optional() + // TODO: Add the app-level httpSigning section: +}) + +const LocalAuthConfigSchema = z.object({ + clientSecret: z.string().nullish() +}) + +const AuthConfigSchema = z.object({ + disabled: z.boolean().optional(), + local: LocalAuthConfigSchema.nullable().optional() +}) + +const DataStoreConfigSchema = z.object({ + entity: z.object({ + data: z.object({ + type: z.enum(['HTTP', 'HTTPS']), + url: z.string() + }), + signature: z.object({ + type: z.enum(['HTTP', 'HTTPS']), + url: z.string() + }), + publicKeys: z.array(publicKeySchema) }), - keyring: z.union([ - z.object({ - type: z.literal('raw'), - masterPassword: z.string() + policy: z.object({ + data: z.object({ + type: z.enum(['HTTP', 'HTTPS']), + url: z.string() }), - z.object({ - type: z.literal('awskms'), - masterAwsKmsArn: z.string() + signature: z.object({ + type: z.enum(['HTTP', 'HTTPS']), + url: z.string() + }), + publicKeys: z.array(publicKeySchema) + }) +}) + +const SignerConfigSchema = z.object({ + alg: z.nativeEnum(SigningAlg).optional(), + keyId: z.string().optional(), + publicKey: publicKeySchema.optional(), + privateKey: privateKeySchema.optional() +}) + +const ClientConfigSchema = z.object({ + name: z.string(), + baseUrl: z.string().optional(), + auth: AuthConfigSchema, + dataStore: DataStoreConfigSchema, + decisionAttestation: z.object({ + disabled: z.boolean().optional(), + signer: SignerConfigSchema.optional() + }) +}) +const PolicyEngineConfigSchema = z.object({ + version: z.coerce.string(), + env: z.nativeEnum(Env).nullish(), + port: z.coerce.number().nullish(), + cors: z.array(z.string()).nullish(), + baseUrl: z.string().nullish(), + resourcePath: z.string().nullish(), + app: z + .object({ + id: z.string(), + auth: z.object({ + disabled: z.boolean(), + local: AppLocalAuthConfigSchema.nullable() + }) + }) + .nullish(), + database: z + .object({ + url: z.string() + }) + .nullish(), + keyring: z + .object({ + type: z.enum(['raw', 'awskms']), + encryptionMasterPassword: z.string().nullable().optional(), + encryptionMasterKey: z.string().nullable().optional(), + encryptionMasterAwsKmsArn: z.string().nullable().optional(), + hmacSecret: z.string().nullable().optional() }) - ]), - signingProtocol: z.union([z.literal('simple'), z.literal('mpc')]).default('simple'), - tsm: z + .nullish(), + decisionAttestation: z .object({ - url: z.string(), - apiKey: z.string(), - playerCount: z.coerce.number().default(3) + protocol: z.union([z.literal('simple'), z.literal('mpc')]).nullish(), + tsm: z + .object({ + url: z.string(), + apiKey: z.string(), + playerCount: z.coerce.number().default(3) + }) + .nullish() + .describe('Only required when protocol is mpc. The TSM SDK node config.') }) - .optional() - .describe('Only required when signingProtocol is mpc. The TSM SDK node config.') + .nullish(), + clients: z.record(z.string(), ClientConfigSchema).nullish() }) -export type Config = z.infer +const keyringSchema = z.union([ + z.object({ + type: z.literal('raw'), + encryptionMasterPassword: z.string(), + encryptionMasterKey: z.string().nullable(), + hmacSecret: z.string().nullable() + }), + z.object({ + type: z.literal('awskms'), + encryptionMasterAwsKmsArn: z.string(), + hmacSecret: z.string().nullable() + }) +]) -export const load = (): Config => { - const result = configSchema.safeParse({ - env: process.env.NODE_ENV, - port: process.env.PORT, - cors: process.env.CORS ? process.env.CORS.split(',') : [], - resourcePath: process.env.RESOURCE_PATH, +const LoadConfig = PolicyEngineConfigSchema.transform((yaml, ctx) => { + const appId = process.env.APP_UID || yaml.app?.id + const databaseUrl = process.env.APP_DATABASE_URL || yaml.database?.url + const env = z.nativeEnum(Env).parse(process.env.NODE_ENV || yaml.env) + const port = process.env.PORT || yaml.port + const baseUrl = process.env.BASE_URL || yaml.baseUrl + const resourcePath = process.env.RESOURCE_PATH || yaml.resourcePath + + if (!appId) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'APP_UID is required' + }) + return z.NEVER + } + if (!databaseUrl) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'APP_DATABASE_URL is required' + }) + return z.NEVER + } + if (!port) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'PORT is required' + }) + return z.NEVER + } + if (!baseUrl) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'BASE_URL is required' + }) + return z.NEVER + } + if (!resourcePath) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'RESOURCE_PATH is required' + }) + return z.NEVER + } + + // TODO: add Clients + + // process.env.SIGNING_PROTOCOL is for backwards-compatibility + const signingProtocol = + process.env.SIGNING_PROTOCOL || + process.env.DECISION_ATTESTATION_PROTOCOL || + yaml.decisionAttestation?.protocol || + null + let tsmConfig = null + if (signingProtocol === 'mpc') { + const tsmUrl = process.env.TSM_URL || yaml.decisionAttestation?.tsm?.url + const tsmApiKey = process.env.TSM_API_KEY || yaml.decisionAttestation?.tsm?.apiKey + const tsmPlayerCount = process.env.TSM_PLAYER_COUNT || yaml.decisionAttestation?.tsm?.playerCount + if (!tsmUrl || !tsmApiKey || !tsmPlayerCount) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: + 'TSM_URL, TSM_API_KEY, and TSM_PLAYER_COUNT are required when attestation is enabled and signingProtocol is mpc' + }) + return z.NEVER + } + tsmConfig = { + url: tsmUrl, + apiKey: tsmApiKey, + playerCount: z.coerce.number().parse(tsmPlayerCount) + } + } + + const clients = Object.entries(yaml.clients || {}).map(([clientId, client]) => ({ + clientId, + name: client.name, + baseUrl: client.baseUrl || null, + configurationSource: 'declarative', + auth: { + disabled: !!client.auth.disabled, + local: client.auth.local + ? { + clientSecret: client.auth.local.clientSecret || null + } + : null + }, + dataStore: client.dataStore, + decisionAttestation: client.decisionAttestation + ? { + disabled: !!client.decisionAttestation.disabled, + signer: { + alg: client.decisionAttestation.signer?.alg || SigningAlg.EIP191, + keyId: client.decisionAttestation.signer?.keyId || null, + publicKey: client.decisionAttestation.signer?.publicKey || undefined, + privateKey: client.decisionAttestation.signer?.privateKey || undefined + } + } + : { disabled: true } + })) + + return { + version: yaml.version || CONFIG_VERSION_LATEST, + env, + port, + cors: z.array(z.string()).parse(process.env.CORS || yaml.cors || []), + baseUrl, + resourcePath, database: { - url: process.env.APP_DATABASE_URL + url: databaseUrl }, - engine: { - id: process.env.APP_UID, - adminApiKeyHash: process.env.ADMIN_API_KEY, - masterKey: process.env.MASTER_KEY + + app: { + id: appId, + auth: { + disabled: yaml.app?.auth.disabled || false, + local: + yaml.app?.auth.local || process.env.ADMIN_API_KEY + ? { + adminApiKeyHash: yaml.app?.auth.local?.adminApiKeyHash || process.env.ADMIN_API_KEY || null + } + : null + } }, - keyring: { - type: process.env.KEYRING_TYPE, - masterAwsKmsArn: process.env.MASTER_AWS_KMS_ARN, - masterPassword: process.env.MASTER_PASSWORD + keyring: keyringSchema.parse({ + type: process.env.KEYRING_TYPE || yaml.keyring?.type, + encryptionMasterPassword: process.env.MASTER_PASSWORD || yaml.keyring?.encryptionMasterPassword || null, + encryptionMasterKey: process.env.MASTER_KEY || yaml.keyring?.encryptionMasterKey || null, + encryptionMasterAwsKmsArn: process.env.MASTER_AWS_KMS_ARN || yaml.keyring?.encryptionMasterAwsKmsArn || null, + hmacSecret: process.env.HMAC_SECRET || yaml.keyring?.hmacSecret || null + }), + decisionAttestation: { + protocol: signingProtocol, + tsm: tsmConfig }, - signingProtocol: process.env.SIGNING_PROTOCOL, - tsm: - process.env.SIGNING_PROTOCOL === 'mpc' - ? { - url: process.env.TSM_URL, - apiKey: process.env.TSM_API_KEY, - playerCount: process.env.TSM_PLAYER_COUNT - } - : undefined - }) + clients + } +}) + +export type Config = z.infer + +export const load = (): Config => { + const configFilePathEnv = process.env.CONFIG_FILE_ABSOLUTE_PATH + const configFileRelativePathEnv = process.env.CONFIG_FILE_RELATIVE_PATH + const filePath = configFilePathEnv + ? path.resolve(configFilePathEnv) + : path.resolve(process.cwd(), configFileRelativePathEnv || 'config/policy-engine-config.yaml') + let yamlConfigRaw = {} + try { + if (fs.existsSync(filePath)) { + const fileContents = fs.readFileSync(filePath, 'utf8') + yamlConfigRaw = parse(fileContents) + } + // If file doesn't exist, we'll use empty object as default + } catch (error) { + logger.warn(`Warning: Could not read config file at ${filePath}: ${error.message}`) + // Continue with empty config + } + + const result = LoadConfig.safeParse(yamlConfigRaw) if (result.success) { return result.data @@ -78,3 +295,7 @@ export const load = (): Config => { throw new Error(`Invalid application configuration: ${result.error.message}`) } + +export const getEnv = (): Env => { + return z.nativeEnum(Env).parse(process.env.NODE_ENV) +} diff --git a/apps/policy-engine/src/policy-engine.module.ts b/apps/policy-engine/src/policy-engine.module.ts index f5037ee11..a8eafb763 100644 --- a/apps/policy-engine/src/policy-engine.module.ts +++ b/apps/policy-engine/src/policy-engine.module.ts @@ -1,45 +1,53 @@ -import { ConfigModule, ConfigService } from '@narval/config-module' -import { EncryptionModule } from '@narval/encryption-module' -import { - HttpLoggerMiddleware, - LoggerModule, - LoggerService, - OpenTelemetryModule, - TrackClientIdMiddleware -} from '@narval/nestjs-shared' -import { - MiddlewareConsumer, - Module, - NestModule, - OnApplicationBootstrap, - OnModuleInit, - ValidationPipe -} from '@nestjs/common' +import { ConfigModule } from '@narval/config-module' +import { EncryptionService } from '@narval/encryption-module' +import { HttpLoggerMiddleware, LoggerModule, OpenTelemetryModule, TrackClientIdMiddleware } from '@narval/nestjs-shared' +import { MiddlewareConsumer, Module, NestModule, OnModuleInit, ValidationPipe } from '@nestjs/common' import { APP_PIPE } from '@nestjs/core' import { ZodValidationPipe } from 'nestjs-zod' -import { BootstrapService } from './engine/core/service/bootstrap.service' +import { ClientModule } from './client/client.module' import { EngineService } from './engine/core/service/engine.service' import { ProvisionService } from './engine/core/service/provision.service' import { EngineModule } from './engine/engine.module' +import { EngineRepository } from './engine/persistence/repository/engine.repository' import { load } from './policy-engine.config' -import { EncryptionModuleOptionFactory } from './shared/factory/encryption-module-option.factory' +import { KeyValueModule } from './shared/module/key-value/key-value.module' +import { PersistenceModule } from './shared/module/persistence/persistence.module' const INFRASTRUCTURE_MODULES = [ LoggerModule, ConfigModule.forRoot({ load: [load], - isGlobal: true - }), - EncryptionModule.registerAsync({ - imports: [EngineModule, LoggerModule], - inject: [ConfigService, EngineService, LoggerService], - useClass: EncryptionModuleOptionFactory + isGlobal: true, + cache: true }), OpenTelemetryModule.forRoot() ] @Module({ - imports: [...INFRASTRUCTURE_MODULES, EngineModule], + imports: [ + PersistenceModule.register({ + imports: [] // Specifically erase the imports, so we do NOT initialize the EncryptionModule + }), + KeyValueModule + ], + providers: [EngineRepository, EngineService, ProvisionService, { provide: EncryptionService, useValue: undefined }], + exports: [EngineService, ProvisionService] +}) +export class AppModule implements NestModule { + configure(consumer: MiddlewareConsumer): void { + consumer.apply(HttpLoggerMiddleware).forRoutes('*') + } +} + +@Module({ + imports: [ + ...INFRASTRUCTURE_MODULES, + AppModule, + PersistenceModule.forRoot(), + // Domain + EngineModule, + ClientModule + ], providers: [ { // DEPRECATE: Use Zod generated DTOs to validate request and responses. @@ -52,16 +60,10 @@ const INFRASTRUCTURE_MODULES = [ } ] }) -export class PolicyEngineModule implements OnApplicationBootstrap, NestModule { - constructor(private bootstrapService: BootstrapService) {} - +export class PolicyEngineModule implements NestModule { configure(consumer: MiddlewareConsumer): void { consumer.apply(HttpLoggerMiddleware, TrackClientIdMiddleware).forRoutes('*') } - - async onApplicationBootstrap() { - await this.bootstrapService.boot() - } } // IMPORTANT: To avoid application failure on the first boot due to a missing @@ -75,7 +77,7 @@ export class PolicyEngineModule implements OnApplicationBootstrap, NestModule { // context, dependencies requiring encryption will fail because the keyring was // already set as undefined. @Module({ - imports: [...INFRASTRUCTURE_MODULES, EngineModule] + imports: [...INFRASTRUCTURE_MODULES, AppModule] }) export class ProvisionModule implements OnModuleInit { constructor(private provisionService: ProvisionService) {} diff --git a/apps/policy-engine/src/shared/factory/encryption-module-option.factory.ts b/apps/policy-engine/src/shared/factory/encryption-module-option.factory.ts index 17b2499c9..ebd23a6c4 100644 --- a/apps/policy-engine/src/shared/factory/encryption-module-option.factory.ts +++ b/apps/policy-engine/src/shared/factory/encryption-module-option.factory.ts @@ -36,12 +36,12 @@ export class EncryptionModuleOptionFactory { } if (keyringConfig.type === 'raw') { - if (!engine.masterKey) { + if (!engine.encryptionMasterKey) { throw new Error('Master key not set') } - const kek = generateKeyEncryptionKey(keyringConfig.masterPassword, engine.id) - const unencryptedMasterKey = await decryptMasterKey(kek, toBytes(engine.masterKey)) + const kek = generateKeyEncryptionKey(keyringConfig.encryptionMasterPassword, engine.id) + const unencryptedMasterKey = await decryptMasterKey(kek, toBytes(engine.encryptionMasterKey)) return { keyring: new RawAesKeyringNode({ @@ -53,7 +53,7 @@ export class EncryptionModuleOptionFactory { } } else if (keyringConfig.type === 'awskms') { // We have AWS KMS config so we'll use that instead as the MasterKey, which means we don't need a KEK separately - const keyring = new KmsKeyringNode({ generatorKeyId: keyringConfig.masterAwsKmsArn }) + const keyring = new KmsKeyringNode({ generatorKeyId: keyringConfig.encryptionMasterAwsKmsArn }) return { keyring } } diff --git a/apps/policy-engine/src/shared/guard/__test__/unit/admin-api-key.guard.spec.ts b/apps/policy-engine/src/shared/guard/__test__/unit/admin-api-key.guard.spec.ts index 81f6cfb2c..a3ad1d864 100644 --- a/apps/policy-engine/src/shared/guard/__test__/unit/admin-api-key.guard.spec.ts +++ b/apps/policy-engine/src/shared/guard/__test__/unit/admin-api-key.guard.spec.ts @@ -3,6 +3,7 @@ import { ExecutionContext } from '@nestjs/common' import { mock } from 'jest-mock-extended' import { EngineService } from '../../../../engine/core/service/engine.service' import { ApplicationException } from '../../../exception/application.exception' +import { Engine } from '../../../type/domain.type' import { AdminApiKeyGuard } from '../../admin-api-key.guard' describe(AdminApiKeyGuard.name, () => { @@ -20,11 +21,12 @@ describe(AdminApiKeyGuard.name, () => { } const mockEngineService = (adminApiKey = 'test-admin-api-key') => { - const engine = { - adminApiKey: secret.hash(adminApiKey), + const engine: Engine = { + adminApiKeyHash: secret.hash(adminApiKey), id: 'test-engine-id', - masterKey: 'test-master-key', - activated: true + encryptionKeyringType: 'raw', + encryptionMasterKey: 'test-master-key', + authDisabled: false } const serviceMock = mock() diff --git a/apps/policy-engine/src/shared/guard/__test__/unit/client-secret.guard.spec.ts b/apps/policy-engine/src/shared/guard/__test__/unit/client-secret.guard.spec.ts index 28686f509..d7a2a3c25 100644 --- a/apps/policy-engine/src/shared/guard/__test__/unit/client-secret.guard.spec.ts +++ b/apps/policy-engine/src/shared/guard/__test__/unit/client-secret.guard.spec.ts @@ -1,10 +1,10 @@ import { REQUEST_HEADER_CLIENT_ID, REQUEST_HEADER_CLIENT_SECRET, secret } from '@narval/nestjs-shared' import { HttpSource, SourceType } from '@narval/policy-engine-shared' -import { Alg, privateKeyToJwk } from '@narval/signature' +import { Alg, SigningAlg, privateKeyToJwk, secp256k1PrivateKeyToPublicJwk } from '@narval/signature' import { ExecutionContext } from '@nestjs/common' import { mock } from 'jest-mock-extended' import { generatePrivateKey } from 'viem/accounts' -import { ClientService } from '../../../../engine/core/service/client.service' +import { ClientService } from '../../../../client/core/service/client.service' import { ApplicationException } from '../../../exception/application.exception' import { Client } from '../../../type/domain.type' import { ClientSecretGuard } from '../../client-secret.guard' @@ -32,9 +32,18 @@ describe(ClientSecretGuard.name, () => { url: 'http://9.9.9.9:99/test-data-store' } + const clientSignerKey = generatePrivateKey() const client: Client = { clientId: CLIENT_ID, - clientSecret: secret.hash(clientSecret), + name: 'test-client', + configurationSource: 'dynamic', + baseUrl: null, + auth: { + disabled: false, + local: { + clientSecret: secret.hash(clientSecret) + } + }, dataStore: { entity: { data: dataStoreSource, @@ -47,8 +56,14 @@ describe(ClientSecretGuard.name, () => { keys: [] } }, - signer: { - privateKey: privateKeyToJwk(generatePrivateKey(), Alg.ES256K) + decisionAttestation: { + disabled: false, + signer: { + alg: SigningAlg.EIP191, + keyId: 'test-key-id', + publicKey: secp256k1PrivateKeyToPublicJwk(clientSignerKey), + privateKey: privateKeyToJwk(clientSignerKey, Alg.ES256K) + } }, updatedAt: new Date(), createdAt: new Date() diff --git a/apps/policy-engine/src/shared/guard/admin-api-key.guard.ts b/apps/policy-engine/src/shared/guard/admin-api-key.guard.ts index c035fccc5..752619095 100644 --- a/apps/policy-engine/src/shared/guard/admin-api-key.guard.ts +++ b/apps/policy-engine/src/shared/guard/admin-api-key.guard.ts @@ -20,6 +20,6 @@ export class AdminApiKeyGuard implements CanActivate { const engine = await this.engineService.getEngineOrThrow() - return engine.adminApiKey === secret.hash(apiKey) + return engine.adminApiKeyHash === secret.hash(apiKey) } } diff --git a/apps/policy-engine/src/shared/guard/client-secret.guard.ts b/apps/policy-engine/src/shared/guard/client-secret.guard.ts index a718cd0e7..070c62e2e 100644 --- a/apps/policy-engine/src/shared/guard/client-secret.guard.ts +++ b/apps/policy-engine/src/shared/guard/client-secret.guard.ts @@ -1,6 +1,6 @@ import { REQUEST_HEADER_CLIENT_ID, REQUEST_HEADER_CLIENT_SECRET, secret } from '@narval/nestjs-shared' import { CanActivate, ExecutionContext, HttpStatus, Injectable } from '@nestjs/common' -import { ClientService } from '../../engine/core/service/client.service' +import { ClientService } from '../../client/core/service/client.service' import { ApplicationException } from '../exception/application.exception' @Injectable() @@ -26,6 +26,6 @@ export class ClientSecretGuard implements CanActivate { const client = await this.clientService.findById(clientId) - return client?.clientSecret === secret.hash(clientSecret) + return client?.auth.local?.clientSecret === secret.hash(clientSecret) } } diff --git a/apps/policy-engine/src/shared/module/key-value/key-value.module.ts b/apps/policy-engine/src/shared/module/key-value/key-value.module.ts index 2a652b8d4..56912675b 100644 --- a/apps/policy-engine/src/shared/module/key-value/key-value.module.ts +++ b/apps/policy-engine/src/shared/module/key-value/key-value.module.ts @@ -3,7 +3,7 @@ import { EncryptionModule } from '@narval/encryption-module' import { LoggerService } from '@narval/nestjs-shared' import { Module, forwardRef } from '@nestjs/common' import { EngineService } from '../../../engine/core/service/engine.service' -import { EngineModule } from '../../../engine/engine.module' +import { AppModule } from '../../../policy-engine.module' import { EncryptionModuleOptionFactory } from '../../factory/encryption-module-option.factory' import { PersistenceModule } from '../persistence/persistence.module' import { KeyValueRepository } from './core/repository/key-value.repository' @@ -14,9 +14,11 @@ import { PrismaKeyValueRepository } from './persistence/repository/prisma-key-va @Module({ imports: [ - PersistenceModule, + PersistenceModule.register({ + imports: [] // Specifically erase the imports, so we do NOT initialize the EncryptionModule + }), EncryptionModule.registerAsync({ - imports: [forwardRef(() => EngineModule)], + imports: [forwardRef(() => AppModule)], inject: [ConfigService, EngineService, LoggerService], useClass: EncryptionModuleOptionFactory }) diff --git a/apps/policy-engine/src/shared/module/persistence/exception/parse.exception.ts b/apps/policy-engine/src/shared/module/persistence/exception/parse.exception.ts new file mode 100644 index 000000000..2ff485b9f --- /dev/null +++ b/apps/policy-engine/src/shared/module/persistence/exception/parse.exception.ts @@ -0,0 +1,11 @@ +import { PersistenceException } from './persistence.exception' + +export class ParseException extends PersistenceException { + readonly origin: Error + + constructor(origin: Error) { + super(origin.message) + + this.origin = origin + } +} diff --git a/apps/policy-engine/src/shared/module/persistence/exception/persistence.exception.ts b/apps/policy-engine/src/shared/module/persistence/exception/persistence.exception.ts new file mode 100644 index 000000000..b0faa3fc9 --- /dev/null +++ b/apps/policy-engine/src/shared/module/persistence/exception/persistence.exception.ts @@ -0,0 +1 @@ +export class PersistenceException extends Error {} diff --git a/apps/policy-engine/src/shared/module/persistence/persistence.module.ts b/apps/policy-engine/src/shared/module/persistence/persistence.module.ts index 95d5dcd4c..10ec85878 100644 --- a/apps/policy-engine/src/shared/module/persistence/persistence.module.ts +++ b/apps/policy-engine/src/shared/module/persistence/persistence.module.ts @@ -1,9 +1,43 @@ -import { Module } from '@nestjs/common' +import { ConfigService } from '@narval/config-module' +import { EncryptionModule } from '@narval/encryption-module' +import { LoggerService } from '@narval/nestjs-shared' +import { DynamicModule, ForwardReference, Module, Type, forwardRef } from '@nestjs/common' +import { EngineService } from '../../../engine/core/service/engine.service' +import { AppModule } from '../../../policy-engine.module' +import { EncryptionModuleOptionFactory } from '../../factory/encryption-module-option.factory' import { PrismaService } from './service/prisma.service' import { TestPrismaService } from './service/test-prisma.service' -@Module({ - exports: [PrismaService, TestPrismaService], - providers: [PrismaService, TestPrismaService] -}) -export class PersistenceModule {} +@Module({}) +export class PersistenceModule { + static forRoot(): DynamicModule { + return { + module: PersistenceModule, + global: true, + imports: [ + EncryptionModule.registerAsync({ + imports: [forwardRef(() => AppModule)], + inject: [ConfigService, EngineService, LoggerService], + useClass: EncryptionModuleOptionFactory + }) + ], + providers: [PrismaService, TestPrismaService], + exports: [PrismaService, TestPrismaService] + } + } + + static register(config: { imports?: Array } = {}): DynamicModule { + return { + module: PersistenceModule, + imports: config.imports || [ + EncryptionModule.registerAsync({ + imports: [forwardRef(() => AppModule)], + inject: [ConfigService, EngineService, LoggerService], + useClass: EncryptionModuleOptionFactory + }) + ], + providers: [PrismaService, TestPrismaService], + exports: [PrismaService, TestPrismaService] + } + } +} diff --git a/apps/policy-engine/src/shared/module/persistence/schema/migrations/20250131164306_engine_db_normalization/migration.sql b/apps/policy-engine/src/shared/module/persistence/schema/migrations/20250131164306_engine_db_normalization/migration.sql new file mode 100644 index 000000000..9367e5011 --- /dev/null +++ b/apps/policy-engine/src/shared/module/persistence/schema/migrations/20250131164306_engine_db_normalization/migration.sql @@ -0,0 +1,41 @@ +/* + Warnings: + + - You are about to drop the column `admin_api_key` on the `engine` table. All the data in the column will be lost. + - You are about to drop the column `master_key` on the `engine` table. All the data in the column will be lost. + - Added the required column `encryption_keyring_type` to the `engine` table without a default value. This is not possible if the table is not empty. + +*/ +-- AlterTable +ALTER TABLE "engine" DROP COLUMN "admin_api_key", +DROP COLUMN "master_key", +ADD COLUMN "admin_api_key_hash" TEXT, +ADD COLUMN "auth_disabled" BOOLEAN, +ADD COLUMN "encryption_keyring_type" TEXT NOT NULL, +ADD COLUMN "encryption_master_aws_kms_arn" TEXT, +ADD COLUMN "encryption_master_key" TEXT; + +-- CreateTable +CREATE TABLE "client" ( + "client_id" TEXT NOT NULL, + "name" TEXT NOT NULL, + "configuration_source" TEXT NOT NULL, + "base_url" TEXT, + "auth_disabled" BOOLEAN NOT NULL, + "client_secret" TEXT, + "data_store_entity_data_url" TEXT NOT NULL, + "data_store_entity_signature_url" TEXT NOT NULL, + "data_store_entity_public_keys" TEXT NOT NULL, + "data_store_policy_data_url" TEXT NOT NULL, + "data_store_policy_signature_url" TEXT NOT NULL, + "data_store_policy_public_keys" TEXT NOT NULL, + "decision_attestation_disabled" BOOLEAN NOT NULL, + "signer_alg" TEXT, + "signer_key_id" TEXT, + "signer_public_key" TEXT, + "signer_private_key" TEXT, + "created_at" TIMESTAMP(3) NOT NULL, + "updated_at" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "client_pkey" PRIMARY KEY ("client_id") +); diff --git a/apps/policy-engine/src/shared/module/persistence/schema/migrations/20250131171229_client_hmac/migration.sql b/apps/policy-engine/src/shared/module/persistence/schema/migrations/20250131171229_client_hmac/migration.sql new file mode 100644 index 000000000..fde5828a6 --- /dev/null +++ b/apps/policy-engine/src/shared/module/persistence/schema/migrations/20250131171229_client_hmac/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "client" ADD COLUMN "_integrity" TEXT; diff --git a/apps/policy-engine/src/shared/module/persistence/schema/schema.prisma b/apps/policy-engine/src/shared/module/persistence/schema/schema.prisma index 3990d8226..cb33a69b1 100644 --- a/apps/policy-engine/src/shared/module/persistence/schema/schema.prisma +++ b/apps/policy-engine/src/shared/module/persistence/schema/schema.prisma @@ -14,12 +14,49 @@ datasource db { model Engine { id String @id - masterKey String? @map("master_key") - adminApiKey String? @map("admin_api_key") + // Encryption options, possibly set from Config file + encryptionKeyringType String @map("encryption_keyring_type") // raw | awskms + encryptionMasterKey String? @map("encryption_master_key") /// @encrypted by masterPassword KEK + encryptionMasterAwsKmsArn String? @map("encryption_master_aws_kms_arn") // only if type = awskms + // Auth Options, set from Config file + authDisabled Boolean? @map("auth_disabled") + adminApiKeyHash String? @map("admin_api_key_hash") /// hash, not plaintext @@map("engine") } +model Client { + clientId String @id @map("client_id") + name String @map("name") + configurationSource String @map("configuration_source") // declarative | dynamic + baseUrl String? @map("base_url") // If you want to override the used for verifying jwsd/httpsig + authDisabled Boolean @map("auth_disabled") + clientSecret String? @map("client_secret") /// hash, not plaintext + + // Data Store Config + dataStoreEntityDataUrl String @map("data_store_entity_data_url") + dataStoreEntitySignatureUrl String @map("data_store_entity_signature_url") + dataStoreEntityPublicKeys String @map("data_store_entity_public_keys") // stringified json array of public keys + dataStorePolicyDataUrl String @map("data_store_policy_data_url") + dataStorePolicySignatureUrl String @map("data_store_policy_signature_url") + dataStorePolicyPublicKeys String @map("data_store_policy_public_keys") // stringified json array of public keys + + + // Signer Config + decisionAttestationDisabled Boolean @map("decision_attestation_disabled") + signerAlg String? @map("signer_alg") + signerKeyId String? @map("signer_key_id") + signerPublicKey String? @map("signer_public_key") + signerPrivateKey String? @map("signer_private_key") + + createdAt DateTime @map("created_at") + updatedAt DateTime @map("updated_at") + + integrity String? @map("_integrity") + + @@map("client") +} + // TODO: (@wcalderipe, 12/03/23) use hstore extension for better performance. // See https://www.postgresql.org/docs/9.1/hstore.html model KeyValue { diff --git a/apps/policy-engine/src/shared/module/persistence/seed.ts b/apps/policy-engine/src/shared/module/persistence/seed.ts index 83c8585af..48750e260 100644 --- a/apps/policy-engine/src/shared/module/persistence/seed.ts +++ b/apps/policy-engine/src/shared/module/persistence/seed.ts @@ -1,22 +1,13 @@ /* eslint-disable */ import { LoggerService } from '@narval/nestjs-shared' -import { Engine, PrismaClient } from '@prisma/client/policy-engine' +import { PrismaClient } from '@prisma/client/policy-engine' const prisma = new PrismaClient() -const engine: Engine = { - id: '7d704a62-d15e-4382-a826-1eb41563043b', - adminApiKey: 'admin-api-key-xxx', - masterKey: 'master-key-xxx' -} - async function main() { const logger = new LoggerService() logger.log('Seeding Engine database') - await prisma.$transaction(async (txn) => { - // await txn.engine.create({ data: engine }) - }) logger.log('Engine database germinated 🌱') } diff --git a/apps/policy-engine/src/shared/module/persistence/service/prisma.service.ts b/apps/policy-engine/src/shared/module/persistence/service/prisma.service.ts index 7154fc3ba..f2163bd17 100644 --- a/apps/policy-engine/src/shared/module/persistence/service/prisma.service.ts +++ b/apps/policy-engine/src/shared/module/persistence/service/prisma.service.ts @@ -1,22 +1,345 @@ import { ConfigService } from '@narval/config-module' +import { EncryptionService } from '@narval/encryption-module' import { LoggerService } from '@narval/nestjs-shared' -import { Inject, Injectable, OnApplicationShutdown, OnModuleDestroy, OnModuleInit } from '@nestjs/common' -import { PrismaClient } from '@prisma/client/policy-engine' +import { Injectable, OnApplicationShutdown, OnModuleDestroy, OnModuleInit, Optional } from '@nestjs/common' +import { hmac } from '@noble/hashes/hmac' +import { sha256 } from '@noble/hashes/sha2' +import { bytesToHex } from '@noble/hashes/utils' +import { Prisma, PrismaClient } from '@prisma/client/policy-engine' +import { canonicalize } from 'packages/signature/src/lib/json.util' import { Config } from '../../../../policy-engine.config' +import { ParseException } from '../exception/parse.exception' + +const ENCRYPTION_PREFIX = 'enc.v1.' // Version prefix helps with future encryption changes +const INTEGRITY_PREFIX = 'hmac.v1.' // Version prefix helps with future integrity changes + +/** + * To encrypt a field, simply reference the Model as the key, and the fields in an array. + * NOTE: encrypted fields MUST be of string type. JSON data should be stringified before/after encryption/decryption; this assumes Strings. + */ +const encryptedModelFields = { + Client: [Prisma.ClientScalarFieldEnum.clientSecret, Prisma.ClientScalarFieldEnum.signerPrivateKey] +} + +const modelWithHmacIntegrity = { + Client: { + [Prisma.ClientScalarFieldEnum.clientId]: { + integrity: true, + nullable: false + }, + [Prisma.ClientScalarFieldEnum.name]: { + integrity: true, + nullable: false + }, + [Prisma.ClientScalarFieldEnum.configurationSource]: { + integrity: true, + nullable: false + }, + [Prisma.ClientScalarFieldEnum.baseUrl]: { + integrity: true, + nullable: true + }, + [Prisma.ClientScalarFieldEnum.authDisabled]: { + integrity: true, + nullable: false + }, + [Prisma.ClientScalarFieldEnum.clientSecret]: { + integrity: true, + nullable: true + }, + [Prisma.ClientScalarFieldEnum.dataStoreEntityDataUrl]: { + integrity: true, + nullable: false + }, + [Prisma.ClientScalarFieldEnum.dataStoreEntitySignatureUrl]: { + integrity: true, + nullable: false + }, + [Prisma.ClientScalarFieldEnum.dataStoreEntityPublicKeys]: { + integrity: true, + nullable: false + }, + [Prisma.ClientScalarFieldEnum.dataStorePolicyDataUrl]: { + integrity: true, + nullable: false + }, + [Prisma.ClientScalarFieldEnum.dataStorePolicySignatureUrl]: { + integrity: true, + nullable: false + }, + [Prisma.ClientScalarFieldEnum.dataStorePolicyPublicKeys]: { + integrity: true, + nullable: false + }, + [Prisma.ClientScalarFieldEnum.decisionAttestationDisabled]: { + integrity: true, + nullable: false + }, + [Prisma.ClientScalarFieldEnum.signerAlg]: { + integrity: true, + nullable: true + }, + [Prisma.ClientScalarFieldEnum.signerKeyId]: { + integrity: true, + nullable: true + }, + [Prisma.ClientScalarFieldEnum.signerPublicKey]: { + integrity: true, + nullable: true + }, + [Prisma.ClientScalarFieldEnum.signerPrivateKey]: { + integrity: true, + nullable: true + }, + [Prisma.ClientScalarFieldEnum.createdAt]: { + integrity: true, + nullable: false + }, + [Prisma.ClientScalarFieldEnum.updatedAt]: { + integrity: true, + nullable: false + } + } +} + +const getHmac = (secret: string, value: Record) => { + const integrity = hmac(sha256, secret, canonicalize(value)) + return `${INTEGRITY_PREFIX}${bytesToHex(integrity)}` +} + +const buildEncryptionExtension = ( + configService: ConfigService, + logger: LoggerService, + encryptionService: EncryptionService +) => { + // Generate the hmac + const hmacSecret = configService.get('keyring.hmacSecret') + if (!hmacSecret) { + logger.error('HMAC secret is not set, integrity verification will not be performed') + throw new Error('HMAC secret is not set, integrity verification will not be performed') + } + + const encryptToString = async (value: string) => { + const encryptedBuffer = await encryptionService.encrypt(value) + const encryptedString = encryptedBuffer.toString('hex') + return `${ENCRYPTION_PREFIX}${encryptedString}` + } + + const decryptToString = async (value: string) => { + if (!value.startsWith(ENCRYPTION_PREFIX)) { + return value + } + const decryptedBuffer = await encryptionService.decrypt(Buffer.from(value.slice(ENCRYPTION_PREFIX.length), 'hex')) + return decryptedBuffer.toString() + } + + return Prisma.defineExtension({ + name: 'encryption', + query: { + async $allOperations({ model, operation, args, query }) { + if (!model || !(model in encryptedModelFields)) { + return query(args) + } + const fields = encryptedModelFields[model as keyof typeof encryptedModelFields] + + // For write operations, encrypt. + const writeOps = ['create', 'upsert', 'update', 'updateMany', 'createMany'] + if (writeOps.includes(operation)) { + let dataToUpdate: Record[] = [] + if (operation === 'upsert') { + if (args.update) { + dataToUpdate.push(args.update) + } + if (args.create) { + dataToUpdate.push(args.create) + } + } else if (Array.isArray(args.data)) { + dataToUpdate = args.data + } else { + dataToUpdate = [args.data] + } + // For each field-to-encrypt, for each object being created, encrypt the field. + await Promise.all( + fields.map(async (field) => { + await Promise.all( + dataToUpdate.map(async (item: Record) => { + if (item[field] && typeof item[field] === 'string') { + item[field] = await encryptToString(item[field] as string) + } + }) + ) + }) + ) + // Data has been encrypted. + // Now, generate the _integrity hmac + // The data must include every field on the model; if not, we will reject this operation. + if (model in modelWithHmacIntegrity) { + const fields = modelWithHmacIntegrity[model as keyof typeof modelWithHmacIntegrity] + for (const data of dataToUpdate) { + // Create object to hold fields that should be covered by integrity + const integrityCovered: Record = {} + + // Iterate through all configured fields for this model + for (const [fieldName, fieldSettings] of Object.entries(fields)) { + // Check if field is required but missing + integrityCovered[fieldName] = data[fieldName] + if (!fieldSettings.nullable && data[fieldName] === undefined) { + logger.error(`Missing required field ${fieldName} in data, needed for integrity hmac`) + throw new Error(`Missing required field ${fieldName} in data, needed for integrity hmac`) + } + if (fieldSettings.nullable && !data[fieldName]) { + // Ensure we capture the null in the integrity object + integrityCovered[fieldName] = null + } + } + + const integrity = getHmac(hmacSecret, integrityCovered) + data.integrity = integrity + } + } + + return query(args) + } + + // For read operations, decrypt. + const readOps = ['findUnique', 'findMany', 'findUniqueOrThrow', 'findFirst', 'findFirstOrThrow'] as const + type ReadOp = (typeof readOps)[number] + + if (readOps.includes(operation as ReadOp)) { + const result = await query(args) + + // Handle non-record results + if (!result || typeof result === 'number' || 'count' in result) { + return result + } + + // Handle array or single result + const items = Array.isArray(result) ? result : [result] + + await Promise.all( + items.map(async (item: Record) => { + // If it has an `integrity` field, verify it's integrity + let skipIntegrityAndDecryption = false + if (model in modelWithHmacIntegrity) { + const fields = modelWithHmacIntegrity[model as keyof typeof modelWithHmacIntegrity] + // Create object to hold fields that should be covered by integrity + const integrityCovered: Record = {} + + // Iterate through all configured fields for this model + for (const [fieldName, fieldSettings] of Object.entries(fields)) { + integrityCovered[fieldName] = item[fieldName] + + // If there is an integrity field that is in args.select with `false` then skip integrity verification & decryption + if (fieldSettings.integrity && args.select && args.select[fieldName] === false) { + logger.log(`Skipping integrity verification & decryption due to subset of fields queried`) + skipIntegrityAndDecryption = true + return + } + + // Check if field is required but missing + if (!fieldSettings.nullable && item[fieldName] === undefined) { + logger.error( + `Missing required field ${fieldName} in data, needed for integrity hmac, did your query forget it?` + ) + throw new Error(`Missing required field ${fieldName} in data, needed for integrity hmac`) + } + } + + const integrityToVerify = getHmac(hmacSecret, integrityCovered) + if (integrityToVerify !== item.integrity) { + logger.error('Integrity verification failed', { + integrityToVerify, + item, + args + }) + throw new Error('Integrity verification failed') + } + } + // We passed integrity verification, so we can decrypt the fields + if (!skipIntegrityAndDecryption) { + await Promise.all( + fields.map(async (field) => { + if (item[field] && typeof item[field] === 'string') { + item[field] = await decryptToString(item[field] as string) + } + }) + ) + } + }) + ) + + return result + } + + return query(args) + } + } + }) +} @Injectable() export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy, OnApplicationShutdown { constructor( - @Inject(ConfigService) configService: ConfigService, - private logger: LoggerService + configService: ConfigService, + private logger: LoggerService, + @Optional() encryptionService?: EncryptionService ) { const url = configService.get('database.url') - super({ datasources: { db: { url } } }) + if (encryptionService) { + logger.log('Instantiating Prisma encryption extension') + Object.assign(this, this.$extends(buildEncryptionExtension(configService, logger, encryptionService))) + } + } + + static toPrismaJson(value?: T | null): Prisma.InputJsonValue | Prisma.NullTypes.JsonNull { + if (value === null || value === undefined) { + return Prisma.JsonNull + } + + // Handle basic JSON-serializable types. + if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean' || Array.isArray(value)) { + return value as Prisma.InputJsonValue + } + + // For objects, ensure they're JSON-serializable. + if (typeof value === 'object') { + try { + return JSON.parse(JSON.stringify(value)) as Prisma.InputJsonValue + } catch (error) { + throw new ParseException(error) + } + } + + return Prisma.JsonNull + } + + static toStringJson(value?: T | null): string | null { + if (value) { + try { + return JSON.stringify(value) + } catch (error) { + throw new ParseException(error) + } + } + + return null + } + + static toJson(value?: string | null) { + if (value) { + try { + return JSON.parse(value) + } catch (error) { + throw new ParseException(error) + } + } + + return null } async onModuleInit() { @@ -40,7 +363,7 @@ export class PrismaService extends PrismaClient implements OnModuleInit, OnModul onApplicationShutdown(signal: string) { this.logger.log('Disconnecting from Prisma on application shutdown', signal) - // The $disconnect method returns a promise, so idealy we should wait for it + // The $disconnect method returns a promise, so ideally we should wait for it // to finish. However, the onApplicationShutdown, returns `void` making it // impossible to ensure the database will be properly disconnected before // the shutdown. diff --git a/apps/policy-engine/src/shared/type/domain.type.ts b/apps/policy-engine/src/shared/type/domain.type.ts index b88529f8c..3bdb4ece9 100644 --- a/apps/policy-engine/src/shared/type/domain.type.ts +++ b/apps/policy-engine/src/shared/type/domain.type.ts @@ -1,5 +1,5 @@ import { DataStoreConfiguration } from '@narval/policy-engine-shared' -import { privateKeySchema, publicKeySchema } from '@narval/signature' +import { privateKeySchema, publicKeySchema, SigningAlg } from '@narval/signature' import { z } from 'zod' @@ -7,15 +7,46 @@ export const SignerFunction = z.function().args(z.string()).returns(z.promise(z. export type SignerFunction = z.infer export const SignerConfig = z.object({ + alg: z.nativeEnum(SigningAlg).default(SigningAlg.EIP191), // Temporarily default to EIP191 TODO: remove the default after migration from v1 data + keyId: z.string().nullable().describe('Unique id of the signer key. Matches the kid in both jwks'), publicKey: publicKeySchema.optional(), privateKey: privateKeySchema.optional(), - keyId: z.string().optional().describe('Unique id of the signer key. Matches the kid in both jwks'), signer: SignerFunction.optional() }) export type SignerConfig = z.infer export const Client = z.object({ + clientId: z.string(), + name: z.string(), + configurationSource: z.literal('declarative').or(z.literal('dynamic')), // Declarative = comes from config file, Dynamic = created at runtime + // Override if you want to use a different baseUrl for a single client. + baseUrl: z.string().nullable(), + + auth: z.object({ + disabled: z.boolean(), + local: z + .object({ + clientSecret: z.string().nullable() + }) + .nullable() + }), + + dataStore: z.object({ + entity: DataStoreConfiguration, + policy: DataStoreConfiguration + }), + + decisionAttestation: z.object({ + disabled: z.boolean(), + signer: SignerConfig.nullable() + }), + createdAt: z.coerce.date(), + updatedAt: z.coerce.date() +}) +export type Client = z.infer + +export const ClientV1 = z.object({ clientId: z.string(), clientSecret: z.string(), dataStore: z.object({ @@ -26,11 +57,56 @@ export const Client = z.object({ createdAt: z.coerce.date(), updatedAt: z.coerce.date() }) -export type Client = z.infer +export type ClientV1 = z.infer -export const Engine = z.object({ +export const PublicClient = z.object({ + clientId: z.string(), + name: z.string(), + configurationSource: z.literal('declarative').or(z.literal('dynamic')), // Declarative = comes from config file, Dynamic = created at runtime + baseUrl: z.string().nullable(), + + auth: z.object({ + disabled: z.boolean(), + local: z + .object({ + clientSecret: z.string().nullable() + }) + .nullable() + }), + + dataStore: z.object({ + entity: DataStoreConfiguration, + policy: DataStoreConfiguration + }), + + decisionAttestation: z.object({ + disabled: z.boolean(), + signer: z + .object({ + alg: z.nativeEnum(SigningAlg), + keyId: z.string().nullable().describe('Unique id of the signer key. Matches the kid in both jwks'), + publicKey: publicKeySchema.optional() + }) + .nullable() + }), + createdAt: z.coerce.date(), + updatedAt: z.coerce.date() +}) +export type PublicClient = z.infer + +export const EngineV1 = z.object({ id: z.string().min(1), adminApiKey: z.string().min(1).optional(), masterKey: z.string().min(1).optional() }) +export type EngineV1 = z.infer + +export const Engine = z.object({ + id: z.string().min(1), + adminApiKeyHash: z.string().min(1).nullish(), + encryptionMasterKey: z.string().min(1).nullish(), + encryptionKeyringType: z.literal('raw').or(z.literal('awskms')), + encryptionMasterAwsKmsArn: z.string().nullish(), + authDisabled: z.boolean().optional() +}) export type Engine = z.infer diff --git a/apps/vault/src/app.service.ts b/apps/vault/src/app.service.ts index 7a152af25..1ff07452c 100644 --- a/apps/vault/src/app.service.ts +++ b/apps/vault/src/app.service.ts @@ -56,7 +56,8 @@ export class AppService { /** Temporary migration function, converting the key-value format of the App config into the table format */ async migrateV1Data(): Promise { const appV1 = await this.appRepository.findByIdV1(this.getId()) - if (appV1) { + const appV2 = await this.appRepository.findById(this.getId()) + if (appV1 && !appV2) { this.logger.log('Migrating App V1 data to V2') const keyring = this.configService.get('keyring') const app = App.parse({ diff --git a/apps/vault/src/client/__test__/e2e/client.spec.ts b/apps/vault/src/client/__test__/e2e/client.spec.ts index 3f0b48822..720fb9b98 100644 --- a/apps/vault/src/client/__test__/e2e/client.spec.ts +++ b/apps/vault/src/client/__test__/e2e/client.spec.ts @@ -111,7 +111,7 @@ describe('Client', () => { .send(payload) expect(body.statusCode).toEqual(HttpStatus.BAD_REQUEST) - expect(body.message).toEqual('client already exist') + expect(body.message).toEqual('Client already exist') expect(status).toEqual(HttpStatus.BAD_REQUEST) }) diff --git a/apps/vault/src/client/core/service/client.service.ts b/apps/vault/src/client/core/service/client.service.ts index 0c02dc6f1..392d87bbf 100644 --- a/apps/vault/src/client/core/service/client.service.ts +++ b/apps/vault/src/client/core/service/client.service.ts @@ -71,7 +71,7 @@ export class ClientService { if (exists && exists.configurationSource === 'dynamic') { throw new ApplicationException({ - message: 'client already exist', + message: 'Client already exist', suggestedHttpStatusCode: HttpStatus.BAD_REQUEST, context: { clientId: client.clientId } }) diff --git a/apps/vault/src/main.config.ts b/apps/vault/src/main.config.ts index 6f865c101..4bbfa393a 100644 --- a/apps/vault/src/main.config.ts +++ b/apps/vault/src/main.config.ts @@ -277,7 +277,7 @@ const LoadConfig = VaultConfigSchema.transform((yaml, ctx) => { export type Config = z.output export const load = (): Config => { - const configFilePathEnv = process.env.CONFIG_FILE + const configFilePathEnv = process.env.CONFIG_FILE_ABSOLUTE_PATH const configFileRelativePathEnv = process.env.CONFIG_FILE_RELATIVE_PATH const filePath = configFilePathEnv ? path.resolve(configFilePathEnv) diff --git a/apps/vault/src/provision.service.ts b/apps/vault/src/provision.service.ts index 76e9c671f..b007741a0 100644 --- a/apps/vault/src/provision.service.ts +++ b/apps/vault/src/provision.service.ts @@ -27,14 +27,14 @@ export class ProvisionService { // 2. Check if we have Encryption set up; Encryption is initialized once. // 3. Auth can be updated, so change it if it's changed. - // NOTE: The `adminApiKeyHash` argument is for test convinience in case it + // NOTE: The `adminApiKeyHash` argument is for test convenience in case it // needs to provision the application. async provision(adminApiKeyHash?: string): Promise { return this.run({ adminApiKeyHash, setupEncryption: async (app, thisApp, keyring) => { await this.setupEncryption(app, thisApp, keyring) - await this.setupRawEncryption(thisApp, keyring) + await this.verifyRawEncryption(thisApp, keyring) } }) } @@ -133,7 +133,7 @@ export class ProvisionService { } } - protected async setupRawEncryption(thisApp: App, keyring: Config['keyring']) { + protected async verifyRawEncryption(thisApp: App, keyring: Config['keyring']) { // if raw encryption, verify the encryptionMasterPassword in config is the valid kek for the encryptionMasterKey if (thisApp?.encryptionKeyringType === 'raw' && keyring.type === 'raw' && thisApp.encryptionMasterKey) { try { diff --git a/apps/vault/src/shared/type/domain.type.ts b/apps/vault/src/shared/type/domain.type.ts index fe1c735d4..64b4f6feb 100644 --- a/apps/vault/src/shared/type/domain.type.ts +++ b/apps/vault/src/shared/type/domain.type.ts @@ -95,7 +95,7 @@ export type ClientV1 = z.infer export const Client = z.object({ clientId: z.string(), name: z.string(), - configurationSource: z.literal('declarative').or(z.literal('dynamic')), // Declarative = comes from config file, Dyanmic = created at runtime + configurationSource: z.literal('declarative').or(z.literal('dynamic')), // Declarative = comes from config file, Dynamic = created at runtime backupPublicKey: rsaPublicKeySchema.nullable(), // Override if you want to use a different baseUrl for a single client. baseUrl: z.string().nullable(), diff --git a/config/policy-engine-config.example.yaml b/config/policy-engine-config.example.yaml new file mode 100644 index 000000000..f912992d7 --- /dev/null +++ b/config/policy-engine-config.example.yaml @@ -0,0 +1,168 @@ +# Policy Engine config.yaml, v1 + +##### +# THIS FILE CONTAINS SECRETS; DO NOT COMMIT OUR CONFIG TO SOURCE CONTROL. +##### + +# Config File Version +version: '1' + +# Core service configuration +env: development # Enum: development, test, production +port: 3010 +cors: [] +# Base URL where the Engine is deployed. Used to verify jwsd request signatures. +baseUrl: http://localhost:3010 +# Internal path to open-policy-agent resource files. Should always be this. Only change if you know what you're doing. +resourcePath: './apps/policy-engine/src/resource' + +# Application identity and security +app: + id: local-dev-engine-instance-1 + + auth: + # Disable all auth; only useful in dev + disabled: false + # Local authentication options, either signed requests or basic api key + local: + # [optional]: Sets the admin API key for client provisioning operations + # + # Key should be hashed, like this: `echo -n "engine-admin-api-key" | openssl dgst -sha256 | awk '{print $2}'` + # Plain text API key: engine-admin-api-key + adminApiKeyHash: 'dde1fba05d6b0b1a40f2cd9f480f6dcc37a6980bcff3db54377a46b056dc472c' + +# Encryption Key management configuration +keyring: + # Either "raw" or "awskms" + type: raw + # If type=raw: + # A master password that uses PBKDF2 to derive the Key Encryption Key (KEK) used to encrypt the master key. + encryptionMasterPassword: unsafe-local-dev-master-password + # If type=raw, you can set the master key to be used here. + # It must be an AES-256 key encoded as a hex string, encrypted by the KEK derived from the masterPassword. Ensure you wrap the string in quotes otherwise it will be interpreted as a number. + # If not set, it will be generated during first-boot. + encryptionMasterKey: '0x02057802bb22a3d6a22dd01bbb71238992e70830577198a972c97d681467f2575a55f8009800030003617070001861726d6f72792e656e6372797074696f6e2d6d6f64756c6500156177732d63727970746f2d7075626c69632d6b65790044413464467572374b485a7561566a2f5341384d6e4741324a706b52614a756d71386f4162374537735367344470534a317756726f4e6e6175586f796a6c6d384a72513d3d0007707572706f7365000f646174612d656e6372797074696f6e000100146e617276616c2e61726d6f72792e656e67696e65002561726d6f72792e656e67696e652e6b656b000000800000000cb65c5e0f2e79a2fe104c8f100030b4d4e54b0b481bbc7110101fccd9514906cbfbf32549ef9b1c4578c0d4e64ca5ee57ea534bfdcb5c0aaacd41c52dba8902000010004398f6b5221c1a59738bbbcfa23457d2df8180d1929124c8e6e70b95f4e86319c22e0d2dc620c9033dd10dd97c556efeffffffff00000001000000000000000000000001000000207e92b845f7374c08d155138746061a30a2991e5cdc14d420c389185c0631e6888cf7404e677af76f3b2d00ee348d1bda0067306502304a210311734831cc24b1536acf42a9c3f69221173de1a2610c98b2c678d573b3c475aab6a17bd83f25cc229740d720c4023100fbfedabec5166003ec6584dcecf871dae0d48b6031fe2931f8f3489081893f7c80e5fbbcf6e62c844fa8f41e2e1efe7f' + + # If type=awskms: + # The ARN of the AWS KMS key used as the Master Key. + encryptionMasterAwsKmsArn: null + + # HMAC secret for integrity verification of data in the database. Ensure you wrap the string in quotes otherwise it will be interpreted as a number. + hmacSecret: '4ce6d3404a13c971202693b669668e49e2d6d7e190428d0edd99d1cec1536efb' + +# Decision Attestation configuration +decisionAttestation: + protocol: simple # Either "simple" or "mpc" + + # Only required when protocol=mpc + # This is the TSM SDK node configuration & requires the private MPC library to be installed. + # tsm: + # url: https://tsm.example.com + # apiKey: tsm-api-key-here + # playerCount: 3 + +# Declarative clients (tenants) +clients: + # Each key is the client ID + dev-client-1: + name: 'Example Client' + # Override default baseUrl for this client, used for verifying domain-specific signatures + baseUrl: 'http://localhost:3010' # [optional] + + # Whether to identify the principal from the request authentication signature + # If false, the principal id is provided. + identifyPrincipalFromRequest: true # TODO: implement + + # The Client's Signer, used for generating the signatures on Policy Decisions. + decisionAttestation: + # Whether to turn off signed policy decisions + disabled: false + signer: + # [optional] The signing algorithm to sign with. Defaults to EIP191. + alg: 'EIP191' # or 'ES256K', 'ES256', 'EDDSA', 'RS256' #TODO: actually support the others! + # [optional] Unique identifier for the signer key. + # If only keyId is set, then the signing key will be generated using this for the kid. + keyId: 'key-2024-1' + # [optional] The public key for the signing key. Can not be used with `mpc` signing.protocol. + publicKey: + kid: 'key-2024-1' # If keyId is set, this should match. + kty: 'EC' + alg: 'ES256K' + crv: 'secp256k1' + x: 'kmDs8BM_h4YRZfUMGQhD5E9Ih8ZLOb6vdSx5aPVMdKY' + y: 'wqUIXS3YmZXxM_TRDUyTGE5pInwTJxCRtvRzjwRu32o' + # [optional] The private key for the signing key. Can not be used with `mpc` signing.protocol. + privateKey: + kid: 'key-2024-1' # If keyId is set, this should match. + kty: 'EC' + alg: 'ES256K' + crv: 'secp256k1' + x: 'kmDs8BM_h4YRZfUMGQhD5E9Ih8ZLOb6vdSx5aPVMdKY' + y: 'wqUIXS3YmZXxM_TRDUyTGE5pInwTJxCRtvRzjwRu32o' + d: 'hYCWM5W73pwRA0OqNKwMok8H1k_9OCxZOiYWhYI4b4Q' + + # TODO: Add jwt signing options here + + auth: + # Disable all auth; only useful in dev + disabled: false + # Local authentication options, either signed requests or basic api key + local: + # [optional] SHA256 hash of the client secret, passed in `x-client-secret` header + # echo -n "engine-client-secret" | openssl dgst -sha256 | awk '{print $2}' + # TODO: Do we even need this? + clientSecret: 'd8c56539ad31ecb12a1e7334b341a7b3d46dea0b076421add198325efb77f583' + + # TODO: Add other auth & token validation details here + + dataStore: + # Entity Data Store configuration - this is context data used in policy evaluation. + entity: + # The URL to fetch to load the Entity Data. It must include any authentication secrets in the url. + data: + type: HTTP # or HTTPS + # The dataSecret here must match the dataSecret in the Armory config.yaml + url: http://localhost:3005/v1/data/entities?clientId=client-123&dataSecret=data-secret-plaintext + # The URL to fetch for Signature of the Entity Data. + # Typically the same as the Data url, but possible to store the attestation signature separately. + signature: + type: HTTP # or HTTPS + # The dataSecret here must match the dataSecret in the Armory config.yaml + url: http://localhost:3005/v1/data/entities?clientId=client-123&dataSecret=data-secret-plaintext + # The pinned public keys for verifying the Entity signature + publicKeys: + - kid: 'data-key-1' # Must match the kid the signer puts in signature jwt header + kty: EC + crv: secp256k1 + alg: ES256K + use: sig + # Can use an evm-encoded address instead of x+y, if signing data w/ a wallet (e.g. Metamask) using EIP191 + addr: '0x04B12F0863b83c7162429f0Ebb0DfdA20E1aA97B' + # If you have the full public key, include the x+y even if also using Addr. + x: null + y: null + # Policy Data Store configuration - this is the policy set used for evaluation. + policy: + # The URL to fetch to load the Policy Data. It must include any authentication secrets in the url. + data: + type: HTTP # or HTTPS + # The dataSecret here must match the dataSecret in the Armory config.yaml + url: http://localhost:3005/v1/data/policies?clientId=client-123&dataSecret=data-secret-plaintext + # The URL to fetch for Signature of the Policy Data. + # Typically the same as the Data url, but possible to store the attestation signature separately. + signature: + type: HTTP # or HTTPS + # The dataSecret here must match the dataSecret in the Armory config.yaml + url: http://localhost:3005/v1/data/policies?clientId=client-123&dataSecret=data-secret-plaintext + # The pinned public keys for verifying the Policy signature + publicKeys: + - kid: 'data-key-1' # Must match the kid the signer puts in signature jwt header + kty: EC + crv: secp256k1 + alg: ES256K + use: sig + # Can use an evm-encoded address instead of x+y, if signing data w/ a wallet (e.g. Metamask) using EIP191 + addr: '0x04B12F0863b83c7162429f0Ebb0DfdA20E1aA97B' + # If you have the full public key, include the x+y even if also using Addr. + x: null + y: null diff --git a/config/policy-engine-config.template.yaml b/config/policy-engine-config.template.yaml new file mode 100644 index 000000000..b8c9b14e4 --- /dev/null +++ b/config/policy-engine-config.template.yaml @@ -0,0 +1,179 @@ +# Policy Engine config.yaml, v1 + +##### +# THIS FILE CONTAINS SECRETS; DO NOT COMMIT OUR CONFIG TO SOURCE CONTROL. +##### + +# Config File Version +version: '1' + +# Core service configuration +env: development # Enum: development, test, production +port: 3010 +cors: [] +# Base URL where the Engine is deployed. Used to verify jwsd request signatures. +baseUrl: http://localhost:3010 +# Internal path to open-policy-agent resource files. Should always be this. Only change if you know what you're doing. +resourcePath: './apps/policy-engine/src/resource' + +# Database configuration. +# database: +# url: postgresql://postgres:postgres@localhost:5432/engine?schema=public + +# Application identity and security +app: + id: local-dev-engine-instance-1 + + auth: + # Disable all auth; only useful in dev + disabled: false + # OIDC configuration to use an external auth provider + oidc: null + # Local authentication options, either signed requests or basic api key + local: + # [optional]: Sets the admin API key for client provisioning operations + # + # Key should be hashed, like this: `echo -n "engine-admin-api-key" | openssl dgst -sha256 | awk '{print $2}'` + # Plain text API key: engine-admin-api-key + adminApiKeyHash: 'dde1fba05d6b0b1a40f2cd9f480f6dcc37a6980bcff3db54377a46b056dc472c' + # Auth config for requests from this service + outgoing: null + +# Encryption Key management configuration +keyring: + # Either "raw" or "awskms" + type: raw + # If type=raw: + # A master password that uses PBKDF2 to derive the Key Encryption Key (KEK) used to encrypt the master key. + encryptionMasterPassword: unsafe-local-dev-master-password + # Encryption master key: + # - Required if type=raw + # - Must be an AES-256 key encoded as hex string + # - Must be encrypted by KEK derived from masterPassword + # - Must be quoted to prevent number interpretation + # - Will auto-generate on first-boot if not set + # encryptionMasterKey: "0x02057802bb22a3d6a22dd01bbb71238992e70830577198a972c97d681467f2575a55f8009800030003617070001861726d6f72792e656e6372797074696f6e2d6d6f64756c6500156177732d63727970746f2d7075626c69632d6b65790044413464467572374b485a7561566a2f5341384d6e4741324a706b52614a756d71386f4162374537735367344470534a317756726f4e6e6175586f796a6c6d384a72513d3d0007707572706f7365000f646174612d656e6372797074696f6e000100146e617276616c2e61726d6f72792e656e67696e65002561726d6f72792e656e67696e652e6b656b000000800000000cb65c5e0f2e79a2fe104c8f100030b4d4e54b0b481bbc7110101fccd9514906cbfbf32549ef9b1c4578c0d4e64ca5ee57ea534bfdcb5c0aaacd41c52dba8902000010004398f6b5221c1a59738bbbcfa23457d2df8180d1929124c8e6e70b95f4e86319c22e0d2dc620c9033dd10dd97c556efeffffffff00000001000000000000000000000001000000207e92b845f7374c08d155138746061a30a2991e5cdc14d420c389185c0631e6888cf7404e677af76f3b2d00ee348d1bda0067306502304a210311734831cc24b1536acf42a9c3f69221173de1a2610c98b2c678d573b3c475aab6a17bd83f25cc229740d720c4023100fbfedabec5166003ec6584dcecf871dae0d48b6031fe2931f8f3489081893f7c80e5fbbcf6e62c844fa8f41e2e1efe7f" + + # If type=awskms: + # The ARN of the AWS KMS key used as the Master Key. + encryptionMasterAwsKmsArn: null + + # HMAC secret for integrity verification of data in the database. Ensure you wrap the string in quotes otherwise it will be interpreted as a number. + hmacSecret: '4ce6d3404a13c971202693b669668e49e2d6d7e190428d0edd99d1cec1536efb' + +# Decision Attestation configuration +decisionAttestation: + protocol: simple # Either "simple" or "mpc" + + # Only required when protocol=mpc + # This is the TSM SDK node configuration & requires the private MPC library to be installed. + # tsm: + # url: https://tsm.example.com + # apiKey: tsm-api-key-here + # playerCount: 3 + +# Declarative clients (tenants) +clients: + # Each key is the client ID + dev-client-1: + name: 'Example Client' + # Override default baseUrl for this client, used for verifying domain-specific signatures + baseUrl: 'http://localhost:3010' # [optional] + + # Whether to identify the principal from the request authentication signature + # If false, the principal id is provided. + identifyPrincipalFromRequest: true # TODO: implement + + # The Client's Signer, used for generating the signatures on Policy Decisions. + decisionAttestation: + # Whether to turn off signed policy decisions + disabled: false + signer: + # [optional] The signing algorithm to sign with. Defaults to EIP191. + alg: 'EIP191' # or 'ES256K', 'ES256', 'EDDSA', 'RS256' #TODO: actually support the others! + # [optional] Unique identifier for the signer key. + # If only keyId is set, then the signing key will be generated using this for the kid. + keyId: 'key-2024-1' + # [optional] The public key for the signing key. Can not be used with `mpc` signing.protocol. + publicKey: + kid: 'key-2024-1' # If keyId is set, this should match. + kty: 'EC' + alg: 'ES256K' + crv: 'secp256k1' + x: 'kmDs8BM_h4YRZfUMGQhD5E9Ih8ZLOb6vdSx5aPVMdKY' + y: 'wqUIXS3YmZXxM_TRDUyTGE5pInwTJxCRtvRzjwRu32o' + # [optional] The private key for the signing key. Can not be used with `mpc` signing.protocol. + privateKey: + kid: 'key-2024-1' # If keyId is set, this should match. + kty: 'EC' + alg: 'ES256K' + crv: 'secp256k1' + x: 'kmDs8BM_h4YRZfUMGQhD5E9Ih8ZLOb6vdSx5aPVMdKY' + y: 'wqUIXS3YmZXxM_TRDUyTGE5pInwTJxCRtvRzjwRu32o' + d: 'hYCWM5W73pwRA0OqNKwMok8H1k_9OCxZOiYWhYI4b4Q' + + # TODO: Add jwt signing options here + + auth: + # Disable all auth; only useful in dev + disabled: false + # Local authentication options, either signed requests or basic api key + local: + # [optional] SHA256 hash of the client secret, passed in `x-client-secret` header + # echo -n "engine-client-secret" | openssl dgst -sha256 | awk '{print $2}' + # TODO: Remove; do we even need this? + clientSecret: 'd8c56539ad31ecb12a1e7334b341a7b3d46dea0b076421add198325efb77f583' + + # TODO: Add other auth & token validation details here + + dataStore: + # Entity Data Store configuration - this is context data used in policy evaluation. + entity: + # The URL to fetch to load the Entity Data. It must include any authentication secrets in the url. + data: + type: HTTP # or HTTPS + # The dataSecret here must match the dataSecret in the Armory config.yaml + url: http://localhost:3005/v1/data/entities?clientId=client-123&dataSecret=data-secret-plaintext + # The URL to fetch for Signature of the Entity Data. + # Typically the same as the Data url, but possible to store the attestation signature separately. + signature: + type: HTTP # or HTTPS + # The dataSecret here must match the dataSecret in the Armory config.yaml + url: http://localhost:3005/v1/data/entities?clientId=client-123&dataSecret=data-secret-plaintext + # The pinned public keys for verifying the Entity signature + publicKeys: + - kid: 'data-key-1' # Must match the kid the signer puts in signature jwt header + kty: EC + crv: secp256k1 + alg: ES256K + use: sig + # Can use an evm-encoded address instead of x+y, if signing data w/ a wallet (e.g. Metamask) using EIP191 + addr: '0x04B12F0863b83c7162429f0Ebb0DfdA20E1aA97B' + # If you have the full public key, include the x+y even if also using Addr. + x: null + y: null + # Policy Data Store configuration - this is the policy set used for evaluation. + policy: + # The URL to fetch to load the Policy Data. It must include any authentication secrets in the url. + data: + type: HTTP # or HTTPS + # The dataSecret here must match the dataSecret in the Armory config.yaml + url: http://localhost:3005/v1/data/policies?clientId=client-123&dataSecret=data-secret-plaintext + # The URL to fetch for Signature of the Policy Data. + # Typically the same as the Data url, but possible to store the attestation signature separately. + signature: + type: HTTP # or HTTPS + # The dataSecret here must match the dataSecret in the Armory config.yaml + url: http://localhost:3005/v1/data/policies?clientId=client-123&dataSecret=data-secret-plaintext + # The pinned public keys for verifying the Policy signature + publicKeys: + - kid: 'data-key-1' # Must match the kid the signer puts in signature jwt header + kty: EC + crv: secp256k1 + alg: ES256K + use: sig + # Can use an evm-encoded address instead of x+y, if signing data w/ a wallet (e.g. Metamask) using EIP191 + addr: '0x04B12F0863b83c7162429f0Ebb0DfdA20E1aA97B' + # If you have the full public key, include the x+y even if also using Addr. + x: null + y: null diff --git a/config/vault-config.example.yaml b/config/vault-config.example.yaml index 026dcac32..94a67dc62 100644 --- a/config/vault-config.example.yaml +++ b/config/vault-config.example.yaml @@ -17,7 +17,6 @@ baseUrl: http://localhost:3011 # Application identity and security app: id: local-dev-vault-instance-1 - # OPTIONAL: Sets the admin API key instead of generating a new one during the provision. auth: # Disable all auth; only useful in dev @@ -28,7 +27,7 @@ app: local: # [optional]: Sets the admin API key for client provisioning operations # - # Key should be hashed, like this: `echo -n "my-api-key" | openssl dgst -sha256 | awk '{print $2}'` + # Key should be hashed, like this: `echo -n "vault-admin-api-key" | openssl dgst -sha256 | awk '{print $2}'` # Plain text API key: vault-admin-api-key adminApiKeyHash: d4a6b4c1cb71dbdb68a1dd429ad737369f74b9e264b9dfa639258753987caaad # Auth config for requests from this service diff --git a/config/vault-config.template.yaml b/config/vault-config.template.yaml index 802583de3..08625613b 100644 --- a/config/vault-config.template.yaml +++ b/config/vault-config.template.yaml @@ -21,7 +21,6 @@ database: # Application identity and security app: id: local-dev-vault-instance-1 - # OPTIONAL: Sets the admin API key instead of generating a new one during the provision. auth: # Disable all auth; only useful in dev diff --git a/docker-compose.mpc.yml b/docker-compose.mpc.yml index d1633ad78..efd7fe49a 100644 --- a/docker-compose.mpc.yml +++ b/docker-compose.mpc.yml @@ -77,9 +77,11 @@ services: - TSM_API_KEY=apikey0 - TSM_PLAYER_COUNT=3 - ADMIN_API_KEY=dde1fba05d6b0b1a40f2cd9f480f6dcc37a6980bcff3db54377a46b056dc472c # engine-admin-api-key + - CONFIG_FILE_ABSOLUTE_PATH=/config/policy-engine-config.local.yaml volumes: - ./packages:/app/packages - ./apps:/app/apps + - ./config:/config depends_on: postgres: condition: service_healthy @@ -104,9 +106,11 @@ services: - TSM_API_KEY=apikey1 - TSM_PLAYER_COUNT=3 - ADMIN_API_KEY=dde1fba05d6b0b1a40f2cd9f480f6dcc37a6980bcff3db54377a46b056dc472c # engine-admin-api-key + - CONFIG_FILE_ABSOLUTE_PATH=/config/policy-engine-config.local.yaml volumes: - ./packages:/app/packages - ./apps:/app/apps + - ./config:/config depends_on: postgres: condition: service_healthy @@ -131,9 +135,11 @@ services: - TSM_API_KEY=apikey2 - TSM_PLAYER_COUNT=3 - ADMIN_API_KEY=dde1fba05d6b0b1a40f2cd9f480f6dcc37a6980bcff3db54377a46b056dc472c # engine-admin-api-key + - CONFIG_FILE_ABSOLUTE_PATH=/config/policy-engine-config.local.yaml volumes: - ./packages:/app/packages - ./apps:/app/apps + - ./config:/config depends_on: postgres: condition: service_healthy diff --git a/examples/approvals-by-spending-limit/0-create-client.ts b/examples/approvals-by-spending-limit/0-create-client.ts new file mode 100644 index 000000000..1aab4efbf --- /dev/null +++ b/examples/approvals-by-spending-limit/0-create-client.ts @@ -0,0 +1,66 @@ +/* eslint-disable no-console */ +import { AuthAdminClient } from '@narval-xyz/armory-sdk' +import { hexSchema } from '@narval-xyz/armory-sdk/policy-engine-shared' +import { secp256k1PrivateKeyToPublicJwk } from '@narval-xyz/armory-sdk/signature' +import { CreateClientRequestDtoDataStoreEntityDataOneOf1TypeEnum } from '@narval-xyz/armory-sdk/src/lib/http/client/auth' +import 'dotenv/config' + +/* +Use this to create a new Client. The URLs are set up for the docker network, so edit this if you're not using docker. +If you already have a Client, move on to `1-setup.ts`. +*/ + +const main = async () => { + console.log('🚀 Starting...\n') + const dataStoreSignerPrivateKey = hexSchema.parse(process.env.DATA_STORE_SIGNER_PRIVATE_KEY) + const adminApiKey = process.env.ADMIN_API_KEY + const vaultHost = process.env.VAULT_HOST + const authHost = process.env.AUTH_HOST + const clientId = process.env.CLIENT_ID + + if (!authHost || !vaultHost || !clientId || !adminApiKey) { + throw new Error('Missing configuration') + } + + const admin = new AuthAdminClient({ + host: authHost, + adminApiKey + }) + + const publicKey = secp256k1PrivateKeyToPublicJwk(dataStoreSignerPrivateKey, process.env.DATA_STORE_SIGNER_ADDRESS) + + const { clientSecret, policyEngine } = await admin.createClient({ + id: clientId, + name: 'Example - ASL2', + useManagedDataStore: true, + dataStore: { + entity: { + data: { + type: authHost.split(':')[0].toUpperCase() as CreateClientRequestDtoDataStoreEntityDataOneOf1TypeEnum, + url: `http://armory/data/policies?clientId=${clientId}` + }, + signature: { + type: authHost.split(':')[0].toUpperCase() as CreateClientRequestDtoDataStoreEntityDataOneOf1TypeEnum, + url: `http://armory/data/policies?clientId=${clientId}` + }, + keys: [publicKey] + }, + policy: { + data: { + type: authHost.split(':')[0].toUpperCase() as CreateClientRequestDtoDataStoreEntityDataOneOf1TypeEnum, + url: `http://armory/data/policies?clientId=${clientId}` + }, + signature: { + type: authHost.split(':')[0].toUpperCase() as CreateClientRequestDtoDataStoreEntityDataOneOf1TypeEnum, + url: `http://armory/data/policies?clientId=${clientId}` + }, + keys: [publicKey] + } + } + }) + console.log('clientSecret - PUT THIS IN YOUR .env', clientSecret) + + console.log('✅ Setup completed successfully \n') +} + +main().catch(console.error) diff --git a/packages/policy-engine-shared/src/lib/type/client.type.ts b/packages/policy-engine-shared/src/lib/type/client.type.ts index a053dce75..de19fae26 100644 --- a/packages/policy-engine-shared/src/lib/type/client.type.ts +++ b/packages/policy-engine-shared/src/lib/type/client.type.ts @@ -1,34 +1,6 @@ -import { privateKeySchema, publicKeySchema } from '@narval/signature' import { z } from 'zod' import { DataStoreConfiguration } from './data-store.type' -export const SignerConfig = z.object({ - publicKey: publicKeySchema.optional(), - privateKey: privateKeySchema.optional() -}) - -export type SignerConfig = z.infer - -export const Client = z.object({ - clientId: z.string(), - clientSecret: z.string(), - dataStore: z.object({ - entity: DataStoreConfiguration, - policy: DataStoreConfiguration - }), - signer: SignerConfig, - createdAt: z.coerce.date(), - updatedAt: z.coerce.date() -}) -export type Client = z.infer - -export const PublicClient = Client.extend({ - signer: z.object({ - publicKey: publicKeySchema - }) -}) -export type PublicClient = z.infer - export const CreateClient = z.object({ clientId: z.string().optional(), clientSecret: z From 10cd68925b176f85e9a9cce715728730acad16d2 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Tue, 4 Feb 2025 18:28:28 +0100 Subject: [PATCH 115/120] Fix authorization guard access check (#129) * Fix authorization guard access check * Fix JWT decode --- .../vault/src/shared/decorator/permission-guard.decorator.ts | 2 +- apps/vault/src/shared/guard/authorization.guard.ts | 4 ++-- packages/signature/src/lib/schemas.ts | 5 +++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/apps/vault/src/shared/decorator/permission-guard.decorator.ts b/apps/vault/src/shared/decorator/permission-guard.decorator.ts index 5c3234066..085974165 100644 --- a/apps/vault/src/shared/decorator/permission-guard.decorator.ts +++ b/apps/vault/src/shared/decorator/permission-guard.decorator.ts @@ -4,7 +4,7 @@ import { Reflector } from '@nestjs/core' import { AuthorizationGuard } from '../guard/authorization.guard' import { VaultPermission } from '../type/domain.type' -const RequiredPermission = Reflector.createDecorator() +export const RequiredPermission = Reflector.createDecorator() export function PermissionGuard(...permissions: VaultPermission[]) { return applyDecorators( diff --git a/apps/vault/src/shared/guard/authorization.guard.ts b/apps/vault/src/shared/guard/authorization.guard.ts index 1af0080d9..81a758e02 100644 --- a/apps/vault/src/shared/guard/authorization.guard.ts +++ b/apps/vault/src/shared/guard/authorization.guard.ts @@ -6,7 +6,7 @@ import { Reflector } from '@nestjs/core' import { z } from 'zod' import { ClientService } from '../../client/core/service/client.service' import { Config } from '../../main.config' -import { PermissionGuard } from '../decorator/permission-guard.decorator' +import { RequiredPermission } from '../decorator/permission-guard.decorator' import { ApplicationException } from '../exception/application.exception' import { Client, VaultPermission } from '../type/domain.type' @@ -105,7 +105,7 @@ export class AuthorizationGuard implements CanActivate { // Get the Permissions (scopes) required from the request decorator, if it exists. const { request: requestHash } = req.body - const permissions: VaultPermission[] | undefined = this.reflector.get(PermissionGuard, context.getHandler()) + const permissions: VaultPermission[] | undefined = this.reflector.get(RequiredPermission, context.getHandler()) const access = permissions && permissions.length > 0 ? [ diff --git a/packages/signature/src/lib/schemas.ts b/packages/signature/src/lib/schemas.ts index 07e399983..b2f62daa9 100644 --- a/packages/signature/src/lib/schemas.ts +++ b/packages/signature/src/lib/schemas.ts @@ -1,6 +1,6 @@ import { z } from 'zod' import { addressSchema } from './address.schema' -import { Alg, Curves, KeyTypes, Use } from './types' +import { Alg, Curves, KeyTypes, PayloadAccessSchema, Use } from './types' // Base JWK Schema export const jwkBaseSchema = z.object({ @@ -210,7 +210,8 @@ export const Payload = z.object({ cnf: publicKeySchema.optional(), requestHash: z.string().optional(), hashWildcard: z.array(z.string()).optional(), - data: z.string().optional() + data: z.string().optional(), + access: z.array(PayloadAccessSchema).optional() }) export const Jwt = z.object({ From 5d9dd4578bc162667b1efbb38b094265fbe109ea Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Tue, 4 Feb 2025 21:40:47 +0100 Subject: [PATCH 116/120] Revert "Fix authorization guard access check (#129)" (#131) This reverts commit 10cd68925b176f85e9a9cce715728730acad16d2. --- .../vault/src/shared/decorator/permission-guard.decorator.ts | 2 +- apps/vault/src/shared/guard/authorization.guard.ts | 4 ++-- packages/signature/src/lib/schemas.ts | 5 ++--- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/apps/vault/src/shared/decorator/permission-guard.decorator.ts b/apps/vault/src/shared/decorator/permission-guard.decorator.ts index 085974165..5c3234066 100644 --- a/apps/vault/src/shared/decorator/permission-guard.decorator.ts +++ b/apps/vault/src/shared/decorator/permission-guard.decorator.ts @@ -4,7 +4,7 @@ import { Reflector } from '@nestjs/core' import { AuthorizationGuard } from '../guard/authorization.guard' import { VaultPermission } from '../type/domain.type' -export const RequiredPermission = Reflector.createDecorator() +const RequiredPermission = Reflector.createDecorator() export function PermissionGuard(...permissions: VaultPermission[]) { return applyDecorators( diff --git a/apps/vault/src/shared/guard/authorization.guard.ts b/apps/vault/src/shared/guard/authorization.guard.ts index 81a758e02..1af0080d9 100644 --- a/apps/vault/src/shared/guard/authorization.guard.ts +++ b/apps/vault/src/shared/guard/authorization.guard.ts @@ -6,7 +6,7 @@ import { Reflector } from '@nestjs/core' import { z } from 'zod' import { ClientService } from '../../client/core/service/client.service' import { Config } from '../../main.config' -import { RequiredPermission } from '../decorator/permission-guard.decorator' +import { PermissionGuard } from '../decorator/permission-guard.decorator' import { ApplicationException } from '../exception/application.exception' import { Client, VaultPermission } from '../type/domain.type' @@ -105,7 +105,7 @@ export class AuthorizationGuard implements CanActivate { // Get the Permissions (scopes) required from the request decorator, if it exists. const { request: requestHash } = req.body - const permissions: VaultPermission[] | undefined = this.reflector.get(RequiredPermission, context.getHandler()) + const permissions: VaultPermission[] | undefined = this.reflector.get(PermissionGuard, context.getHandler()) const access = permissions && permissions.length > 0 ? [ diff --git a/packages/signature/src/lib/schemas.ts b/packages/signature/src/lib/schemas.ts index b2f62daa9..07e399983 100644 --- a/packages/signature/src/lib/schemas.ts +++ b/packages/signature/src/lib/schemas.ts @@ -1,6 +1,6 @@ import { z } from 'zod' import { addressSchema } from './address.schema' -import { Alg, Curves, KeyTypes, PayloadAccessSchema, Use } from './types' +import { Alg, Curves, KeyTypes, Use } from './types' // Base JWK Schema export const jwkBaseSchema = z.object({ @@ -210,8 +210,7 @@ export const Payload = z.object({ cnf: publicKeySchema.optional(), requestHash: z.string().optional(), hashWildcard: z.array(z.string()).optional(), - data: z.string().optional(), - access: z.array(PayloadAccessSchema).optional() + data: z.string().optional() }) export const Jwt = z.object({ From 7697642fd0c93618d5222f20c7d86b9229c73e18 Mon Sep 17 00:00:00 2001 From: Matt Schoch Date: Wed, 5 Feb 2025 14:21:45 +0100 Subject: [PATCH 117/120] HOTFIX - engine should not use nowSeconds, iat should be set by armory --- .../core/service/cluster.service.ts | 29 ++++++++--- .../engine/core/service/evaluation.service.ts | 6 +-- .../6-generate-wallet.ts | 50 +++++++++++++++++++ 3 files changed, 75 insertions(+), 10 deletions(-) create mode 100644 examples/approvals-by-spending-limit/6-generate-wallet.ts diff --git a/apps/armory/src/policy-engine/core/service/cluster.service.ts b/apps/armory/src/policy-engine/core/service/cluster.service.ts index eb3f0f110..d0e00d4a2 100644 --- a/apps/armory/src/policy-engine/core/service/cluster.service.ts +++ b/apps/armory/src/policy-engine/core/service/cluster.service.ts @@ -1,7 +1,7 @@ import { ConfigService } from '@narval/config-module' import { LoggerService, MetricService, OTEL_ATTR_CLIENT_ID, TraceService } from '@narval/nestjs-shared' import { Decision, EvaluationRequest, EvaluationResponse } from '@narval/policy-engine-shared' -import { PublicKey, verifyJwt } from '@narval/signature' +import { PublicKey, nowSeconds, verifyJwt } from '@narval/signature' import { HttpStatus, Inject, Injectable } from '@nestjs/common' import { Counter } from '@opentelemetry/api' import { isEmpty } from 'lodash' @@ -117,6 +117,11 @@ export class ClusterService { nodes: nodes.map(({ id, url }) => ({ id, url })) }) + evaluation.metadata = { + issuedAt: nowSeconds(), // Ensure we have the SAME issuedAt for all nodes + ...evaluation.metadata + } + const responses = await Promise.all( nodes.map((node) => this.policyEngineClient.evaluate({ @@ -171,16 +176,16 @@ export class ClusterService { this.logger.log('Loaded finalizeEcdsaJwtSignature function', { finalizeEcdsaJwtSignature: this.finalizeEcdsaJwtSignature }) + } else { + throw new ApplicationException({ + message: 'The function finalizeEcdsaJwtSignature from @narval-xyz/armory-mpc-module is undefined', + suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR + }) } - - throw new ApplicationException({ - message: 'The function finalizeEcdsaJwtSignature from @narval-xyz/armory-mpc-module is undefined', - suggestedHttpStatusCode: HttpStatus.INTERNAL_SERVER_ERROR - }) } try { - // If MPC, wehave multiple partialSig responses to combine. If they don't + // If MPC, we have multiple partialSig responses to combine. If they don't // have exactly the same decision & accessToken, signature can't be // finalized and it will throw. const jwts = evaluations.map(({ accessToken }) => accessToken?.value).filter(isDefined) @@ -200,6 +205,16 @@ export class ClusterService { context: { jwts } }) } catch (error) { + this.logger.error('Finalizing JWT Error', { + evaluations, + partialTokens: evaluations.reduce( + (acc, { accessToken }, index) => ({ + ...acc, + [index]: accessToken?.value + }), + {} + ) + }) throw new ApplicationException({ message: 'Fail to finalize ECDSA JWT signature', suggestedHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY, diff --git a/apps/policy-engine/src/engine/core/service/evaluation.service.ts b/apps/policy-engine/src/engine/core/service/evaluation.service.ts index 2bea62f9a..8e6a89daa 100644 --- a/apps/policy-engine/src/engine/core/service/evaluation.service.ts +++ b/apps/policy-engine/src/engine/core/service/evaluation.service.ts @@ -1,6 +1,6 @@ import { TraceService } from '@narval/nestjs-shared' import { Action, Decision, EvaluationRequest, EvaluationResponse } from '@narval/policy-engine-shared' -import { Payload, hash, nowSeconds, signJwt } from '@narval/signature' +import { Payload, hash, signJwt } from '@narval/signature' import { HttpStatus, Inject, Injectable } from '@nestjs/common' import { ClientService } from '../../../client/core/service/client.service' import { ApplicationException } from '../../../shared/exception/application.exception' @@ -34,8 +34,8 @@ export async function buildPermitTokenPayload(clientId: string, evaluation: Eval } const { audience, issuer } = evaluation.metadata || {} - const iat = evaluation.metadata?.issuedAt || nowSeconds() - const exp = evaluation.metadata?.expiresIn ? evaluation.metadata.expiresIn + iat : null + const iat = evaluation.metadata?.issuedAt + const exp = evaluation.metadata?.expiresIn && iat ? evaluation.metadata.expiresIn + iat : null const hashWildcard = buildTransactionRequestHashWildcard(evaluation.request) const payload: Payload = { diff --git a/examples/approvals-by-spending-limit/6-generate-wallet.ts b/examples/approvals-by-spending-limit/6-generate-wallet.ts new file mode 100644 index 000000000..b78aed55a --- /dev/null +++ b/examples/approvals-by-spending-limit/6-generate-wallet.ts @@ -0,0 +1,50 @@ +/* eslint-disable no-console */ +import { AuthClient, AuthConfig, Permission, buildSignerEip191, privateKeyToJwk } from '@narval-xyz/armory-sdk' +import { Action, hexSchema } from '@narval-xyz/armory-sdk/policy-engine-shared' +import 'dotenv/config' +import { v4 } from 'uuid' + +const main = async () => { + console.log(`🚀 Generate Wallet \n`) + const adminUserPrivateKey = hexSchema.parse(process.env.ADMIN_USER_PRIVATE_KEY) + const host = process.env.AUTH_HOST + const clientId = process.env.CLIENT_ID + if (!host || !clientId) { + throw new Error('Missing configuration') + } + + const authJwk = privateKeyToJwk(adminUserPrivateKey) + const signer = buildSignerEip191(adminUserPrivateKey) + const authConfig: AuthConfig = { + host, + clientId, + signer: { + jwk: authJwk, + alg: 'EIP191', + sign: signer + } + } + const auth = new AuthClient(authConfig) + + const nonces = [v4()] + const tokens = await Promise.all( + nonces.map((nonce) => + auth.requestAccessToken({ + action: Action.GRANT_PERMISSION, + resourceId: 'vault', + nonce, + permissions: [Permission.WALLET_CREATE] + }) + ) + ) + + tokens.map((token, i) => { + if (!token) { + console.error('❌ Unauthorized, nonce: ', nonces[i]) + return + } + console.log('🔐 Approval token: \n', token.value) + }) +} + +main().catch(console.error) From 66cf58b3770fefa5d7c2df17cdb441593fffd284 Mon Sep 17 00:00:00 2001 From: Matt Schoch Date: Wed, 5 Feb 2025 14:26:03 +0100 Subject: [PATCH 118/120] Fixing iat in test --- .../core/service/__test__/unit/evaluation.service.spec.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/apps/policy-engine/src/engine/core/service/__test__/unit/evaluation.service.spec.ts b/apps/policy-engine/src/engine/core/service/__test__/unit/evaluation.service.spec.ts index 401c50beb..51e8e8300 100644 --- a/apps/policy-engine/src/engine/core/service/__test__/unit/evaluation.service.spec.ts +++ b/apps/policy-engine/src/engine/core/service/__test__/unit/evaluation.service.spec.ts @@ -11,7 +11,7 @@ import { Request, SignTransactionAction } from '@narval/policy-engine-shared' -import { Alg, PrivateKey, SigningAlg, decodeJwt, generateJwk, getPublicKey, nowSeconds } from '@narval/signature' +import { Alg, PrivateKey, SigningAlg, decodeJwt, generateJwk, getPublicKey } from '@narval/signature' import { Test } from '@nestjs/testing' import { MockProxy, mock } from 'jest-mock-extended' import { ClientService } from '../../../../../client/core/service/client.service' @@ -80,7 +80,6 @@ describe('buildPermitTokenPayload for signTransaction action', () => { expect(payload).toEqual({ cnf, - iat: nowSeconds(), requestHash: '0x608abe908cffeab1fc33edde6b44586f9dacbc9c6fe6f0a13fa307237290ce5a', hashWildcard: [ 'transactionRequest.gas', @@ -125,12 +124,9 @@ describe('buildPermitTokenPayload for grantPermission action', () => { it('returns a jwt payload if all conditions are met', async () => { const payload = await buildPermitTokenPayload('clientId', evalResponse) - const iat = nowSeconds() expect(payload).toEqual({ cnf, - iat, - exp: iat + ONE_DAY, iss: 'clientId.armory.narval.xyz', sub: 'test-alice-user-uid', access: [ From 9b1c6ce30f4910b9ed9ef556e07924b1dc981706 Mon Sep 17 00:00:00 2001 From: William Calderipe Date: Wed, 5 Feb 2025 14:34:53 +0100 Subject: [PATCH 119/120] Add "Fix authorization guard access check" back (#133) * Revert "Revert "Fix authorization guard access check (#129)" (#131)" This reverts commit 5d9dd4578bc162667b1efbb38b094265fbe109ea. * Add tests for auth guard and decode * Bump SDK to 0.20.0 --- .../decorator/permission-guard.decorator.ts | 2 +- .../__test__/unit/authorization.guard.spec.ts | 96 +++++++++++++++++-- .../src/shared/guard/authorization.guard.ts | 4 +- package-lock.json | 14 +-- packages/armory-sdk/package.json | 2 +- .../src/lib/__test__/unit/decode.spec.ts | 22 +++++ packages/signature/src/lib/decode.ts | 4 +- packages/signature/src/lib/schemas.ts | 29 +----- 8 files changed, 124 insertions(+), 49 deletions(-) diff --git a/apps/vault/src/shared/decorator/permission-guard.decorator.ts b/apps/vault/src/shared/decorator/permission-guard.decorator.ts index 5c3234066..085974165 100644 --- a/apps/vault/src/shared/decorator/permission-guard.decorator.ts +++ b/apps/vault/src/shared/decorator/permission-guard.decorator.ts @@ -4,7 +4,7 @@ import { Reflector } from '@nestjs/core' import { AuthorizationGuard } from '../guard/authorization.guard' import { VaultPermission } from '../type/domain.type' -const RequiredPermission = Reflector.createDecorator() +export const RequiredPermission = Reflector.createDecorator() export function PermissionGuard(...permissions: VaultPermission[]) { return applyDecorators( diff --git a/apps/vault/src/shared/guard/__test__/unit/authorization.guard.spec.ts b/apps/vault/src/shared/guard/__test__/unit/authorization.guard.spec.ts index 74c1c5dbc..8920c53b1 100644 --- a/apps/vault/src/shared/guard/__test__/unit/authorization.guard.spec.ts +++ b/apps/vault/src/shared/guard/__test__/unit/authorization.guard.spec.ts @@ -119,7 +119,7 @@ const getAccessToken = async (request: unknown, opts: object = {}) => { return signJwt(payload, enginePrivateJwk, { alg: SigningAlg.EIP191 }, signer) } -describe('AuthorizationGuard', () => { +describe(AuthorizationGuard.name, () => { let mockClientService = mock() let mockConfigService = mock>() @@ -134,11 +134,6 @@ describe('AuthorizationGuard', () => { mockReflector = mock() }) - it('should be defined', () => { - const guard = new AuthorizationGuard(mockClientService, mockConfigService, mockReflector, mockLogger) - expect(guard).toBeDefined() - }) - describe('canActivate', () => { const mockExecutionContext = ({ request }: { request?: unknown } = {}) => { const mockRequest = request || { @@ -276,7 +271,7 @@ describe('AuthorizationGuard', () => { await expect(guard.canActivate(context)).resolves.toEqual(true) }) - it('should throw when token validation is enabled and missing accessToken', async () => { + it('throws when token validation is enabled and missing accessToken', async () => { expect.assertions(2) const client = getBaseClient() mockClientService.findById.mockResolvedValue(client) @@ -331,7 +326,7 @@ describe('AuthorizationGuard', () => { await expect(guard.canActivate(context)).rejects.toThrow('No engine key configured') }) - it('should throw when requieBoundTokens is true and token is not bound', async () => { + it('throws when requieBoundTokens is true and token is not bound', async () => { const userPrivateJwk = secp256k1PrivateKeyToJwk(FIXTURE.UNSAFE_PRIVATE_KEY.Alice) const client = getBaseClient() mockClientService.findById.mockResolvedValue(client) @@ -417,5 +412,90 @@ describe('AuthorizationGuard', () => { await expect(guard.canActivate(context)).resolves.toEqual(true) }) + + it('passes when token contains required permissions', async () => { + const userPrivateJwk = secp256k1PrivateKeyToJwk(FIXTURE.UNSAFE_PRIVATE_KEY.Alice) + const userJwk = secp256k1PublicKeyToJwk(FIXTURE.VIEM_ACCOUNT.Alice.publicKey) + const client = getBaseClient() + mockClientService.findById.mockResolvedValue(client) + + // Mock the reflector to return permissions + mockReflector.get.mockReturnValue(['WALLET_READ']) + + const guard = new AuthorizationGuard(mockClientService, mockConfigService, mockReflector, mockLogger) + const payload = { + value: 'test-value' + } + + const accessToken = await getAccessToken(payload, { + sub: 'user-1', + cnf: userJwk, + access: [ + { + resource: 'vault', + permissions: ['WALLET_READ'] + } + ] + }) + const jwsd = await getJwsd({ + userPrivateJwk, + requestUrl: '/test', + payload, + accessToken + }) + + const mockRequest = { + headers: { 'x-client-id': 'test-client', authorization: `GNAP ${accessToken}`, 'detached-jws': jwsd }, + body: payload, + url: '/test', + method: 'POST' + } + const context = mockExecutionContext({ request: mockRequest }) + + await expect(guard.canActivate(context)).resolves.toEqual(true) + }) + + it('throws when token does not contain required permissions', async () => { + const userPrivateJwk = secp256k1PrivateKeyToJwk(FIXTURE.UNSAFE_PRIVATE_KEY.Alice) + const userJwk = secp256k1PublicKeyToJwk(FIXTURE.VIEM_ACCOUNT.Alice.publicKey) + const client = getBaseClient() + mockClientService.findById.mockResolvedValue(client) + + // Mock the reflector to return permissions + mockReflector.get.mockReturnValue(['WALLET_READ']) + + const guard = new AuthorizationGuard(mockClientService, mockConfigService, mockReflector, mockLogger) + const payload = { + value: 'test-value' + } + + // Token with different permission than required + const accessToken = await getAccessToken(payload, { + sub: 'user-1', + cnf: userJwk, + access: [ + { + resource: 'vault', + permissions: ['WALLET_WRITE'] + } + ] + }) + const jwsd = await getJwsd({ + userPrivateJwk, + requestUrl: '/test', + payload, + accessToken + }) + + const mockRequest = { + headers: { 'x-client-id': 'test-client', authorization: `GNAP ${accessToken}`, 'detached-jws': jwsd }, + body: payload, + url: '/test', + method: 'POST' + } + const context = mockExecutionContext({ request: mockRequest }) + + await expect(guard.canActivate(context)).rejects.toThrow('Invalid permissions') + }) }) }) diff --git a/apps/vault/src/shared/guard/authorization.guard.ts b/apps/vault/src/shared/guard/authorization.guard.ts index 1af0080d9..81a758e02 100644 --- a/apps/vault/src/shared/guard/authorization.guard.ts +++ b/apps/vault/src/shared/guard/authorization.guard.ts @@ -6,7 +6,7 @@ import { Reflector } from '@nestjs/core' import { z } from 'zod' import { ClientService } from '../../client/core/service/client.service' import { Config } from '../../main.config' -import { PermissionGuard } from '../decorator/permission-guard.decorator' +import { RequiredPermission } from '../decorator/permission-guard.decorator' import { ApplicationException } from '../exception/application.exception' import { Client, VaultPermission } from '../type/domain.type' @@ -105,7 +105,7 @@ export class AuthorizationGuard implements CanActivate { // Get the Permissions (scopes) required from the request decorator, if it exists. const { request: requestHash } = req.body - const permissions: VaultPermission[] | undefined = this.reflector.get(PermissionGuard, context.getHandler()) + const permissions: VaultPermission[] | undefined = this.reflector.get(RequiredPermission, context.getHandler()) const access = permissions && permissions.length > 0 ? [ diff --git a/package-lock.json b/package-lock.json index da253687a..e4e804945 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17890,9 +17890,9 @@ "peer": true }, "node_modules/@react-native/community-cli-plugin/node_modules/semver": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.0.tgz", - "integrity": "sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "license": "ISC", "peer": true, "bin": { @@ -40240,9 +40240,9 @@ } }, "node_modules/react-native/node_modules/semver": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.0.tgz", - "integrity": "sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "license": "ISC", "peer": true, "bin": { @@ -46122,7 +46122,7 @@ }, "packages/armory-sdk": { "name": "@narval-xyz/armory-sdk", - "version": "0.19.0", + "version": "0.20.0", "license": "MPL-2.0", "dependencies": { "@noble/curves": "1.6.0", diff --git a/packages/armory-sdk/package.json b/packages/armory-sdk/package.json index 57e933265..10a50fa99 100644 --- a/packages/armory-sdk/package.json +++ b/packages/armory-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@narval-xyz/armory-sdk", - "version": "0.19.0", + "version": "0.20.0", "license": "MPL-2.0", "publishConfig": { "access": "public" diff --git a/packages/signature/src/lib/__test__/unit/decode.spec.ts b/packages/signature/src/lib/__test__/unit/decode.spec.ts index 8c7f02c43..2e0b584c1 100644 --- a/packages/signature/src/lib/__test__/unit/decode.spec.ts +++ b/packages/signature/src/lib/__test__/unit/decode.spec.ts @@ -16,6 +16,7 @@ describe('decodeJwt', () => { const rawJwt = await signJwt(payload, key, { alg: 'ES256K' }) const jwt = decodeJwt(rawJwt) + expect(jwt).toEqual({ header: { alg: 'ES256K', @@ -34,4 +35,25 @@ describe('decodeJwt', () => { it('throws an error if token is in correct format but not valid base64url encoded data', async () => { expect(() => decodeJwt('invalid.invalid.invalid')).toThrow(JwtError) }) + + it('does not strip arbitrary data from the payload', async () => { + const payloadWithArbitraryData = { + ...payload, + foo: 'foo', + bar: 'bar' + } + const rawJwt = await signJwt(payloadWithArbitraryData, key, { alg: 'ES256K' }) + + const jwt = decodeJwt(rawJwt) + + expect(jwt).toEqual({ + header: { + alg: 'ES256K', + kid: key.kid, + typ: 'JWT' + }, + payload: payloadWithArbitraryData, + signature: rawJwt.split('.')[2] + }) + }) }) diff --git a/packages/signature/src/lib/decode.ts b/packages/signature/src/lib/decode.ts index 7dbd53fdb..a87d6b4f8 100644 --- a/packages/signature/src/lib/decode.ts +++ b/packages/signature/src/lib/decode.ts @@ -1,6 +1,6 @@ import { JwtError } from './error' -import { Header, Payload } from './schemas' -import { type Jwsd, type Jwt } from './types' +import { Header } from './schemas' +import { Payload, type Jwsd, type Jwt } from './types' import { base64UrlToBytes } from './utils' diff --git a/packages/signature/src/lib/schemas.ts b/packages/signature/src/lib/schemas.ts index 07e399983..fae915861 100644 --- a/packages/signature/src/lib/schemas.ts +++ b/packages/signature/src/lib/schemas.ts @@ -1,6 +1,6 @@ import { z } from 'zod' import { addressSchema } from './address.schema' -import { Alg, Curves, KeyTypes, Use } from './types' +import { Alg, Curves, KeyTypes, Payload, Use } from './types' // Base JWK Schema export const jwkBaseSchema = z.object({ @@ -186,33 +186,6 @@ export const JwsdHeader = z.object({ ) }) -/** - * Defines the payload of JWT. - * - * @param {string} requestHash - The hashed request. - * @param {string} [iss] - The issuer of the JWT. - * @param {number} [iat] - The time the JWT was issued. - * @param {number} [exp] - The time the JWT expires. - * @param {string} sub - The subject of the JWT. - * @param {string} [aud] - The audience of the JWT. - * @param {string[]} [hashWildcard] - A list of paths that were not hashed in the request. - * @param {string} [jti] - The JWT ID. - * @param {Jwk} cnf - The client-bound key. - * - */ -export const Payload = z.object({ - sub: z.string().optional(), - iat: z.number().optional(), - exp: z.number().optional(), - iss: z.string().optional(), - aud: z.string().optional(), - jti: z.string().optional(), - cnf: publicKeySchema.optional(), - requestHash: z.string().optional(), - hashWildcard: z.array(z.string()).optional(), - data: z.string().optional() -}) - export const Jwt = z.object({ header: Header, payload: Payload, From 1a40068d80fa83609e257758d50b033ea5fcd2cf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Feb 2025 13:59:43 +0000 Subject: [PATCH 120/120] Bump @nx/devkit from 19.5.1 to 20.4.0 Bumps [@nx/devkit](https://github.com/nrwl/nx/tree/HEAD/packages/devkit) from 19.5.1 to 20.4.0. - [Release notes](https://github.com/nrwl/nx/releases) - [Commits](https://github.com/nrwl/nx/commits/20.4.0/packages/devkit) --- updated-dependencies: - dependency-name: "@nx/devkit" dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- package-lock.json | 21 ++++++--------------- package.json | 2 +- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index e4e804945..d0f92a959 100644 --- a/package-lock.json +++ b/package-lock.json @@ -99,7 +99,7 @@ "@docusaurus/types": "3.1.0", "@faker-js/faker": "9.0.1", "@nestjs/testing": "10.4.1", - "@nx/devkit": "19.5.1", + "@nx/devkit": "20.4.0", "@nx/eslint": "19.3.2", "@nx/eslint-plugin": "19.3.2", "@nx/jest": "20.0.8", @@ -7436,15 +7436,6 @@ "node": ">= 8" } }, - "node_modules/@nrwl/devkit": { - "version": "19.5.1", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.5.1.tgz", - "integrity": "sha512-ZsckDZszLTv3oshNsY5fZ86g8a/VcGvgDpdiP/z/A/krtOHL8iUjdT/72Eo5DIult5WcSFjnifyWcyWIGe1PeA==", - "dev": true, - "dependencies": { - "@nx/devkit": "19.5.1" - } - }, "node_modules/@nrwl/eslint-plugin-nx": { "version": "19.3.2", "resolved": "https://registry.npmjs.org/@nrwl/eslint-plugin-nx/-/eslint-plugin-nx-19.3.2.tgz", @@ -7630,12 +7621,12 @@ } }, "node_modules/@nx/devkit": { - "version": "19.5.1", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.5.1.tgz", - "integrity": "sha512-Vj8wwzNIR5VIWmuLHhOi4aUVq7eVV5YTbctnEewKT+V/O4LZj+hClGyVNyT8s6b8JIjNWoIO4HXStLnH8rDOlw==", + "version": "20.4.0", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-20.4.0.tgz", + "integrity": "sha512-qog9oGbuz7DDoXH5k+19tTI3WtaR1p9G5NobiDPfcWmsr1BTK2WH2V2/vVYFAfAcM/DEFgK3ITC5L3PSaJvMmw==", "dev": true, + "license": "MIT", "dependencies": { - "@nrwl/devkit": "19.5.1", "ejs": "^3.1.7", "enquirer": "~2.3.6", "ignore": "^5.0.4", @@ -7646,7 +7637,7 @@ "yargs-parser": "21.1.1" }, "peerDependencies": { - "nx": ">= 17 <= 20" + "nx": ">= 19 <= 21" } }, "node_modules/@nx/devkit/node_modules/semver": { diff --git a/package.json b/package.json index 7bba43f77..37728d4af 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "@docusaurus/types": "3.1.0", "@faker-js/faker": "9.0.1", "@nestjs/testing": "10.4.1", - "@nx/devkit": "19.5.1", + "@nx/devkit": "20.4.0", "@nx/eslint": "19.3.2", "@nx/eslint-plugin": "19.3.2", "@nx/jest": "20.0.8",